packages feed

mercury-api (empty) → 0.1.0.0

raw patch · 98 files changed

+38192/−0 lines, 98 filesdep +HUnitdep +ansi-terminaldep +basesetup-changed

Dependencies added: HUnit, ansi-terminal, base, bytestring, clock, directory, hashable, mercury-api, optparse-applicative, text, unordered-containers

Files

+ ChangeLog.md view
@@ -0,0 +1,5 @@+# Revision history for mercury-api++## 0.1.0.0  -- 2017-06-05++* First version. Released on an unsuspecting world.
+ LICENSE view
@@ -0,0 +1,45 @@+Copyright (c) 2017 Patrick Pelletier++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.++----------------------------------------------------------------------++ThingMagic Mercury API Software License++Copyright (c) 2009 - 2012 Trimble Navigation Limited++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.
+ README.md view
@@ -0,0 +1,55 @@+Latest:+[![Hackage](https://img.shields.io/hackage/v/hs-mercury-api.svg)](https://hackage.haskell.org/package/hs-mercury-api)+Linux:+[![Build Status](https://travis-ci.org/ppelleti/hs-mercury-api.svg?branch=master)](https://travis-ci.org/ppelleti/hs-mercury-api)+Windows:+[![Build status](https://ci.appveyor.com/api/projects/status/aywuy9y05ow8wja2/branch/master?svg=true)](https://ci.appveyor.com/project/ppelleti/hs-mercury-api/branch/master)++This package is a Haskell binding to the [Mercury API][5] C API for+[ThingMagic][6] RFID readers.  It is especially geared toward+the [SparkFun Simultaneous RFID Reader][1], which uses ThingMagic's+[M6e Nano][7] module, but it should work with other ThingMagic+readers.  (Though currently, only support for serial readers is+compiled in.)  Most of the function and type names are the same as+their counterparts in the C API, with the `TMR_` prefix dropped.  For+more in-depth, language-independent documentation of Mercury API, see+[Mercury API Programmers Guide][2].++This package includes a copy of the Mercury API C library, so no+external libraries are necessary.  Several small bug fixes have been+applied to the included version of the library.  (I have submitted+these patches upstream, but I don't know if or when they will be+included in the official version.)  If you need to upgrade to a newer+version of Mercury API than the included one, see [UPGRADING.md][9].++The Haskell binding doesn't support background reads.  I recommend+that you just spawn a new Haskell thread and do foreground reads+instead.++Currently, only support for the serial reader is compiled in, but it+probably wouldn't be too hard to enable LLRP support.  (I don't have+any way to test LLRP, however, as the M6e Nano doesn't support it.)++On Mac OS X, be sure to use the serial device that starts with+`/dev/cu.`, not the serial device that starts with `/dev/tty.`.++Only some parameters and some tagops are currently supported in the+Haskell binding.  (There are a lot of them, and I only implemented the+ones I needed.)  If you need support for additional parameters or+tagops, please file an issue in GitHub and I will add them.++Additional resources:++* [RFID Basics][8]+* [SparkFun Simultaneous RFID Reader hookup guide][3]+* [ThingMagic manuals and firmware][4]++[1]: https://www.sparkfun.com/products/14066+[2]: http://www.thingmagic.com/images/Downloads/Docs/MercuryAPI_ProgrammerGuide_for_v1.27.3.pdf+[3]: https://learn.sparkfun.com/tutorials/simultaneous-rfid-tag-reader-hookup-guide+[4]: http://www.thingmagic.com/index.php/manuals-firmware+[5]: http://www.thingmagic.com/index.php/manuals-firmware#Mercury_API+[6]: http://www.thingmagic.com/+[7]: http://www.thingmagic.com/index.php/embedded-rfid-readers/thingmagic-nano-module+[8]: https://learn.sparkfun.com/tutorials/rfid-basics+[9]: https://github.com/ppelleti/hs-mercury-api/blob/master/UPGRADING.md
+ Setup.hs view
@@ -0,0 +1,2 @@+import Distribution.Simple+main = defaultMain
+ UPGRADING.md view
@@ -0,0 +1,30 @@+Hopefully I will keep this package up-to-date with the latest version+of Mercury API.  But if you're in the position of needing to update+Mercury API, follow these instructions:++* Unzip the Mercury API zipfile.++* Copy the files from `c/src/api/` in the Mercury API distribution to+  `cbits/api/` in this package.++* Run `dos2unix` on the files you copied, to normalize the line+  endings.  (In the Mercury API distribution, they are a random+  combination of DOS and Unix line endings, often in the same file.)++* Apply the patches from the `cbits/api/patches/` directory.++* Update `mercury-api.cabal` with any additional C files that were+  added in the new release.  Note that not all C files are needed; in+  particular, `serial_transport_tcp_posix.c` and+  `tmr_loadsave_configuration.c` are not needed.  Also, note that the+  files are supposed to be listed in [dependency order][1].  (And+  sadly, to get them in the right order, we have to list all the files+  for both Windows and POSIX, because the files end up in the wrong+  order if some are conditional and some are unconditional.  Yuck!)++* Run `util/generate-tmr-hsc.pl` (no arguments needed), which will+  update the generated files `Enums.hsc` and `Params.hs` based on the+  new `.h` and `.c` files.  (In particular, this will automatically+  pick up new status codes and new parameters.)++[1]: https://ghc.haskell.org/trac/ghc/ticket/13786#comment:3
+ cbits/api/hex_bytes.c view
@@ -0,0 +1,151 @@+/**+ *  @file hex_bytes.c+ *  @brief Routines for converting between byte arrays and hex strings+ *  @author Nathan Williams+ *  @date 10/23/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 <stdlib.h>++#include "tm_reader.h"+#include "serial_reader_imp.h"++static char hexchars[] = "0123456789ABCDEF";+++TMR_Status+TMR_hexToBytes(const char *hex, uint8_t *bytes, uint32_t size,+               uint32_t *convertLen)+{+  char c;+  int i, len;+  uint8_t val[2];++  if (hex[0] == '0' && (hex[1] == 'x' || hex[1] == 'X'))+  {+    hex += 2;+  }++  len = 0;+  while (size > 0 && *hex != '\0')+  {+    for (i = 0; i < 2; i++)+    {+      c = *hex++;+      if (c >= '0' && c <= '9')+        val[i] = c - '0';+      else if (c >= 'a' && c <= 'f')+        val[i] = 10 + c - 'a';+      else if (c >= 'A' && c <= 'F')+        val[i] = 10 + c - 'A';+      else+        return TMR_ERROR_INVALID;+    }+    *bytes = (val[0] << 4) | val[1];++    len++;+    bytes++;+    size--;+  }++  if (convertLen != NULL)+  {+    *convertLen = len;+  }++  return TMR_SUCCESS;+}++void+TMR_bytesToHex(const uint8_t *bytes, uint32_t size, char *hex)+{++  while (size--)+  {+    *hex++ = hexchars[*bytes >> 4];+    *hex++ = hexchars[*bytes & 15];+    bytes++;+  }+  *hex = '\0';+}++/**+ * Convert a four-byte array into a null-terminated string+ * with the format %02X.%02X.%02X.%02X (AA.BB.CC.DD).+ *+ * @param bytes The array of four bytes to convert+ * @param buf The string to write to. Must be at least 12 bytes.+ */+void+TMR_hexDottedQuad(const uint8_t bytes[4], char buf[12])+{+  int i;++  for (i = 0; i < 4 ; i++)+  {+    *buf++ = hexchars[*bytes >> 4];+    *buf++ = hexchars[*bytes & 15];+    *buf++ = '.';+    bytes++;+  }+  *--buf = '\0';+}++/**+ * Convert a 12-byte null-terminated string hexDottedQuad into a uint32_t+ *+ * @param bytes The array of twelve bytes to convert+ * @param result The resulting uint32_t+ * @return uint32_t represented but the 12 bytes+ */+TMR_Status+TMR_hexDottedQuadToUint32(const char bytes[12], uint32_t *result)+{+  TMR_Status retVal;+  uint32_t tmpResult;+  uint8_t byteVal;+  int i,j;++  tmpResult=0;+  for (i = 0, j = 0; i < 12 ; i+=3,++j)+  {+    retVal = TMR_hexToBytes(&bytes[i], &byteVal, 1, NULL);+    if (TMR_SUCCESS == retVal)+    {+      tmpResult |= (byteVal << (8 * (3-j)));+    }+    else+    {+      return retVal;+    }+  }++  if (NULL != result)+  {+    *result = tmpResult;+  }+  return retVal;+}
+ cbits/api/llrp_reader_imp.h view
@@ -0,0 +1,293 @@+#ifndef _LLRP_READER_IMP_H+#define _LLRP_READER_IMP_H++/**+ *  @file llrp_reader_imp.h+ *  @brief LLRP reader internal implementation header+ *  @author Somu+ *  @date 05/25/2011+ */++/*+ * Copyright (c) 2011 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 <time.h>+#include "tm_reader.h"+#include "tmr_status.h"+#include "ltkc.h"++#ifdef  __cplusplus+extern "C" {+#endif++/**+ * Magic Number to reboot the Thingmagic LLRP+ * fixed reader.+ **/+#define TMR_POWER_CYCLE_MAGIC_NUMBER 0x20000920  ++/**+ * LLRP specific AccessCommandOpSpecResult parameter typenums+ **/+#define TMR_LLRP_C1G2READOPSPECRESULT 349+#define TMR_LLRP_C1G2WRITEOPSPECRESULT 350+#define TMR_LLRP_C1G2KILLOPSPECRESULT 351+#define TMR_LLRP_C1G2LOCKOPSPECRESULT 352+#define TMR_LLRP_C1G2BLOCKERASEOPSPECRESULT 353+#define TMR_LLRP_C1G2BLOCKWRITEOPSPECRESULT 354+#define TMR_LLRP_CUSTOM_BLOCKPERMALOCKOPSPECRESULT 22+#define TMR_LLRP_CUSTOM_HIGGS2PARTIALLOADIMAGEOPSPECRESULT 24+#define TMR_LLRP_CUSTOM_HIGGS2FULLLOADIMAGEOPSPECRESULT 26+#define TMR_LLRP_CUSTOM_HIGGS3FASTLOADIMAGEOPSPECRESULT 28+#define TMR_LLRP_CUSTOM_HIGGS3LOADIMAGEOPSPECRESULT 30+#define TMR_LLRP_CUSTOM_HIGGS3BLOCKREADLOCKOPSPECRESULT 32+#define TMR_LLRP_CUSTOM_G2ISETREADPROTECTOPSPECRESULT 34                               +#define TMR_LLRP_CUSTOM_G2XSETREADPROTECTOPSPECRESULT 36                               +#define TMR_LLRP_CUSTOM_G2IRESETREADPROTECTOPSPECRESULT 38                             +#define TMR_LLRP_CUSTOM_G2XRESETREADPROTECTOPSPECRESULT 40                             +#define TMR_LLRP_CUSTOM_G2ICHANGEEASOPSPECRESULT 42                                    +#define TMR_LLRP_CUSTOM_G2XCHANGEEASOPSPECRESULT 44                                    +#define TMR_LLRP_CUSTOM_G2IEASALARMOPSPECRESULT 46                                     +#define TMR_LLRP_CUSTOM_G2XEASALARMOPSPECRESULT 48                                     +#define TMR_LLRP_CUSTOM_G2ICALIBRATEOPSPECRESULT 50                                    +#define TMR_LLRP_CUSTOM_G2XCALIBRATEOPSPECRESULT 52                                    +#define TMR_LLRP_CUSTOM_G2ICHANGECONFIGOPSPECRESULT 54                                 +#define TMR_LLRP_CUSTOM_MONZA4QTREADWRITEOPSPECRESULT 57+#define TMR_LLRP_CUSTOM_IDS_SETSFEPARAMETERSOPSPECRESULT 99+#define TMR_LLRP_CUSTOM_IDS_GETMEASUREMENTSETUPOPSPECRESULT 93+#define TMR_LLRP_CUSTOM_IDS_GETBATTERYLEVELOPSPECRESULT 103+#define TMR_LLRP_CUSTOM_IDS_SETLOGLIMITSOPSPECRESULT 116+#define TMR_LLRP_CUSTOM_IDS_SETSHELFLIFEOPSPECRESULT 124+#define TMR_LLRP_CUSTOM_IDS_SETPASSWORDOPSPECRESULT 118+#define TMR_LLRP_CUSTOM_WRITETAGOPSPECRESULT  61+#define TMR_LLRP_CUSTOM_IDS_GETSENSORVALUEOPSPECRESULT 77+#define TMR_LLRP_CUSTOM_IDS_SETLOGMODEOPSPECRESULT 85+#define TMR_LLRP_CUSTOM_IDS_STARTLOGMODEOPSPECRESULT 87+#define TMR_LLRP_CUSTOM_IDS_GETLOGSTATEOPSPECRESULT 79+#define TMR_LLRP_CUSTOM_IDS_ENDLOGOPSPECRESULT 89+#define TMR_LLRP_CUSTOM_IDS_INITIALIZEOPSPECRESULT 91+#define TMR_LLRP_CUSTOM_IDS_ACCESSFIFOSTATUSOPSPECRESULT 101+#define TMR_LLRP_CUSTOM_IDS_ACCESSFIFOWRITEOPSPECRESULT 114+#define TMR_LLRP_CUSTOM_IDS_ACCESSFIFOREADOPSPECRESULT 112+#define TMR_LLRP_CUSTOM_IDS_GETCALIBRATIONDATAOPSPECRESULT 95+#define TMR_LLRP_CUSTOM_IDS_SETCALIBRATIONDATAOPSPECRESULT 97+#define TMR_LLRP_CUSTOM_DENATRAN_IAV_ACTIVATESECUREMODEOPSPECRESULT 127+#define TMR_LLRP_CUSTOM_DENATRAN_IAV_AUTHENTICATEOBUOPSPECRESULT 129+#define TMR_LLRP_CUSTOM_DENATRAN_IAV_ACTIVATESINIAVMODEOPSPECRESULT 131+#define TMR_LLRP_CUSTOM_DENATRAN_IAV_AUTHENTICATEIDOPSPECRESULT 133+#define TMR_LLRP_CUSTOM_DENATRAN_IAV_AUTHENTICATEFULLPASS1OPSPECRESULT 135+#define TMR_LLRP_CUSTOM_DENATRAN_IAV_AUTHENTICATEFULLPASS2OPSPECRESULT 137+#define TMR_LLRP_CUSTOM_DENATRAN_IAV_OBUREADFROMMEMMAPOPSPECRESULT 139+#define TMR_LLRP_CUSTOM_DENATRAN_IAV_OBUWRITETOMEMMAPOPSPECRESULT 141++#ifdef TMR_ENABLE_ISO180006B+#define TMR_LLRP_CUSTOM_ISO_READDATAOPSPECRESULT  65+#define TMR_LLRP_CUSTOM_ISO_WRITEDATAOPSPECRESULT 68+#define TMR_LLRP_CUSTOM_ISO_LOCKOPSPECRESULT 70+#endif /* TMR_ENABLE_ISO180006B */++/**+ * Maximum number of ROSpecs supported by reader.+ **/+#define TMR_LLRP_MAX_ROSPECS 32+/**+ * Maximum milliseconds required for reader to stop an ongoing search+ **/+#define TMR_LLRP_STOP_TIMEOUT 5000++/**+ * This structure is returned from TMR_LLRP_cmdAntennaDetect.+ **/+typedef struct TMR_LLRP_PortDetect+{+  /** The port number. */+  uint16_t port;+  /** Whether the antenna is connected? */+  bool connected;+  /** Antenna gain */+  int16_t gain;+}TMR_LLRP_PortDetect;++/**+ * This struture is returned from ThingMagicDeDuplication+ **/+typedef struct TMR_LLRP_TMDeDuplication+{+  /** Record Highest RSSI */+  llrp_u1_t highestRSSI;++  /** Unique By Antenna */+  llrp_u1_t uniquebyAntenna;++  /** Unique By Data */+  llrp_u1_t uniquebyData;+}TMR_LLRP_TMDeDuplication;+  +/**+ * This structure is returned from cmdGetThingmagicReaderConfiguration+ **/+typedef struct TMR_LLRP_TMReaderConfiguration+{+  /** Reader description */+  llrp_utf8v_t description;+  /** Reader Role */+  llrp_utf8v_t role;+  /** Reader host name */+  llrp_utf8v_t hostName;+} TMR_LLRP_TMReaderConfiguration;++/**+ * This value is returned from TMR_LLRP_cmdVersionModel.+ **/+# define  TMR_LLRP_MODEL_M6  0x06+# define  TMR_LLRP_MODEL_ASTRA_EX 0x30+# define  TMR_LLRP_MODEL_SARGAS 0x3430++TMR_Status TMR_LLRP_notifyTransportListener(TMR_Reader *reader, LLRP_tSMessage *pMsg, bool tx, int timeout);+TMR_Status TMR_LLRP_sendMessage(TMR_Reader *reader, LLRP_tSMessage *pMsg, int timeoutMs);+TMR_Status TMR_LLRP_receiveMessage(TMR_Reader *reader, LLRP_tSMessage **pMsg, int timeoutMs);+TMR_Status TMR_LLRP_sendTimeout(TMR_Reader *reader, LLRP_tSMessage *pMsg, LLRP_tSMessage **pRsp, int timeoutMs);+TMR_Status TMR_LLRP_send(TMR_Reader *reader, LLRP_tSMessage *pMsg, LLRP_tSMessage **pRsp);+void TMR_LLRP_freeMessage(LLRP_tSMessage *pMsg);+TMR_Status TMR_LLRP_checkLLRPStatus(LLRP_tSLLRPStatus *pLLRPStatus);++TMR_Status TMR_LLRP_cmdGetRegion(TMR_Reader *reader, TMR_Region *region);+TMR_Status TMR_LLRP_cmdAntennaDetect(TMR_Reader *reader, uint8_t *count, TMR_LLRP_PortDetect *ports);+TMR_Status TMR_LLRP_cmdGetTMAsyncOffTime(TMR_Reader *reader, uint32_t *offtime);++TMR_Status TMR_LLRP_cmdGetGPIState(TMR_Reader *reader, uint8_t *count, TMR_GpioPin state[]);+TMR_Status TMR_LLRP_cmdSetGPOState(TMR_Reader *reader, uint8_t count, const TMR_GpioPin state[]);++TMR_Status TMR_LLRP_cmdGetReaderCapabilities(TMR_Reader *reader, TMR_LLRP_ReaderCapabilities *capabilities);++TMR_Status TMR_LLRP_cmdGetReadTransmitPowerList(TMR_Reader *reader, TMR_PortValueList *pPortValueList);+TMR_Status TMR_LLRP_cmdSetReadTransmitPowerList(TMR_Reader *reader, TMR_PortValueList *pPortValueList);++TMR_Status TMR_LLRP_cmdGetWriteTransmitPowerList(TMR_Reader *reader, TMR_PortValueList *pPortValueList);+TMR_Status TMR_LLRP_cmdSetWriteTransmitPowerList(TMR_Reader *reader, TMR_PortValueList *pPortValueList);+TMR_Status TMR_LLRP_cmdGetTMDeviceInformationCapabilities(TMR_Reader *reader, int param, TMR_String  *version);+TMR_Status TMR_LLRP_cmdGetActiveRFControl(TMR_Reader *reader, TMR_LLRP_RFControl *rfControl);+TMR_Status TMR_LLRP_cmdSetActiveRFControl(TMR_Reader *reader, TMR_LLRP_RFControl *rfControl);+TMR_Status TMR_LLRP_cmdGetGen2Session(TMR_Reader *reader, TMR_GEN2_Session  *session);+TMR_Status TMR_LLRP_cmdSetGen2Session(TMR_Reader *reader, TMR_GEN2_Session  *session);+TMR_Status TMR_LLRP_cmdSetTMAsyncOffTime(TMR_Reader *reader, uint32_t offtime);++/*ThingMagic Licensed Features*/+TMR_Status TMR_LLRP_cmdGetLicensedFeatures(TMR_Reader *reader, TMR_uint8List  *features);++/*ThingMagic Selected Protocols*/+TMR_Status TMR_LLRP_cmdGetSelectedProtocols(TMR_Reader *reader, TMR_TagProtocolList *protocolList);++/* ThingMagic DeDuplication */+TMR_Status TMR_LLRP_cmdGetThingMagicDeDuplication(TMR_Reader *reader, TMR_LLRP_TMDeDuplication *duplication);+TMR_Status TMR_LLRP_cmdSetThingMagicDeDuplication(TMR_Reader *reader, TMR_LLRP_TMDeDuplication *duplication);++/* Thingmagic Reader configuration */+TMR_Status TMR_LLRP_cmdGetThingmagicReaderConfiguration(TMR_Reader *reader, TMR_LLRP_TMReaderConfiguration *config);+TMR_Status TMR_LLRP_cmdSetThingmagicReaderConfiguration(TMR_Reader *reader, TMR_LLRP_TMReaderConfiguration *config);+void TMR_LLRP_freeTMReaderConfiguration(TMR_LLRP_TMReaderConfiguration *config);++/* Thingmagic Current Time */+TMR_Status TMR_LLRP_cmdGetThingMagicCurrentTime(TMR_Reader *reader, struct tm *curTime);++/* Thingmagic Reader Module Temperature */+TMR_Status TMR_LLRP_cmdGetThingMagicReaderModuleTemperature(TMR_Reader *reader, uint8_t *temp);++/* Thingmagic protocol configuration: Gen2 Q */+TMR_Status TMR_LLRP_cmdSetGen2Q(TMR_Reader *reader, TMR_GEN2_Q *q);+TMR_Status TMR_LLRP_cmdGetGen2Q(TMR_Reader *reader, TMR_GEN2_Q *q);++/* Thingmagic Protocol configuration:Gen2 Target */+TMR_Status TMR_LLRP_cmdSetGen2Target(TMR_Reader *reader, TMR_GEN2_Target *target);+TMR_Status TMR_LLRP_cmdGetGen2Target(TMR_Reader *reader, TMR_GEN2_Target *target);++/* Thingmagic LicenseKey */+TMR_Status TMR_LLRP_cmdSetTMLicenseKey(TMR_Reader *reader, TMR_uint8List *license);++/* Thingmagic ISO 18K6B Delimiter */+TMR_Status TMR_LLRP_cmdSetISO18K6BDelimiter(TMR_Reader *reader, TMR_ISO180006B_Delimiter *delimiter);+TMR_Status TMR_LLRP_cmdGetISO18K6BDelimiter(TMR_Reader *reader, TMR_ISO180006B_Delimiter *delimiter);++/* Thingmagic ISO 18K6B Modulation Depth */+TMR_Status TMR_LLRP_cmdSetISO18K6BModDepth(TMR_Reader *reader, TMR_ISO180006B_ModulationDepth *modDepth);+TMR_Status TMR_LLRP_cmdGetISO18K6BModDepth(TMR_Reader *reader, TMR_ISO180006B_ModulationDepth *modDepth);++/* Thingmagic ISO 1806B Link Frequency */+TMR_Status TMR_LLRP_cmdSetISO18K6BLinkFrequency(TMR_Reader *reader, TMR_ISO180006B_LinkFrequency *linkFreq);+TMR_Status TMR_LLRP_cmdGetISO18K6BLinkFrequency(TMR_Reader *reader, TMR_ISO180006B_LinkFrequency *linkFreq);++/* Thingmagic Device Protocol Capabilities */+TMR_Status TMR_LLRP_cmdGetTMDeviceProtocolCapabilities(TMR_Reader *reader, TMR_TagProtocolList * protocol);++/* Thingmagic Device Antenna Detection */+TMR_Status TMR_LLRP_cmdGetThingMagicAntennaDetection(TMR_Reader *reader, bool *antennaport);+TMR_Status TMR_LLRP_cmdSetThingMagicAntennaDetection(TMR_Reader *reader, bool *antennaport);++/* Read  */+TMR_Status TMR_LLRP_cmdPrepareROSpec(TMR_Reader *reader, uint16_t timeout, TMR_uint8List *antennaList,+            const TMR_TagFilter *filter, TMR_TagProtocol protocol);+TMR_Status TMR_LLRP_cmdAddROSpec(TMR_Reader *reader, uint16_t readDuration, TMR_uint8List *antennaList,+                                  const TMR_TagFilter *filter, TMR_TagProtocol protocol);+TMR_Status TMR_LLRP_cmdEnableROSpec(TMR_Reader *reader);+TMR_Status TMR_LLRP_cmdDisableROSpec(TMR_Reader *reader);+TMR_Status TMR_LLRP_cmdStartROSpec(TMR_Reader *reader, llrp_u32_t roSpecId);+TMR_Status TMR_LLRP_cmdStopROSpec(TMR_Reader *reader, bool receiveResponse);+TMR_Status TMR_LLRP_cmdDeleteAllROSpecs(TMR_Reader *reader, bool receiveResponse);+TMR_Status TMR_LLRP_parseMetadataFromMessage(TMR_Reader *reader, TMR_TagReadData *data, LLRP_tSTagReportData *msg);+TMR_Status TMR_LLRP_verifyReadOperation(TMR_Reader *reader, int32_t *tagCount);+TMR_Status TMR_LLRP_cmdStopReading(struct TMR_Reader *reader);++TMR_Status TMR_LLRP_cmdGetVersionSerial(TMR_Reader *reader, TMR_String *version);+TMR_Status TMR_LLRP_cmdrebootReader(TMR_Reader *reader);++/* Reset Reader */+TMR_Status TMR_LLRP_stopActiveROSpecs(TMR_Reader *reader);++/* Reports, Notifications and Keepalives */+TMR_Status TMR_LLRP_setKeepAlive(TMR_Reader *reader);+TMR_Status TMR_LLRP_enableEventsAndReports(TMR_Reader *reader);+TMR_Status TMR_LLRP_setHoldEventsAndReportsStatus(TMR_Reader *reader, llrp_u1_t status);+TMR_Status TMR_LLRP_handleKeepAlive(TMR_Reader *reader, LLRP_tSMessage *pMsg);+TMR_Status TMR_LLRP_startBackgroundReceiver(TMR_Reader *reader);+TMR_Status TMR_LLRP_cmdSetEventNotificationSpec(TMR_Reader *reader, bool state);+TMR_Status TMR_LLRP_handleReaderEvents(TMR_Reader *reader, LLRP_tSMessage *pMsg);+TMR_Status TMR_LLRP_processReceivedMessage(TMR_Reader *reader, LLRP_tSMessage *pMsg);+void TMR_LLRP_setBackgroundReceiverState(TMR_Reader *reader, bool state);++/* Access Spec */+TMR_Status TMR_LLRP_cmdEnableAccessSpec(TMR_Reader *reader, llrp_u32_t accessSpecId);+TMR_Status TMR_LLRP_msgPrepareAccessCommand(TMR_Reader *reader, LLRP_tSAccessCommand *pAccessCommand,+                                                              TMR_TagFilter *filter, TMR_TagOp *tagop);+TMR_Status TMR_LLRP_cmdAddAccessSpec(TMR_Reader *reader, TMR_TagProtocol protocol, TMR_TagFilter *filter,+                                            llrp_u32_t roSpecId, TMR_TagOp *tagop, bool isStandalone);+TMR_Status TMR_LLRP_verifyOpSpecResultStatus(TMR_Reader *reader, LLRP_tSParameter *pParameter);+TMR_Status TMR_LLRP_cmdDeleteAllAccessSpecs(TMR_Reader *reader);++TMR_Status TMR_LLRP_parseCustomTagOpSpecResultType(LLRP_tEThingMagicCustomTagOpSpecResultType status);+void TMR_LLRP_parseTagOpSpecData(LLRP_tSParameter *pParameter, TMR_uint8List *data);++TMR_Status TMR_LLRP_cmdGetReport(TMR_Reader *reader);+#ifdef __cplusplus+}+#endif++#endif /* _LLRP_READER_IMP_H */
+ cbits/api/osdep.h view
@@ -0,0 +1,96 @@+#ifndef _OSDEP_H+#define _OSDEP_H++/**+ *  @file osdep.h+ *  @brief Mercury API - OS dependencies+ *  @author Nathan Williams+ *  @date 2/24/2010+ */++/*+ * Copyright (c) 2010 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.+ */++#ifdef WINCE+#include <stdint_win32.h>+#else+#include <stdint.h>+#endif++#ifdef  __cplusplus+extern "C" {+#endif++/* These are functions that must be provided for the library to operate */++  /*+  * Thing magic reader time objeect to reprejent the time stamp+  */+  typedef struct TMR_TimeStructure+  {+    uint32_t tm_sec;+    uint32_t tm_min;+    uint32_t tm_hour;+    uint32_t tm_mday;+    uint32_t tm_mon;+    uint32_t tm_year;+  }TMR_TimeStructure;++/*+ * The time function used to return the current time in+ * thing magic time structure.+ */+TMR_TimeStructure tmr_gettimestructure(void);++uint64_t tmr_gettime(void);++/* The time functions collectively return a 64-bit counter in units of+ * milliseconds. Both methods are used when timestamping events such+ * as tag reads. For controlling elapsed time, only the lower one is+ * used, so If your platform does not support more than 32 bits of+ * millisecond counting, returning 0 from the high method will not+ * cause problems internal to the library.+ */++/**+ * Return the low 32-bits of a system millisecond counter. This is+ * used internally for operation timing and to timestamp tag reads.+ */+uint32_t tmr_gettime_low(void);++/**+ * Return the high 32-bits of a system millisecond counter. This is+ * used to timestamp tag reads.+ */+uint32_t tmr_gettime_high(void);++/**+ * Suspend operation for a given duration.+ * @param sleepms The number of milliseconds to sleep for.+ */+void tmr_sleep(uint32_t sleepms);++#ifdef __cplusplus+}+#endif++#endif /* _OSDEP_H */
+ cbits/api/osdep_posix.c view
@@ -0,0 +1,97 @@++/**+ *  @file osdep_posix.c+ *  @brief Mercury API - POSIX platform implementation of OS dependencies+ *  @author Nathan Williams+ *  @date 2/24/2010+ */++/*+ * Copyright (c) 2010 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 <time.h>+#include <sys/time.h>++#include "osdep.h"++uint64_t+tmr_gettime()+{+  struct timeval tv;+  uint64_t totalms;++  gettimeofday(&tv, NULL);+  totalms = (((uint64_t)tv.tv_sec) * 1000) + ((uint64_t) tv.tv_usec) / 1000;++  return totalms;+}++uint32_t+tmr_gettime_low()+{++  return (tmr_gettime() >>  0) & 0xffffffff;+}++uint32_t+tmr_gettime_high()+{++  return (tmr_gettime() >> 32) & 0xffffffff;+}+++void+tmr_sleep(uint32_t sleepms)+{+  struct timespec sleep, rem;++  sleep.tv_sec = sleepms / 1000;+  sleep.tv_nsec = (sleepms % 1000) * 1000000L;++  /* Sleep until the proper time has elapsed, and re-sleep if interrupted. */+  while (-1 == nanosleep(&sleep, &rem))+  {+    sleep = rem;+  }+}++TMR_TimeStructure +tmr_gettimestructure()+{+  time_t now;+  uint64_t temp;+  struct tm *timestamp;+  TMR_TimeStructure timestructure;++  temp = tmr_gettime();+  now = (time_t)(temp/1000);+  timestamp = localtime(&now);++  timestructure.tm_year = (uint32_t)(1900 + timestamp->tm_year);+  timestructure.tm_mon = (uint32_t)(1 + timestamp->tm_mon);+  timestructure.tm_mday = (uint32_t)timestamp->tm_mday;+  timestructure.tm_hour = (uint32_t)timestamp->tm_hour;+  timestructure.tm_min = (uint32_t)timestamp->tm_min;+  timestructure.tm_sec = (uint32_t)timestamp->tm_sec;+  return timestructure;  +}
+ cbits/api/osdep_win32.c view
@@ -0,0 +1,86 @@+/**+ *  @file osdep_win32.c+ *  @brief Mercury API - Windows platform implementation of OS dependencies+*/++/*+ * Copyright (c) 2010 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.+ */++#if !defined(_WINSOCK2API_) && !defined(_WINSOCKAPI_)+#include <winsock2.h>+#endif+#include <time.h>+#include "osdep.h"++// https://stackoverflow.com/questions/6161776/convert-windows-filetime-to-second-in-unix-linux+#define SEC_TO_UNIX_EPOCH 11644473600LL++uint64_t+tmr_gettime()+{+  uint64_t totalms;+  SYSTEMTIME st;+  FILETIME ft;+  LARGE_INTEGER li;    +  GetSystemTime(&st);+  SystemTimeToFileTime(&st, &ft);+  li.LowPart = ft.dwLowDateTime;+  li.HighPart = ft.dwHighDateTime;+  totalms=(((uint64_t)li.LowPart) | ((uint64_t)li.HighPart)<<32)/10000;+  totalms -= SEC_TO_UNIX_EPOCH * 1000;+  return totalms;+}++uint32_t+tmr_gettime_low()+{+  return (uint32_t) tmr_gettime();+}++uint32_t+tmr_gettime_high()+{+  return (uint32_t) (tmr_gettime() >> 32);+}++void+tmr_sleep(uint32_t sleepms)+{+  Sleep(sleepms);+}++TMR_TimeStructure +tmr_gettimestructure()+{ +  SYSTEMTIME st;+  TMR_TimeStructure timestructure;++  GetSystemTime(&st);++  timestructure.tm_year = (uint32_t)st.wYear;+  timestructure.tm_mon = (uint32_t)st.wMonth;+  timestructure.tm_mday = (uint32_t)st.wDay;+  timestructure.tm_hour = (uint32_t)st.wHour;+  timestructure.tm_min = (uint32_t)st.wMinute;+  timestructure.tm_sec = (uint32_t)st.wSecond;+  return timestructure;  +}
+ cbits/api/patches/README.md view
@@ -0,0 +1,23 @@+These are patches to be applied to Mercury API to fix various bugs.+I've submitted all of them (except `config.patch`) to ThingMagic for+possible inclusion in a future release.++`config.patch` - This increases the maximum length of URIs from 64 bytes to 256 bytes.  Unlike all the other patches, this is a configuration change, not a bug fix, so it has not been submitted upstream.++`eintr.patch` - This retries the `select()` operation when it returns `EINTR`.  This is always good practice, but it seemed to be necessary in my situation to avoid failing with a timeout.  There are probably plenty of other places in the API where this should be done, too.++`extern.patch` - This fixes a problem I ran into with `isSecureAccessEnabled` being multiply defined, when compiling with cabal.  (Strangely, doesn't happen when using ThingMagic's Makefile.)++`host-c-library.patch` - The build failed when `TMR_USE_HOST_C_LIBRARY` was defined.  This fixes that.++`infinite-loop.patch` - This avoids an infinite loop that I ran into, when somehow `readOffSet` was 142, and `dataLength` was 128.  Not sure how that happened, and it probably indicates another bug, but at least this fix prevents going into an infinite loop in that situation.++`metadataflag-size.patch` - `paramSet()` treated `TMR_PARAM_METADATAFLAG` as `TMR_TRD_MetadataFlag`, while `paramGet()` treated `TMR_PARAM_METADATAFLAG` as `uint16_t`.  Since `sizeof(TMR_TRD_MetadataFlag)` is 4 but `sizeof(uint16_t)` is 2, the sizes didn't match.  This patch fixes `paramGet()` to also treat it as `TMR_TRD_MetadataFlag`.++`mingw-dword-pointer.patch` - Fixes a compiler warning about `warning: passing argument 4 of 'ReadFile' from incompatible pointer type [-Wincompatible-pointer-types]`.  Somehow the warning was getting treated as an error on Appveyor.++`mingw-snprintf.patch` - Fixes a problem I ran into on MinGW, where `sprintf_s()` doesn't seem to work properly, but `snprintf()` does work properly.++`typos.patch` - This just fixes a bunch of small typos I found.++`windows-time.patch` - On Windows, `tmr_gettime_low()` and `tmr_gettime_high()` were returning the number of 100-nanosecond units since 1/1/1601, rather than the number of milliseconds since 1/1/1970.  This caused the `timestampLow` and `timestampHigh` fields of `TMR_TagReadData` to be populated incorrectly.  This patch fixes that problem.
+ cbits/api/patches/config.patch view
@@ -0,0 +1,23 @@+commit 092146c3eb431d9358135e5a2919f5a9a6f4c0db+Author: Patrick Pelletier <code@funwithsoftware.org>+Date:   Thu May 25 15:55:39 2017 -0700++    increase the maximum length of a reader URI+    +    This is necessary because in the case of test:// URIs, we are passing+    an arbitrary filename.  Even 256 is fairly arbitrary, but it seems+    like enough for most cases, while 64 seemed tight.++diff --git a/tm_config.h b/tm_config.h+index a749b26..ea5892e 100644+--- a/tm_config.h++++ b/tm_config.h+@@ -56,7 +56,7 @@ extern "C" {+ /**+  * The longest possible name for a reader.+  */+-#define TMR_MAX_READER_NAME_LENGTH 64++#define TMR_MAX_READER_NAME_LENGTH 256+ + /**+  * The maximum number of protocols supported in a multiprotocol search command
+ cbits/api/patches/eintr.patch view
@@ -0,0 +1,30 @@+diff --git a/serial_transport_posix.c b/serial_transport_posix.c+index 9146589..4127ee3 100644+--- a/serial_transport_posix.c++++ b/serial_transport_posix.c+@@ -127,12 +127,19 @@ s_receiveBytes(TMR_SR_SerialTransport *this, uint32_t length,+ +   do+   {+-    FD_ZERO(&set);+-    FD_SET(c->handle, &set);+-    tv.tv_sec = timeoutMs / 1000;+-    tv.tv_usec = (timeoutMs % 1000) * 1000;+-    /* Ideally should reset this timeout value every time through */+-    ret = select(c->handle + 1, &set, NULL, NULL, &tv);++    do++    {++      FD_ZERO(&set);++      FD_SET(c->handle, &set);++      tv.tv_sec = timeoutMs / 1000;++      tv.tv_usec = (timeoutMs % 1000) * 1000;++      /* Ideally should reset this timeout value every time through */++      ret = select(c->handle + 1, &set, NULL, NULL, &tv);++    } while (ret == -1 && errno == EINTR);++    if (ret == -1)++    {++      return TMR_ERROR_COMM_ERRNO(errno);++    }+     if (ret < 1)+     {+       return TMR_ERROR_TIMEOUT;
+ cbits/api/patches/extern.patch view
@@ -0,0 +1,28 @@+diff --git a/serial_reader_imp.h b/serial_reader_imp.h+index 9f5fd54..16e30b1 100644+--- a/serial_reader_imp.h++++ b/serial_reader_imp.h+@@ -40,7 +40,7 @@ extern "C" {+ /* This is used to enable the Gen2 secure readdata option */+ + #ifndef BARE_METAL+-  bool isSecureAccessEnabled ;++  extern bool isSecureAccessEnabled ;+ #else+   static bool isSecureAccessEnabled;	+ #endif+diff --git a/serial_reader_l3.c b/serial_reader_l3.c+index 99986bf..71c4192 100644+--- a/serial_reader_l3.c++++ b/serial_reader_l3.c+@@ -36,6 +36,10 @@+ #include "serial_reader_imp.h"+ #include "tmr_utils.h"+ ++#ifndef BARE_METAL++bool isSecureAccessEnabled;++#endif+++ void+ notify_read_listeners(TMR_Reader *reader, TMR_TagReadData *trd);+ #ifdef TMR_ENABLE_SERIAL_READER
+ cbits/api/patches/host-c-library.patch view
@@ -0,0 +1,33 @@+diff --git a/tm_reader_async.c b/tm_reader_async.c+index 4bcec6f..a464c5f 100644+--- a/tm_reader_async.c++++ b/tm_reader_async.c+@@ -40,6 +40,7 @@ TMR_Status restart_reading(struct TMR_Reader *reader);+ #include <semaphore.h>+ #include <time.h>+ #include <stdio.h>++#include <string.h>+ + #ifndef WIN32+ #include <sys/time.h>+diff --git a/tmr_utils.c b/tmr_utils.c+index 194a63a..80c7ce9 100644+--- a/tmr_utils.c++++ b/tmr_utils.c+@@ -28,6 +28,7 @@+  */+ + #include <stddef.h>++#include <string.h>+ + #include "osdep.h"+ #include "tmr_types.h"+@@ -171,7 +172,7 @@ TMR_stringCopy(TMR_String *dest, const char *src, int len)+   }+   if (dest->max > 0)+   {+-    tm_memcpy(dest->value, src, len);++    memcpy(dest->value, src, len);+     dest->value[len] = '\0';+   }+ }
+ cbits/api/patches/infinite-loop.patch view
@@ -0,0 +1,13 @@+diff --git a/serial_reader_l3.c b/serial_reader_l3.c+index 99986bf..458740e 100644+--- a/serial_reader_l3.c++++ b/serial_reader_l3.c+@@ -1767,7 +1767,7 @@ TMR_SR_parseMetadataFromMessage(TMR_Reader *reader, TMR_TagReadData *read, uint1+     uint16_t epcDataLength;+     while (dataLength != 0)+     {+-      if (readOffSet == dataLength)++      if (readOffSet >= dataLength)+         break;+       bank = ((read->data.list[readOffSet] >> 4) & 0x1F);+       epcDataLength = (read->data.list[readOffSet + 1] * 2);
+ cbits/api/patches/metadataflag-size.patch view
@@ -0,0 +1,13 @@+diff --git a/serial_reader.c b/serial_reader.c+index 7001ab1..c711aac 100644+--- a/serial_reader.c++++ b/serial_reader.c+@@ -4178,7 +4178,7 @@ TMR_SR_paramGet(struct TMR_Reader *reader, TMR_Param key, void *value)+     break;+   case TMR_PARAM_METADATAFLAG:+ 	  {+-		*(uint16_t *)value = reader->userMetadataFlag;++		*(TMR_TRD_MetadataFlag *)value = reader->userMetadataFlag;+ 		break;+ 	  }+ 		    
+ cbits/api/patches/mingw-dword-pointer.patch view
@@ -0,0 +1,13 @@+diff --git a/serial_transport_win32.c b/serial_transport_win32.c+index ce4cc46..ff007b6 100644+--- a/serial_transport_win32.c++++ b/serial_transport_win32.c+@@ -126,7 +126,7 @@ s_receiveBytes(TMR_SR_SerialTransport *this, uint32_t length,+               uint32_t* messageLength, uint8_t* message, const uint32_t+ timeoutMs)+ {+- uint32_t readLength;++ DWORD readLength;+  DWORD errorFlags;+  COMSTAT comStat;+  TMR_SR_SerialPortNativeContext *c;
+ cbits/api/patches/mingw-snprintf.patch view
@@ -0,0 +1,13 @@+diff --git a/serial_transport_win32.c b/serial_transport_win32.c+index ce4cc46..e8e27cb 100644+--- a/serial_transport_win32.c++++ b/serial_transport_win32.c+@@ -39,7 +39,7 @@+ + #  if defined(WINCE)+ #    define snprintf _snprintf+-#  else++#  elif !defined(__GNUC__)+ #    define snprintf sprintf_s+ #  endif+ 
+ cbits/api/patches/typos.patch view
@@ -0,0 +1,884 @@+diff --git a/llrp_reader_l3.c b/llrp_reader_l3.c+index 555fe0a..de3fe19 100644+--- a/llrp_reader_l3.c++++ b/llrp_reader_l3.c+@@ -9691,7 +9691,7 @@ TMR_LLRP_verifyOpSpecResultStatus(TMR_Reader *reader,+ +           case LLRP_C1G2ReadResultType_Memory_Locked_Error:+             {+-              ret = TMR_ERROR_GEN2_PROCOCOL_MEMORY_LOCKED;++              ret = TMR_ERROR_GEN2_PROTOCOL_MEMORY_LOCKED;+               break;+             }+ +@@ -9725,7 +9725,7 @@ TMR_LLRP_verifyOpSpecResultStatus(TMR_Reader *reader,+ +           case LLRP_C1G2WriteResultType_Tag_Memory_Locked_Error:+             {+-              ret = TMR_ERROR_GEN2_PROCOCOL_MEMORY_LOCKED;++              ret = TMR_ERROR_GEN2_PROTOCOL_MEMORY_LOCKED;+               break;+             }+ +@@ -9881,7 +9881,7 @@ TMR_LLRP_verifyOpSpecResultStatus(TMR_Reader *reader,+ +           case LLRP_C1G2BlockEraseResultType_Tag_Memory_Locked_Error:+             {+-              ret = TMR_ERROR_GEN2_PROCOCOL_MEMORY_LOCKED;++              ret = TMR_ERROR_GEN2_PROTOCOL_MEMORY_LOCKED;+               break;+             }+ +@@ -9939,7 +9939,7 @@ TMR_LLRP_verifyOpSpecResultStatus(TMR_Reader *reader,+ +           case LLRP_C1G2BlockWriteResultType_Tag_Memory_Locked_Error:+             {+-              ret = TMR_ERROR_GEN2_PROCOCOL_MEMORY_LOCKED;++              ret = TMR_ERROR_GEN2_PROTOCOL_MEMORY_LOCKED;+               break;+             }+ +diff --git a/osdep.h b/osdep.h+index d9661ac..126e3b9 100644+--- a/osdep.h++++ b/osdep.h+@@ -56,7 +56,7 @@ extern "C" {+   }TMR_TimeStructure;+ + /*+- * The time funcution used to return the current time in++ * The time function used to return the current time in+  * thing magic time structure.+  */+ TMR_TimeStructure tmr_gettimestructure(void);+diff --git a/serial_reader.c b/serial_reader.c+index 7001ab1..1d017b1 100644+--- a/serial_reader.c++++ b/serial_reader.c+@@ -228,7 +228,7 @@ TMR_SR_boot(TMR_Reader *reader, uint32_t currentBaudRate)+   }+ +   /**+-   * In case for M6E and it's varient  check for CRC++   * 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]) ||+@@ -426,7 +426,7 @@ TMR_SR_boot(TMR_Reader *reader, uint32_t currentBaudRate)+       {+         /*+          * Modules with firmware older than wilder will throw 0x105 error, as it was not +-         * implemented. Catch this error and but do not return.++         * implemented. Catch this error but do not return.+          */+ 		sr->productId = 0xFFFF;+       }+@@ -497,7 +497,7 @@ TMR_SR_boot(TMR_Reader *reader, uint32_t currentBaudRate)+ +   /**+    * Enable the extended EPC flag in case+-   * of M5E and its varients++   * of M5E and its variants+    */+   if ((TMR_SR_MODEL_M6E != sr->versionInfo.hardware[0]) &&+       (TMR_SR_MODEL_MICRO != sr->versionInfo.hardware[0]) &&+@@ -4020,7 +4020,7 @@ TMR_SR_paramGet(struct TMR_Reader *reader, TMR_Param key, void *value)+     case TMR_SR_MODEL_MICRO:+       {+         /**+-         * Micro has following varients.++         * Micro has following variants.+          **/+         switch (sr->versionInfo.hardware[3])+         {+@@ -4751,7 +4751,7 @@ TMR_SR_executeTagOp(struct TMR_Reader *reader, TMR_TagOp *tagop, TMR_TagFilter *+     {+       TMR_TagOp_GEN2_IDS_SL900A_GetSensorValue op;+ +-      /* Set the protocol for tag opearation */++      /* Set the protocol for tag operation */+       ret = setProtocol(reader, TMR_TAG_PROTOCOL_GEN2);+       if (TMR_SUCCESS != ret)+       {+@@ -4773,7 +4773,7 @@ TMR_SR_executeTagOp(struct TMR_Reader *reader, TMR_TagOp *tagop, TMR_TagFilter *+     {+       TMR_TagOp_GEN2_IDS_SL900A_GetMeasurementSetup op;+ +-      /* Set the protocol for tag opearation */++      /* Set the protocol for tag operation */+       ret = setProtocol(reader, TMR_TAG_PROTOCOL_GEN2);+       if (TMR_SUCCESS != ret)+       {+@@ -4795,7 +4795,7 @@ TMR_SR_executeTagOp(struct TMR_Reader *reader, TMR_TagOp *tagop, TMR_TagFilter *+     {+       TMR_TagOp_GEN2_IDS_SL900A_GetCalibrationData op;+ +-      /* Set the protocol for tag opearation */++      /* Set the protocol for tag operation */+       ret = setProtocol(reader, TMR_TAG_PROTOCOL_GEN2);+       if (TMR_SUCCESS != ret)+       {+@@ -4817,7 +4817,7 @@ TMR_SR_executeTagOp(struct TMR_Reader *reader, TMR_TagOp *tagop, TMR_TagFilter *+     {+       TMR_TagOp_GEN2_IDS_SL900A_SetCalibrationData op;+ +-      /* Set the protocol for tag opearation */++      /* Set the protocol for tag operation */+       ret = setProtocol(reader, TMR_TAG_PROTOCOL_GEN2);+       if (TMR_SUCCESS != ret)+       {+@@ -4839,7 +4839,7 @@ TMR_SR_executeTagOp(struct TMR_Reader *reader, TMR_TagOp *tagop, TMR_TagFilter *+     {+       TMR_TagOp_GEN2_IDS_SL900A_SetSfeParameters op;+ +-      /* Set the protocol for tag opearation */++      /* Set the protocol for tag operation */+       ret = setProtocol(reader, TMR_TAG_PROTOCOL_GEN2);+       if (TMR_SUCCESS != ret)+       {+@@ -4862,7 +4862,7 @@ TMR_SR_executeTagOp(struct TMR_Reader *reader, TMR_TagOp *tagop, TMR_TagFilter *+     {+       TMR_TagOp_GEN2_IDS_SL900A_GetLogState op;+ +-      /* Set the protocol for tag opearation */++      /* Set the protocol for tag operation */+       ret = setProtocol(reader, TMR_TAG_PROTOCOL_GEN2);+       if (TMR_SUCCESS != ret)+       {+@@ -4884,7 +4884,7 @@ TMR_SR_executeTagOp(struct TMR_Reader *reader, TMR_TagOp *tagop, TMR_TagFilter *+     {+       TMR_TagOp_GEN2_IDS_SL900A_SetLogMode op;+ +-      /* Set the protocol for tag opearation */++      /* Set the protocol for tag operation */+       ret = setProtocol(reader, TMR_TAG_PROTOCOL_GEN2);+       if (TMR_SUCCESS != ret)+       {+@@ -4907,7 +4907,7 @@ TMR_SR_executeTagOp(struct TMR_Reader *reader, TMR_TagOp *tagop, TMR_TagFilter *+     {+       TMR_TagOp_GEN2_IDS_SL900A_Initialize op;+       +-      /* Set the protocol for tag opearation */++      /* Set the protocol for tag operation */+       ret = setProtocol(reader, TMR_TAG_PROTOCOL_GEN2);+       if (TMR_SUCCESS != ret)+       {+@@ -4930,7 +4930,7 @@ TMR_SR_executeTagOp(struct TMR_Reader *reader, TMR_TagOp *tagop, TMR_TagFilter *+     {+       TMR_TagOp_GEN2_IDS_SL900A_EndLog op;+ +-      /* Set the protocol for tag opearation */++      /* Set the protocol for tag operation */+       ret = setProtocol(reader, TMR_TAG_PROTOCOL_GEN2);+       if (TMR_SUCCESS != ret)+       {+@@ -4952,7 +4952,7 @@ TMR_SR_executeTagOp(struct TMR_Reader *reader, TMR_TagOp *tagop, TMR_TagFilter *+     {+       TMR_TagOp_GEN2_IDS_SL900A_SetPassword op;+ +-      /* Set the protocol for tag opearation */++      /* Set the protocol for tag operation */+       ret = setProtocol(reader, TMR_TAG_PROTOCOL_GEN2);+       if (TMR_SUCCESS != ret)+       {+@@ -4974,7 +4974,7 @@ TMR_SR_executeTagOp(struct TMR_Reader *reader, TMR_TagOp *tagop, TMR_TagFilter *+     {+       TMR_TagOp_GEN2_IDS_SL900A_AccessFifoStatus op;+       +-      /* Set the protocol for tag opearation */++      /* Set the protocol for tag operation */+       ret = setProtocol(reader, TMR_TAG_PROTOCOL_GEN2);+       if (TMR_SUCCESS != ret)+       {+@@ -4995,7 +4995,7 @@ TMR_SR_executeTagOp(struct TMR_Reader *reader, TMR_TagOp *tagop, TMR_TagFilter *+     {+       TMR_TagOp_GEN2_IDS_SL900A_AccessFifoRead op;+ +-      /* Set the protocol for tag opearation */++      /* Set the protocol for tag operation */+       ret = setProtocol(reader, TMR_TAG_PROTOCOL_GEN2);+       if (TMR_SUCCESS != ret)+       {+@@ -5016,7 +5016,7 @@ TMR_SR_executeTagOp(struct TMR_Reader *reader, TMR_TagOp *tagop, TMR_TagFilter *+     {+       TMR_TagOp_GEN2_IDS_SL900A_AccessFifoWrite op;+ +-      /* Set the protocol for tag opearation */++      /* Set the protocol for tag operation */+       ret = setProtocol(reader, TMR_TAG_PROTOCOL_GEN2);+       if (TMR_SUCCESS != ret)+       {+@@ -5037,7 +5037,7 @@ TMR_SR_executeTagOp(struct TMR_Reader *reader, TMR_TagOp *tagop, TMR_TagFilter *+     {+       TMR_TagOp_GEN2_IDS_SL900A_StartLog op;+       +-      /* Set the protocol for tag opearation */++      /* Set the protocol for tag operation */+       ret = setProtocol(reader, TMR_TAG_PROTOCOL_GEN2);+       if (TMR_SUCCESS != ret)+       {+@@ -5059,7 +5059,7 @@ TMR_SR_executeTagOp(struct TMR_Reader *reader, TMR_TagOp *tagop, TMR_TagFilter *+     {+       TMR_TagOp_GEN2_IDS_SL900A_GetBatteryLevel op;+ +-      /* Set the protocol for tag opearation */++      /* Set the protocol for tag operation */+       ret = setProtocol(reader, TMR_TAG_PROTOCOL_GEN2);+       if (TMR_SUCCESS != ret)+       {+@@ -5081,7 +5081,7 @@ TMR_SR_executeTagOp(struct TMR_Reader *reader, TMR_TagOp *tagop, TMR_TagFilter *+     {+       TMR_TagOp_GEN2_IDS_SL900A_SetLogLimits op;+ +-      /* Set the protocol for tag opearation */++      /* Set the protocol for tag operation */+       ret = setProtocol(reader, TMR_TAG_PROTOCOL_GEN2);+       if (TMR_SUCCESS != ret)+       {+@@ -5103,7 +5103,7 @@ TMR_SR_executeTagOp(struct TMR_Reader *reader, TMR_TagOp *tagop, TMR_TagFilter *+     {+       TMR_TagOp_GEN2_IDS_SL900A_SetShelfLife op;+ +-      /* Set the protocol for tag opearation */++      /* Set the protocol for tag operation */+       ret = setProtocol(reader, TMR_TAG_PROTOCOL_GEN2);+       if (TMR_SUCCESS != ret)+       {+diff --git a/serial_reader_imp.h b/serial_reader_imp.h+index 9f5fd54..a96405f 100644+--- a/serial_reader_imp.h++++ b/serial_reader_imp.h+@@ -467,7 +467,7 @@ typedef struct TMR_SR_Gen2ReaderWriteTimeOut+   /* Status of reader timeout */+   bool earlyexit;+ +-  /* Timeout value used for write opearation */++  /* Timeout value used for write operation */+   uint16_t writetimeout;+ }TMR_SR_Gen2ReaderWriteTimeOut;+ /**+@@ -677,11 +677,11 @@ TMR_Status TMR_SR_cmdSL900aGetBatteryLevel(TMR_Reader *reader, uint16_t timeout,+                                            uint8_t CommandCode, uint32_t password, PasswordLevel level,BatteryType type,+                                            TMR_uint8List *data, TMR_TagFilter* target);+ TMR_Status TMR_SR_cmdSL900aAccessFifoStatus(TMR_Reader *reader, uint16_t timeout, TMR_GEN2_Password accessPassword, uint8_t CommandCode,+-           uint32_t password, PasswordLevel level, AccessFifoOperation opearation, TMR_uint8List * data, TMR_TagFilter* target);++           uint32_t password, PasswordLevel level, AccessFifoOperation operation, TMR_uint8List * data, TMR_TagFilter* target);+ TMR_Status TMR_SR_cmdSL900aAccessFifoRead(TMR_Reader *reader, uint16_t timeout, TMR_GEN2_Password accessPassword, uint8_t CommandCode,+-            uint32_t password, PasswordLevel level, AccessFifoOperation opearation, uint8_t length,TMR_uint8List * data, TMR_TagFilter* target);++            uint32_t password, PasswordLevel level, AccessFifoOperation operation, uint8_t length,TMR_uint8List * data, TMR_TagFilter* target);+ TMR_Status TMR_SR_cmdSL900aAccessFifoWrite(TMR_Reader *reader, uint16_t timeout, TMR_GEN2_Password accessPassword, uint8_t CommandCode,+-           uint32_t password, PasswordLevel level, AccessFifoOperation opearation, TMR_uint8List *payLoad, TMR_uint8List * data, TMR_TagFilter* target);++           uint32_t password, PasswordLevel level, AccessFifoOperation operation, TMR_uint8List *payLoad, TMR_uint8List * data, TMR_TagFilter* target);+ TMR_Status TMR_SR_cmdHibikiReadLock(TMR_Reader *reader, uint16_t timeout,+             TMR_GEN2_Password accessPassword, uint16_t mask, uint16_t action);+ TMR_Status TMR_SR_cmdHibikiGetSystemInformation(TMR_Reader *reader, uint16_t timeout,+@@ -945,7 +945,7 @@ TMR_SR_msgAddIdsSL900aSetPassword(uint8_t *msg, uint8_t *i, uint16_t timeout, TM+                                   PasswordLevel newPasswordLevel, TMR_TagFilter* target);+ void + TMR_SR_msgAddIdsSL900aAccessFifoStatus(uint8_t *msg, uint8_t *i, uint16_t timeout, TMR_GEN2_Password accessPassword,+-                                  uint8_t CommandCode, uint32_t password, PasswordLevel level, AccessFifoOperation opearation,++                                  uint8_t CommandCode, uint32_t password, PasswordLevel level, AccessFifoOperation operation,+                                   TMR_TagFilter* target);+ void + TMR_SR_msgAddIdsSL900aGetBatteryLevel(uint8_t *msg, uint8_t *i, uint16_t timeout, TMR_GEN2_Password accessPassword,+@@ -953,11 +953,11 @@ TMR_SR_msgAddIdsSL900aGetBatteryLevel(uint8_t *msg, uint8_t *i, uint16_t timeout+                                       TMR_TagFilter* target);+ void + TMR_SR_msgAddIdsSL900aAccessFifoRead(uint8_t *msg, uint8_t *i, uint16_t timeout, TMR_GEN2_Password accessPassword,+-                                  uint8_t CommandCode, uint32_t password, PasswordLevel level, AccessFifoOperation opearation,++                                  uint8_t CommandCode, uint32_t password, PasswordLevel level, AccessFifoOperation operation,+                                   uint8_t length, TMR_TagFilter* target);+ void + TMR_SR_msgAddIdsSL900aAccessFifoWrite(uint8_t *msg, uint8_t *i, uint16_t timeout, TMR_GEN2_Password accessPassword,+-                                  uint8_t CommandCode, uint32_t password, PasswordLevel level, AccessFifoOperation opearation,++                                  uint8_t CommandCode, uint32_t password, PasswordLevel level, AccessFifoOperation operation,+                                   TMR_uint8List *payLoad, TMR_TagFilter* target);+ void + TMR_SR_msgAddIdsSL900aStartLog(uint8_t *msg, uint8_t *i, uint16_t timeout, TMR_GEN2_Password accessPassword,+diff --git a/serial_reader_l3.c b/serial_reader_l3.c+index 99986bf..c20af74 100644+--- a/serial_reader_l3.c++++ b/serial_reader_l3.c+@@ -360,7 +360,7 @@ retryHeader:+      }+ +     /* We got a response for a different command than the one we+-     * sent. This usually means we recieved the boot-time message from++     * sent. This usually means we received the boot-time message from+      * a M6e, and thus that the device was rebooted somewhere between+      * the previous command and this one. Report this as a problem.+      */+@@ -1756,7 +1756,7 @@ TMR_SR_parseMetadataFromMessage(TMR_Reader *reader, TMR_TagReadData *read, uint1+ 	}+ +   /**+-   * if the gen2AllMemoryBankEnabled is enbled,++   * if the gen2AllMemoryBankEnabled is enabled,+    * extract the values+    **/+   if (reader->u.serialReader.gen2AllMemoryBankEnabled)+@@ -3778,7 +3778,7 @@ TMR_SR_msgSetupMultipleProtocolSearch(TMR_Reader *reader, uint8_t *msg, TMR_SR_O+     case TMR_SR_OPCODE_READ_TAG_ID_MULTIPLE:+       {+         /**+-        * simple read plan uses this funcution, only when tagop is NULL,++        * simple read plan uses this function, only when tagop is NULL,+         * s0, need to check for simple read plan tagop.+         **/+         if (TMR_READ_PLAN_TYPE_MULTI == reader->readParams.readPlan->type)+@@ -5162,7 +5162,7 @@ void TMR_SR_msgAddIdsSL900aGetBatteryLevel(uint8_t *msg, uint8_t *i, uint16_t ti+  * @param reader The reader+  * @param timeout The timeout of the operation, in milliseconds. Valid range is 0-65535.+  * @param accessPassword The access password to use to write on the tag+- * @param commandcode to specify the opearation++ * @param commandcode to specify the operation+  * @param password to specify SL900A password access level values+  * @param data If the operation is success, this data contains the requested value+  * @param target Filter to be applied.+@@ -5234,7 +5234,7 @@ void TMR_SR_msgAddIdsSL900aGetSensorValue(uint8_t *msg, uint8_t *i, uint16_t tim+  * @param reader The reader+  * @param timeout The timeout of the operation, in milliseconds. Valid range is 0-65535.+  * @param accessPassword The access password to use to write on the tag+- * @param commandcode to specify the opearation++ * @param commandcode to specify the operation+  * @param password to specify SL900A password access level values+  * @param data If the operation is success, this data contains the requested value+  * @param target Filter to be applied.+@@ -5304,7 +5304,7 @@ void TMR_SR_msgAddIdsSL900aGetMeasurementSetup(uint8_t *msg, uint8_t *i, uint16_+  * @param reader The reader+  * @param timeout The timeout of the operation, in milliseconds. Valid range is 0-65535.+  * @param accessPassword The access password to use to write on the tag+- * @param commandcode to specify the opearation++ * @param commandcode to specify the operation+  * @param password to specify SL900A password access level values+  * @param data If the operation is success, this data contains the requested value+  * @param target Filter to be applied.+@@ -5374,7 +5374,7 @@ void TMR_SR_msgAddIdsSL900aGetLogState(uint8_t *msg, uint8_t *i, uint16_t timeou+  * @param reader The reader+  * @param timeout The timeout of the operation, in milliseconds. Valid range is 0-65535.+  * @param accessPassword The access password to use to write on the tag+- * @param commandcode to specify the opearation++ * @param commandcode to specify the operation+  * @param password to specify SL900A password access level values+  * @param to specify SL900A sensor type+  * @param data If the operation is success, this data contains the requested value+@@ -5459,7 +5459,7 @@ void TMR_SR_msgAddIdsSL900aSetLogMode(uint8_t *msg, uint8_t *i, uint16_t timeout+  * @param reader The reader+  * @param timeout The timeout of the operation, in milliseconds. Valid range is 0-65535.+  * @param accessPassword The access password to use to write on the tag+- * @param commandcode to specify the opearation++ * @param commandcode to specify the operation+  * @param password to specify SL900A password access level values+  * @param level IDS password level+  * @param form IDS logging form+@@ -5518,7 +5518,7 @@ void TMR_SR_msgAddIdsSL900aInitialize(uint8_t *msg, uint8_t *i, uint16_t timeout+  * @param reader The reader+  * @param timeout The timeout of the operation, in milliseconds. Valid range is 0-65535.+  * @param accessPassword The access password to use to write on the tag+- * @param commandcode to specify the opearation++ * @param commandcode to specify the operation+  * @param password to specify SL900A password access level values+  * @param delayTime to secify delayTime+  * @param applicatioData to specify applicationData+@@ -5569,7 +5569,7 @@ void TMR_SR_msgAddIdsSL900aEndLog(uint8_t *msg, uint8_t *i, uint16_t timeout, TM+  * @param reader The reader+  * @param timeout The timeout of the operation, in milliseconds. Valid range is 0-65535.+  * @param accessPassword The access password to use to write on the tag+- * @param commandcode to specify the opearation++ * @param commandcode to specify the operation+  * @param password to specify SL900A password access level values+  * @param data If the operation is success, this data contains the requested value+  * @param target Filter to be applied.+@@ -5589,7 +5589,7 @@ TMR_SR_cmdSL900aEndLog(TMR_Reader *reader, uint16_t timeout, TMR_GEN2_Password a+ }+ + /**+- * Helper funcution to form the IDS SL900A SetPassword command++ * Helper function to form the IDS SL900A SetPassword command+  */ + void TMR_SR_msgAddIdsSL900aSetPassword(uint8_t *msg, uint8_t *i, uint16_t timeout, TMR_GEN2_Password accessPassword,+                                        uint8_t CommandCode, uint32_t password, PasswordLevel level, uint32_t newPassword,+@@ -5619,7 +5619,7 @@ void TMR_SR_msgAddIdsSL900aSetPassword(uint8_t *msg, uint8_t *i, uint16_t timeou+  * @param reader The reader+  * @param timeout The timeout of the operation, in milliseconds. Valid range is 0-65535.+  * @param accessPassword The access password to use to write on the tag+- * @param commandcode to specify the opearation++ * @param commandcode to specify the operation+  * @param password to specify SL900A password access level values+  * @param data If the operation is success, this data contains the requested value+  * @param target Filter to be applied.+@@ -5669,7 +5669,7 @@ void TMR_SR_msgAddIdsSL900aAccessFifoStatus(uint8_t *msg, uint8_t *i, uint16_t t+  * @param reader The reader+  * @param timeout The timeout of the operation, in milliseconds. Valid range is 0-65535.+  * @param accessPassword The access password to use to write on the tag+- * @param commandcode to specify the opearation++ * @param commandcode to specify the operation+  * @param password to specify SL900A password access level values+  * @param data If the operation is success, this data contains the requested value+  * @param target Filter to be applied.+@@ -5740,7 +5740,7 @@ void TMR_SR_msgAddIdsSL900aAccessFifoRead(uint8_t *msg, uint8_t *i, uint16_t tim+  * @param reader The reader+  * @param timeout The timeout of the operation, in milliseconds. Valid range is 0-65535.+  * @param accessPassword The access password to use to write on the tag+- * @param commandcode to specify the opearation++ * @param commandcode to specify the operation+  * @param password to specify SL900A password access level values+  * @param data If the operation is success, this data contains the requested value+  * @param target Filter to be applied.+@@ -5814,7 +5814,7 @@ void TMR_SR_msgAddIdsSL900aAccessFifoWrite(uint8_t *msg, uint8_t *i, uint16_t ti+  * @param reader The reader+  * @param timeout The timeout of the operation, in milliseconds. Valid range is 0-65535.+  * @param accessPassword The access password to use to write on the tag+- * @param commandcode to specify the opearation++ * @param commandcode to specify the operation+  * @param password to specify SL900A password access level values+  * @param data If the operation is success, this data contains the requested value+  * @param target Filter to be applied.+@@ -5885,7 +5885,7 @@ void TMR_SR_msgAddIdsSL900aStartLog(uint8_t *msg, uint8_t *i, uint16_t timeout,+  * @param reader The reader+  * @param timeout The timeout of the operation, in milliseconds. Valid range is 0-65535.+  * @param accessPassword The access password to use to write on the tag+- * @param commandcode to specify the opearation++ * @param commandcode to specify the operation+  * @param password to specify SL900A password access level values+  * @param startTime to specify count start time+  * @param target Filter to be applied.+@@ -5932,7 +5932,7 @@ void TMR_SR_msgAddIdsSL900aGetCalibrationData(uint8_t *msg, uint8_t *i, uint16_t+  * @param reader The reader+  * @param timeout The timeout of the operation, in milliseconds. Valid range is 0-65535.+  * @param accessPassword The access password to use to write on the tag+- * @param commandcode to specify the opearation++ * @param commandcode to specify the operation+  * @param password to specify SL900A password access level values+  * @param data If the operation is success, this data contains the requested value+  * @param target Filter to be applied.+@@ -6017,7 +6017,7 @@ void TMR_SR_msgAddIdsSL900aSetCalibrationData(uint8_t *msg, uint8_t *i, uint16_t+  * @param reader The reader+  * @param timeout The timeout of the operation, in milliseconds. Valid range is 0-65535.+  * @param accessPassword The access password to use to write on the tag+- * @param commandcode to specify the opearation++ * @param commandcode to specify the operation+  * @param password to specify SL900A password access level values+  * @param calibration to spcify the calibration data+  * @param target Filter to be applied.+@@ -6067,7 +6067,7 @@ void TMR_SR_msgAddIdsSL900aSetSfeParameters(uint8_t *msg, uint8_t *i, uint16_t t+  * @param reader The reader+  * @param timeout The timeout of the operation, in milliseconds. Valid range is 0-65535.+  * @param accessPassword The access password to use to write on the tag+- * @param commandcode to specify the opearation++ * @param commandcode to specify the operation+  * @param password to specify SL900A password access level values+  * @param sfe to spcify the sfe parameters+  * @param target Filter to be applied.+@@ -6184,7 +6184,7 @@ void TMR_SR_msgAddIdsSL900aSetShelfLife(uint8_t *msg, uint8_t *i, uint16_t timeo+  * @param reader The reader+  * @param timeout The timeout of the operation, in milliseconds. Valid range is 0-65535.+  * @param accessPassword The access password to use to write on the tag+- * @param commandcode to specify the opearation++ * @param commandcode to specify the operation+  * @param password to specify SL900A password access level values+  * @param data If the operation is success, this data contains the requested value+  * @param target Filter to be applied.+@@ -6809,7 +6809,7 @@ TMR_SR_cmdResetReaderStatistics(TMR_Reader *reader, TMR_SR_ReaderStatisticsFlag+ + + /**+- * Helper funcution to be used in GetReaderStats++ * Helper function to be used in GetReaderStats+  */ + TMR_Status+ TMR_fillReaderStats(TMR_Reader *reader, TMR_Reader_StatsValues* stats, uint16_t flag, uint8_t* msg, uint8_t offset)+diff --git a/tm_config.h b/tm_config.h+index 989fa86..691b095 100644+--- a/tm_config.h++++ b/tm_config.h+@@ -153,14 +153,14 @@ Note:To run readsync_baremetal codelet you have to+ + /**+  * Enabling  this option will enable the support for the parameters defined +- * in stdio.h header file like FILE *. This check is required as stdio.h doese not++ * in stdio.h header file like FILE *. This check is required as stdio.h does not+  * exist in some of the embedded  architectures.+  */+ #define  TMR_ENABLE_STDIO+   + /**+  * Enabling  this option will enable the support for the parameters defined +- * in string.h header file like sterror(). This check is required as string.h doese not++ * in string.h header file like strerror(). This check is required as string.h does not+  * exist in some of the embedded  architectures.+  */+ #define  TMR_USE_STRERROR+@@ -214,14 +214,14 @@ Note:To run readsync_baremetal codelet you have to+ + /**+  * Enabling  this option will enable the support for the parameters defined +- * in stdio.h header file like FILE *. This check is required as stdio.h doese not++ * in stdio.h header file like FILE *. This check is required as stdio.h does not+  * exist in some of the embedded  architectures.+  */+ #undef  TMR_ENABLE_STDIO+   + /**+  * Enabling  this option will enable the support for the parameters defined +- * in string.h header file like sterror(). This check is required as string.h doese not++ * in string.h header file like strerror(). This check is required as string.h does not+  * exist in some of the embedded  architectures.+  */+ #undef  TMR_USE_STRERROR+diff --git a/tm_reader.c b/tm_reader.c+index 5ba8edf..1b71dec 100644+--- a/tm_reader.c++++ b/tm_reader.c+@@ -3058,7 +3058,7 @@ TMR_init_GEN2_Impinj_Monza4_Payload(TMR_Monza4_Payload *payload)+ }+ + /**+- * Helper funcution to update or modifying the sfe parameters++ * Helper function to update or modifying the sfe parameters+  */+ TMR_Status+ TMR_update_GEN2_IDS_SL900A_SfeParameters(TMR_TagOp_GEN2_IDS_SL900A_SfeParameters *sfe)+@@ -3122,7 +3122,7 @@ TMR_update_GEN2_IDS_SL900A_SfeParameters(TMR_TagOp_GEN2_IDS_SL900A_SfeParameters+ }+ + /**+- * Helper funcution to update or modifying the calibration Data++ * Helper function to update or modifying the calibration Data+  */+ TMR_Status+ TMR_update_GEN2_IDS_SL900A_CalibrationData(TMR_TagOp_GEN2_IDS_SL900A_CalibrationData *cal)+@@ -3219,7 +3219,7 @@ TMR_update_GEN2_IDS_SL900A_CalibrationData(TMR_TagOp_GEN2_IDS_SL900A_Calibration+ }+ + /**+- * Helper funcution to set the calibration Data++ * Helper function to set the calibration Data+  */+ TMR_Status+ TMR_init_GEN2_IDS_SL900A_CalibrationData(uint8_t byte[7], TMR_TagOp_GEN2_IDS_SL900A_CalibrationData *cal)+@@ -3249,7 +3249,7 @@ TMR_init_GEN2_IDS_SL900A_CalibrationData(uint8_t byte[7], TMR_TagOp_GEN2_IDS_SL9+ }+ + /**+- * Helper funcution to set the sfe parameters++ * Helper function to set the sfe parameters+  */+ TMR_Status+ TMR_init_GEN2_IDS_SL900A_SfeParameters(uint8_t byte[2], TMR_TagOp_GEN2_IDS_SL900A_SfeParameters *sfe)+diff --git a/tm_reader.h b/tm_reader.h+index 559c0c5..49630cf 100644+--- a/tm_reader.h++++ b/tm_reader.h+@@ -130,9 +130,9 @@ typedef enum TMR_Reader_StatsFlag+   TMR_READER_STATS_FLAG_RF_ON_TIME = (1 << 0),+   /** Noise floor with the TX on for the antennas were last configured for searching */+   TMR_READER_STATS_FLAG_NOISE_FLOOR_SEARCH_RX_TX_WITH_TX_ON = (1 << 6),+-  /** Current frequency in uints of Khz */++  /** Current frequency in units of Khz */+   TMR_READER_STATS_FLAG_FREQUENCY = (1 << 7),+-  /** Current temperature of the device in units of Celcius */++  /** Current temperature of the device in units of Celsius */+   TMR_READER_STATS_FLAG_TEMPERATURE = (1 << 8),+   /** Current antenna */+   TMR_READER_STATS_FLAG_ANTENNA_PORTS = (1 << 9),+@@ -381,7 +381,7 @@ struct TMR_Reader+   bool isStopNTags;+   /* Param wait indicator for Reader and protocol param control during continuous read */+   bool paramWait;+-  /* Param responsefor Reader and protocol param control during continuous read */++  /* Param response for Reader and protocol param control during continuous read */+   uint8_t paramMessage[256];+   /* True Continuous Read Start indicator */+   bool hasContinuousReadStarted;+@@ -1013,7 +1013,7 @@ TMR_Param TMR_paramID(const char *name);+  * @ingroup reader+  * +  * Add a listener to the list of functions that will be called for+- * each message sent to or recieved from the reader.++ * each message sent to or received from the reader.+  *+  * @param reader The reader to operate on.+  * @param block A structure containing a pointer to the listener+@@ -1027,7 +1027,7 @@ TMR_Status TMR_addTransportListener(TMR_Reader *reader, TMR_TransportListenerBlo+  * @ingroup reader+  * +  * Remove a listener from the list of functions that will be called+- * for each message sent to or recieved from the reader.++ * for each message sent to or received from the reader.+  *+  * @param reader The reader to operate on.+  * @param block A structure containing a pointer to the listener+@@ -1179,9 +1179,9 @@ TMR_Status TMR_stopReading(struct TMR_Reader *reader);+ + /**+  * @ingroup reader+- * Stores the transport init function againest the provided scheme.++ * Stores the transport init function against the provided scheme.+  *+- * @param scheme the transport schme name.++ * @param scheme the transport scheme name.+  * @param nativeInit reference to the init function.+  */ + TMR_Status TMR_setSerialTransport(char* scheme, TMR_TransportNativeInit nativeInit);+@@ -1197,14 +1197,14 @@ const char *TMR_strerr(TMR_Reader *reader, TMR_Status status);+ + /**+  * @ingroup reader+- * This funcution will initialize the++ * This function will initialize the+  * TMR_StatValues structure with the default values+  */+ TMR_Status TMR_STATS_init(TMR_Reader_StatsValues *stats);+ + /**+  * @ingroup reader+- * This funcution loads the reader configuration parameters from file and applies to module.++ * This function loads the reader configuration parameters from file and applies to module.+  *+  * @param reader The reader to operate on.+  * @param filePath load reader configurations from filepath.+@@ -1213,7 +1213,7 @@ TMR_Status TMR_loadConfig(struct TMR_Reader *reader, char *filePath);+ + /**+  * @ingroup reader+- * This funcution saves the current reader configuration parameters and its values to a file.++ * This function saves the current reader configuration parameters and its values to a file.+  *+  * @param reader The reader to operate on.+  * @param filePath  save reader configurations from filepath.+diff --git a/tmr_gen2.h b/tmr_gen2.h+index 311ad27..9696f61 100644+--- a/tmr_gen2.h++++ b/tmr_gen2.h+@@ -135,7 +135,7 @@ typedef struct TMR_GEN2_Select+   bool invert;+   /** The memory bank in which to compare the mask */+   TMR_GEN2_Bank bank;+-  /** The location (in bits) at which t to begin comparing the mask */++  /** The location (in bits) at which to begin comparing the mask */+   uint32_t bitPointer;+   /** The length (in bits) of the mask */+   uint16_t maskBitLength;+diff --git a/tmr_params.h b/tmr_params.h+index 581c5d2..d48c9bc 100644+--- a/tmr_params.h++++ b/tmr_params.h+@@ -67,7 +67,7 @@ typedef enum TMR_Param+   TMR_PARAM_ANTENNA_PORTSWITCHGPOS,+   /** "/reader/antenna/settlingTimeList", TMR_PortValueList  */+   TMR_PARAM_ANTENNA_SETTLINGTIMELIST,+-  /** "reader/antenna/returnLoss", TMR_PortValueList */++  /** "/reader/antenna/returnLoss", TMR_PortValueList */+   TMR_PARAM_ANTENNA_RETURNLOSS,+   /** "/reader/antenna/txRxMap", TMR_AntennaMapList  */+   TMR_PARAM_ANTENNA_TXRXMAP,+@@ -85,15 +85,15 @@ typedef enum TMR_Param+   TMR_PARAM_GEN2_SESSION,+   /** "/reader/gen2/target", TMR_GEN2_Target */+   TMR_PARAM_GEN2_TARGET,+-  /** "/reader/gen2/BLF", TMR_Gen2_LinkFrequency */++  /** "/reader/gen2/BLF", TMR_GEN2_LinkFrequency */+   TMR_PARAM_GEN2_BLF,+-  /** "/reader/gen2/tari", TMR_Gen2_Tari */++  /** "/reader/gen2/tari", TMR_GEN2_Tari */+   TMR_PARAM_GEN2_TARI,+-  /**"/reader/gen2/writeMode", TMR_Gen2_WriteMode*/++  /**"/reader/gen2/writeMode", TMR_GEN2_WriteMode */+   TMR_PARAM_GEN2_WRITEMODE,+-  /** "/reader/gen2/bap", TMR_Gen2_Bap */++  /** "/reader/gen2/bap", TMR_GEN2_Bap */+   TMR_PARAM_GEN2_BAP,+-  /** "/reader/gen2/protocolExtension", TMR_PARAM_GEN2_PROTOCOLEXTENSION */++  /** "/reader/gen2/protocolExtension", TMR_GEN2_ProtocolExtension */+   TMR_PARAM_GEN2_PROTOCOLEXTENSION,+   /** "/reader/iso180006b/BLF", TMR_ISO180006B_LinkFrequency */+   TMR_PARAM_ISO180006B_BLF,+@@ -107,7 +107,7 @@ typedef enum TMR_Param+   TMR_PARAM_READ_ASYNCONTIME,+   /** "/reader/read/plan", TMR_ReadPlan */+   TMR_PARAM_READ_PLAN,+-  /** "/reader/radio/enablePowerSave, bool **/++  /** "/reader/radio/enablePowerSave", bool **/+   TMR_PARAM_RADIO_ENABLEPOWERSAVE,+   /** "/reader/radio/powerMax", int16_t */+   TMR_PARAM_RADIO_POWERMAX,+@@ -165,7 +165,7 @@ typedef enum TMR_Param+   TMR_PARAM_EXTENDEDEPC,+   /** "/reader/statistics", TMR_SR_ReaderStatistics */+   TMR_PARAM_READER_STATISTICS,+-  /** "/reader/stats", TMR_ */++  /** "/reader/stats", TMR_Reader_StatsValues */+   TMR_PARAM_READER_STATS,+   /** "/reader/uri", TMR_String */+   TMR_PARAM_URI,+@@ -193,7 +193,7 @@ typedef enum TMR_Param+   TMR_PARAM_TAGREADDATA_UNIQUEBYPROTOCOL,+   /** "/reader/description", TMR_String */+   TMR_PARAM_READER_DESCRIPTION,+-  /** "reader/hostname", TMR_String */++  /** "/reader/hostname", TMR_String */+   TMR_PARAM_READER_HOSTNAME,+   /** "/reader/currentTime", struct tm */+   TMR_PARAM_CURRENTTIME,+@@ -201,12 +201,13 @@ typedef enum TMR_Param+ 	TMR_PARAM_READER_WRITE_REPLY_TIMEOUT,+ 	/** "/reader/gen2/writeEarlyExit", bool */+ 	TMR_PARAM_READER_WRITE_EARLY_EXIT,+-  /** "reader/stats/enable", TMR_StatsEnable */++  /** "/reader/stats/enable", TMR_StatsEnable */+   TMR_PARAM_READER_STATS_ENABLE,+   /** "/reader/trigger/read/Gpi", TMR_uint8List */+   TMR_PARAM_TRIGGER_READ_GPI,+   /** "/reader/metadataflags", TMR_TRD_MetadataFlag*/+   TMR_PARAM_METADATAFLAG,++  /** "/reader/licensedFeatures", TMR_uint8List */+   TMR_PARAM_LICENSED_FEATURES,+   TMR_PARAM_SELECTED_PROTOCOLS,+   TMR_PARAM_END,+diff --git a/tmr_serial_reader.h b/tmr_serial_reader.h+index b246277..bca3fe9 100644+--- a/tmr_serial_reader.h++++ b/tmr_serial_reader.h+@@ -169,7 +169,7 @@ typedef struct TMR_SR_GEN2_Q+ } TMR_SR_GEN2_Q;+ + +-/** An antenna port with an associated uint16_t value. */++/** An antenna port with an associated int32_t value. */+ typedef struct TMR_PortValue+ {+   /** The port number */+@@ -309,7 +309,7 @@ typedef struct TM_SR_SerialReader+   int tagsRemaining;+   /* Buffer tag records fetched from module but not yet passed to caller. */+   uint8_t bufResponse[TMR_SR_MAX_PACKET_SIZE];+-  /* bufResopnse read index */++  /* bufResponse read index */+   uint8_t bufPointer;+   /* Number of tag records in buffer but not yet passed to caller */+   uint8_t tagsRemainingInBuffer;+diff --git a/tmr_serial_transport.h b/tmr_serial_transport.h+index c618d1e..290cf23 100644+--- a/tmr_serial_transport.h++++ b/tmr_serial_transport.h+@@ -80,7 +80,7 @@ struct TMR_SR_SerialTransport+   /**+    * This callback causes the communication interface to be opened but+    * does not transmit any serial-layer data. This should perform+-   * actionms such as opening a serial port device or establishing a++   * actions such as opening a serial port device or establishing a+    * network connection within a wrapper protocol.+    *+    * @param this The TMR_SR_SerialTransport structure.+@@ -109,7 +109,7 @@ struct TMR_SR_SerialTransport+    * @param this The TMR_SR_SerialTransport structure.+    * @param length The number of bytes to receive.+    * @param[out] messageLength The number of bytes received.+-   * @param[out] message Pointer to the location to store recieved bytes.++   * @param[out] message Pointer to the location to store received bytes.+    * @param timeoutMs The duration for the operation to complete.+    */+   TMR_Status (*receiveBytes)(TMR_SR_SerialTransport *, uint32_t length,+diff --git a/tmr_status.h b/tmr_status.h+index 50ccc16..2832184 100644+--- a/tmr_status.h++++ b/tmr_status.h+@@ -78,7 +78,7 @@ typedef uint32_t TMR_Status;+ #define TMR_ERROR_INVALID_BAUD_RATE                       TMR_ERROR_CODE(0x10a)+ /**Region is not supported. */+ #define TMR_ERROR_INVALID_REGION                          TMR_ERROR_CODE(0x10b)+-/** License key code in invalid */++/** License key code is invalid */+ #define TMR_ERROR_INVALID_LICENSE_KEY                     TMR_ERROR_CODE(0x10c)+ /**Firmware is corrupt: Checksum doesn't match content. */+ #define TMR_ERROR_BL_INVALID_IMAGE_CRC                    TMR_ERROR_CODE(0x200)+@@ -137,10 +137,10 @@ typedef uint32_t TMR_Status;+ /**Internal reader error.  Contact support. */+ #define TMR_ERROR_GEN2_PROTOCOL_MEMORY_OVERRUN_BAD_PC     TMR_ERROR_CODE(0x423)+ /**Internal reader error.  Contact support. */+-#define TMR_ERROR_GEN2_PROCOCOL_MEMORY_LOCKED             TMR_ERROR_CODE(0x424)++#define TMR_ERROR_GEN2_PROTOCOL_MEMORY_LOCKED             TMR_ERROR_CODE(0x424)+ /**Authentication failed with specified key. */+ #define TMR_ERROR_GEN2_PROTOCOL_V2_AUTHEN_FAILED				TMR_ERROR_CODE(0x425)+-/** Untrace opearation failed. */++/** Untrace operation failed. */+ #define TMR_ERROR_GEN2_PROTOCOL_V2_UNTRACE_FAILED				TMR_ERROR_CODE(0x426)+ /**Internal reader error.  Contact support. */+ #define TMR_ERROR_GEN2_PROTOCOL_INSUFFICIENT_POWER        TMR_ERROR_CODE(0x42b)+diff --git a/tmr_strerror.c b/tmr_strerror.c+index 211695c..4540a5a 100644+--- a/tmr_strerror.c++++ b/tmr_strerror.c+@@ -174,7 +174,7 @@ TMR_strerr(TMR_Reader *reader, TMR_Status status)+     return "Other Gen2 error";+   case TMR_ERROR_GEN2_PROTOCOL_MEMORY_OVERRUN_BAD_PC:+     return "Gen2 memory overrun - bad PC";+-  case TMR_ERROR_GEN2_PROCOCOL_MEMORY_LOCKED:\++  case TMR_ERROR_GEN2_PROTOCOL_MEMORY_LOCKED:+     return "Gen2 memory locked";+   case TMR_ERROR_GEN2_PROTOCOL_INSUFFICIENT_POWER:+     return "Gen2 tag has insufficent power for operation";+@@ -185,7 +185,7 @@ TMR_strerr(TMR_Reader *reader, TMR_Status status)+ 	case TMR_ERROR_GEN2_PROTOCOL_V2_AUTHEN_FAILED:+ 		return "Authentication failed with specified key.";+ 	case TMR_ERROR_GEN2_PROTOCOL_V2_UNTRACE_FAILED:+-		return "Untrace opearation failed.";++		return "Untrace operation failed.";+   case TMR_ERROR_AHAL_INVALID_FREQ:+     return "Invalid frequency";+   case TMR_ERROR_AHAL_CHANNEL_OCCUPIED:+diff --git a/tmr_tag_data.h b/tmr_tag_data.h+index 2f1ad8e..be42c53 100644+--- a/tmr_tag_data.h++++ b/tmr_tag_data.h+@@ -140,7 +140,7 @@ typedef struct TMR_TagReadData+   uint8_t gpioCount;+   /** Number of times the tag was read */+   uint32_t readCount;+-  /** Strength of the signal recieved from the tag */++  /** Strength of the signal received from the tag */+   int32_t rssi;+   /** RF carrier frequency the tag was read with */+   uint32_t frequency;+diff --git a/tmr_tag_protocol.h b/tmr_tag_protocol.h+index 1c47fce..da5b267 100644+--- a/tmr_tag_protocol.h++++ b/tmr_tag_protocol.h+@@ -67,4 +67,4 @@ typedef struct TMR_TagProtocolList+ #endif+ + +-#endif /* _TMR_TAG_PROTOCL_H_ */++#endif /* _TMR_TAG_PROTOCOL_H_ */+diff --git a/tmr_tagop.h b/tmr_tagop.h+index eb92f85..7b22248 100644+--- a/tmr_tagop.h++++ b/tmr_tagop.h+@@ -363,7 +363,7 @@ typedef struct SecurePasswordLookup+ + typedef struct TMR_TagOp_GEN2_SecureReadData+ {+-  /** Gen2 read opearation */++  /** Gen2 read operation */+   TMR_TagOp_GEN2_ReadData readData;+ +   /** type of Gen2 Secure operation*/+@@ -1291,7 +1291,7 @@ typedef struct TMR_TagOp_GEN2_IDS_SL900A_Initialize+   Delay delayTime;+ }TMR_TagOp_GEN2_IDS_SL900A_Initialize;+ +-/** Sub-Class for specifying AccessFifo opearation */++/** Sub-Class for specifying AccessFifo operation */+ typedef enum AccessFifoOperation+ {+   /* Read from FIFO */+@@ -1312,7 +1312,7 @@ typedef struct TMR_TagOp_GEN2_IDS_SL900A_AccessFifo+   uint32_t AccessPassword;+   /* IDS SL900A Password */+   uint32_t Password;+-  /* specify the opearationn do be done on fifo */++  /* specify the operation do be done on fifo */+   AccessFifoOperation operation;+ }TMR_TagOp_GEN2_IDS_SL900A_AccessFifo;+ 
+ cbits/api/patches/windows-time.patch view
@@ -0,0 +1,55 @@+diff --git a/osdep_win32.c b/osdep_win32.c+index ba65bfa..4ea7603 100644+--- a/osdep_win32.c++++ b/osdep_win32.c+@@ -31,8 +31,8 @@+ #include <time.h>+ #include "osdep.h"+ +-/* FILETIME of Jan 1 1970 00:00:00. */+-static const unsigned __int64 epoch = ((unsigned __int64) 116444736000000000ULL);++// https://stackoverflow.com/questions/6161776/convert-windows-filetime-to-second-in-unix-linux++#define SEC_TO_UNIX_EPOCH 11644473600LL+ + uint64_t+ tmr_gettime()+@@ -41,35 +41,25 @@ tmr_gettime()+   SYSTEMTIME st;+   FILETIME ft;+   LARGE_INTEGER li;    +-  struct timeval tv;+   GetSystemTime(&st);+   SystemTimeToFileTime(&st, &ft);+   li.LowPart = ft.dwLowDateTime;+   li.HighPart = ft.dwHighDateTime;+-  tv.tv_sec = (long) ((li.QuadPart - epoch) / 10000000L);+-  tv.tv_usec =(long) (st.wMilliseconds * 1000);+-  totalms = (((uint64_t)tv.tv_sec) * 1000) + ((uint64_t) tv.tv_usec) / 1000;++  totalms=(((uint64_t)li.LowPart) | ((uint64_t)li.HighPart)<<32)/10000;++  totalms -= SEC_TO_UNIX_EPOCH * 1000;+   return totalms;+ }+ + uint32_t+ tmr_gettime_low()+ {+-  SYSTEMTIME st;+-  FILETIME ft;+-  GetSystemTime(&st);+-  SystemTimeToFileTime(&st, &ft);+-  return ft.dwLowDateTime;++  return (uint32_t) tmr_gettime();+ }+ + uint32_t+ tmr_gettime_high()+ {+-  SYSTEMTIME st;+-  FILETIME ft;+-  GetSystemTime(&st);+-  SystemTimeToFileTime(&st, &ft);+-  return ft.dwHighDateTime;++  return (uint32_t) (tmr_gettime() >> 32);+ }+ + void
+ cbits/api/serial_reader.c view
@@ -0,0 +1,6169 @@+/**+ *  @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 <stdlib.h>+#include <stdio.h>+#include <string.h>++#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; iWord<wordCount; iWord++)+    {+      data16[iWord] = 0;+      data16[iWord] |= data[(2*iWord)+0];+      data16[iWord] <<= 8;+      data16[iWord] |= data[(2*iWord)+1];+    }++    switch (mode)+    {+    case TMR_GEN2_WORD_ONLY:+      return TMR_SR_cmdGEN2WriteTagData(reader, (uint16_t)(sr->commandTimeout),+        (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; tmplen<len; tmplen++)+      {+        tmp[tmplen] = (char)buf[idx+tmplen];+      }+    }+  }+  if (0 == count)+  {+    TMR_String *serial = (TMR_String *)value;+    /**+     * Command failure: +     * Serial number not implemented on this reader+     * Leave value at default "no value" +     */+    serial->value[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; i<TMR_SR_MAX_ANTENNA_PORTS; i++)+    {+      detected[i] = false;+    }+    u8list = value;++    {+      TMR_SR_PortDetect ports[TMR_SR_MAX_ANTENNA_PORTS];+      uint8_t numPorts;++      numPorts = numberof(ports);+      ret = TMR_SR_cmdAntennaDetect(reader, &numPorts, ports);+      if (TMR_SUCCESS != ret)+      {+        break;+      }+      for (i=0; i<numPorts; i++)+      {+        detected[ports[i].port] = ports[i].detected;+      }+    }+    +    u8list->len = 0;+    for (i=0; i<reader->u.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 */
+ cbits/api/serial_reader_imp.h view
@@ -0,0 +1,1011 @@+#ifndef _SERIAL_READER_IMP_H+#define _SERIAL_READER_IMP_H++/**+ *  @file serial_reader_imp.h+ *  @brief Serial reader internal implementation header+ *  @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 "tm_reader.h"+#include "tmr_status.h"++#ifdef  __cplusplus+extern "C" {+#endif++  +/* This is used to enable the Gen2 secure readdata option */++#ifndef BARE_METAL+  extern bool isSecureAccessEnabled ;+#else+  static bool isSecureAccessEnabled;	+#endif++typedef enum TMR_SR_OpCode+{+  TMR_SR_OPCODE_WRITE_FLASH             = 0x01,+  TMR_SR_OPCODE_READ_FLASH              = 0x02,+  TMR_SR_OPCODE_VERSION                 = 0x03,+  TMR_SR_OPCODE_BOOT_FIRMWARE           = 0x04,+  TMR_SR_OPCODE_SET_BAUD_RATE           = 0x06,+  TMR_SR_OPCODE_ERASE_FLASH             = 0x07,+  TMR_SR_OPCODE_VERIFY_IMAGE_CRC        = 0x08,+  TMR_SR_OPCODE_BOOT_BOOTLOADER         = 0x09,+  TMR_SR_OPCODE_HW_VERSION              = 0x10,+  TMR_SR_OPCODE_MODIFY_FLASH            = 0x0A,+  TMR_SR_OPCODE_GET_DSP_SILICON_ID      = 0x0B,+  TMR_SR_OPCODE_GET_CURRENT_PROGRAM     = 0x0C,+  TMR_SR_OPCODE_WRITE_FLASH_SECTOR      = 0x0D,+  TMR_SR_OPCODE_GET_SECTOR_SIZE         = 0x0E,+  TMR_SR_OPCODE_MODIFY_FLASH_SECTOR     = 0x0F,+  TMR_SR_OPCODE_READ_TAG_ID_SINGLE      = 0x21,+  TMR_SR_OPCODE_READ_TAG_ID_MULTIPLE    = 0x22,+  TMR_SR_OPCODE_WRITE_TAG_ID            = 0x23,+  TMR_SR_OPCODE_WRITE_TAG_DATA          = 0x24,+  TMR_SR_OPCODE_LOCK_TAG                = 0x25,+  TMR_SR_OPCODE_KILL_TAG                = 0x26,+  TMR_SR_OPCODE_READ_TAG_DATA           = 0x28,+  TMR_SR_OPCODE_GET_TAG_ID_BUFFER       = 0x29,+  TMR_SR_OPCODE_CLEAR_TAG_ID_BUFFER     = 0x2A,+  TMR_SR_OPCODE_WRITE_TAG_SPECIFIC      = 0x2D,+  TMR_SR_OPCODE_ERASE_BLOCK_TAG_SPECIFIC= 0x2E,+  TMR_SR_OPCODE_MULTI_PROTOCOL_TAG_OP   = 0x2F,+  TMR_SR_OPCODE_GET_ANTENNA_PORT        = 0x61,+  TMR_SR_OPCODE_GET_READ_TX_POWER       = 0x62,+  TMR_SR_OPCODE_GET_TAG_PROTOCOL        = 0x63,+  TMR_SR_OPCODE_GET_WRITE_TX_POWER      = 0x64,+  TMR_SR_OPCODE_GET_FREQ_HOP_TABLE      = 0x65,+  TMR_SR_OPCODE_GET_USER_GPIO_INPUTS    = 0x66,+  TMR_SR_OPCODE_GET_REGION              = 0x67,+  TMR_SR_OPCODE_GET_POWER_MODE          = 0x68,+  TMR_SR_OPCODE_GET_USER_MODE           = 0x69,+  TMR_SR_OPCODE_GET_READER_OPTIONAL_PARAMS=0x6A,+  TMR_SR_OPCODE_GET_PROTOCOL_PARAM      = 0x6B,+  TMR_SR_OPCODE_GET_READER_STATS        = 0x6C,+  TMR_SR_OPCODE_GET_USER_PROFILE        = 0x6D,+  TMR_SR_OPCODE_GET_AVAILABLE_PROTOCOLS = 0x70,+  TMR_SR_OPCODE_GET_AVAILABLE_REGIONS   = 0x71,+  TMR_SR_OPCODE_GET_TEMPERATURE         = 0x72,+  TMR_SR_OPCODE_SET_ANTENNA_PORT        = 0x91,+  TMR_SR_OPCODE_SET_READ_TX_POWER       = 0x92,+  TMR_SR_OPCODE_SET_TAG_PROTOCOL        = 0x93,+  TMR_SR_OPCODE_SET_WRITE_TX_POWER      = 0x94,+  TMR_SR_OPCODE_SET_FREQ_HOP_TABLE      = 0x95,+  TMR_SR_OPCODE_SET_USER_GPIO_OUTPUTS   = 0x96,+  TMR_SR_OPCODE_SET_REGION              = 0x97,+  TMR_SR_OPCODE_SET_POWER_MODE          = 0x98,+  TMR_SR_OPCODE_SET_USER_MODE           =  0x99,+  TMR_SR_OPCODE_SET_READER_OPTIONAL_PARAMS=0x9a,+  TMR_SR_OPCODE_SET_PROTOCOL_PARAM      = 0x9B,+  TMR_SR_OPCODE_SET_USER_PROFILE        = 0x9D,+  TMR_SR_OPCODE_SET_PROTOCOL_LICENSEKEY = 0x9E,+  TMR_SR_OPCODE_SET_OPERATING_FREQ      = 0xC1,+  TMR_SR_OPCODE_TX_CW_SIGNAL            = 0xC3,+}TMR_SR_OpCode;++typedef enum TMR_SR_Gen2SingulationOptions+{+  TMR_SR_GEN2_SINGULATION_OPTION_SELECT_DISABLED         = 0x00,+  TMR_SR_GEN2_SINGULATION_OPTION_SELECT_ON_EPC           = 0x01,+  TMR_SR_GEN2_SINGULATION_OPTION_SELECT_ON_TID           = 0x02,+  TMR_SR_GEN2_SINGULATION_OPTION_SELECT_ON_USER_MEM      = 0x03,+  TMR_SR_GEN2_SINGULATION_OPTION_SELECT_ON_ADDRESSED_EPC = 0x04,+  TMR_SR_GEN2_SINGULATION_OPTION_USE_PASSWORD            = 0x05,+  TMR_SR_GEN2_SINGULATION_OPTION_SELECT_ON_LENGTH_OF_EPC = 0x06,+  TMR_SR_GEN2_SINGULATION_OPTION_SELECT_GEN2TRUNCATE	 = 0x07,+  TMR_SR_GEN2_SINGULATION_OPTION_INVERSE_SELECT_BIT      = 0x08,+  TMR_SR_GEN2_SINGULATION_OPTION_FLAG_METADATA           = 0x10,+  TMR_SR_GEN2_SINGULATION_OPTION_EXTENDED_DATA_LENGTH    = 0x20,+  TMR_SR_GEN2_SINGULATION_OPTION_SECURE_READ_DATA        = 0x40+}TMR_SR_Gen2SingulationOptions;++typedef enum TMR_SR_TagidOption+{+  TMR_SR_TAG_ID_OPTION_NONE    = 0x00,+  TMR_SR_TAG_ID_OPTION_REWIND  = 0x01+}TMR_SR_TagidOption;++typedef enum TMR_SR_ModelHardwareID+{+  TMR_SR_MODEL_M5E         = 0x00,+  TMR_SR_MODEL_M5E_COMPACT = 0x01,+  TMR_SR_MODEL_M5E_I       = 0x02,+  TMR_SR_MODEL_M4E         = 0x03,+  TMR_SR_MODEL_M6E         = 0x18,+  TMR_SR_MODEL_M6E_I	   = 0x19,+  TMR_SR_MODEL_MICRO       = 0x20,+  TMR_SR_MODEL_M6E_NANO    = 0x30,+  TMR_SR_MODEL_UNKNOWN     = 0xFF,+} TMR_SR_ModelHardwareID;++typedef enum TMR_SR_ModelMicro+{+  TMR_SR_MODEL_M6E_MICRO     = 0x01,+  TMR_SR_MODEL_M6E_MICRO_USB = 0x02,+  TMR_SR_MODEL_M6E_MICRO_USB_PRO = 0x03,+}TMR_SR_ModelMicro;++typedef enum TMR_SR_ModelM6E_I+{+  TMR_SR_MODEL_M6E_I_REV1 = 0x01,+  TMR_SR_MODEL_M6E_I_PRC  = 0x02,+  TMR_SR_MODEL_M6E_I_JIC  = 0x03,+}TMR_SR_ModelM6E_I;++typedef enum TMR_SR_ModelM5EInternational+{+  TMR_SR_MODEL_M5E_I_REV_EU  = 0x01,+  TMR_SR_MODEL_M5E_I_REV_NA  = 0x02,+  TMR_SR_MODEL_M5E_I_REV_JP  = 0x03,+  TMR_SR_MODEL_M5E_I_REV_PRC = 0x04,+}TMR_SR_ModelM5EInternational;++typedef enum TMR_SR_ProductGroupID+{+  TMR_SR_PRODUCT_MODULE = 0,+  TMR_SR_PRODUCT_RUGGEDIZED_READER = 1,+  TMR_SR_PRODUCT_USB_READER = 2,+  TMR_SR_PRODUCT_INVALID = 0xFFFF,+}TMR_SR_ProductGroupID;++TMR_Status TMR_SR_sendTimeout(TMR_Reader *reader, uint8_t *data,+                              uint32_t timeoutMs);+TMR_Status TMR_SR_send(TMR_Reader *reader, uint8_t *data);+TMR_Status TMR_SR_sendMessage(TMR_Reader *reader, uint8_t *data,+                              uint8_t *opcode, uint32_t timeoutMs);+TMR_Status TMR_SR_receiveMessage(TMR_Reader *reader, uint8_t *data,+                                 uint8_t opcode, uint32_t timeoutMs);+TMR_Status TMR_SR_receiveAutonomousReading(struct TMR_Reader *reader, TMR_TagReadData *trd, TMR_Reader_StatsValues *stats);++void TMR_SR_parseMetadataFromMessage(TMR_Reader *reader, TMR_TagReadData *read, uint16_t flags,+                                     uint8_t *i, uint8_t msg[]);++void+TMR_SR_parseMetadataOnly(TMR_Reader *reader, TMR_TagReadData *read, uint16_t flags,+                                uint8_t *i, uint8_t msg[]);+void TMR_SR_postprocessReaderSpecificMetadata(TMR_TagReadData *read,+                                              TMR_SR_SerialReader *sr);+bool isContinuousReadParamSupported(TMR_Reader *reader);++/**+ * This structure is returned from read tag multiple embedded commands.+ */+typedef struct TMR_SR_MultipleStatus+{+  /** The number of tags found during the read. */+  uint16_t tagsFound;+  /** The number of tags for which the embedded operation succeeded. */+  uint16_t successCount;+  /** The number of tags for which the embedded operation failed. */+  uint16_t failureCount;+}TMR_SR_MultipleStatus;++/**+ * This structure is returned from TMR_SR_cmdGetTxRxPorts and+ * TMR_SR_cmdGetAntennaSearchList, and passed as a parameter to+ * TMR_SR_cmdSetAntennaSearchList.+ */+typedef struct TMR_SR_PortPair+{+  /** The transmit port. */+  uint8_t txPort;+  /** The receive port. */+  uint8_t rxPort;+}TMR_SR_PortPair;++/**+ * This structure is returned from TMR_SR_cmdAntennaDetect.+ */+typedef struct TMR_SR_PortDetect+{+  /** The port number. */+  uint8_t port;+  /** Whether an antenna was detected on the port. */+  bool detected;+}TMR_SR_PortDetect;++/**+ * Reader statistics options enum+ */ +typedef enum TMR_SR_ReaderStatsOption+{+  /* Get statistics specified by the statistics flag */+  TMR_SR_READER_STATS_OPTION_GET=   0x00,+  /* Reset the specified statistic */+  TMR_SR_READER_STATS_OPTION_RESET= 0x01,+  /* Get the per-port statistics specified by the statistics flag*/+  TMR_SR_READER_STATS_OPTION_GET_PER_PORT = 0x02,+}TMR_SR_ReaderStatsOption;+  ++/**+ *  Reader Statistics Flag Enum+ */+typedef enum TMR_SR_ReaderStatisticsFlag+{+  /* Total time the port has been transmitting, in milliseconds. Resettable */+  TMR_SR_READER_STATS_FLAG_RF_ON_TIME     = (1<<0),+  /* Detected noise floor with transmitter off. Recomputed when requested, not resettable.*/+  TMR_SR_READER_STATS_FLAG_NOISE_FLOOR    = (1<<1),+  /* Detected noise floor with transmitter on. Recomputed when requested, not resettable. */+  TMR_SR_READER_STATS_FLAG_NOISE_FLOOR_TX_ON = (1<<3),+  /* ALL */+  TMR_SR_READER_STATS_ALL = (TMR_SR_READER_STATS_FLAG_RF_ON_TIME | +      TMR_SR_READER_STATS_FLAG_NOISE_FLOOR |+      TMR_SR_READER_STATS_FLAG_NOISE_FLOOR_TX_ON),+}TMR_SR_ReaderStatisticsFlag;++/**+ * Antenna Configuration. Returned by TMR_SR_cmdGetAntennaConfiguration.+ */+typedef struct TMR_SR_AntennaPort+{+  /** The number of physical antenna ports. */+  uint8_t numPorts;+  /** The current logical Transmit port. */+  uint8_t txPort;+  /** The current logical Recieve port. */+  uint8_t rxPort;+  /** List specifying what ports are terminated. */+  TMR_uint8List portTerminatedList;+}TMR_SR_AntennaPort;++/** Per-port power levels. Used by TMR_SR_cmd{Get,Set}AntennaPortPowers */+typedef struct TMR_SR_PortPower+{+  /** The port number. */+  uint8_t port;+  /** The power level to use for read operations, in centidBm. */+  uint16_t readPower;+  /** The power level to use for write operations, in centidBm. */+  uint16_t writePower;+} TMR_SR_PortPower;++/**+ * Per-port power levels and settling times. Used by+ * TMR_SR_cmd{Get,Set}AntennaPortPowersAndSettlingTime.+ */+typedef struct TMR_SR_PortPowerAndSettlingTime+{+  /** The port number. */+  uint8_t port;+  /** The power level to use for read operations, in centidBm. */+  int16_t readPower;+  /** The power level to use for write operations, in centidBm. */+  int16_t writePower;+  /** The duration to wait after switching to this port, in microseconds. */+  uint16_t settlingTime;+} TMR_SR_PortPowerAndSettlingTime;++/** The current power level and the bounds of the power level range. */+typedef struct TMR_SR_PowerWithLimits+{+  /** The current power level, in centidBm. */+  uint16_t setPower;+  /** The maximum power level, in centidBm. */+  uint16_t maxPower;+  /** The minimum power level, in centidBm. */+  uint16_t minPower;+} TMR_SR_PowerWithLimits;+++void TMR_hexDottedQuad(const uint8_t bytes[4], char buf[12]);+TMR_Status TMR_hexDottedQuadToUint32(const char bytes[12], uint32_t *result);+++/**+ * This type enumerates the serial reader configuration parameters for+ * TMR_SR_cmdSetReaderConfiguration and+ * TMR_SR_cmdGetReaderConfiguration.  Each value is+ * associated with a particular data type for the setting.+ */+typedef enum TMR_SR_Configuration+{+  /**+   *  Key tag buffer records off of antenna ID as well as EPC;+   *  i.e., keep separate records for the same EPC read on different antennas+   *  0: Disable -- Different antenna overwrites previous record.+   *  1: Enable -- Different Antenna creates a new record.+   */+  TMR_SR_CONFIGURATION_UNIQUE_BY_ANTENNA        = 0,+  /**+   *  Run transmitter in lower-performance, power-saving mode.+   *  0: Disable -- Higher transmitter bias for improved reader sensitivity+   *  1: Enable -- Lower transmitter bias sacrifices sensitivity for power consumption+   */+  TMR_SR_CONFIGURATION_TRANSMIT_POWER_SAVE      = 1,+  /**+   *  Support 496-bit EPCs (vs normal max 96 bits)+   *  0: Disable (max max EPC length = 96)+   *  1: Enable 496-bit EPCs+   */+  TMR_SR_CONFIGURATION_EXTENDED_EPC             = 2,+  /**+   *  Configure GPOs to drive antenna switch.+   *  0: No switch+   *  1: Switch on GPO1+   *  2: Switch on GPO2+   *  3: Switch on GPO1,GPO2+   */+  TMR_SR_CONFIGURATION_ANTENNA_CONTROL_GPIO     = 3,+  /**+   *  Refuse to transmit if antenna is not detected+   */+  TMR_SR_CONFIGURATION_SAFETY_ANTENNA_CHECK     = 4,+  /**+   *  Refuse to transmit if overtemperature condition detected+   */+  TMR_SR_CONFIGURATION_SAFETY_TEMPERATURE_CHECK = 5,+  /**+   *  If tag read duplicates an existing tag buffer record (key is the same),+   *  update the record's timestamp if incoming read has higher RSSI reading.+   *  0: Keep timestamp of record's first read+   *  1: Keep timestamp of read with highest RSSI+   */+  TMR_SR_CONFIGURATION_RECORD_HIGHEST_RSSI      = 6,+  /**+   *  Key tag buffer records off tag data as well as EPC;+   *  i.e., keep separate records for the same EPC read with different data+   *  0: Disable -- Different data overwrites previous record.+   *  1: Enable -- Different data creates new record.+   */+  TMR_SR_CONFIGURATION_UNIQUE_BY_DATA           = 8,+  /**+   *  Whether RSSI values are reported in dBm, as opposed to+   *  arbitrary uncalibrated units.+   */+  TMR_SR_CONFIGURATION_RSSI_IN_DBM              = 9,+  /**+   *  Self jammer cancellation+   *  User can enable/disable through level2 API+   */+  TMR_SR_CONFIGURATION_SELF_JAMMER_CANCELLATION = 0x0A,+  /**+   *  Key tag buffer records off of protocol as well as EPC;+   *  i.e., keep separate records for the same EPC read on different protocols+   *  0: Disable -- Different protocol overwrites previous record.+   *  1: Enable -- Different protocol creates a new record.+   */+  TMR_SR_CONFIGURATION_UNIQUE_BY_PROTOCOL       = 0x0B,+  /**+   *  Enable read filtering+   */+  TMR_SR_CONFIGURATION_ENABLE_READ_FILTER         = 0x0C,+  /**+   *  Tag buffer entry timeout+   */+  TMR_SR_CONFIGURATION_READ_FILTER_TIMEOUT        = 0x0D,+  /**+    * Transport (bus) type+    **/ +  TMR_SR_CONFIGURATION_CURRENT_MSG_TRANSPORT      = 0x0E,+  /**+   * Enable the CRC calculation+   */+  TMR_SR_CONFIGURATION_SEND_CRC               = 0x1B,+  /**+   *  General category of finished reader into which module is integrated; e.g.,+   *  0: bare module+   *  1: In-vehicle Reader (e.g., Tool Link, Vega)+   *  2: USB Reader+   */+  TMR_SR_CONFIGURATION_PRODUCT_GROUP_ID         = 0x12,+  /**+   * Product ID (Group ID 0x0002 ) information+   * 0x0001 :M5e-C USB reader+   * 0x0002 :Backback NA antenna+   * 0x0003 :Backback EU antenna+   **/+  TMR_SR_CONFIGURATION_PRODUCT_ID              = 0x13,+  /**+   *  Configure GPIs to drive trigger read.+   *  0: No switch+   *  1: Switch on GPI1+   *  2: Switch on GPI2+   *  3: Switch on GPI3 (if supported)+   *  4: Switch on GOI4 (if supported)+   */+  TMR_SR_CONFIGURATION_TRIGGER_READ_GPIO                     = 0x1E,+} TMR_SR_Configuration;+++/**+ * This type enumerates the region configuration parameters for+ * the TMR_SR_cmdGetRegionConfiguration() command.+ */+typedef enum TMR_SR_RegionConfiguration+{+  TMR_SR_REGION_CONFIGURATION_LBT_ENABLED = 0x40,+} TMR_SR_RegionConfiguration;++/**+ * This is the enumeration of Gen2-specific configuration values. Each+ * enumerated value is associated with a particular data type for the+ * setting value.+ */+typedef enum TMR_SR_Gen2Configuration+{+  TMR_SR_GEN2_CONFIGURATION_SESSION = 0x00,+  TMR_SR_GEN2_CONFIGURATION_TARGET  = 0x01,+  TMR_SR_GEN2_CONFIGURATION_TAGENCODING = 0x02,+  TMR_SR_GEN2_CONFIGURATION_LINKFREQUENCY = 0x10,+  TMR_SR_GEN2_CONFIGURATION_TARI    = 0x11,+  TMR_SR_GEN2_CONFIGURATION_Q       = 0x12,+  TMR_SR_GEN2_CONFIGURATION_BAP    = 0x13,+  TMR_SR_GEN2_CONFIGURATION_PROTCOLEXTENSION = 0x14+} TMR_SR_Gen2Configuration;++/**+ * This struture is retuned from TMR_SR_Gen2ReaderResponseTimeOut+ */+typedef struct TMR_SR_Gen2ReaderWriteTimeOut+{+  /* Status of reader timeout */+  bool earlyexit;++  /* Timeout value used for write operation */+  uint16_t writetimeout;+}TMR_SR_Gen2ReaderWriteTimeOut;+/**+ * This is the enumeration of ISO 18000-6B-specific configuration+ * values. Each enumerated value is associated with a particular data+ * type for the setting value.+ */+typedef enum TMR_SR_Iso180006bConfiguration+{+  TMR_SR_ISO180006B_CONFIGURATION_LINKFREQUENCY = 0x10,+  TMR_SR_ISO180006B_CONFIGURATION_MODULATION_DEPTH = 0x11,+  TMR_SR_ISO180006B_CONFIGURATION_DELIMITER = 0x12+} TMR_SR_Iso180006bConfiguration;++/**+ * This is the enumeration of iPx-specific configuration+ * values. Each enumerated value is associated with a particular data+ * type for the setting value.+ */+typedef enum TMR_SR_iPxConfiguration+{+  TMR_SR_IPX_CONFIGURATION_LINKFREQUENCY = 0x10+} TMR_SR_iPxConfiguration;+++/**+ * This type selects the protocol configuration option for+ * TMR_SR_cmdSetProtocolConfiguration() and+ * TMR_SR_cmdGetProtocolConfiguration().  Each value is associated+ * with a particular data type for the setting.+ */+typedef struct TMR_SR_ProtocolConfiguration+{+  /** The protocol to configure. Determines which union member is valid. */+  TMR_TagProtocol protocol;+  union+  {+    /** The configuration key for a Gen2 option. */+    TMR_SR_Gen2Configuration gen2;+    /** The configuration key for an ISO18000-6B option. */+    TMR_SR_Iso180006bConfiguration iso180006b;+    TMR_SR_iPxConfiguration ipx;+  }u;+} TMR_SR_ProtocolConfiguration;+++/**+ * Defines the values for search flags for TMR_SR_cmdReadTagMultiple.+ */+typedef enum TMR_SR_SearchFlag+{+  TMR_SR_SEARCH_FLAG_CONFIGURED_ANTENNA = 0,+  TMR_SR_SEARCH_FLAG_ANTENNA_1_THEN_2   = 1,+  TMR_SR_SEARCH_FLAG_ANTENNA_2_THEN_1   = 2,+  TMR_SR_SEARCH_FLAG_CONFIGURED_LIST    = 3,+  TMR_SR_SEARCH_FLAG_ANTENNA_MASK       = 3,+  TMR_SR_SEARCH_FLAG_EMBEDDED_COMMAND   = 4,+  TMR_SR_SEARCH_FLAG_TAG_STREAMING      = 8,+  TMR_SR_SEARCH_FLAG_LARGE_TAG_POPULATION_SUPPORT = 16,+  TMR_SR_SEARCH_FLAG_STATUS_REPORT_STREAMING = 32,+  TMR_SR_SEARCH_FLAG_RETURN_ON_N_TAGS = 64,+  TMR_SR_SEARCH_FLAG_READ_MULTIPLE_FAST_SEARCH = 128,+  TMR_SR_SEARCH_FLAG_STATS_REPORT_STREAMING = 256,+  TMR_SR_SEARCH_FLAG_GPI_TRIGGER_READ = 512,+  TMR_SR_SEARCH_FLAG_DUTY_CYCLE_CONTROL = 1024,+}TMR_SR_SearchFlag;++typedef enum TMR_SR_ISO180006BCommands+{+  TMR_SR_ISO180006B_COMMAND_DATA_READ           = 0x0B,+  TMR_SR_ISO180006B_COMMAND_READ                = 0x0C,+  TMR_SR_ISO180006B_COMMAND_WRITE               = 0x0D,+  TMR_SR_ISO180006B_COMMAND_WRITE_MULTIPLE      = 0x0E,+  TMR_SR_ISO180006B_COMMAND_WRITE4BYTE          = 0x1B,+  TMR_SR_ISO180006B_COMMAND_WRITE4BYTE_MULTIPLE = 0x1C,+} TMR_SR_ISO180006BCommands;++typedef enum TMR_SR_ISO180006BCommandOptions+{+  TMR_SR_ISO180006B_WRITE_OPTION_READ_AFTER           = 0x00,+  TMR_SR_ISO180006B_WRITE_OPTION_NO_VERIFY            = 0x01,+  TMR_SR_ISO180006B_WRITE_OPTION_READ_VERIFY_AFTER    = 0x02,+  TMR_SR_ISO180006B_WRITE_OPTION_GROUP_SELECT         = 0x03,+  TMR_SR_ISO180006B_WRITE_OPTION_COUNT_PROVIDED       = 0x08,+  TMR_SR_ISO180006B_WRITE_LOCK_NO                     = 0x00,+  TMR_SR_ISO180006B_WRITE_LOCK_YES                    = 0x01,+  TMR_SR_ISO180006B_LOCK_OPTION_TYPE_FOLLOWS          = 0x01,+  TMR_SR_ISO180006B_LOCK_TYPE_QUERYLOCK_THEN_LOCK     = 0x01,+} TMR_SR_ISO180006BCommandOptions;++TMR_Status TMR_SR_cmdRaw(TMR_Reader *reader, uint32_t timeout, uint8_t msgLen,+            uint8_t msg[]);+TMR_Status TMR_SR_setSerialBaudRate(TMR_Reader *reader, uint32_t rate);+TMR_Status TMR_SR_cmdVersion(TMR_Reader *reader, TMR_SR_VersionInfo *info);+TMR_Status TMR_SR_cmdBootFirmware(TMR_Reader *reader);+TMR_Status TMR_SR_cmdSetBaudRate(TMR_Reader *reader, uint32_t rate);+TMR_Status TMR_SR_cmdVerifyImage(TMR_Reader *reader, bool *status);+TMR_Status TMR_SR_cmdEraseFlash(TMR_Reader *reader, uint8_t sector, +            uint32_t password);+TMR_Status TMR_SR_cmdWriteFlashSector(TMR_Reader *reader, uint8_t sector, +            uint32_t address, uint32_t password, uint8_t length,+            const uint8_t data[], uint32_t offset);+TMR_Status TMR_SR_cmdGetSectorSize(TMR_Reader *reader, uint8_t sector,+            uint32_t *size);+TMR_Status TMR_SR_cmdModifyFlashSector(TMR_Reader *reader, uint8_t sector, +            uint32_t address, uint32_t password, uint8_t length,+            const uint8_t data[], uint32_t offset);+TMR_Status TMR_SR_cmdBootBootloader(TMR_Reader *reader);+TMR_Status TMR_SR_cmdGetHardwareVersion(TMR_Reader *reader, uint8_t option,+            uint8_t flags, uint8_t* count, uint8_t data[]);+TMR_Status TMR_SR_cmdGetCurrentProgram(TMR_Reader *reader, uint8_t *program);+TMR_Status TMR_SR_cmdReadTagSingle(TMR_Reader *reader, uint16_t timeout, +            uint16_t metadataFlags, const TMR_TagFilter *filter, +            TMR_TagProtocol protocol, TMR_TagReadData *tagData);+TMR_Status TMR_SR_cmdReadTagMultiple(TMR_Reader *reader, uint16_t timeout,+            TMR_SR_SearchFlag flags, const TMR_TagFilter *filter,+            TMR_TagProtocol protocol, uint32_t *tagCount);+TMR_Status TMR_SR_cmdWriteGen2TagEpc(TMR_Reader *reader, const TMR_TagFilter *filter, TMR_GEN2_Password accessPassword,+			uint16_t timeout, uint8_t count, const uint8_t *id, bool lock);+TMR_Status TMR_SR_cmdGEN2WriteTagData(TMR_Reader *reader,+            uint16_t timeout, TMR_GEN2_Bank bank, uint32_t address,+            uint8_t count, const uint8_t data[],+            TMR_GEN2_Password accessPassword, const TMR_TagFilter *filter);+TMR_Status TMR_SR_cmdGEN2LockTag(TMR_Reader *reader, uint16_t timeout, +            uint16_t mask, uint16_t action, TMR_GEN2_Password accessPassword, +            const TMR_TagFilter *filter);+TMR_Status TMR_SR_cmdKillTag(TMR_Reader *reader, uint16_t timeout,+            TMR_GEN2_Password killPassword, const TMR_TagFilter *filter);+TMR_Status TMR_SR_cmdGEN2ReadTagData(TMR_Reader *reader,+            uint16_t timeout, TMR_GEN2_Bank bank,+            uint32_t address, uint8_t length, uint32_t accessPassword,+            const TMR_TagFilter *filter, TMR_TagReadData *data);+TMR_Status TMR_SR_cmdGetTagsRemaining(TMR_Reader *reader, uint16_t *remaining);+TMR_Status TMR_SR_cmdGetTagBuffer(TMR_Reader *reader, uint16_t count, bool epc496,+            TMR_TagProtocol protocol, TMR_TagData tagData[]);+TMR_Status TMR_SR_cmdClearTagBuffer(TMR_Reader *reader);+TMR_Status TMR_SR_cmdHiggs2PartialLoadImage(TMR_Reader *reader, uint16_t timeout,+            TMR_GEN2_Password accessPassword, TMR_GEN2_Password killPassword, +            uint8_t len, const uint8_t epc[], TMR_TagFilter* target);+TMR_Status TMR_SR_cmdHiggs2FullLoadImage(TMR_Reader *reader, uint16_t timeout,+            TMR_GEN2_Password accessPassword, TMR_GEN2_Password killPassword,+            uint16_t lockBits, uint16_t pcWord, uint8_t count,+            const uint8_t epc[], TMR_TagFilter* target);+TMR_Status TMR_SR_cmdHiggs3FastLoadImage(TMR_Reader *reader, uint16_t timeout,+            TMR_GEN2_Password currentAccessPassword, +            TMR_GEN2_Password accessPassword, TMR_GEN2_Password killPassword,+            uint16_t pcWord, uint8_t count, const uint8_t epc[], TMR_TagFilter* target);+TMR_Status TMR_SR_cmdHiggs3LoadImage(TMR_Reader *reader, uint16_t timeout,+            TMR_GEN2_Password currentAccessPassword,+            TMR_GEN2_Password accessPassword, TMR_GEN2_Password killPassword,+            uint16_t pcWord, uint8_t len, const uint8_t epcAndUserData[], TMR_TagFilter* target);+TMR_Status TMR_SR_cmdHiggs3BlockReadLock(TMR_Reader *reader, uint16_t timeout,+            TMR_GEN2_Password accessPassword, uint8_t lockBits, TMR_TagFilter* target);+TMR_Status TMR_SR_cmdNxpSetReadProtect(TMR_Reader *reader, uint16_t timeout,+            TMR_SR_GEN2_SiliconType chip, TMR_GEN2_Password accessPassword, TMR_TagFilter* target);+TMR_Status TMR_SR_cmdNxpResetReadProtect(TMR_Reader *reader, uint16_t timeout,+            TMR_SR_GEN2_SiliconType chip, TMR_GEN2_Password accessPassword, TMR_TagFilter* target);+TMR_Status TMR_SR_cmdNxpChangeEas(TMR_Reader *reader, uint16_t timeout,+            TMR_SR_GEN2_SiliconType chip, TMR_GEN2_Password accessPassword, bool reset, TMR_TagFilter* target);+TMR_Status TMR_SR_cmdNxpEasAlarm(TMR_Reader *reader, uint16_t timeout,+            TMR_SR_GEN2_SiliconType chip, TMR_GEN2_DivideRatio dr, TMR_GEN2_TagEncoding m, TMR_GEN2_TrExt trExt,+            TMR_uint8List *data, TMR_TagFilter* target);+TMR_Status TMR_SR_cmdNxpCalibrate(TMR_Reader *reader, uint16_t timeout,+            TMR_SR_GEN2_SiliconType chip, TMR_GEN2_Password accessPassword, TMR_uint8List *data, TMR_TagFilter* target);+TMR_Status TMR_SR_cmdNxpChangeConfig(TMR_Reader *reader, uint16_t timeout,+            TMR_SR_GEN2_SiliconType chip, TMR_GEN2_Password accessPassword, TMR_NXP_ConfigWord configWord, TMR_uint8List *data, TMR_TagFilter* target);+TMR_Status TMR_SR_cmdGen2v2NXPUntraceable(TMR_Reader *reader, uint16_t timeout,TMR_SR_GEN2_SiliconType chip, TMR_GEN2_Password accessPassword, uint16_t configWord,+			TMR_TagOp_GEN2_NXP_Untraceable op,TMR_uint8List *data, TMR_TagFilter* target);+TMR_Status TMR_SR_cmdGen2v2NXPAuthenticate(TMR_Reader *reader, uint16_t timeout,TMR_SR_GEN2_SiliconType chip,+	         TMR_GEN2_Password accessPassword, TMR_TagOp_GEN2_NXP_Authenticate op, TMR_uint8List *data, TMR_TagFilter* target);+TMR_Status TMR_SR_cmdGen2v2NXPReadBuffer(TMR_Reader *reader, uint16_t timeout,TMR_SR_GEN2_SiliconType chip,+					TMR_GEN2_Password accessPassword, TMR_TagOp_GEN2_NXP_Readbuffer op, TMR_uint8List *data, TMR_TagFilter* target);+TMR_Status TMR_SR_cmdMonza4QTReadWrite(TMR_Reader *reader, uint16_t timeout, TMR_GEN2_Password accessPassword,+            TMR_Monza4_ControlByte controlByte, TMR_Monza4_Payload payload, TMR_uint8List *data, TMR_TagFilter* target);+TMR_Status TMR_SR_cmdSL900aGetSensorValue(TMR_Reader *reader, uint16_t timeout, TMR_GEN2_Password accessPassword,+            uint8_t CommandCode, uint32_t password, PasswordLevel level, Sensor sensortype, TMR_uint8List *data, TMR_TagFilter* target);+TMR_Status TMR_SR_cmdSL900aGetMeasurementSetup(TMR_Reader *reader, uint16_t timeout, TMR_GEN2_Password accessPassword,+            uint8_t CommandCode, uint32_t password, PasswordLevel level,TMR_uint8List *data, TMR_TagFilter* target);+TMR_Status TMR_SR_cmdSL900aGetCalibrationData(TMR_Reader *reader, uint16_t timeout, TMR_GEN2_Password accessPassword,+            uint8_t CommandCode, uint32_t password, PasswordLevel level, TMR_uint8List *data, TMR_TagFilter* target);+TMR_Status TMR_SR_cmdSL900aSetCalibrationData(TMR_Reader *reader, uint16_t timeout, TMR_GEN2_Password accessPassword,+            uint8_t CommandCode, uint32_t password, PasswordLevel level, uint64_t calibration, TMR_TagFilter* target);+TMR_Status TMR_SR_cmdSL900aSetSfeParameters(TMR_Reader *reader, uint16_t timeout, TMR_GEN2_Password accessPassword,+            uint8_t CommandCode, uint32_t password, PasswordLevel level, uint16_t sfe, TMR_TagFilter* target);+TMR_Status TMR_SR_cmdSL900aGetLogState(TMR_Reader *reader, uint16_t timeout, TMR_GEN2_Password accessPassword,+            uint8_t CommandCode, uint32_t password, PasswordLevel level, TMR_uint8List *data, TMR_TagFilter* target);+TMR_Status TMR_SR_cmdSL900aSetLogMode(TMR_Reader *reader, uint16_t timeout, TMR_GEN2_Password accessPassword,+           uint8_t CommandCode, uint32_t password, PasswordLevel level, LoggingForm form, StorageRule rule, bool Ext1Enable,+           bool Ext2Enable, bool TempEnable, bool BattEnable, uint16_t LogInterval, TMR_TagFilter* target);+TMR_Status TMR_SR_cmdSL900aSetLogLimit(TMR_Reader *reader, uint16_t timeout, TMR_GEN2_Password accessPassword,+           uint8_t CommandCode, uint32_t password, PasswordLevel level, uint16_t exLower,+           uint16_t lower, uint16_t upper, uint16_t exUpper, TMR_TagFilter* target);+TMR_Status TMR_SR_cmdSL900aSetShelfLife(TMR_Reader *reader, uint16_t timeout, TMR_GEN2_Password accessPassword,+                             uint8_t CommandCode, uint32_t password, PasswordLevel level, uint32_t block0, uint32_t block1,+                             TMR_TagFilter* target);+TMR_Status TMR_SR_cmdSL900aInitialize(TMR_Reader *reader, uint16_t timeout, TMR_GEN2_Password accessPassword,+                                      uint8_t CommandCode, uint32_t password, PasswordLevel level, uint16_t delayTime,+                                      uint16_t applicatioData, TMR_TagFilter* target);+TMR_Status TMR_SR_cmdSL900aStartLog(TMR_Reader *reader, uint16_t timeout, TMR_GEN2_Password accessPassword, uint8_t CommandCode,+                                    uint32_t password, PasswordLevel level, uint32_t time, TMR_TagFilter* target);+TMR_Status TMR_SR_cmdSL900aEndLog(TMR_Reader *reader, uint16_t timeout, TMR_GEN2_Password accessPassword,+           uint8_t CommandCode, uint32_t password, PasswordLevel level, TMR_TagFilter* target);+TMR_Status TMR_SR_cmdSL900aSetPassword(TMR_Reader *reader, uint16_t timeout, TMR_GEN2_Password accessPassword,+           uint8_t CommandCode, uint32_t password, PasswordLevel level, uint32_t newPassword,+           PasswordLevel newPasswordLevel, TMR_TagFilter* target);+TMR_Status TMR_SR_cmdSL900aGetBatteryLevel(TMR_Reader *reader, uint16_t timeout, TMR_GEN2_Password accessPassword,+                                           uint8_t CommandCode, uint32_t password, PasswordLevel level,BatteryType type,+                                           TMR_uint8List *data, TMR_TagFilter* target);+TMR_Status TMR_SR_cmdSL900aAccessFifoStatus(TMR_Reader *reader, uint16_t timeout, TMR_GEN2_Password accessPassword, uint8_t CommandCode,+           uint32_t password, PasswordLevel level, AccessFifoOperation operation, TMR_uint8List * data, TMR_TagFilter* target);+TMR_Status TMR_SR_cmdSL900aAccessFifoRead(TMR_Reader *reader, uint16_t timeout, TMR_GEN2_Password accessPassword, uint8_t CommandCode,+            uint32_t password, PasswordLevel level, AccessFifoOperation operation, uint8_t length,TMR_uint8List * data, TMR_TagFilter* target);+TMR_Status TMR_SR_cmdSL900aAccessFifoWrite(TMR_Reader *reader, uint16_t timeout, TMR_GEN2_Password accessPassword, uint8_t CommandCode,+           uint32_t password, PasswordLevel level, AccessFifoOperation operation, TMR_uint8List *payLoad, TMR_uint8List * data, TMR_TagFilter* target);+TMR_Status TMR_SR_cmdHibikiReadLock(TMR_Reader *reader, uint16_t timeout,+            TMR_GEN2_Password accessPassword, uint16_t mask, uint16_t action);+TMR_Status TMR_SR_cmdHibikiGetSystemInformation(TMR_Reader *reader, uint16_t timeout,+            TMR_GEN2_Password accessPassword,+            TMR_GEN2_HibikiSystemInformation *info);+TMR_Status TMR_SR_cmdHibikiSetAttenuate(TMR_Reader *reader, uint16_t timeout,+            TMR_GEN2_Password accessPassword, uint8_t level, bool lock);+TMR_Status TMR_SR_cmdHibikiBlockLock(TMR_Reader *reader, uint16_t timeout,+            TMR_GEN2_Password accessPassword, uint8_t block,+            TMR_GEN2_Password blockPassword, uint8_t mask, uint8_t action);+TMR_Status TMR_SR_cmdHibikiBlockReadLock(TMR_Reader *reader, uint16_t timeout,+            TMR_GEN2_Password accessPassword, uint8_t block,+            TMR_GEN2_Password blockPassword, uint8_t mask, uint8_t action);+TMR_Status TMR_SR_cmdHibikiWriteMultipleWords(TMR_Reader *reader,+            uint16_t timeout, TMR_GEN2_Password accessPassword,+            TMR_GEN2_Bank bank, uint32_t wordOffset, uint8_t count,+            const uint8_t data[]);+TMR_Status TMR_SR_cmdEraseBlockTagSpecific(TMR_Reader *reader, uint16_t timeout,+            TMR_GEN2_Bank bank, uint32_t address, uint8_t count);+TMR_Status TMR_SR_cmdGetTxRxPorts(TMR_Reader *reader, TMR_SR_PortPair *ant);+TMR_Status TMR_SR_cmdGetAntennaConfiguration(TMR_Reader *reader,+            TMR_SR_AntennaPort *config);+TMR_Status TMR_SR_cmdGetAntennaSearchList(TMR_Reader *reader, uint8_t *count,+            TMR_SR_PortPair *ants);+TMR_Status TMR_SR_cmdGetAntennaPortPowers(TMR_Reader *reader, uint8_t *count,+            TMR_SR_PortPower *ports);+TMR_Status TMR_SR_cmdGetAntennaPortPowersAndSettlingTime(TMR_Reader *reader,+            uint8_t *count, TMR_SR_PortPowerAndSettlingTime *ports);+TMR_Status TMR_SR_cmdGetAntennaReturnLoss(TMR_Reader *reader, TMR_PortValueList *ports);+TMR_Status TMR_SR_cmdAntennaDetect(TMR_Reader *reader, uint8_t *count,+            TMR_SR_PortDetect *ports);+TMR_Status TMR_SR_cmdGetReadTxPower(TMR_Reader *reader, int32_t *power);+TMR_Status TMR_SR_cmdGetReadTxPowerWithLimits(TMR_Reader *reader,+            TMR_SR_PowerWithLimits *power);+TMR_Status TMR_SR_cmdGetWriteTxPower(TMR_Reader *reader, int32_t *power);+TMR_Status TMR_SR_cmdGetWriteTxPowerWithLimits(TMR_Reader *reader,+            TMR_SR_PowerWithLimits *power);+TMR_Status TMR_SR_cmdGetCurrentProtocol(TMR_Reader *reader,+            TMR_TagProtocol *protocol);+TMR_Status TMR_SR_cmdMultipleProtocolSearch(TMR_Reader *reader,TMR_SR_OpCode op,TMR_TagProtocolList *protocols, TMR_TRD_MetadataFlag metadataFlags,TMR_SR_SearchFlag antennas, TMR_TagFilter **filter, uint16_t timeout, uint32_t *tagsFound);+TMR_Status TMR_SR_cmdGetFrequencyHopTable(TMR_Reader *reader, uint8_t *count,+            uint32_t *hopTable);+TMR_Status TMR_SR_cmdGetFrequencyHopTime(TMR_Reader *reader, uint32_t *hopTime);+TMR_Status TMR_SR_cmdGetGPIO(TMR_Reader *reader, uint8_t *count, TMR_GpioPin *state);+TMR_Status TMR_SR_cmdGetGPIODirection(TMR_Reader *reader, uint8_t pin,+            bool *out);+TMR_Status TMR_SR_cmdGetRegion(TMR_Reader *reader, TMR_Region *region);+TMR_Status TMR_SR_cmdGetRegionConfiguration(TMR_Reader *reader,+            TMR_SR_RegionConfiguration key, void *value);+TMR_Status TMR_SR_cmdGetPowerMode(TMR_Reader *reader, TMR_SR_PowerMode *mode);+TMR_Status TMR_SR_cmdGetUserMode(TMR_Reader *reader, TMR_SR_UserMode *mode);+TMR_Status TMR_SR_cmdGetReaderConfiguration(TMR_Reader *reader,+            TMR_SR_Configuration key, void *value);+TMR_Status TMR_SR_cmdIAVDenatranCustomOp(TMR_Reader *reader, uint16_t timeout, TMR_GEN2_Password accessPassword, uint8_t mode, uint8_t rfu,+           TMR_uint8List *data, TMR_TagFilter* target);+TMR_Status TMR_SR_cmdIAVDenatranCustomActivateSiniavMode(TMR_Reader *reader, uint16_t timeout, TMR_GEN2_Password accessPassword, uint8_t mode, uint8_t payload,+           TMR_uint8List *data, TMR_TagFilter* target, bool tokenDesc, uint8_t *token);+TMR_Status TMR_SR_cmdIAVDenatranCustomReadFromMemMap(TMR_Reader *reader, uint16_t timeout, TMR_GEN2_Password accessPassword, uint8_t mode, uint8_t payload,+            TMR_uint8List *data, TMR_TagFilter* target, uint16_t wordAddress);+TMR_Status TMR_SR_cmdIAVDenatranCustomWriteToMemMap(TMR_Reader *reader, uint16_t timeout, TMR_GEN2_Password accessPassword, uint8_t mode, uint8_t payload,+            TMR_uint8List *data, TMR_TagFilter* target, uint16_t wordPtr, uint16_t wordData, uint8_t* tagId, uint8_t* dataBuf);+TMR_Status TMR_SR_cmdIAVDenatranCustomWriteSec(TMR_Reader *reader, uint16_t timeout, TMR_GEN2_Password accessPassword, uint8_t mode, uint8_t payload,+            TMR_uint8List *data, TMR_TagFilter* target, uint8_t* dataWords, uint8_t* dataBuf);+TMR_Status TMR_SR_cmdIAVDenatranCustomGetTokenId(TMR_Reader *reader, uint16_t timeout, TMR_GEN2_Password accessPassword, uint8_t mode,+           TMR_uint8List *data, TMR_TagFilter* target);+TMR_Status TMR_SR_cmdIAVDenatranCustomReadSec(TMR_Reader *reader, uint16_t timeout, TMR_GEN2_Password accessPassword, uint8_t mode, uint8_t payload,+            TMR_uint8List *data, TMR_TagFilter* target, uint16_t wordAddress);+TMR_Status TMR_SR_cmdGetProtocolConfiguration(TMR_Reader *reader, TMR_TagProtocol protocol,+            TMR_SR_ProtocolConfiguration key, void *value);+TMR_Status TMR_SR_cmdGetReaderStats(TMR_Reader *reader,+           TMR_Reader_StatsFlag statFlags,+           TMR_Reader_StatsValues *stats);+TMR_Status TMR_SR_cmdGetReaderStatistics(TMR_Reader *reader,+            TMR_SR_ReaderStatisticsFlag statFlags,+            TMR_SR_ReaderStatistics *stats);+TMR_Status TMR_SR_cmdGetAvailableProtocols(TMR_Reader *reader,+            TMR_TagProtocolList *protocols);+TMR_Status TMR_SR_cmdGetAvailableRegions(TMR_Reader *reader,+            TMR_RegionList *regions);+TMR_Status TMR_SR_cmdGetTemperature(TMR_Reader *reader, int8_t *temp);+TMR_Status TMR_SR_cmdSetTxRxPorts(TMR_Reader *reader, uint8_t txPrt,+            uint8_t rxPort);+TMR_Status TMR_SR_cmdSetAntennaSearchList(TMR_Reader *reader,+            uint8_t count, const TMR_SR_PortPair *ports);+TMR_Status TMR_SR_cmdSetAntennaPortPowers(TMR_Reader *reader,+            uint8_t count, const TMR_SR_PortPower *ports);+TMR_Status TMR_SR_cmdSetAntennaPortPowersAndSettlingTime(TMR_Reader *reader,+            uint8_t count, const TMR_SR_PortPowerAndSettlingTime *ports);+TMR_Status TMR_SR_cmdSetReadTxPower(TMR_Reader *reader, int32_t power);+TMR_Status TMR_SR_cmdSetWriteTxPower(TMR_Reader *reader, int32_t power);+TMR_Status TMR_SR_cmdSetProtocol(TMR_Reader *reader, TMR_TagProtocol protocol);+TMR_Status TMR_SR_cmdSetFrequencyHopTable(TMR_Reader *reader, uint8_t count,+            const uint32_t *table);+TMR_Status TMR_SR_cmdSetFrequencyHopTime(TMR_Reader *reader, uint32_t hopTime);+TMR_Status TMR_SR_cmdSetGPIO(TMR_Reader *reader, uint8_t gpio, bool high);+TMR_Status TMR_SR_cmdSetGPIODirection(TMR_Reader *reader, uint8_t pin,+            bool out);+TMR_Status TMR_SR_cmdSetRegion(TMR_Reader *reader, TMR_Region region);+TMR_Status TMR_SR_cmdSetRegionLbt(TMR_Reader *reader, TMR_Region region, bool lbt);+TMR_Status TMR_SR_cmdSetPowerMode(TMR_Reader *reader, TMR_SR_PowerMode mode);+TMR_Status TMR_SR_cmdSetUserMode(TMR_Reader *reader, TMR_SR_UserMode mode);+TMR_Status TMR_SR_cmdSetReaderConfiguration(TMR_Reader *reader, +            TMR_SR_Configuration key, const void *value);+TMR_Status TMR_SR_cmdSetProtocolLicenseKey(TMR_Reader *reader, TMR_SR_SetProtocolLicenseOption option, uint8_t key[], int key_len,uint32_t *retData);+TMR_Status TMR_SR_cmdSetProtocolConfiguration(TMR_Reader *reader,+            TMR_TagProtocol protocol, TMR_SR_ProtocolConfiguration key,+            const void *value);+TMR_Status TMR_SR_cmdResetReaderStats(TMR_Reader *reader,+           TMR_Reader_StatsFlag statFlags);+TMR_Status TMR_SR_cmdResetReaderStatistics(TMR_Reader *reader,+            TMR_SR_ReaderStatisticsFlag statFlags);+TMR_Status TMR_SR_cmdTestSetFrequency(TMR_Reader *reader, uint32_t frequency);+TMR_Status TMR_SR_cmdTestSendCw(TMR_Reader *reader, bool on);+TMR_Status TMR_SR_cmdTestSendPrbs(TMR_Reader *reader, uint16_t duration);+TMR_Status TMR_SR_cmdSetUserProfile(TMR_Reader *reader,+                                    TMR_SR_UserConfigOperation op,TMR_SR_UserConfigCategory category, TMR_SR_UserConfigType type);+TMR_Status TMR_SR_cmdGetUserProfile(TMR_Reader *reader, +                                    uint8_t byte[], uint8_t length, uint8_t response[], uint8_t* response_length);+TMR_Status TMR_SR_cmdBlockWrite(TMR_Reader *reader, uint16_t timeout, TMR_GEN2_Bank bank, uint32_t wordPtr, +                                 uint32_t wordCount, const uint16_t* data, uint32_t accessPassword, const TMR_TagFilter* target);+TMR_Status TMR_SR_cmdBlockErase(TMR_Reader *reader, uint16_t timeout, TMR_GEN2_Bank bank, uint32_t wordPtr,+                                 uint8_t wordCount, uint32_t accessPassword, TMR_TagFilter *target);+TMR_Status TMR_SR_cmdBlockPermaLock(TMR_Reader *reader, uint16_t timeout,uint32_t readLock, TMR_GEN2_Bank bank, +                         uint32_t blockPtr, uint32_t blockRange, uint16_t* mask, uint32_t accessPassword, TMR_TagFilter* target, TMR_uint8List *data);+TMR_Status TMR_SR_msgSetupReadTagMultiple(TMR_Reader *reader, uint8_t *msg, uint8_t *i,+            uint16_t timeout, TMR_SR_SearchFlag searchFlag,+            const TMR_TagFilter *filter, TMR_TagProtocol protocol,+            TMR_GEN2_Password accessPassword);++TMR_Status+TMR_SR_msgSetupReadTagMultipleWithMetadata(TMR_Reader *reader, uint8_t *msg, uint8_t *i, uint16_t timeout,+                               TMR_SR_SearchFlag searchFlag,+							                 TMR_TRD_MetadataFlag metadataFlag,+                               const TMR_TagFilter *filter,+                               TMR_TagProtocol protocol,+                               TMR_GEN2_Password accessPassword);++TMR_Status TMR_SR_msgSetupReadTagSingle(uint8_t *msg, uint8_t *i, TMR_TagProtocol protocol,TMR_TRD_MetadataFlag metadataFlags, const TMR_TagFilter *filter,uint16_t timeout);+void TMR_SR_msgAddGEN2WriteTagEPC(uint8_t *msg, uint8_t *i, uint16_t timeout, uint8_t *epc, uint8_t count);+void TMR_SR_msgAddGEN2DataRead(uint8_t *msg, uint8_t *i, uint16_t timeout,+      TMR_GEN2_Bank bank, uint32_t wordAddress, uint8_t len, uint8_t option, bool withMetaData);+void TMR_SR_msgAddGEN2DataWrite(uint8_t *msg, uint8_t *i, uint16_t timeout,+      TMR_GEN2_Bank bank, uint32_t address);+void TMR_SR_msgAddGEN2LockTag(uint8_t *msg, uint8_t *i, uint16_t timeout,+      uint16_t mask, uint16_t action, TMR_GEN2_Password password);+void TMR_SR_msgAddGEN2KillTag(uint8_t *msg, uint8_t *i, uint16_t timeout,+      TMR_GEN2_Password password);+void+TMR_SR_msgAddGEN2BlockWrite(uint8_t *msg, uint8_t *i, uint16_t timeout,TMR_GEN2_Bank bank, uint32_t wordPtr, uint32_t wordCount, uint16_t* data, uint32_t accessPassword,TMR_TagFilter* target);++void+TMR_SR_msgAddGEN2BlockPermaLock(uint8_t *msg, uint8_t *i, uint16_t timeout, uint32_t readLock, TMR_GEN2_Bank bank, uint32_t blockPtr, uint32_t blockRange, uint16_t* mask, uint32_t accessPassword,TMR_TagFilter* target);++void+TMR_SR_msgAddGEN2BlockErase(uint8_t *msg, uint8_t *i, uint16_t timeout, uint32_t wordPtr, TMR_GEN2_Bank bank,+                            uint8_t wordCount, uint32_t accessPassword, TMR_TagFilter* target);++void +TMR_SR_msgAddHiggs2PartialLoadImage(uint8_t *msg, uint8_t *i, uint16_t timeout, TMR_GEN2_Password accessPassword, +                                    TMR_GEN2_Password killPassword, uint8_t len, const uint8_t *epc, TMR_TagFilter* target);+void +TMR_SR_msgAddHiggs2FullLoadImage(uint8_t *msg, uint8_t *i, uint16_t timeout,+      TMR_GEN2_Password accessPassword, TMR_GEN2_Password killPassword, uint16_t lockBits, uint16_t pcWord, uint8_t len, const uint8_t *epc, TMR_TagFilter* target);+void +TMR_SR_msgAddHiggs3FastLoadImage(uint8_t *msg, uint8_t *i, uint16_t timeout, TMR_GEN2_Password currentAccessPassword,+      TMR_GEN2_Password accessPassword, TMR_GEN2_Password killPassword, uint16_t pcWord, uint8_t len, const uint8_t *epc, TMR_TagFilter* target);+void +TMR_SR_msgAddHiggs3LoadImage(uint8_t *msg, uint8_t *i, uint16_t timeout, TMR_GEN2_Password currentAccessPassword,+      TMR_GEN2_Password accessPassword, TMR_GEN2_Password killPassword, uint16_t pcWord, uint8_t len, const uint8_t *epcAndUserData, TMR_TagFilter* target);++void +TMR_SR_msgAddHiggs3BlockReadLock(uint8_t *msg, uint8_t *i, uint16_t timeout, TMR_GEN2_Password accessPassword, uint8_t lockBits, TMR_TagFilter* target);++void +TMR_SR_msgAddNXPSetReadProtect(uint8_t *msg, uint8_t *i, uint16_t timeout, TMR_SR_GEN2_SiliconType chip,+                            TMR_GEN2_Password accessPassword, TMR_TagFilter* target);+void +TMR_SR_msgAddNXPResetReadProtect(uint8_t *msg, uint8_t *i, uint16_t timeout, TMR_SR_GEN2_SiliconType chip,+                            TMR_GEN2_Password accessPassword, TMR_TagFilter* target);+void+TMR_SR_msgAddNXPChangeEAS(uint8_t *msg, uint8_t *i, uint16_t timeout, TMR_SR_GEN2_SiliconType chip,+                          TMR_GEN2_Password accessPassword, bool reset, TMR_TagFilter* target);+void +TMR_SR_msgAddNXPEASAlarm(uint8_t *msg, uint8_t *i, uint16_t timeout, TMR_SR_GEN2_SiliconType chip,+                         TMR_GEN2_DivideRatio dr, TMR_GEN2_TagEncoding m, TMR_GEN2_TrExt trExt, TMR_TagFilter* target);+void+TMR_SR_msgAddIAVDenatranCustomOp(uint8_t *msg, uint8_t *i, uint16_t timeout, TMR_GEN2_Password accessPassword,+                         uint8_t mode, uint8_t rfu, TMR_TagFilter* target);+void +TMR_SR_msgAddIAVDenatranCustomActivateSiniavMode(uint8_t *msg, uint8_t *i, uint16_t timeout, TMR_GEN2_Password accessPassword,+                         uint8_t mode, uint8_t payload, TMR_TagFilter* target, bool tokenDesc, uint8_t *token);+void +TMR_SR_msgAddIAVDenatranCustomReadFromMemMap(uint8_t *msg, uint8_t *i, uint16_t timeout, TMR_GEN2_Password accessPassword,+                        uint8_t mode, uint8_t payload, TMR_TagFilter* target, uint16_t wordAddress);+void +TMR_SR_msgAddIAVDenatranCustomWriteToMemMap(uint8_t *msg, uint8_t *i, uint16_t timeout, TMR_GEN2_Password accessPassword,+                        uint8_t mode, uint8_t payload, TMR_TagFilter* target, uint16_t wordPtr, uint16_t wordData, uint8_t* tagId, uint8_t* dataBuf);+void+TMR_SR_msgAddIAVDenatranCustomWriteSec(uint8_t *msg, uint8_t *i, uint16_t timeout, TMR_GEN2_Password accessPassword,+                        uint8_t mode, uint8_t payload, TMR_TagFilter* target, uint8_t* data, uint8_t* dataBuf);+void +TMR_SR_msgAddIAVDenatranCustomGetTokenId(uint8_t *msg, uint8_t *i, uint16_t timeout,+                        TMR_GEN2_Password accessPassword, uint8_t mode, TMR_TagFilter* target);+void +TMR_SR_msgAddIAVDenatranCustomReadSec(uint8_t *msg, uint8_t *i, uint16_t timeout, TMR_GEN2_Password accessPassword,+                        uint8_t mode, uint8_t payload, TMR_TagFilter* target, uint16_t wordAddress);+void +TMR_SR_msgAddNXPCalibrate(uint8_t *msg, uint8_t *i, uint16_t timeout, TMR_SR_GEN2_SiliconType chip,+                         TMR_GEN2_Password accessPassword, TMR_TagFilter* target);+void +TMR_SR_msgAddNXPChangeConfig(uint8_t *msg, uint8_t *i, uint16_t timeout,+                         TMR_SR_GEN2_SiliconType chip, TMR_GEN2_Password accessPassword, TMR_NXP_ConfigWord configword, TMR_TagFilter* target);+void +TMR_SR_msgAddMonza4QTReadWrite(uint8_t *msg, uint8_t *i, uint16_t timeout, TMR_GEN2_Password accessPassword,+                               TMR_Monza4_ControlByte controlByte, TMR_Monza4_Payload payload, TMR_TagFilter* target);++void +TMR_SR_msgAddIdsSL900aGetSensorValue(uint8_t *msg, uint8_t *i, uint16_t timeout, TMR_GEN2_Password accessPassword,+                                     uint8_t CommandCode, uint32_t password, PasswordLevel level, Sensor sensortype,+                                     TMR_TagFilter* target);+void +TMR_SR_msgAddIdsSL900aGetMeasurementSetup(uint8_t *msg, uint8_t *i, uint16_t timeout, TMR_GEN2_Password accessPassword,+                                          uint8_t CommandCode, uint32_t password, PasswordLevel level, TMR_TagFilter* target);++void +TMR_SR_msgAddIdsSL900aGetCalibrationData(uint8_t *msg, uint8_t *i, uint16_t timeout, TMR_GEN2_Password accessPassword,+                                     uint8_t CommandCode, uint32_t password, PasswordLevel level, TMR_TagFilter* target);+void +TMR_SR_msgAddIdsSL900aSetCalibrationData(uint8_t *msg, uint8_t *i, uint16_t timeout, TMR_GEN2_Password accessPassword,+                                          uint8_t CommandCode, uint32_t password, PasswordLevel level, uint64_t calibration, TMR_TagFilter* target);+void +TMR_SR_msgAddIdsSL900aSetSfeParameters(uint8_t *msg, uint8_t *i, uint16_t timeout, TMR_GEN2_Password accessPassword,+                                          uint8_t CommandCode, uint32_t password, PasswordLevel level, uint16_t sfe,+                                          TMR_TagFilter* target);+void +TMR_SR_msgAddIdsSL900aGetLogState(uint8_t *msg, uint8_t *i, uint16_t timeout, TMR_GEN2_Password accessPassword,+                                  uint8_t CommandCode, uint32_t password, PasswordLevel level, TMR_TagFilter* target);+void+TMR_SR_msgAddIdsSL900aSetLogMode(uint8_t *msg, uint8_t *i, uint16_t timeout, TMR_GEN2_Password accessPassword,+                                 uint8_t CommandCode, uint32_t password, PasswordLevel level, LoggingForm form,+                                 StorageRule rule, bool Ext1Enable, bool Ext2Enable, bool TempEnable, bool BattEnable,+                                 uint16_t LogInterval, TMR_TagFilter* target);+void +TMR_SR_msgAddIdsSL900aSetLogLimit(uint8_t *msg, uint8_t *i, uint16_t timeout, TMR_GEN2_Password accessPassword,+                                  uint8_t CommandCode, uint32_t password, PasswordLevel level, uint16_t exLower,+                                  uint16_t lower, uint16_t upper, uint16_t exUpper, TMR_TagFilter* target);+void +TMR_SR_msgAddIdsSL900aSetShelfLife(uint8_t *msg, uint8_t *i, uint16_t timeout, TMR_GEN2_Password accessPassword,+                                   uint8_t CommandCode, uint32_t password, PasswordLevel level, uint32_t block0, uint32_t block1,+                                   TMR_TagFilter* target);+void+TMR_SR_msgAddIdsSL900aInitialize(uint8_t *msg, uint8_t *i, uint16_t timeout, TMR_GEN2_Password accessPassword,+                                 uint8_t CommandCode, uint32_t password, PasswordLevel level, uint16_t delayTime,+                                 uint16_t applicatioData, TMR_TagFilter* target);+void+TMR_SR_msgAddIdsSL900aEndLog(uint8_t *msg, uint8_t *i, uint16_t timeout, TMR_GEN2_Password accessPassword,+                             uint8_t CommandCode, uint32_t password, PasswordLevel level, TMR_TagFilter* target);+void+TMR_SR_msgAddIdsSL900aSetPassword(uint8_t *msg, uint8_t *i, uint16_t timeout, TMR_GEN2_Password accessPassword,+                                  uint8_t CommandCode, uint32_t password, PasswordLevel level, uint32_t newPassword,+                                  PasswordLevel newPasswordLevel, TMR_TagFilter* target);+void +TMR_SR_msgAddIdsSL900aAccessFifoStatus(uint8_t *msg, uint8_t *i, uint16_t timeout, TMR_GEN2_Password accessPassword,+                                  uint8_t CommandCode, uint32_t password, PasswordLevel level, AccessFifoOperation operation,+                                  TMR_TagFilter* target);+void +TMR_SR_msgAddIdsSL900aGetBatteryLevel(uint8_t *msg, uint8_t *i, uint16_t timeout, TMR_GEN2_Password accessPassword,+                                      uint8_t CommandCode, uint32_t password, PasswordLevel level, BatteryType batteryType,+                                      TMR_TagFilter* target);+void +TMR_SR_msgAddIdsSL900aAccessFifoRead(uint8_t *msg, uint8_t *i, uint16_t timeout, TMR_GEN2_Password accessPassword,+                                  uint8_t CommandCode, uint32_t password, PasswordLevel level, AccessFifoOperation operation,+                                  uint8_t length, TMR_TagFilter* target);+void +TMR_SR_msgAddIdsSL900aAccessFifoWrite(uint8_t *msg, uint8_t *i, uint16_t timeout, TMR_GEN2_Password accessPassword,+                                  uint8_t CommandCode, uint32_t password, PasswordLevel level, AccessFifoOperation operation,+                                  TMR_uint8List *payLoad, TMR_TagFilter* target);+void +TMR_SR_msgAddIdsSL900aStartLog(uint8_t *msg, uint8_t *i, uint16_t timeout, TMR_GEN2_Password accessPassword,+                               uint8_t CommandCode, uint32_t password, PasswordLevel level, uint32_t time, TMR_TagFilter* target);++TMR_Status TMR_SR_executeEmbeddedRead(TMR_Reader *reader, uint8_t *msg,+            uint16_t timeout, TMR_SR_MultipleStatus *status);++TMR_Status TMR_SR_cmdISO180006BWriteTagData(TMR_Reader *reader,+      uint16_t timeout, uint8_t address, uint8_t count, const uint8_t data[],+      const TMR_TagFilter *filter);+TMR_Status TMR_SR_cmdISO180006BReadTagData(TMR_Reader *reader,+      uint16_t timeout, uint8_t address, uint8_t length,+      const TMR_TagFilter *filter, TMR_TagReadData *read);+TMR_Status TMR_SR_cmdISO180006BLockTag(TMR_Reader *reader, uint16_t timeout,+      uint8_t address, const TMR_TagFilter *filter);+TMR_Status TMR_iso18000BBLFValToInt(int val, void *lf);+TMR_Status TMR_SR_cmdStopReading(struct TMR_Reader *reader);+TMR_Status TMR_SR_cmdGetReaderWriteTimeOut (struct TMR_Reader *reader, TMR_TagProtocol protocol,+																						TMR_SR_Gen2ReaderWriteTimeOut *value);+TMR_Status TMR_SR_cmdSetReaderWriteTimeOut (struct TMR_Reader *reader, TMR_TagProtocol protocol,+																						TMR_SR_Gen2ReaderWriteTimeOut *value);+TMR_Status TMR_SR_cmdAuthReqResponse(struct TMR_Reader *reader, TMR_TagAuthentication *auth);++TMR_Status TMR_SR_addTagOp(struct TMR_Reader *reader, TMR_TagOp *tagop,TMR_ReadPlan *rp, uint8_t *msg, uint8_t *i, uint32_t readTimeMs, uint8_t *lenbyte);++TMR_Status+TMR_fillReaderStats(TMR_Reader *reader, TMR_Reader_StatsValues* stats, uint16_t flag, uint8_t* msg, uint8_t offset);+bool compareAntennas(TMR_MultiReadPlan *multi);+bool compareVersion(TMR_Reader *reader, uint8_t firstByte, uint8_t secondByte, uint8_t thirdByte, uint8_t fourthByte);+TMR_Status+TMR_SR_cmdrebootReader(TMR_Reader *reader);+TMR_Status+prepForSearch(TMR_Reader *reader, TMR_uint8List *antennaList);+TMR_Status +TMR_SR_msgSetupMultipleProtocolSearch(TMR_Reader *reader, uint8_t *msg, TMR_SR_OpCode op, TMR_TagProtocolList *protocols, TMR_TRD_MetadataFlag metadataFlags, TMR_SR_SearchFlag antennas, TMR_TagFilter **filter, uint16_t timeout);+TMR_Status TMR_SR_cmdProbeBaudRate(TMR_Reader *reader, uint32_t *currentBaudRate);+void TMR_SR_updateBaseTimeStamp(TMR_Reader *reader);+TMR_Status verifySearchStatus(TMR_Reader *reader);+++#ifdef TMR_ENABLE_BACKGROUND_READS+void notify_authreq_listeners(TMR_Reader *reader, TMR_TagReadData *trd, TMR_TagAuthentication *auth);+#endif+++#ifdef __cplusplus+}+#endif++#endif /* _SERIAL_READER_IMP_H */
+ cbits/api/serial_reader_l3.c view
@@ -0,0 +1,7295 @@+/**+ *  @file serial_reader_l3.c+ *  @brief Mercury API - serial reader low level implementation+ *  @author Nathan Williams+ *  @date 11/2/2009+ */++/*+ * Copyright (c) 2009 ThingMagic, Inc.+ *+ * Permission is hereby granted, free of charge, to any person obtaining a copy+ * of this software and associated documentation files (the "Software"), to deal+ * in the Software without restriction, including without limitation the rights+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell+ * copies of the Software, and to permit persons to whom the Software is+ * furnished to do so, subject to the following conditions:+ *+ * The above copyright notice and this permission notice shall be included in+ * all copies or substantial portions of the Software.+ * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN+ * THE SOFTWARE.+ */++#include <inttypes.h>+#include <stdio.h>+#include <stdlib.h>+#include <string.h>++#include "tm_reader.h"+#include "serial_reader_imp.h"+#include "tmr_utils.h"++#ifndef BARE_METAL+bool isSecureAccessEnabled;+#endif++void+notify_read_listeners(TMR_Reader *reader, TMR_TagReadData *trd);+#ifdef TMR_ENABLE_SERIAL_READER++static TMR_Status filterbytes(TMR_TagProtocol protocol,+                              const TMR_TagFilter *filter, +                              uint8_t *option, uint8_t *i, uint8_t *msg,+                              uint32_t accessPassword, bool usePassword);+TMR_Status+TMR_SR_sendBytes(TMR_Reader *reader, uint8_t len, uint8_t *data, uint32_t timeoutMs);++/*+ * ThingMagic-mutated CRC used for messages.+ * Notably, not a CCITT CRC-16, though it looks close.+ */+static uint16_t crctable[] = +{+  0x0000, 0x1021, 0x2042, 0x3063,+  0x4084, 0x50a5, 0x60c6, 0x70e7,+  0x8108, 0x9129, 0xa14a, 0xb16b,+  0xc18c, 0xd1ad, 0xe1ce, 0xf1ef,+};++static uint16_t+tm_crc(uint8_t *u8Buf, uint8_t len)+{+  uint16_t crc;+  int i;++  crc = 0xffff;++  for (i = 0; i < len ; i++)+  {+    crc = ((crc << 4) | (u8Buf[i] >> 4))  ^ crctable[crc >> 12];+    crc = ((crc << 4) | (u8Buf[i] & 0xf)) ^ crctable[crc >> 12];+  }++  return crc;+}+++/**+ * Send a byte string+ *+ * @param reader The reader+ * @param[in] len Number of bytes to send+ * @param[in] data Bytes to send, with length in byte 1. Byte 0 is reserved for the SOF character, and two characters at the end are reserved for the CRC.+ * @param timeoutMs Timeout value.+ */+TMR_Status+TMR_SR_sendBytes(TMR_Reader *reader, uint8_t len, uint8_t *data, uint32_t timeoutMs)+{+  TMR_SR_SerialTransport *transport;+  TMR_Status ret;++  transport = &reader->u.serialReader.transport;++  if (NULL != reader->transportListeners)+  {+    TMR__notifyTransportListeners(reader, true, len, data, timeoutMs);+  }++  ret = transport->sendBytes(transport, len, data, timeoutMs);+  return ret;+}++/**+ * Send a message to the reader+ *+ * @param reader The reader+ * @param[in] data Message to send, with length in byte 1. Byte 0 is reserved for the SOF character, and two characters at the end are reserved for the CRC.+ * @param[out] opcode Opcode sent with message (pass this value to receiveMessage to match against response)+ * @param timeoutMs Timeout value.+ */+TMR_Status+TMR_SR_sendMessage(TMR_Reader *reader, uint8_t *data, uint8_t *opcode, uint32_t timeoutMs)+{+  TMR_SR_SerialReader *sr;+  TMR_Status ret;+  uint16_t crc;+  uint8_t len;+  uint8_t j;+  //uint8_t byteLen;++  sr = &reader->u.serialReader;+  timeoutMs += sr->transportTimeout;+/*  if (reader->u.serialReader.crcEnabled)+  {+    byteLen = 5;+  }+  else+  {+    byteLen = 3;+  }*/++  /* Wake up processor from deep sleep.  Tickle the RS-232 line, then+   * wait a fixed delay while the processor spins up communications again. */+  if (sr->supportsPreamble && ((sr->powerMode == TMR_SR_POWER_MODE_INVALID) ||+                              (sr->powerMode == TMR_SR_POWER_MODE_SLEEP)) )+  {+    uint8_t flushBytes[] = {+      0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF+    };++    TMR_SR_sendBytes(reader, sizeof(flushBytes)/sizeof(uint8_t), flushBytes, timeoutMs);+    {+      uint32_t bytesper100ms;+      uint32_t bytesSent;++      /* Calculate fixed delay in terms of byte-lengths at current speed */+      /* @todo Optimize delay length.  This value (100 bytes at 9600bps) is taken+       * directly from arbser, which was itself using a hastily-chosen value. */+      bytesper100ms = sr->baudRate / 50;+      for (bytesSent=0; bytesSent<bytesper100ms;+         bytesSent += (sizeof(flushBytes)/sizeof(uint8_t)))+      {+        TMR_SR_sendBytes(reader, sizeof(flushBytes)/sizeof(uint8_t), flushBytes, timeoutMs);+      }+    }+  }    ++  /* Layout of message in data array: +   * [0] [1] [2] [3] [4]  ... [LEN+2] [LEN+3] [LEN+4]+   * FF  LEN OP  xx  xx   ... xx      CRCHI   CRCLO+   */+  data[0] = 0xff;+  len = data[1];+  *opcode = data[2];++  if (isContinuousReadParamSupported(reader))+  {+	  for (j = 0; j <= len; j++)+	  {+		  reader->paramMessage[j] = data[2 + j];+	  }+	  data[1] = 5 + len;+	  data[2] = 0x2f;+	  data[3] = 0x00;+	  data[4] = 0x00;+	  data[5] = 0x04;+	  data[6] = len;+	  for (j = 0; j <= len ; j++)+	  {+		  data[7 + j] = reader->paramMessage[j];+	  }+	  len = data[1];+	  reader->paramWait = true;+  }++ // if (reader->u.serialReader.crcEnabled)+  {+  crc = tm_crc(&data[1], len + 2);+  data[len + 3] = crc >> 8;+  data[len + 4] = crc & 0xff;+  }+  +  ret = TMR_SR_sendBytes(reader, len+5, data, timeoutMs);+  return ret;+}+++bool+isContinuousReadParamSupported(TMR_Reader *reader)+{+	uint16_t i; +	uint8_t *readerVersion = reader->u.serialReader.versionInfo.fwVersion ;+	uint8_t checkVersion[4];++	if (reader->hasContinuousReadStarted == false || reader->continuousReading == false)+		return false;++	switch (reader->u.serialReader.versionInfo.hardware[0])+	{+		case TMR_SR_MODEL_M6E:+		case TMR_SR_MODEL_M6E_I:+			checkVersion[0] = 0x01; checkVersion[1] = 0x21; checkVersion[2] = 0x01; checkVersion[3] = 0x19;+			break;+		case TMR_SR_MODEL_MICRO:+			checkVersion[0] = 0x01; checkVersion[1] = 0x09; checkVersion[2] = 0x00; checkVersion[3] = 0x14;+			break;+		case TMR_SR_MODEL_M6E_NANO:+			checkVersion[0] = 0x01; checkVersion[1] = 0x07; checkVersion[2] = 0x00; checkVersion[3] = 0x0E;+			break;+		default:+			checkVersion[0] = 0xFF; checkVersion[1] = 0xFF; checkVersion[2] = 0xFF; checkVersion[3] = 0xFF;+	}+	for (i = 0; i < 4; i++)+	{+		if (readerVersion[i] < checkVersion[i])+		{+			return false;+		}+	}+	return true;+}++/**+ * Receive a response.+ *+ * @param reader The reader+ * @param[in] data Message to send, with length in byte 1. Byte 0 is reserved for the SOF character, and two characters at the end are reserved for the CRC.+ * @param[out] data Message received.+ * @param opcode Opcode that was sent with message that elicited this response, to be matched against incoming response opcode.+ * @param timeoutMs Timeout value.+ */+TMR_Status+TMR_SR_receiveMessage(TMR_Reader *reader, uint8_t *data, uint8_t opcode, uint32_t timeoutMs)+{+  TMR_Status ret;+  uint16_t crc, status;+  uint8_t len,headerOffset;+  uint8_t receiveBytesLen;+  uint32_t inlen;+  int i;+  TMR_SR_SerialTransport *transport;+  uint8_t retryCount = 0;++  transport = &reader->u.serialReader.transport;+  timeoutMs += reader->u.serialReader.transportTimeout;++  /**+   * Initialize the receive bytes length based on+   * sr->expectCRC option+   **/+  if (reader->u.serialReader.crcEnabled)+  {+    receiveBytesLen = 7;+  }+  else+  {+    receiveBytesLen = 5;+  }++  headerOffset = 0;+retryHeader:+  inlen = 0;+  retryCount++;+  ret = transport->receiveBytes(transport, receiveBytesLen - headerOffset, &inlen, data + headerOffset, timeoutMs);+  if (TMR_SUCCESS != ret)+  {+    /* @todo Figure out how many bytes were actually obtained in a failed receive */+    TMR__notifyTransportListeners(reader, false, inlen, data, timeoutMs);+    return ret;+  }++  if (data[0] != (uint8_t)0xFF)+  {+    for (i = 1; i < receiveBytesLen; i++) +    {+      if (data[i] == 0xFF)+      {+        /* An SOH has been found, so we won't enter the "NO SOH" section of code again */+        headerOffset = receiveBytesLen - i;+        memmove(data, data + i, headerOffset);+        goto retryHeader;+      }+    }+    if (retryCount < 20)+    {+      /* Retry to get SOH */+      goto retryHeader;+    }+    return TMR_ERROR_TIMEOUT;+  }++  /* After this point, we have the the bare minimum (5 or 7)  of bytes in the buffer */++  /* Layout of response in data array: +   * [0] [1] [2] [3]      [4]      [5] [6]  ... [LEN+4] [LEN+5] [LEN+6]+   * FF  LEN OP  STATUSHI STATUSLO xx  xx   ... xx      CRCHI   CRCLO+   */+  len = data[1];++  if (0 == len)+  {+    inlen = 0;+  }+  else if ((TMR_SR_MAX_PACKET_SIZE - receiveBytesLen) < len)+  {+    /**+     * packet data size is overflowing the buffer size. This could be a+     * corrupted packet. Discard it and move on. Return back with TMR_ERROR_TOO_BIG+     * error.+     **/+    return TMR_ERROR_TOO_BIG;+  }+  else+  {+    ret = transport->receiveBytes(transport, len, &inlen, data + receiveBytesLen, timeoutMs);+  }++  if (NULL != reader->transportListeners)+  {+    TMR__notifyTransportListeners(reader, false, inlen + receiveBytesLen, data, timeoutMs);+  }++  if (TMR_SUCCESS != ret)+  {+    /* before we can actually process the message, we have to properly receive the message */+    return ret;+  }++  /**+   * Calculate the CRC only if expectCRC option+   * is enabled+   **/+  if (reader->u.serialReader.crcEnabled)+  {+  crc = tm_crc(&data[1], len + 4);+  if ((data[len + 5] != (crc >> 8)) ||+      (data[len + 6] != (crc & 0xff)))+  {+    return TMR_ERROR_CRC_ERROR;+  }+  }++  if ((data[2] != opcode) && ((data[2] != 0x2F) || (!reader->continuousReading)))+  {+    if(data[2] == 0x9D)+     {+       return TMR_ERROR_AUTOREAD_ENABLED;+     }++    /* We got a response for a different command than the one we+     * sent. This usually means we received the boot-time message from+     * a M6e, and thus that the device was rebooted somewhere between+     * the previous command and this one. Report this as a problem.+     */+    return TMR_ERROR_DEVICE_RESET;+ }++  status = GETU16AT(data, 3);+  if (status != 0)+  {+    ret = TMR_ERROR_CODE(status);+    if (ret == TMR_ERROR_TM_ASSERT_FAILED)+    {+	  uint32_t line;+	  uint8_t *assert = (uint8_t *) (data + 5);++	  memset(reader->u.serialReader.errMsg, 0 ,TMR_SR_MAX_PACKET_SIZE);+	  line = GETU32AT(assert, 0);+	  sprintf(reader->u.serialReader.errMsg, "Assertion failed at line %"PRId32" in file ", line);+	  memcpy(reader->u.serialReader.errMsg + strlen(reader->u.serialReader.errMsg), assert + 4, len - 4);+  }+  }  +  return ret;+}++/**+ * Send a message and receive a response.+ *+ * @param reader The reader+ * @param[in] data Message to send, with length in byte 1. Byte 0 is reserved for the SOF character, and two characters at the end are reserved for the CRC.+ * @param[out] data Message received.+ * @param timeoutMs Timeout value.+ */+TMR_Status+TMR_SR_sendTimeout(TMR_Reader *reader, uint8_t *data, uint32_t timeoutMs)+{+  TMR_Status ret;+  uint8_t opcode;+  ret = TMR_SR_sendMessage(reader, data, &opcode, timeoutMs);+  if (TMR_SUCCESS != ret)+  {+    return ret;+  }+  if (isContinuousReadParamSupported(reader))+  {+	  while(reader->paramWait)+	  {+#ifdef SINGLE_THREAD_ASYNC_READ+		TMR_TagReadData trd;+		ret = TMR_hasMoreTags(reader);+		if (TMR_SUCCESS == ret)+		{+			TMR_getNextTag(reader, &trd);+			notify_read_listeners(reader, &trd);+		}+#endif+	  }++	  reader->paramWait = false;	  +	  memcpy(data , &reader->paramMessage[5], reader->paramMessage[1] * sizeof(uint8_t));+	  data[0] = 0xFF;+	  ret = (TMR_Status) GETU16AT(&reader->paramMessage[0], 3);+	  if (TMR_SUCCESS != ret)+	  {+		  return TMR_ERROR_CODE(ret);+	  }+	  ret = (TMR_Status) GETU16AT(data, 3);+	  if (TMR_SUCCESS != ret)+	  {+		  return TMR_ERROR_CODE(ret);+	  }+  }+  else+  {+    ret = TMR_SR_receiveMessage(reader, data, opcode, timeoutMs);+    if (TMR_SUCCESS != ret)+    {+		return ret;+	}+  }+  return ret;+}+++TMR_Status+TMR_SR_send(TMR_Reader *reader, uint8_t *data)+{+  return TMR_SR_sendTimeout(reader, data,+                            reader->u.serialReader.commandTimeout);+}++/**+ * Set the operating frequency of the device.+ * Testing command.+ *+ * @param reader The reader+ * @param frequency the frequency to set, in kHz+ */ +TMR_Status +TMR_SR_cmdTestSetFrequency(TMR_Reader *reader, uint32_t frequency)+{+  +  uint8_t msg[TMR_SR_MAX_PACKET_SIZE];+  uint8_t i;+  i = 2;+  SETU8(msg, i,TMR_SR_OPCODE_SET_OPERATING_FREQ);+  SETU32(msg, i, frequency);+  msg[1] = i - 3; /* Install length */+  return TMR_SR_send(reader, msg);+}++/**+ * Turn CW transmission on or off.+ * Testing command.+ *+ * @param reader The reader+ * @param on whether to turn CW on or off+ */ +TMR_Status +TMR_SR_cmdTestSendCw(TMR_Reader *reader, bool on)+{+  uint8_t msg[TMR_SR_MAX_PACKET_SIZE];+  uint8_t i;+  i = 2;+  SETU8(msg, i,TMR_SR_OPCODE_TX_CW_SIGNAL);+  if(on)+    SETU8(msg, i,1);+  else+    SETU8(msg, i,0);+  msg[1] = i - 3; /* Install length */+  return TMR_SR_send(reader, msg);+}++/**+ * Turn on pseudo-random bit stream transmission for a particular+ * duration.  + * Testing command.+ *+ * @param reader The reader+ * @param duration the duration to transmit the PRBS signal.+ */ +TMR_Status +TMR_SR_cmdTestSendPrbs(TMR_Reader *reader, uint16_t duration)+{+  uint8_t msg[TMR_SR_MAX_PACKET_SIZE];+  uint8_t i;+  i = 2;+  SETU8(msg, i,TMR_SR_OPCODE_TX_CW_SIGNAL);+  SETU8(msg, i,2);+  SETU16(msg, i,duration);+  msg[1] = i - 3; /* Install length */+  return TMR_SR_send(reader, msg);+}++/**+ * Setting user profile on the basis of operation, category and type parameter+ *+ * @param reader The reader+ * @param op operation to be performed on configuration (Save,restore,verify and reset)+ * @param category Which category of configuration to operate on -- only TMR_SR_ALL is currently supported+ * @param type Type of configuration value to use (default, custom...)+ */++TMR_Status +TMR_SR_cmdSetUserProfile(TMR_Reader *reader,TMR_SR_UserConfigOperation op,TMR_SR_UserConfigCategory category, TMR_SR_UserConfigType type)+{+  uint8_t msg[TMR_SR_MAX_PACKET_SIZE];+  uint8_t i;+  TMR_Status ret;+  TMR_Status ret1;+  uint16_t readTime = 250;+  TMR_SR_SerialReader *sr;+  TMR_SR_SerialTransport *transport;++  sr = &reader->u.serialReader;+  transport = &reader->u.serialReader.transport;++  i = 2;+  SETU8(msg,i,TMR_SR_OPCODE_SET_USER_PROFILE);+  SETU8(msg,i,op);+  SETU8(msg,i,category);+  SETU8(msg,i,type);++#ifdef TMR_ENABLE_BACKGROUND_READS+  readTime = (uint16_t)reader->readParams.asyncOnTime; +#endif++  if (op == TMR_USERCONFIG_CLEAR)+  {+    /* Resrt the Autonomous option if enabled */+    sr->enableAutonomousRead = false;+  }++  if (op == TMR_USERCONFIG_SAVE_WITH_READPLAN)+  {+    /** +     * extract the read plan configuration form API read plan object, frame+     * the serial command for read by using existing parser methods in read+     * operation and append that to save configuration command.+     **/+    TMR_uint8List *antennaList = NULL;+    TMR_ReadPlan *rp;+    uint8_t tempMsg[TMR_SR_MAX_PACKET_SIZE];++    rp = reader->readParams.readPlan;    ++    /**+     * Currently Mercury API supports only true continuous read as a part of+     * save configuration with read plan.+     * TODO: Add support for other read types as well if needed in future.+     **/++    /* Add the Autonomous read option */+    sr->enableAutonomousRead = rp->enableAutonomousRead;+    SETU8(msg,i,rp->enableAutonomousRead);++    if (TMR_READ_PLAN_TYPE_MULTI == rp->type)+    {+      /* The Multi read plan */+      uint8_t i; +      TMR_TagProtocolList p;+      TMR_TagProtocolList *protocolList = &p;+      TMR_TagFilter *filters[TMR_MAX_SERIAL_MULTIPROTOCOL_LENGTH];+      TMR_TagProtocol protocols[TMR_MAX_SERIAL_MULTIPROTOCOL_LENGTH];++      if (TMR_MAX_SERIAL_MULTIPROTOCOL_LENGTH < rp->u.multi.planCount)+      {+        return TMR_ERROR_TOO_BIG ;+      }+      protocolList->len = rp->u.multi.planCount;+      protocolList->max = rp->u.multi.planCount;+      protocolList->list = protocols;++      for (i = 0; i < rp->u.multi.planCount; i++)+      {+        protocolList->list[i] = rp->u.multi.plans[i]->u.simple.protocol;+        filters[i]= rp->u.multi.plans[i]->u.simple.filter; +      }++      if ((0 < rp->u.multi.planCount) &&+        (rp->u.multi.plans[0]->type == TMR_READ_PLAN_TYPE_SIMPLE) &&+        (compareAntennas(&rp->u.multi)))+      {        +        TMR_SR_SearchFlag antennas = TMR_SR_SEARCH_FLAG_CONFIGURED_LIST;++        reader->continuousReading = true;+        antennas |= ((reader->continuousReading)? TMR_SR_SEARCH_FLAG_TAG_STREAMING : 0);+        antennaList = &(rp->u.multi.plans[0]->u.simple.antennas);+        ret = prepForSearch(reader, antennaList);+        if (TMR_SUCCESS != ret)+        {+          return ret;+        }++        if (reader->continuousReading)+        {+          bool value = false;+          ret = TMR_SR_cmdSetReaderConfiguration(reader, TMR_SR_CONFIGURATION_ENABLE_READ_FILTER, &value);+          if (TMR_SUCCESS != ret)+          {+            return ret;+          }+        }+        +        /* Call the helper function to frame the multi protocol read command */+        ret = TMR_SR_msgSetupMultipleProtocolSearch(reader, tempMsg, TMR_SR_OPCODE_READ_TAG_ID_MULTIPLE, protocolList,+          reader->userMetadataFlag, antennas, filters, (uint16_t)readTime);+        if (TMR_SUCCESS != ret)+        {+          return ret;+        }+      }+      else+      {+        /**+         * Coming here means the requested read plan is not for true continuous read.+         * Throw error back to user.+         * TODO:Remove this validation, if we need to support for other type of read+         * operation in future.+         */+        return TMR_ERROR_UNSUPPORTED;+      }+    }+    else+    {+      /* The Simple Read Plan */+      TMR_TagProtocolList p;+      TMR_TagProtocolList *protocolList = &p;+      TMR_TagFilter *filters[TMR_MAX_SERIAL_MULTIPROTOCOL_LENGTH];+      TMR_TagProtocol protocols[TMR_MAX_SERIAL_MULTIPROTOCOL_LENGTH];+      TMR_SR_SearchFlag antennas;++      antennaList = &rp->u.simple.antennas;+      reader->continuousReading = true;+      reader->fastSearch = rp->u.simple.useFastSearch;+      reader->triggerRead = rp->u.simple.triggerRead.enable;+      protocolList->len = 1;+      protocolList->max = 1;+      protocolList->list = protocols;++      ret = prepForSearch(reader, antennaList);+      if (TMR_SUCCESS != ret)+      {+        return ret;+      }++      if (reader->continuousReading)+      {+        bool value = false;+        ret = TMR_SR_cmdSetReaderConfiguration(reader, TMR_SR_CONFIGURATION_ENABLE_READ_FILTER, &value);+        if (TMR_SUCCESS != ret)+        {+          return ret;+        }+      }++      protocolList->list[0] = rp->u.simple.protocol;+      filters[0]= rp->u.simple.filter;++      antennas = TMR_SR_SEARCH_FLAG_CONFIGURED_LIST;+      antennas |= ((reader->continuousReading)? TMR_SR_SEARCH_FLAG_TAG_STREAMING : 0);+      antennaList = &(rp->u.simple.antennas);++      ret = TMR_SR_msgSetupMultipleProtocolSearch(reader, tempMsg, TMR_SR_OPCODE_READ_TAG_ID_MULTIPLE, protocolList,+        reader->userMetadataFlag, antennas, filters, (uint16_t)readTime);+      if (TMR_SUCCESS != ret)+      {+        return ret;+      }      +    }++    /* Append the serial read command to save configuration command */+    memcpy((msg + i), tempMsg+1, tempMsg[1]+2);+    /* Add two bytes for Opcode and header */+    i = (i + tempMsg[1] + 2);    +    reader->continuousReading = false;+  }++  msg[1] = i - 3; /* Install length */+  ret1 = TMR_SR_send(reader, msg);+  if (TMR_SUCCESS != ret1)+  {+    return ret1;+  }++  /* If Autonomous read is enabled skip this */+  if (!sr->enableAutonomousRead)+  {+    if ((op == TMR_USERCONFIG_RESTORE)||(op == TMR_USERCONFIG_CLEAR))  //reprobe the baudrate+    {+      uint32_t rate;+      if (reader->connected == false)+      {+        ret = transport->open(transport);+        if (TMR_SUCCESS != ret)+        {+          return ret;+        }+      }++      ret = TMR_SR_cmdProbeBaudRate(reader, &rate);+      if (TMR_SUCCESS != ret)+      {+        return ret;+      }+      reader->connected = true;+    }++    /* Restore the region and protocol*/+    if ((op == TMR_USERCONFIG_RESTORE) || (op == TMR_USERCONFIG_CLEAR))+    {+      ret = TMR_SR_cmdGetRegion(reader, &sr->regionId);+      if (TMR_SUCCESS != ret)+      {+        return ret;+      }++      ret = TMR_SR_cmdGetCurrentProtocol(reader, &reader->tagOpParams.protocol);+      if (TMR_SUCCESS != ret)+      {+        return ret;+      }+      sr->currentProtocol = reader->tagOpParams.protocol;+    }+  }+  return ret1;+}++/**+ * Get Save/Restore Configuration + *+ * @param reader The reader+ * @param byte array consists of a opcode option(s)+ * @param length Length of byte array+ * @param response Response of the operation+ * @param response_length Length of response array+ */++TMR_Status TMR_SR_cmdGetUserProfile(TMR_Reader *reader, uint8_t byte[], uint8_t length, uint8_t response[], uint8_t* response_length)+{+  TMR_Status ret;+  uint8_t msg[TMR_SR_MAX_PACKET_SIZE];+  uint8_t i,j;+  i = 2;+  SETU8(msg,i,TMR_SR_OPCODE_GET_USER_PROFILE);+  for(j=0;j<length;j++)+  {+    SETU8(msg,i,byte[j]);+  }+  msg[1] = i - 3;+  ret = TMR_SR_send(reader, msg);+  if (TMR_SUCCESS != ret)+  {+    return ret;+  }+  for(j=0;j<msg[1];j++)+  {+    response[j]=msg[5+j];+  }+  *response_length=msg[1];+  return ret;+}++TMR_Status TMR_SR_cmdBlockWrite(TMR_Reader *reader, uint16_t timeout, TMR_GEN2_Bank bank, uint32_t wordPtr, +                                 uint32_t wordCount, const uint16_t* data, uint32_t accessPassword, const TMR_TagFilter* target)+        {   +            uint8_t msg[TMR_SR_MAX_PACKET_SIZE];+            uint8_t i, option=0,rec;+            i = 2;        +            SETU8(msg,i,TMR_SR_OPCODE_WRITE_TAG_SPECIFIC);+            SETU16(msg, i,timeout);+            SETU8(msg,i,0x00);//chip type+            rec=i;+            SETU8(msg,i,0x40);//option+            SETU8(msg,i,0x00);+            SETU8(msg,i,0xC7);+            filterbytes(TMR_TAG_PROTOCOL_GEN2, target, &option, &i, msg,accessPassword,true);+            msg[rec]=msg[rec]|option;+            SETU8(msg,i,0x00);+            SETU8(msg,i,bank);+            SETU32(msg,i,wordPtr);+            SETU8(msg,i,(uint8_t)wordCount);+            {+              uint32_t iWord;+              for (iWord = 0; iWord < wordCount; iWord++)+              {+                SETU8(msg, i, ((data[iWord]>>8)&0xFF));+                SETU8(msg, i, ((data[iWord]>>0)&0xFF));+              }+            }+            msg[1] = i - 3;+            return TMR_SR_send(reader, msg);+         }++TMR_Status +TMR_SR_cmdBlockErase(TMR_Reader *reader, uint16_t timeout,+                     TMR_GEN2_Bank bank, uint32_t wordPtr,+                     uint8_t wordCount, uint32_t accessPassword,+                     TMR_TagFilter *target)+{+  uint8_t msg[TMR_SR_MAX_PACKET_SIZE];+  uint8_t i;+  i = 2;++  TMR_SR_msgAddGEN2BlockErase(msg, &i, timeout, wordPtr, bank, wordCount, accessPassword, target);++  msg[1] = i - 3;+  return TMR_SR_send(reader, msg);+}++TMR_Status+TMR_SR_cmdBlockPermaLock(TMR_Reader *reader, uint16_t timeout,uint32_t readLock, TMR_GEN2_Bank bank, uint32_t blockPtr, uint32_t blockRange, uint16_t* mask, uint32_t accessPassword, TMR_TagFilter* target, TMR_uint8List* data)+        { +            TMR_Status ret;+            uint8_t msg[TMR_SR_MAX_PACKET_SIZE];+            uint8_t i, option=0,rec;+            unsigned int j;+            i = 2;    +            SETU8(msg,i,TMR_SR_OPCODE_ERASE_BLOCK_TAG_SPECIFIC);+            SETU16(msg,i,timeout);+            SETU8(msg,i,0x00);+            rec=i;+            SETU8(msg,i,0x40);+            SETU8(msg,i,0x01);+            filterbytes(TMR_TAG_PROTOCOL_GEN2,target, &option, &i, msg,accessPassword,true);+            msg[rec]=msg[rec]|option;+            SETU8(msg,i,0x00);+            SETU8(msg,i,(uint8_t)readLock);+            +            SETU8(msg,i,bank);+            SETU32(msg,i,blockPtr);+            SETU8(msg,i,(uint8_t)blockRange);+            +            if (readLock==0x01)+            {+              for(j=0;j<blockRange;j++)+              {+               SETU8(msg,i,(mask[j]>>8)&(0xff));+               SETU8(msg,i,(mask[j]>>0) & (0xff));+              }+            }+            msg[1] = i - 3;+            ret =  TMR_SR_send(reader, msg);+            if (TMR_SUCCESS != ret)+            {+              return ret;+            }+            if ((0 == readLock) && (NULL != data))+            {+              data->len = msg[1]-2;+              if (data->len > data->max)+              {+                data->len = data->max;+            }+              memcpy(data->list, msg+7, data->len);+            }+            return ret;+        }  +TMR_Status+TMR_SR_cmdVersion(TMR_Reader *reader, TMR_SR_VersionInfo *info)+{+  TMR_Status ret;+  uint8_t msg[TMR_SR_MAX_PACKET_SIZE];+  uint8_t i, j;+  uint32_t tTimeout = 0;++  tTimeout = reader->u.serialReader.transportTimeout;++  /**+   * If user not set any trasportTimeout value.+   * Use the default value.+   */+  if (false == reader->u.serialReader.usrTimeoutEnable)+  {+  reader->u.serialReader.transportTimeout = 100;+  }++  i = 2;+  SETU8(msg, i, TMR_SR_OPCODE_VERSION);+  msg[1] = i - 3; /* Install length */++  ret = TMR_SR_sendTimeout(reader, msg, 0);+  if (TMR_SUCCESS != ret)+  {+    reader->u.serialReader.transportTimeout = tTimeout;+    return ret;    +  }+  if (NULL != info)+  {+    i = 5;+    for (j = 0; j < 4 ; j++)+    {+      info->bootloader[j] = GETU8(msg, i);+    }+    for (j = 0; j < 4 ; j++)+    {+      info->hardware[j] = GETU8(msg, i);+    }+    for (j = 0; j < 4 ; j++)+    {+      info->fwDate[j] = GETU8(msg, i);+    }+    for (j = 0; j < 4 ; j++)+    {+      info->fwVersion[j] = GETU8(msg, i);+    }+    info->protocols = GETU32(msg, i);+  }++  reader->u.serialReader.transportTimeout = tTimeout;+  return TMR_SUCCESS;+}+++TMR_Status+TMR_SR_cmdBootFirmware(TMR_Reader *reader)+{+  TMR_Status ret;+  uint8_t msg[TMR_SR_MAX_PACKET_SIZE];+  uint8_t i, j;++  i = 2;+  SETU8(msg, i, TMR_SR_OPCODE_BOOT_FIRMWARE);+  msg[1] = i - 3; /* Install length */++  ret = TMR_SR_sendTimeout(reader, msg, 1000);+  if (TMR_SUCCESS != ret)+  {+    return ret;+  }++  i = 5;+  for (j = 0; j < 4 ; j++)+  {+    reader->u.serialReader.versionInfo.bootloader[j] = GETU8(msg, i);+  }+  for (j = 0; j < 4 ; j++)+  {+    reader->u.serialReader.versionInfo.hardware[j] = GETU8(msg, i);+  }+  for (j = 0; j < 4 ; j++)+  {+    reader->u.serialReader.versionInfo.fwDate[j] = GETU8(msg, i);+  }+  for (j = 0; j < 4 ; j++)+  {+    reader->u.serialReader.versionInfo.fwVersion[j] = GETU8(msg, i);+  }+  reader->u.serialReader.versionInfo.protocols = GETU32(msg, i);++  return TMR_SUCCESS;+}+++TMR_Status+TMR_SR_cmdSetBaudRate(TMR_Reader *reader, uint32_t rate)+{+  uint8_t msg[TMR_SR_MAX_PACKET_SIZE];+  uint8_t i;++  i = 2;+  SETU8(msg, i, TMR_SR_OPCODE_SET_BAUD_RATE);+  SETU32(msg, i, rate);+  msg[1] = i - 3; /* Install length */++  return TMR_SR_send(reader, msg);+}+++TMR_Status+TMR_SR_cmdEraseFlash(TMR_Reader *reader, uint8_t sector, uint32_t password)+{+  uint8_t msg[TMR_SR_MAX_PACKET_SIZE];+  uint8_t i;++  i = 2;+  SETU8(msg, i, TMR_SR_OPCODE_ERASE_FLASH);+  SETU32(msg, i, password);+  SETU8(msg, i, sector);+  msg[1] = i - 3; /* Install length */++  return TMR_SR_sendTimeout(reader, msg, 30000);+}+++TMR_Status+TMR_SR_cmdWriteFlashSector(TMR_Reader *reader, uint8_t sector, uint32_t address,+                           uint32_t password, uint8_t length, const uint8_t data[],+                           uint32_t offset)+{+  uint8_t msg[TMR_SR_MAX_PACKET_SIZE];+  uint8_t i;++  i = 2;+  SETU8(msg, i, TMR_SR_OPCODE_WRITE_FLASH_SECTOR);+  SETU32(msg, i, password);+  SETU32(msg, i, address);+  SETU8(msg, i, sector);+  memcpy(&msg[i], data + offset, length);+  i += length;+  msg[1] = i - 3; /* Install length */++  return TMR_SR_sendTimeout(reader, msg, 3000);+}++++TMR_Status+TMR_SR_cmdModifyFlashSector(TMR_Reader *reader, uint8_t sector, uint32_t address,+                            uint32_t password, uint8_t length, const uint8_t data[],+                            uint32_t offset)+{+  uint8_t msg[TMR_SR_MAX_PACKET_SIZE];+  uint8_t i;++  i = 2;+  SETU8(msg, i, TMR_SR_OPCODE_MODIFY_FLASH_SECTOR);+  SETU32(msg, i, password);+  SETU32(msg, i, address);+  SETU8(msg, i, sector);+  memcpy(&msg[i], data + offset, length);+  i += length;+  msg[1] = i - 3; /* Install length */++  return TMR_SR_sendTimeout(reader, msg, 3000);+}++TMR_Status+TMR_SR_cmdBootBootloader(TMR_Reader *reader)+{+  uint8_t msg[TMR_SR_MAX_PACKET_SIZE];+  uint8_t i;++  i = 2;+  SETU8(msg, i, TMR_SR_OPCODE_BOOT_BOOTLOADER);+  msg[1] = i - 3; /* Install length */++  reader->u.serialReader.crcEnabled = true;+  return TMR_SR_send(reader, msg);+}+++TMR_Status+TMR_SR_cmdGetHardwareVersion(TMR_Reader *reader, uint8_t option, uint8_t flags,+                             uint8_t* count, uint8_t data[])+{+  TMR_Status ret;+  uint8_t msg[TMR_SR_MAX_PACKET_SIZE];+  uint8_t i;++  i = 2;+  SETU8(msg, i, TMR_SR_OPCODE_HW_VERSION);+  SETU8(msg, i, option);+  SETU8(msg, i, flags);+  msg[1] = i - 3; /* Install length */++  ret = TMR_SR_send(reader, msg);+  if (TMR_SUCCESS != ret)+  {+    return ret;+  }++  for (i = 0 ; i < msg[1] && i < *count; i++)+  {+    data[i] = msg[5 + i];+  }++  *count = msg[1];++  return TMR_SUCCESS;+}+++TMR_Status+TMR_SR_cmdGetCurrentProgram(TMR_Reader *reader, uint8_t *program)+{+  TMR_Status ret;+  uint8_t msg[TMR_SR_MAX_PACKET_SIZE];+  uint8_t i;++  i = 2;+  SETU8(msg, i, TMR_SR_OPCODE_GET_CURRENT_PROGRAM);+  msg[1] = i - 3; /* Install length */++  ret = TMR_SR_send(reader, msg);+  *program = msg[5];++  return ret;+}++TMR_Status TMR_SR_msgSetupReadTagSingle(uint8_t *msg, uint8_t *i, TMR_TagProtocol protocol,TMR_TRD_MetadataFlag metadataFlags, const TMR_TagFilter *filter,uint16_t timeout)+{+  uint8_t optbyte;++  SETU8(msg, *i, TMR_SR_OPCODE_READ_TAG_ID_SINGLE);+  SETU16(msg, *i, timeout);+  optbyte = *i;+  SETU8(msg, *i, 0); /* Initialize option byte */+  msg[optbyte] |= TMR_SR_GEN2_SINGULATION_OPTION_FLAG_METADATA;+  SETU16(msg,*i, metadataFlags);+  filterbytes(protocol, filter, &msg[optbyte], i, msg,0, true);+  msg[optbyte] |= TMR_SR_GEN2_SINGULATION_OPTION_FLAG_METADATA;+  return TMR_SUCCESS;++}++TMR_Status+TMR_SR_msgSetupReadTagMultiple(TMR_Reader *reader, uint8_t *msg, uint8_t *i, uint16_t timeout,+                               TMR_SR_SearchFlag searchFlag,+                               const TMR_TagFilter *filter,+                               TMR_TagProtocol protocol,+                               TMR_GEN2_Password accessPassword)+{+  return TMR_SR_msgSetupReadTagMultipleWithMetadata(reader, msg, i, timeout,+    searchFlag, reader->userMetadataFlag, filter, protocol,accessPassword);+}+++TMR_Status+TMR_SR_msgSetupReadTagMultipleWithMetadata(TMR_Reader *reader, uint8_t *msg, uint8_t *i, uint16_t timeout,+                               TMR_SR_SearchFlag searchFlag,+							                 TMR_TRD_MetadataFlag metadataFlag,+                               const TMR_TagFilter *filter,+                               TMR_TagProtocol protocol,+                               TMR_GEN2_Password accessPassword)+{+  TMR_Status ret;+  TMR_SR_SerialReader *sr;+  uint8_t optbyte;+  +  sr = &reader->u.serialReader;+  sr->opCode = TMR_SR_OPCODE_READ_TAG_ID_MULTIPLE;+  ret = TMR_SUCCESS;++  SETU8(msg, *i, TMR_SR_OPCODE_READ_TAG_ID_MULTIPLE);++  /**+   * we need to add the option for bap parameters if enabled+   * +   * for adding the bap parameter option, and EBV technique is used+   * raising the lowest order bit of the high opder byte signals the+   * use of new Gen2 Bap support parameters.+   **/+  if (sr->isBapEnabled)+  {+    SETU8(msg,*i,0x81);+  }++  optbyte = *i;+  SETU8(msg, *i, 0); /* Initialize option byte */++  /* add the large tag population support */+  searchFlag= (TMR_SR_SearchFlag)(searchFlag | TMR_SR_SEARCH_FLAG_LARGE_TAG_POPULATION_SUPPORT);++  if (reader->continuousReading)+  {+    msg[optbyte] |= TMR_SR_GEN2_SINGULATION_OPTION_FLAG_METADATA;+    searchFlag = (TMR_SR_SearchFlag)(searchFlag+        | TMR_SR_SEARCH_FLAG_TAG_STREAMING);++    /**+     * We need to send a different flag for the new reader stats,+     * Both these options are mutually exclusive in nature,+     * Hence can not be raised at once.+     **/+    if (TMR_SR_STATUS_NONE != reader->streamStats)+    {+      searchFlag |= TMR_SR_SEARCH_FLAG_STATUS_REPORT_STREAMING;+    }+    else+    {+      if (TMR_READER_STATS_FLAG_NONE != reader->statsFlag)+      {+        searchFlag |= TMR_SR_SEARCH_FLAG_STATS_REPORT_STREAMING;+      }+    }+  }++  /**+   * Add the fast search flag depending on the user choice+   */+  if (reader->fastSearch)+  {+    searchFlag = (TMR_SR_SearchFlag)(searchFlag+      |TMR_SR_SEARCH_FLAG_READ_MULTIPLE_FAST_SEARCH);+    reader->fastSearch = false;+  }++  /**+   * Add the trigger read flag depending on the user choice+   */+  if (reader->triggerRead)+  {+    searchFlag = (TMR_SR_SearchFlag)(searchFlag+      |TMR_SR_SEARCH_FLAG_GPI_TRIGGER_READ);+    reader->triggerRead = false;+  }++  /**+   * Add the duty cycle flag depending on the user choice+   */+  if (reader->dutyCycle)+  {+    searchFlag = (TMR_SR_SearchFlag)(searchFlag+		|TMR_SR_SEARCH_FLAG_DUTY_CYCLE_CONTROL);+  }++  if (reader->isStopNTags && !reader->continuousReading)+  {+    /**+     * Currently stop N Trigger is only supported for+     * sync read.+     **/ +    searchFlag = (TMR_SR_SearchFlag)(searchFlag+        |TMR_SR_SEARCH_FLAG_RETURN_ON_N_TAGS);+  }++  SETU16(msg, *i, searchFlag);+  SETU16(msg, *i, timeout);+  if(reader->dutyCycle)+  {+	  uint32_t offtime;+	  ret = TMR_paramGet(reader,TMR_PARAM_READ_ASYNCOFFTIME,&offtime);+	  SETU16(msg, *i, (uint16_t)offtime);+  }+  reader->dutyCycle = false;+  if (reader->continuousReading)+  {+    SETU16(msg, *i, metadataFlag);++    if (TMR_READER_STATS_FLAG_NONE != reader->statsFlag)+    {+      /**+       * To extend the flag byte, an EBV technique is to be used.+       * When the highest order bit of the flag byte is used,+       * it signals the reader’s parser, that another flag byte is to follow+       */+      if ((0x80) > reader->statsFlag)+      {+        SETU16(msg, *i, (uint16_t)reader->statsFlag);+      }+      else+      {+        SETU16(msg, *i, ((uint16_t)reader->statsFlag));+      }+    }+    else+    {+      if (TMR_SR_STATUS_NONE != reader->streamStats)+      {+        /* Add status report flags, so that the status stream responses are received */+        SETU16(msg, *i, (uint16_t)reader->streamStats);+      }+    }+  }++  /**+   * Add the no of tags to be read requested by user+   * in stop N tag reads.Currently only supported for+   * sync read.+   **/+  if (reader->isStopNTags && !reader->continuousReading)+  {+    SETU32(msg ,*i, (uint32_t)reader->numberOfTagsToRead);+  }++  /*+   * Earlier, this filter bytes were skipped for a null filter and gen2 0 access password.+   * as the filterbytes it self has the checks internally, these were removed.+   * for some protocols (such as ISO180006B) the "null" filter is not zero-length, but we don't need to send+   * that with this command.+   */+  if (TMR_TAG_PROTOCOL_ISO180006B == protocol && NULL == filter)+  {+    /* ISO18000-6B should not include any filter arg bytes if null */+  }+  else+  {+    ret = filterbytes(protocol, filter, &msg[optbyte], i, msg,+        accessPassword, true);+  }++  if (reader->continuousReading)+  {+    msg[optbyte] |= TMR_SR_GEN2_SINGULATION_OPTION_FLAG_METADATA;+  }+	if (isSecureAccessEnabled)+  {+    msg[optbyte] |= TMR_SR_GEN2_SINGULATION_OPTION_SECURE_READ_DATA;+  }++  return ret;+}++TMR_Status+TMR_SR_cmdReadTagMultiple(TMR_Reader *reader, uint16_t timeout,+                          TMR_SR_SearchFlag searchFlag,+                          const TMR_TagFilter *filter, TMR_TagProtocol protocol,+                          uint32_t *tagCount)+{+  TMR_Status ret;+  TMR_SR_SerialReader *sr;+  uint8_t msg[TMR_SR_MAX_PACKET_SIZE];+  uint8_t i;++  i = 2;+  ret = TMR_SR_msgSetupReadTagMultiple(reader, msg, &i, timeout, searchFlag,+                                       filter, protocol, 0);+  if (TMR_SUCCESS != ret)+  {+    return ret;+  }+  msg[1] = i - 3; /* Install length */++  sr = &reader->u.serialReader;+  sr->opCode = TMR_SR_OPCODE_READ_TAG_ID_MULTIPLE;+  if (reader->continuousReading)+  {+    uint8_t opcode;+    ret = TMR_SR_sendMessage(reader, msg, &opcode, timeout);+    *tagCount = (uint32_t)0;+    return ret;+  }+  else+  {+    ret = TMR_SR_sendTimeout(reader, msg, timeout);+    if (TMR_SUCCESS != ret)+    {+      return ret;+    }++    if (NULL != tagCount)+    {+      if (4 == msg[1])+      {+        /* Plain 1-byte count: Reader without large-tag-population support */+        *tagCount = GETU8AT(msg, 8);+      }+      else if (5 == msg[1])+      {+        /* Later 1-byte count: ISO18k select option included in reply */+        *tagCount = GETU8AT(msg, 9);+      }+      else if (7 == msg[1])+      {+        /* Plain 4-byte count: Reader with large-tag-population support */+        *tagCount = GETU32AT(msg, 8);+      }+      else if (8 == msg[1])+      {+        /* Later 4-byte count: Large-tag-population support and ISO18k+         * select option included in reply.+         */+        *tagCount = GETU32AT(msg, 9);+      }+      else+      {+        return TMR_ERROR_PARSE;+      }+    }++    return TMR_SUCCESS;+  }+}+++TMR_Status+TMR_SR_executeEmbeddedRead(TMR_Reader *reader, uint8_t *msg, uint16_t timeout,+                           TMR_SR_MultipleStatus *status)+{+  TMR_Status ret;+  uint8_t i, len, index;+  uint8_t newMsg[TMR_SR_MAX_PACKET_SIZE];+    +  if (reader->continuousReading)+  {+    uint8_t opcode = TMR_SR_OPCODE_MULTI_PROTOCOL_TAG_OP;+    i = 2;+    SETU8(newMsg, i, opcode);  /* Opcode */+    +    /* Timeout should be zero for true continuous reading */+    SETU16(newMsg, i, 0);+    SETU8(newMsg, i, (uint8_t)0x1); /* TM Option 1, for continuous reading */+    SETU8(newMsg, i, (uint8_t)TMR_SR_OPCODE_READ_TAG_ID_MULTIPLE); /* sub command opcode */+    SETU16(newMsg, i, (uint16_t)0x0000); /* search flags, only 0x0001 is supported */+    SETU8(newMsg, i, (uint8_t)TMR_TAG_PROTOCOL_GEN2); /* protocol ID */++    len = msg[1];+    index = i;+    SETU8(newMsg, i, 0); /* Protocol command length (initialize to 0)*/++    /* Copy the protocol command including the command opcode (len + 1)*/+    memcpy(&newMsg[i], &msg[2], (size_t)(len + 1));+    i += len + 1;++    /* Insert the exact protocol command length */+    newMsg[index] = i - index - 2;++    /* Install the total packet length*/+    newMsg[1]=i - 3;    ++    ret = TMR_SR_sendMessage(reader, newMsg, &opcode, timeout);+    status->tagsFound = status->successCount = status->failureCount = 0;++    return ret;+  }+  else+  {+    uint16_t searchFlags = GETU16AT(msg, 4);++    ret = TMR_SR_sendTimeout(reader, msg, timeout);+    if (TMR_SUCCESS != ret)+    {+      return ret;+    }++    if (NULL != status)+    {+      int readIdx = 8;+      if ((TMR_SR_SEARCH_FLAG_LARGE_TAG_POPULATION_SUPPORT & searchFlags) &&+          ((TMR_SR_MODEL_M6E == reader->u.serialReader.versionInfo.hardware[0]) ||+           (TMR_SR_MODEL_M6E_I == reader->u.serialReader.versionInfo.hardware[0]) ||+           (TMR_SR_MODEL_M6E_NANO == reader->u.serialReader.versionInfo.hardware[0]) ||+          (TMR_SR_MODEL_MICRO == reader->u.serialReader.versionInfo.hardware[0])))+	    {+        /* Only in case of M6e, the tag length will be 4 bytes */+		    status->tagsFound = (uint16_t)GETU32AT(msg, readIdx);+		    readIdx += 4;+      }+	    else+	    {+		    status->tagsFound = GETU8AT(msg, readIdx);+		    readIdx += 1;+	    }+      readIdx += 2;+      status->successCount = GETU16AT(msg, readIdx);+      readIdx += 2;+      status->failureCount = GETU16AT(msg, readIdx);+      readIdx += 2;+    }+  }++  return TMR_SUCCESS;+}++void+TMR_SR_msgAddGEN2WriteTagEPC(uint8_t *msg, uint8_t *i, uint16_t timeout, uint8_t *epc, uint8_t count)+{+  SETU8(msg, *i, TMR_SR_OPCODE_WRITE_TAG_ID);+  SETU16(msg, *i, timeout); /* timeout */+  SETU16(msg, *i, 0); /* RFU 2 bytes */+  memcpy(&msg[*i], epc, count);+  *i += count;+}++void+TMR_SR_msgAddGEN2DataRead(uint8_t *msg, uint8_t *i, uint16_t timeout,+                      TMR_GEN2_Bank bank, uint32_t wordAddress, uint8_t len, uint8_t option, bool withMetaData)+{++  SETU8(msg, *i, TMR_SR_OPCODE_READ_TAG_DATA);+  SETU16(msg, *i, timeout);+  SETU8(msg, *i, option);  /* Options - initialize */+  if (withMetaData)+  {+    SETU16(msg, *i, 0x0000);  /* metadata flags - initialize */+  }+  SETU8(msg, *i, bank);+  SETU32(msg, *i, wordAddress);+  SETU8(msg, *i, len);+}+++void+TMR_SR_msgAddGEN2DataWrite(uint8_t *msg, uint8_t *i, uint16_t timeout,+                       TMR_GEN2_Bank bank, uint32_t address)+{++  SETU8(msg, *i, TMR_SR_OPCODE_WRITE_TAG_DATA);+  SETU16(msg, *i, timeout);+  SETU8(msg, *i, 0); /* Option - initialize */+  SETU32(msg, *i, address);+  SETU8(msg, *i, bank);+}+++void+TMR_SR_msgAddGEN2LockTag(uint8_t *msg, uint8_t *i, uint16_t timeout, uint16_t mask,+                         uint16_t action, TMR_GEN2_Password accessPassword)+{++  SETU8(msg, *i, TMR_SR_OPCODE_LOCK_TAG);+  SETU16(msg, *i, timeout);+  SETU8(msg, *i, 0);  /* Option - initialize */+  SETU32(msg, *i, accessPassword);+  SETU16(msg, *i, mask);+  SETU16(msg, *i, action);+}+++void+TMR_SR_msgAddGEN2KillTag(uint8_t *msg, uint8_t *i, uint16_t timeout,+                         TMR_GEN2_Password password)+{++  SETU8(msg, *i, TMR_SR_OPCODE_KILL_TAG);+  SETU16(msg, *i, timeout);+  SETU8(msg, *i, 0);  /* Option - initialize */+  SETU32(msg, *i, password);+  SETU8(msg, *i, 0);  /* RFU */+}++void+TMR_SR_msgAddGEN2BlockWrite(uint8_t *msg, uint8_t *i, uint16_t timeout,TMR_GEN2_Bank bank, uint32_t wordPtr, uint32_t wordCount, uint16_t* data, uint32_t accessPassword, TMR_TagFilter* target)+{+  uint8_t option=0,rec;      +  SETU8(msg,*i,TMR_SR_OPCODE_WRITE_TAG_SPECIFIC);+  SETU16(msg, *i,timeout);+  SETU8(msg,*i,0x00);//chip type+  rec=*i;+  SETU8(msg,*i,0x40);//option+  SETU8(msg,*i,0x00);+  SETU8(msg,*i,0xC7);+  filterbytes(TMR_TAG_PROTOCOL_GEN2, target, &option, i, msg,accessPassword,true);+  msg[rec]=msg[rec]|option;+  SETU8(msg,*i,0x00);+  SETU8(msg,*i,bank);+  SETU32(msg,*i,wordPtr);+  SETU8(msg,*i,(uint8_t)wordCount);+  {+    uint32_t iWord;+    for (iWord=0; iWord<wordCount; iWord++)+    {+      SETU8(msg, *i, ((data[iWord]>>8)&0xFF));+      SETU8(msg, *i, ((data[iWord]>>0)&0xFF));+    }+  }+}++void+TMR_SR_msgAddGEN2BlockPermaLock(uint8_t *msg, uint8_t *i, uint16_t timeout, uint32_t readLock, TMR_GEN2_Bank bank, uint32_t blockPtr, uint32_t blockRange, uint16_t* mask, uint32_t accessPassword,TMR_TagFilter* target)+{+  uint8_t option=0,rec;    +  SETU8(msg,*i,TMR_SR_OPCODE_ERASE_BLOCK_TAG_SPECIFIC);+  SETU16(msg,*i,timeout);+  SETU8(msg,*i,0x00);+  rec=*i;+  SETU8(msg,*i,0x40);+  SETU8(msg,*i,0x01);+  filterbytes(TMR_TAG_PROTOCOL_GEN2,target, &option, i, msg,accessPassword,true);+  msg[rec]=msg[rec]|option;+  SETU8(msg,*i,0x00);+  SETU8(msg,*i,(uint8_t)readLock);++  SETU8(msg,*i,bank);+  SETU32(msg,*i,blockPtr);+  SETU8(msg,*i,(uint8_t)blockRange);+  if (readLock==0x01)+  {+   SETU16(msg, *i, *mask);+  }++}++void+TMR_SR_msgAddGEN2BlockErase(uint8_t *msg, uint8_t *i, uint16_t timeout,+                            uint32_t wordPtr, TMR_GEN2_Bank bank, uint8_t wordCount,+                            uint32_t accessPassword, TMR_TagFilter* target)+{+  uint8_t option = 0, rec;++  SETU8(msg, *i, TMR_SR_OPCODE_ERASE_BLOCK_TAG_SPECIFIC);+  SETU16(msg, *i, timeout);+  SETU8(msg, *i, 0x00);++  rec = *i;+  SETU8(msg, *i, 0x40);+  SETU8(msg, *i, 0x00); /* Block erase */+  filterbytes(TMR_TAG_PROTOCOL_GEN2, target, &option, i, msg, accessPassword, true);+  msg[rec] = msg[rec] | option;++  SETU32(msg, *i, wordPtr);+  SETU8(msg, *i, bank);+  SETU8(msg,*i, wordCount);+}++TMR_Status+TMR_SR_cmdWriteGen2TagEpc(TMR_Reader *reader, const TMR_TagFilter *filter, TMR_GEN2_Password accessPassword, +					  uint16_t timeout, uint8_t count, const uint8_t *id, bool lock)+{+  TMR_Status ret;+  uint8_t msg[TMR_SR_MAX_PACKET_SIZE];+  uint8_t i, optbyte;++  i = 2;+  SETU8(msg, i, TMR_SR_OPCODE_WRITE_TAG_ID);+  SETU16(msg, i, timeout);+  optbyte = i;+  SETU8(msg, i, 0);+  ++  ret = filterbytes(TMR_TAG_PROTOCOL_GEN2, filter, &msg[optbyte], &i, msg,+                    accessPassword, true);+  if (TMR_SUCCESS != ret)+  {+    return ret;+  }++  if (0 == msg[optbyte])+  {+	  SETU8(msg, i, 0);  // Initialize second RFU byte to zero+  }++  if (i + count + 1 > TMR_SR_MAX_PACKET_SIZE)+  {+    return TMR_ERROR_TOO_BIG;+  }++  memcpy(&msg[i], id, count);+  i += count;+  msg[1] = i - 3; /* Install length */++  return TMR_SR_sendTimeout(reader, msg, timeout);+}+++TMR_Status+TMR_SR_cmdClearTagBuffer(TMR_Reader *reader)+{+  uint8_t msg[TMR_SR_MAX_PACKET_SIZE];+  uint8_t i;++  i = 2;+  SETU8(msg, i, TMR_SR_OPCODE_CLEAR_TAG_ID_BUFFER);+  msg[1] = i - 3; /* Install length */++  return TMR_SR_send(reader, msg);+}++TMR_Status TMR_SR_cmdGetTagsRemaining(TMR_Reader *reader, uint16_t *tagCount)+{+  uint8_t msg[TMR_SR_MAX_PACKET_SIZE];+  uint8_t i;+  TMR_Status ret;+	+  i = 2;+  SETU8(msg, i, TMR_SR_OPCODE_GET_TAG_ID_BUFFER);+  msg[1] = i-3; /* Install length */+  ret = TMR_SR_send(reader, msg);+  if (TMR_SUCCESS != ret)+  {+    return ret;+  }+  +  *tagCount = GETU16AT(msg, 7) - GETU16AT(msg, 5);+  return TMR_SUCCESS;+}++void+TMR_SR_parseMetadataFromMessage(TMR_Reader *reader, TMR_TagReadData *read, uint16_t flags,+                                uint8_t *i, uint8_t msg[])+{+  int msgEpcLen;++  read->metadataFlags = flags;+  read->tag.protocol = TMR_TAG_PROTOCOL_NONE;+  read->readCount = 0;+  read->rssi = 0;+  read->antenna = 0;+  read->phase = 0;+  read->frequency = 0;+  read->dspMicros = 0;+  read->timestampLow = 0;+  read->timestampHigh = 0;+  read->isAsyncRead = false;++  switch(reader->u.serialReader.versionInfo.hardware[0])+  {+  case TMR_SR_MODEL_M5E:+    read->gpioCount = 2;+    break;+  case TMR_SR_MODEL_M6E:+    read->gpioCount = 4;+    break;+  default:+    read->gpioCount = 4;+    break;+  }+    ++  /* Fill in tag data from response */+  if (flags & TMR_TRD_METADATA_FLAG_READCOUNT)+  {+    read->readCount = GETU8(msg, *i);+  }+  if (flags & TMR_TRD_METADATA_FLAG_RSSI)+  {+    read->rssi = (int8_t)GETU8(msg, *i);+  }+  if (flags & TMR_TRD_METADATA_FLAG_ANTENNAID)+  {+    read->antenna = GETU8(msg, *i);+  }+  if (flags & TMR_TRD_METADATA_FLAG_FREQUENCY)+  {+    read->frequency = GETU24(msg, *i);+  }+  if (flags & TMR_TRD_METADATA_FLAG_TIMESTAMP)+  {+    read->dspMicros = GETU32(msg, *i);+  }+  if (flags & TMR_TRD_METADATA_FLAG_PHASE)+  {+    read->phase = GETU16(msg, *i);+  }+  if (flags & TMR_TRD_METADATA_FLAG_PROTOCOL)+  {+    read->tag.protocol = (TMR_TagProtocol)GETU8(msg, *i);+  }+  if (flags & TMR_TRD_METADATA_FLAG_DATA)+  {+    int msgDataLen, copyLen;+    +    msgDataLen = tm_u8s_per_bits(GETU16(msg, *i));+    read->data.len = msgDataLen;+    copyLen = msgDataLen;+    if (copyLen > read->data.max)+    {+      copyLen = read->data.max;+    }+	if (NULL != read->data.list)+	{+      memcpy(read->data.list, &msg[*i], copyLen);+	}++  /**+   * if the gen2AllMemoryBankEnabled is enabled,+   * extract the values+   **/+  if (reader->u.serialReader.gen2AllMemoryBankEnabled)+  {+    uint16_t dataLength = read->data.len;+    uint8_t readOffSet = 0;+    uint8_t bank;+    uint16_t epcDataLength;+    while (dataLength != 0)+    {+      if (readOffSet >= dataLength)+        break;+      bank = ((read->data.list[readOffSet] >> 4) & 0x1F);+      epcDataLength = (read->data.list[readOffSet + 1] * 2);+      switch (bank)+      {+        case TMR_GEN2_BANK_EPC:+          {+            read->epcMemData.len = epcDataLength;+            if (epcDataLength > read->epcMemData.max)+            {+              epcDataLength = read->epcMemData.max;+            }+            if (NULL != read->epcMemData.list)+            {+              memcpy(read->epcMemData.list, (read->data.list + readOffSet + 2), epcDataLength);+            }+            readOffSet += (epcDataLength + 2);+            break;++          }+        case TMR_GEN2_BANK_RESERVED:+          {+            read->reservedMemData.len = epcDataLength;+            if (epcDataLength > read->epcMemData.max)+            {+              epcDataLength = read->reservedMemData.max;+            }+            if (NULL != read->reservedMemData.list)+            {+              memcpy(read->reservedMemData.list, (read->data.list + readOffSet + 2), epcDataLength);+            }+            readOffSet += (epcDataLength + 2);+            break;++          }+        case TMR_GEN2_BANK_TID:+          {+            read->tidMemData.len = epcDataLength;+            if (epcDataLength > read->tidMemData.max)+            {+              epcDataLength = read->tidMemData.max;+            }+            if (NULL != read->tidMemData.list)+            {+              memcpy(read->tidMemData.list, (read->data.list + readOffSet + 2), epcDataLength);+            }+            readOffSet += (epcDataLength + 2);+            break;++          }+        case TMR_GEN2_BANK_USER:+          {+            read->userMemData.len = epcDataLength;+            if (epcDataLength > read->userMemData.max)+            {+              epcDataLength = read->userMemData.max;+            }+            if (NULL != read->userMemData.list)+            {+              memcpy(read->userMemData.list, (read->data.list + readOffSet + 2), epcDataLength);+            }+            readOffSet += (epcDataLength + 2);+            break;++          }+        default:+          break;+      }+    }+  }+  /**+   * Now, we extracted all the values,+   * Disable the gen2AllMemoryBankEnabled option.+   **/+  reader->u.serialReader.gen2AllMemoryBankEnabled = false;++	*i += msgDataLen;+  }+  if (flags & TMR_TRD_METADATA_FLAG_GPIO_STATUS)+  {+    int j;+    uint8_t gpioByte=GETU8(msg, *i);+    for (j=0;j<read->gpioCount;j++) +    {+      read->gpio[j].id = j+1;+      read->gpio[j].high = (((gpioByte >> j)&0x1)== 1);+    }+  }++  msgEpcLen = tm_u8s_per_bits(GETU16(msg, *i));  +  if (TMR_TAG_PROTOCOL_ATA != read->tag.protocol)+  {+    /* ATA protocol does not have TAG CRC */+    msgEpcLen -= 2; /* Remove 2 bytes CRC*/+  }+  if (TMR_TAG_PROTOCOL_GEN2 == read->tag.protocol)+  {    +    read->tag.u.gen2.pc[0] = GETU8(msg, *i);+    read->tag.u.gen2.pc[1] = GETU8(msg, *i);+    msgEpcLen -= 2;+    read->tag.u.gen2.pcByteCount = 2;++    /* Add support for XPC bits+     * XPC_W1 is present, when the 6th most significant bit of PC word is set+     */+    if ((read->tag.u.gen2.pc[0] & 0x02) == 0x02)+    {+      /* When this bit is set, the XPC_W1 word will follow the PC word+       * Our TMR_Gen2_TagData::pc has enough space, so copying to the same.+       */+      read->tag.u.gen2.pc[2] = GETU8(msg, *i);+      read->tag.u.gen2.pc[3] = GETU8(msg, *i);+      msgEpcLen -= 2;                           /* EPC length will be length - 4(PC + XPC_W1)*/+      read->tag.u.gen2.pcByteCount += 2;        /* PC bytes are now 4*/++      if ((read->tag.u.gen2.pc[2] & 0x80) == 0x80)+      {+        /*+         * If the most siginificant bit of XPC_W1 is set, then there exists+         * XPC_W2. A total of 6  (PC + XPC_W1 + XPC_W2 bytes)+         */+        read->tag.u.gen2.pc[4] = GETU8(msg, *i);+        read->tag.u.gen2.pc[5] = GETU8(msg, *i);+        msgEpcLen -= 2;                       /* EPC length will be length - 6 (PC + XPC_W1 + XPC_W2)*/+        read->tag.u.gen2.pcByteCount += 2;    /* PC bytes are now 6 */+      }+    }    +  }+  read->tag.epcByteCount = msgEpcLen;+  if (read->tag.epcByteCount > TMR_MAX_EPC_BYTE_COUNT)+  {+    read->tag.epcByteCount = TMR_MAX_EPC_BYTE_COUNT;+  }++  memcpy(read->tag.epc, &msg[*i], read->tag.epcByteCount);+  *i += msgEpcLen;+  if (TMR_TAG_PROTOCOL_ATA != read->tag.protocol)+  {  +    read->tag.crc = GETU16(msg, *i);+  }+  else+  {+	read->tag.crc = 0xffff;+  }++  if(reader->continuousReading)+  {+    read->isAsyncRead = true;+  }+  else+  {+    read->isAsyncRead = false;+  }++}++void+TMR_SR_parseMetadataOnly(TMR_Reader *reader, TMR_TagReadData *read, uint16_t flags,+                                uint8_t *i, uint8_t msg[])+{+  read->metadataFlags = flags;+  read->tag.protocol = TMR_TAG_PROTOCOL_NONE;+  read->readCount = 0;+  read->rssi = 0;+  read->antenna = 0;+  read->phase = 0;+  read->frequency = 0;+  read->dspMicros = 0;+  read->timestampLow = 0;+  read->timestampHigh = 0;+  read->isAsyncRead = false;++  switch(reader->u.serialReader.versionInfo.hardware[0])+  {+  case TMR_SR_MODEL_M5E:+    read->gpioCount = 2;+    break;+  case TMR_SR_MODEL_M6E:+    read->gpioCount = 4;+    break;+  default:+    read->gpioCount = 4;+    break;+  }++  /* Fill in tag data from response */+  if (flags & TMR_TRD_METADATA_FLAG_READCOUNT)+  {+    read->readCount = GETU8(msg, *i);+  }+  if (flags & TMR_TRD_METADATA_FLAG_RSSI)+  {+    read->rssi = GETU8(msg, *i);+  }+  if (flags & TMR_TRD_METADATA_FLAG_ANTENNAID)+  {+    read->antenna = GETU8(msg, *i);+  }+  if (flags & TMR_TRD_METADATA_FLAG_FREQUENCY)+  {+    read->frequency = GETU24(msg, *i);+  }+  if (flags & TMR_TRD_METADATA_FLAG_TIMESTAMP)+  {+    read->dspMicros = GETU32(msg, *i);+  }+  if (flags & TMR_TRD_METADATA_FLAG_PHASE)+  {+    read->phase = GETU16(msg, *i);+  }+  if (flags & TMR_TRD_METADATA_FLAG_PROTOCOL)+  {+    read->tag.protocol = (TMR_TagProtocol)GETU8(msg, *i);+  }+  if (flags & TMR_TRD_METADATA_FLAG_DATA)+  {+    int msgDataLen, copyLen;++    msgDataLen = tm_u8s_per_bits(GETU16(msg, *i));+    read->data.len = msgDataLen;+    copyLen = msgDataLen;+    if (copyLen > read->data.max)+    {+      copyLen = read->data.max;+    }+    memcpy(read->data.list, &msg[*i], copyLen);+    *i += msgDataLen;+  }+  if (flags & TMR_TRD_METADATA_FLAG_GPIO_STATUS)+  {+    int j;+    uint8_t gpioByte=GETU8(msg, *i);+    for (j=0;j<read->gpioCount ;j++) +    {+      read->gpio[j].id = j+1;+      read->gpio[j].high = (((gpioByte >> j)&0x1)== 1);+    }+  }+}++void+TMR_SR_postprocessReaderSpecificMetadata(TMR_TagReadData *read, TMR_SR_SerialReader *sr)+{+  uint16_t j;+  uint32_t timestampLow;+  uint64_t currTime64, lastSentTagTime64; /*for comparison*/+  int32_t tempDiff;++  timestampLow = sr->readTimeLow;+  read->timestampHigh = sr->readTimeHigh;++  timestampLow = timestampLow + read->dspMicros;+  currTime64 = ((uint64_t)read->timestampHigh << 32) | timestampLow;+  lastSentTagTime64 = ((uint64_t)sr->lastSentTagTimestampHigh << 32) | sr->lastSentTagTimestampLow;+  if (lastSentTagTime64 >= currTime64)+  {+    tempDiff = (int32_t)(currTime64 - lastSentTagTime64);+    timestampLow = timestampLow - tempDiff + 1;+    if (timestampLow < sr->lastSentTagTimestampLow) /*account for overflow*/+    {+      read->timestampHigh++;+    }+  }+  if (timestampLow < sr->readTimeLow) /* Overflow */+  {+    read->timestampHigh++;+  }+  read->timestampLow = timestampLow;+  sr->lastSentTagTimestampHigh = read->timestampHigh;+  sr->lastSentTagTimestampLow = read->timestampLow;++  {+    uint8_t tx;+    uint8_t rx;+    tx = (read->antenna >> 4) & 0xF;+    rx = (read->antenna >> 0) & 0xF;++    // Due to limited space, Antenna 16 wraps around to 0+    if (0 == tx) { tx = 16; }+    if (0 == rx) { rx = 16; }++    for (j = 0; j < sr->txRxMap->len; j++)+    {+      if (rx == sr->txRxMap->list[j].rxPort &&+          tx == sr->txRxMap->list[j].txPort)+      {+        read->antenna = sr->txRxMap->list[j].antenna;+		if (read->gpioCount > 2)+		{+			if (read->gpio[2].high)+				read->antenna += 16;+		}+        break;+      }+    }+  }+}++#ifdef TMR_ENABLE_ISO180006B+TMR_Status+TMR_SR_cmdISO180006BReadTagData(TMR_Reader *reader,+                                uint16_t timeout, uint8_t address,+                                uint8_t length, const TMR_TagFilter *filter,+                                TMR_TagReadData *read)+{+  TMR_Status ret;+  uint8_t msg[TMR_SR_MAX_PACKET_SIZE];+  uint8_t copylen, i;++  if (length > 8+      || filter == NULL+      || TMR_FILTER_TYPE_TAG_DATA != filter->type+      || filter->u.tagData.epcByteCount != 8)+  {+    return TMR_ERROR_INVALID;+  }++  i = 2;+  SETU8(msg, i, TMR_SR_OPCODE_READ_TAG_DATA);+  SETU16(msg, i, timeout);+  SETU8(msg, i, 0x01); /* Standard read operations */+  SETU8(msg, i, TMR_SR_ISO180006B_COMMAND_READ);+  SETU8(msg, i, 0x00); /* RFU */+  SETU8(msg, i, length);+  SETU8(msg, i, address);+  memcpy(&msg[i], filter->u.tagData.epc, 8);+  i += 8;+  msg[1] = i - 3; /* Install length */++  ret = TMR_SR_sendTimeout(reader, msg, timeout);+  if (TMR_SUCCESS != ret)+  {+    return ret;+  }++  read->metadataFlags = TMR_TRD_METADATA_FLAG_DATA;+  read->tag.protocol = TMR_TAG_PROTOCOL_ISO180006B;+  read->tag.epcByteCount = 0;++  read->data.len = msg[1];+  copylen = (uint8_t)read->data.len;+  if (copylen > read->data.max)+  {+    copylen = (uint8_t)read->data.max;+  }+  if (NULL != read->data.list)+  {+    memcpy(read->data.list, &msg[5], copylen);+  }++  return TMR_SUCCESS;+}++TMR_Status+TMR_SR_cmdISO180006BWriteTagData(TMR_Reader *reader,+                                 uint16_t timeout, uint8_t address,+                                 uint8_t count, const uint8_t data[],+                                 const TMR_TagFilter *filter)+{+  TMR_Status ret;+  uint8_t msg[TMR_SR_MAX_PACKET_SIZE];+  uint8_t i;++  i = 2;++  SETU8(msg, i, TMR_SR_OPCODE_WRITE_TAG_DATA);+  SETU16(msg, i, timeout);+  if (NULL != filter+    && TMR_FILTER_TYPE_TAG_DATA == filter->type+    && filter->u.tagData.epcByteCount == 8)+  {+    SETU8(msg, i, +          TMR_SR_ISO180006B_WRITE_OPTION_READ_VERIFY_AFTER+          | TMR_SR_ISO180006B_WRITE_OPTION_COUNT_PROVIDED); +    SETU8(msg, i, TMR_SR_ISO180006B_COMMAND_WRITE4BYTE);+    SETU8(msg, i, TMR_SR_ISO180006B_WRITE_LOCK_NO);+    SETU8(msg, i, address);+    memcpy(&msg[i], filter->u.tagData.epc, 8);+    i += 8;+  }+  else+  {+    SETU8(msg, i, TMR_SR_ISO180006B_WRITE_OPTION_GROUP_SELECT +                  | TMR_SR_ISO180006B_WRITE_OPTION_COUNT_PROVIDED);+    SETU8(msg, i, TMR_SR_ISO180006B_COMMAND_WRITE4BYTE_MULTIPLE);+    SETU8(msg, i, TMR_SR_ISO180006B_WRITE_LOCK_NO);+    SETU8(msg, i, address);+    /* +     * Actually, we don't use password in case of iso.+     * passing 1, instead of '0' fixes the crash.+     */+    ret = filterbytes(TMR_TAG_PROTOCOL_ISO180006B, filter, NULL,+                      &i, msg, 1, false);+    if (TMR_SUCCESS != ret)+    {+      return ret;+    }+  }+  SETU16(msg, i, count);+  memcpy(&msg[i], data, count);+  i += count;+  msg[1] = i - 3; /* Install length */++  return TMR_SR_sendTimeout(reader, msg, timeout);++}+++TMR_Status+TMR_SR_cmdISO180006BLockTag(TMR_Reader *reader, uint16_t timeout,+                            uint8_t address, const TMR_TagFilter *filter)+{+  uint8_t msg[TMR_SR_MAX_PACKET_SIZE];+  uint8_t i;++  if (filter == NULL+      || TMR_FILTER_TYPE_TAG_DATA != filter->type+      || filter->u.tagData.epcByteCount != 8)+  {+    return TMR_ERROR_INVALID;+  }++  i = 2;+  SETU8(msg, i, TMR_SR_OPCODE_LOCK_TAG);+  SETU16(msg, i, timeout);+  SETU8(msg, i, TMR_SR_ISO180006B_LOCK_OPTION_TYPE_FOLLOWS);+  SETU8(msg, i, TMR_SR_ISO180006B_LOCK_TYPE_QUERYLOCK_THEN_LOCK);+  SETU8(msg, i, address);+  memcpy(&msg[i], filter->u.tagData.epc, 8);+  i += 8;+  msg[1] = i - 3; /* Install length */++  return TMR_SR_sendTimeout(reader, msg, timeout);+}+#endif /* TMR_ENABLE_ISO180006B */++TMR_Status+TMR_SR_cmdGEN2WriteTagData(TMR_Reader *reader,+                           uint16_t timeout, TMR_GEN2_Bank bank,+                           uint32_t address, uint8_t count,+                           const uint8_t data[],+                           TMR_GEN2_Password accessPassword,+                           const TMR_TagFilter *filter)+{+  TMR_Status ret;+  uint8_t msg[TMR_SR_MAX_PACKET_SIZE];+  uint8_t optbyte, i;++  i = 2;+  TMR_SR_msgAddGEN2DataWrite(msg, &i, timeout, bank, address);+  optbyte = 5;+  ret = filterbytes(TMR_TAG_PROTOCOL_GEN2, filter, &msg[optbyte], &i, msg,+                    accessPassword, true);+  if (TMR_SUCCESS != ret)+  {+    return ret;+  }+  if (i + count + 1 > TMR_SR_MAX_PACKET_SIZE)+  {+    return TMR_ERROR_TOO_BIG;+  }+  memcpy(&msg[i], data, count);+  i += count;+  msg[1] = i - 3; /* Install length */++  return TMR_SR_sendTimeout(reader, msg, timeout);+}++TMR_Status+TMR_SR_cmdGEN2LockTag(TMR_Reader *reader, uint16_t timeout,+                      uint16_t mask, uint16_t action, +                      TMR_GEN2_Password accessPassword, +                      const TMR_TagFilter *filter)+{+  TMR_Status ret;+  uint8_t msg[TMR_SR_MAX_PACKET_SIZE];+  uint8_t optbyte, i;++  i = 2;+  TMR_SR_msgAddGEN2LockTag(msg, &i, timeout, mask, action, accessPassword);+  optbyte = 5;+  ret = filterbytes(TMR_TAG_PROTOCOL_GEN2, filter, &msg[optbyte], &i, msg,+                    0, false);+  if (TMR_SUCCESS != ret)+  {+    return ret;+  }+  msg[1] = i - 3; /* Install length */++  return TMR_SR_sendTimeout(reader, msg, timeout);+}++TMR_Status+TMR_SR_cmdrebootReader(TMR_Reader *reader)+{+  TMR_Status ret;+  TMR_SR_SerialReader *sr;+  TMR_SR_SerialTransport *transport;++  sr = &reader->u.serialReader;+  transport = &sr->transport;++  /*+   * Drop baud to 9600 so we know for sure what it will be after going+   * back to the bootloader.  (Older firmwares always revert to 9600.+   * Newer ones keep the current baud rate.)+   */+  if (NULL != transport->setBaudRate)+  {+    /**+     * some transport layer does not support baud rate settings.+     * for ex: TCP transport. In that case skip the baud rate+     * settings.+     */ ++    ret = TMR_SR_cmdSetBaudRate(reader, 9600);+    if (TMR_SUCCESS != ret)+    {+      return ret;+    }+    ret = transport->setBaudRate(transport, 9600);+    if (TMR_SUCCESS != ret)+    {+      return ret;+    }+  }+  ret = TMR_SR_cmdBootBootloader(reader);+  if ((TMR_SUCCESS != ret)+      /* Invalid Opcode okay -- means "already in bootloader" */+      && (TMR_ERROR_INVALID_OPCODE != ret))+  {+    return ret;+  }++  /*+   * Wait for the bootloader to be entered. 200ms is enough.+   */+  tmr_sleep(200);++  return ret;+}++TMR_Status+TMR_SR_cmdKillTag(TMR_Reader *reader, uint16_t timeout,+                  TMR_GEN2_Password killPassword, +                  const TMR_TagFilter *filter)+{+  TMR_Status ret;+  uint8_t msg[TMR_SR_MAX_PACKET_SIZE];+  uint8_t optbyte, i;++  i = 2;+  TMR_SR_msgAddGEN2KillTag(msg, &i, timeout, killPassword);+  optbyte = 5;+  ret = filterbytes(TMR_TAG_PROTOCOL_GEN2, filter, &msg[optbyte], &i, msg, +                    0, false);+  if (TMR_SUCCESS != ret)+  {+    return ret;+  }+  msg[1] = i - 3; /* Install length */++  return TMR_SR_sendTimeout(reader, msg, timeout);+}+++TMR_Status+TMR_SR_cmdGEN2ReadTagData(TMR_Reader *reader,+                          uint16_t timeout, TMR_GEN2_Bank bank,+                          uint32_t address, uint8_t length,+                          uint32_t accessPassword, const TMR_TagFilter *filter,+                          TMR_TagReadData *read)+{+  TMR_Status ret;+  uint8_t msg[TMR_SR_MAX_PACKET_SIZE];+  uint8_t optbyte, i, mdfbyte;+  uint32_t starttimeHigh, starttimeLow;++  i = 2;+  TMR_SR_msgAddGEN2DataRead(msg, &i, timeout, bank, address, length, 0x00, true);+  optbyte = 5;+  ret = filterbytes(TMR_TAG_PROTOCOL_GEN2, filter, &msg[optbyte], &i, msg, +                    accessPassword, true);+++  msg[optbyte] |= 0x10;+  mdfbyte = 6;+  read->metadataFlags |= TMR_TRD_METADATA_FLAG_DATA | TMR_TRD_METADATA_FLAG_PROTOCOL;+  SETU16(msg, mdfbyte, read->metadataFlags);+++  if (TMR_SUCCESS != ret)+  {+    return ret;+  }+  msg[1] = i - 3; /* Install length */++  /* Cache the read time so it can be put in tag read data later */+  tm_gettime_consistent(&starttimeHigh, &starttimeLow);+  reader->u.serialReader.readTimeHigh = starttimeHigh;+  reader->u.serialReader.readTimeLow = starttimeLow;++  ret = TMR_SR_sendTimeout(reader, msg, timeout);+  if (TMR_SUCCESS != ret)+  {+    return ret;+  }++  if (NULL != read->data.list)+  {+  i = 8;+   +  TMR_SR_parseMetadataOnly(reader, read, read->metadataFlags , &i, msg);+  TMR_SR_postprocessReaderSpecificMetadata(read, &reader->u.serialReader);++  /* Read Tag Data doesn't put actual tag data inside the metadata fields.+   * Read the actual data here (remainder of response.) */+  {+    uint16_t dataLength;+    uint16_t copyLength;+    +    copyLength = dataLength = msg[1] + 5 - i;+    if (copyLength > read->data.max)+    {+      copyLength = read->data.max;+  }+    read->data.len = copyLength;+    memcpy(read->data.list, &msg[i], copyLength);+    i += dataLength;+  }+  }++  return TMR_SUCCESS;+}++TMR_Status+TMR_SR_cmdSetTxRxPorts(TMR_Reader *reader, uint8_t txPort, uint8_t rxPort)+{+  uint8_t msg[TMR_SR_MAX_PACKET_SIZE];+  uint8_t i;++  i = 2;+  SETU8(msg, i, TMR_SR_OPCODE_SET_ANTENNA_PORT);+  SETU8(msg, i, txPort);+  SETU8(msg, i, rxPort);+  msg[1] = i - 3; /* Install length */++  return TMR_SR_send(reader, msg);+}+++TMR_Status+TMR_SR_cmdSetAntennaSearchList(TMR_Reader *reader, uint8_t count,+                               const TMR_SR_PortPair *ports)+{+  uint8_t msg[TMR_SR_MAX_PACKET_SIZE];+  uint8_t i;+  uint8_t j;++  i = 2;+  SETU8(msg, i, TMR_SR_OPCODE_SET_ANTENNA_PORT);+  SETU8(msg, i, 2); /* logical antenna list option */+  for (j = 0; j < count ; j++)+  {+    SETU8(msg, i, ports[j].txPort);+    SETU8(msg, i, ports[j].rxPort);+  }+  msg[1] = i - 3; /* Install length */++  return TMR_SR_send(reader, msg);+}++TMR_Status+TMR_SR_cmdSetAntennaPortPowersAndSettlingTime(+  TMR_Reader *reader, uint8_t count, const TMR_SR_PortPowerAndSettlingTime *ports)+{+  uint8_t msg[TMR_SR_MAX_PACKET_SIZE];+  uint8_t j, i;++  i = 2;+  SETU8(msg, i, TMR_SR_OPCODE_SET_ANTENNA_PORT);+  SETU8(msg, i, 4); /* power and settling time option */++  for (j = 0; j < count; j++)+  {+    SETU8(msg, i, ports[j].port);+    SETS16(msg, i, (int16_t) ports[j].readPower);+    SETS16(msg, i, (int16_t)ports[j].writePower);+    SETU16(msg, i, ports[j].settlingTime);+  }+  msg[1] = i - 3; /* Install length */++  return TMR_SR_send(reader, msg);+}+++TMR_Status+TMR_SR_cmdSetReadTxPower(TMR_Reader *reader, int32_t power)+{+  uint8_t msg[TMR_SR_MAX_PACKET_SIZE];+  uint8_t i;++  i = 2;+  SETU8(msg, i, TMR_SR_OPCODE_SET_READ_TX_POWER);++  /** The read power should always be a 16 bit value */+  if (power > 32767 || power < -32768)+  {+    return TMR_ERROR_ILLEGAL_VALUE;+  }++  SETS16(msg,i, (int16_t)power);+  msg[1] = i - 3; /* Install length */++  return TMR_SR_send(reader, msg);+}+++TMR_Status+TMR_SR_cmdSetProtocol(TMR_Reader *reader, TMR_TagProtocol protocol)+{+  uint8_t msg[TMR_SR_MAX_PACKET_SIZE];+  uint8_t i;++  i = 2;+  SETU8(msg, i, TMR_SR_OPCODE_SET_TAG_PROTOCOL);+  SETU16(msg, i, protocol);+  msg[1] = i - 3; /* Install length */++  return TMR_SR_send(reader, msg);+}+++TMR_Status+TMR_SR_cmdSetWriteTxPower(TMR_Reader *reader, int32_t power)+{+  uint8_t msg[TMR_SR_MAX_PACKET_SIZE];+  uint8_t i;++  i = 2;+  SETU8(msg, i, TMR_SR_OPCODE_SET_WRITE_TX_POWER);++  /** The write power should always be a 16 bit value */+  if (power > 32767 || power < -32768)+  {+    return TMR_ERROR_ILLEGAL_VALUE;+  }++  SETS16(msg, i, (int16_t)power);+  msg[1] = i - 3; /* Install length */++  return TMR_SR_send(reader, msg);+}+++TMR_Status+TMR_SR_cmdSetFrequencyHopTable(TMR_Reader *reader, uint8_t count,+                               const uint32_t *table)+{+  uint8_t msg[TMR_SR_MAX_PACKET_SIZE];+  uint8_t i, j;++  i = 2;++  if (count > 62)+  {+    return TMR_ERROR_TOO_BIG;+  }++  SETU8(msg, i, TMR_SR_OPCODE_SET_FREQ_HOP_TABLE);+  for (j = 0; j < count; j++)+  {+    SETU32(msg, i, table[j]);+  }+  msg[1] = i - 3; /* Install length */++  return TMR_SR_send(reader, msg);+}+++TMR_Status+TMR_SR_cmdSetFrequencyHopTime(TMR_Reader *reader, uint32_t hopTime)+{+  uint8_t msg[TMR_SR_MAX_PACKET_SIZE];+  uint8_t i;++  i = 2;+  SETU8(msg, i, TMR_SR_OPCODE_SET_FREQ_HOP_TABLE);+  SETU8(msg, i, 1); /* hop time option */+  SETU32(msg, i, hopTime);+  msg[1] = i - 3; /* Install length */++  return TMR_SR_send(reader, msg);+}+++TMR_Status+TMR_SR_cmdSetGPIO(TMR_Reader *reader, uint8_t gpio, bool high)+{+  uint8_t msg[TMR_SR_MAX_PACKET_SIZE];+  uint8_t i;++  i = 2;+  SETU8(msg, i, TMR_SR_OPCODE_SET_USER_GPIO_OUTPUTS);+  SETU8(msg, i, gpio);+  SETU8(msg, i, (high == true));+  msg[1] = i - 3; /* Install length */++  return TMR_SR_send(reader, msg);+}+++TMR_Status+TMR_SR_cmdSetRegion(TMR_Reader *reader, TMR_Region region)+{+  uint8_t msg[TMR_SR_MAX_PACKET_SIZE];+  uint8_t i;++  i = 2;+  SETU8(msg, i, TMR_SR_OPCODE_SET_REGION);+  SETU8(msg, i, region);+  msg[1] = i - 3; /* Install length */++  return TMR_SR_send(reader, msg);+}+++TMR_Status+TMR_SR_cmdSetRegionLbt(TMR_Reader *reader, TMR_Region region, bool lbt)+{+  uint8_t msg[TMR_SR_MAX_PACKET_SIZE];+  uint8_t i;++  i = 2;+  SETU8(msg, i, TMR_SR_OPCODE_SET_REGION);+  SETU8(msg, i, region);+  SETU8(msg, i, lbt ? 1 : 0);+  msg[1] = i - 3; /* Install length */++  return TMR_SR_send(reader, msg);+}+++TMR_Status+TMR_SR_cmdSetPowerMode(TMR_Reader *reader, TMR_SR_PowerMode mode)+{+  uint8_t msg[TMR_SR_MAX_PACKET_SIZE];+  uint8_t i;++  i = 2;+  SETU8(msg, i, TMR_SR_OPCODE_SET_POWER_MODE);+  SETU8(msg, i, mode);+  msg[1] = i - 3; /* Install length */++  return TMR_SR_send(reader, msg);+}+++TMR_Status+TMR_SR_cmdSetUserMode(TMR_Reader *reader, TMR_SR_UserMode mode)+{+  uint8_t msg[TMR_SR_MAX_PACKET_SIZE];+  uint8_t i;++  i = 2;+  SETU8(msg, i, TMR_SR_OPCODE_SET_USER_MODE);+  SETU8(msg, i, mode);+  msg[1] = i - 3; /* Install length */++  return TMR_SR_send(reader, msg);+}+++TMR_Status+TMR_SR_cmdSetReaderConfiguration(TMR_Reader *reader, TMR_SR_Configuration key,+                                 const void *value)+{+	TMR_SR_SerialReader *sr = &reader->u.serialReader;+  uint8_t msg[TMR_SR_MAX_PACKET_SIZE];+  uint8_t i;++  i = 2;+  SETU8(msg, i, TMR_SR_OPCODE_SET_READER_OPTIONAL_PARAMS);+  SETU8(msg, i, 1); /* key-value form of command */+  SETU8(msg, i, key);++  switch (key)+  {+  case TMR_SR_CONFIGURATION_ANTENNA_CONTROL_GPIO:+    SETU8(msg, i, *(uint8_t *)value);+    break;+  case TMR_SR_CONFIGURATION_TRIGGER_READ_GPIO:+    SETU8(msg, i, *(uint8_t *)value);+    break;+++  case TMR_SR_CONFIGURATION_UNIQUE_BY_ANTENNA:+  case TMR_SR_CONFIGURATION_UNIQUE_BY_DATA:+  case TMR_SR_CONFIGURATION_UNIQUE_BY_PROTOCOL:+    SETU8(msg, i, *(bool *)value ? 0 : 1);+    break;+  case TMR_SR_CONFIGURATION_TRANSMIT_POWER_SAVE:+		if(TMR_SR_MODEL_MICRO == sr->versionInfo.hardware[0])+		{+			// Open loop power calibration+			SETU8(msg, i, *(bool *)value ? 2 : 1);+		}+		else+		{+			// Closed loop power calibration+			SETU8(msg, i, *(bool *)value ? 1 : 0);+		}+		break;+  case TMR_SR_CONFIGURATION_EXTENDED_EPC:+  case TMR_SR_CONFIGURATION_SAFETY_ANTENNA_CHECK:+  case TMR_SR_CONFIGURATION_SAFETY_TEMPERATURE_CHECK:+  case TMR_SR_CONFIGURATION_RECORD_HIGHEST_RSSI:+  case TMR_SR_CONFIGURATION_RSSI_IN_DBM:+  case TMR_SR_CONFIGURATION_SELF_JAMMER_CANCELLATION:+  case TMR_SR_CONFIGURATION_ENABLE_READ_FILTER:+  case TMR_SR_CONFIGURATION_SEND_CRC:+    SETU8(msg, i, *(bool *)value ? 1 : 0);+    break;++  case TMR_SR_CONFIGURATION_READ_FILTER_TIMEOUT:+    SETS32(msg, i, *(int32_t *)value);+    break;++  default:+    return TMR_ERROR_NOT_FOUND;+  }+  msg[1] = i - 3; /* Install length */++  return TMR_SR_send(reader, msg);+}++/**+ * Handles license key to enable protocol + *+ * @param reader The reader+ * @param option Option to set or erase the license key+ * @param key license key+ * @param key_len Length of license key or the key array+ * @param retData The response data+*/+++TMR_Status TMR_SR_cmdSetProtocolLicenseKey(TMR_Reader *reader, +										   TMR_SR_SetProtocolLicenseOption option, +										   uint8_t key[], int key_len,uint32_t *retData)+{+  uint8_t msg[TMR_SR_MAX_PACKET_SIZE];+  uint8_t i;+  TMR_Status ret;+  i = 2;+  SETU8(msg, i, TMR_SR_OPCODE_SET_PROTOCOL_LICENSEKEY);+  SETU8(msg, i, option);++  if(TMR_SR_SET_LICENSE_KEY == option)+  {+  memcpy(msg+i, key, key_len);+  i+= key_len;+  }++  msg[1] = i - 3; /* Install length */++  ret = TMR_SR_send(reader, msg);+  if (ret != TMR_SUCCESS)+  {+	  return ret;+  }++  reader->u.serialReader.versionInfo.protocols = 0x00;+  for (i = 0; i < msg[1] - 2 ; i += 2)+  {+	reader->u.serialReader.versionInfo.protocols |= (1 << (GETU8AT(msg, 7 + i) - 1)); +  }++  return TMR_SUCCESS;+}++TMR_Status+TMR_SR_cmdSetProtocolConfiguration(TMR_Reader *reader, TMR_TagProtocol protocol,+                                   TMR_SR_ProtocolConfiguration key,+                                   const void *value)+{+  uint8_t msg[TMR_SR_MAX_PACKET_SIZE];+  uint8_t i;+  uint8_t BLF = 0;++  i = 2;+  SETU8(msg, i, TMR_SR_OPCODE_SET_PROTOCOL_PARAM);+  SETU8(msg, i, protocol);+  if (TMR_TAG_PROTOCOL_GEN2 == key.protocol)+  {+    SETU8(msg, i, key.u.gen2);+    switch (key.u.gen2)+    {+    case TMR_SR_GEN2_CONFIGURATION_SESSION:+      SETU8(msg, i, *(TMR_GEN2_Session *)value);+      break;++    case TMR_SR_GEN2_CONFIGURATION_TAGENCODING:+      SETU8(msg, i, *(TMR_GEN2_TagEncoding *)value);+      break;++    case TMR_SR_GEN2_CONFIGURATION_LINKFREQUENCY:+	#ifndef	BARE_METAL+      switch (*(int *)value)+	#else+	  switch (*(TMR_GEN2_LinkFrequency *)value)+    #endif+      {+      case 40:+        BLF = 0x03;+        break;+      case 250:+        BLF = 0x00;+        break;+      case 320:+        BLF = 0x02;+        break;+      case 400:+        BLF = 0x02;+        break;+      case 640:+        BLF = 0x04;+        break;+      default:+        return TMR_ERROR_INVALID;+      }+      SETU8(msg, i, BLF);+      break;++    case TMR_SR_GEN2_CONFIGURATION_TARI:+      SETU8(msg, i, *(TMR_GEN2_Tari *)value);+      break;++	case TMR_SR_GEN2_CONFIGURATION_PROTCOLEXTENSION:+	  SETU8(msg, i, *(TMR_GEN2_ProtocolExtension *)value);+      break;+      +    case TMR_SR_GEN2_CONFIGURATION_TARGET:+      switch (*(TMR_GEN2_Target *)value)+      {+      case TMR_GEN2_TARGET_A:+        SETU16(msg, i, 0x0100);+        break;+      case TMR_GEN2_TARGET_B:+        SETU16(msg, i, 0x0101);+        break;+      case TMR_GEN2_TARGET_AB:+        SETU16(msg, i, 0x0000);+        break;+      case TMR_GEN2_TARGET_BA:+        SETU16(msg, i, 0x0001);+        break;+      default:+        return TMR_ERROR_INVALID;+      }+      break;+      +    case TMR_SR_GEN2_CONFIGURATION_Q:+    {+      const TMR_SR_GEN2_Q *q = value;+      if (q->type == TMR_SR_GEN2_Q_DYNAMIC)+      {+        SETU8(msg, i, 0);+      }+      else if (q->type == TMR_SR_GEN2_Q_STATIC)+      {+        SETU8(msg, i, 1);+        SETU8(msg, i, q->u.staticQ.initialQ);+      }+      else+      {+        return TMR_ERROR_INVALID;+      }+      break;+    }++    case TMR_SR_GEN2_CONFIGURATION_BAP:+    {+      TMR_GEN2_Bap *bap;+      bap = (TMR_GEN2_Bap *)value;++      SETU8(msg, i, 0x01); //version+      SETU16(msg, i, 0x03);// currently we supports only this enable bits.+      SETU32(msg, i, bap->powerUpDelayUs);+      SETU32(msg, i, bap->freqHopOfftimeUs);+      /**+       * Currently support for M value and FlexQueryPayload has been disabled+       * TO DO: add support for these parameters when firmware support has added for this.+       **/ +      break;+    }++    default:+      return TMR_ERROR_NOT_FOUND;+    }+  }+#ifdef TMR_ENABLE_ISO180006B+  else if (TMR_TAG_PROTOCOL_ISO180006B == key.protocol +           || TMR_TAG_PROTOCOL_ISO180006B_UCODE == key.protocol)+  {+    switch (key.u.iso180006b)+    {+    case TMR_SR_ISO180006B_CONFIGURATION_LINKFREQUENCY:+      {+      switch (*(int *)value)+      {+      case 40:+        BLF = 0x01;+        break;+      case 160:+        BLF = 0x00;+        break;+      default:+        return TMR_ERROR_INVALID;+      }+        break;+      }+    case TMR_SR_ISO180006B_CONFIGURATION_MODULATION_DEPTH:+      {+        switch (*(int *)value)+        {+        case 0:+          BLF = TMR_ISO180006B_Modulation99percent;+          break;+        case 1:+          BLF = TMR_ISO180006B_Modulation11percent;+          break;+        default:+          return TMR_ERROR_INVALID;+        }+        break;+      }+    case TMR_SR_ISO180006B_CONFIGURATION_DELIMITER:+      {+        switch (*(int *)value)+        {+        case 1:+          BLF = TMR_ISO180006B_Delimiter1;+          break;+        case 4:+          BLF = TMR_ISO180006B_Delimiter4;+          break;+        default:+          return  TMR_ERROR_INVALID;+        }+        break;+      }+    default:+      return TMR_ERROR_NOT_FOUND;+    }++    SETU8(msg, i, key.u.iso180006b);+    SETU8(msg, i, BLF);+  }+#endif /* TMR_ENABLE_ISO180006B */+  else+  {+    return TMR_ERROR_INVALID;+  }++  msg[1] = i - 3; /* Install length */+  return TMR_SR_send(reader, msg);+}+++TMR_Status TMR_SR_cmdGetTxRxPorts(TMR_Reader *reader, TMR_SR_PortPair *ant)+{+  TMR_Status ret;+  uint8_t msg[TMR_SR_MAX_PACKET_SIZE];+  uint8_t i;++  i = 2;++  SETU8(msg, i, TMR_SR_OPCODE_GET_ANTENNA_PORT);+  SETU8(msg, i, 0); /* just configured ports */+  msg[1] = i - 3; /* Install length */++  ret = TMR_SR_send(reader, msg);+  if (TMR_SUCCESS != ret)+  {+    return ret;+  }++  ant->txPort = msg[5];+  ant->rxPort = msg[6];+  +  return TMR_SUCCESS;+}++TMR_Status+TMR_SR_cmdAntennaDetect(TMR_Reader *reader, uint8_t *count,+                        TMR_SR_PortDetect *ports)+{+  TMR_Status ret;+  uint8_t msg[TMR_SR_MAX_PACKET_SIZE];+  uint8_t i, j; ++  i = 2;+  SETU8(msg, i, TMR_SR_OPCODE_GET_ANTENNA_PORT);+  SETU8(msg, i, 5); /* antenna detect option */+  msg[1] = i - 3; /* Install length */++  ret = TMR_SR_send(reader, msg);+  if (TMR_SUCCESS != ret)+  {+    return ret;+  }++  +  for (i = 1, j = 0; i < msg[1] && j < *count; i += 2, j++)+  {+    ports[j].port = msg[i + 5];+    ports[j].detected = (msg[i + 6] == 1);+  }+  *count = j;++  return TMR_SUCCESS;+}+++TMR_Status+TMR_SR_cmdGetAntennaPortPowersAndSettlingTime(+  TMR_Reader *reader, uint8_t *count, TMR_SR_PortPowerAndSettlingTime *ports)+{+  TMR_Status ret;+  uint8_t msg[TMR_SR_MAX_PACKET_SIZE];+  uint8_t i, j;++  i = 2;+  SETU8(msg, i, TMR_SR_OPCODE_GET_ANTENNA_PORT);+  SETU8(msg, i, 4); /* power and settling time option */+  msg[1] = i - 3; /* Install length */++  ret = TMR_SR_send(reader, msg);+  if (TMR_SUCCESS != ret)+  {+    return ret;+  }++  +  for (i = 1, j = 0; i < msg[1] && j < *count; i += 7, j++)+  {+    ports[j].port = GETU8AT(msg, i + 5);+    ports[j].readPower = (int16_t)GETS16AT(msg, i + 6);+    ports[j].writePower = (int16_t)GETS16AT(msg, i + 8);+    ports[j].settlingTime = GETU16AT(msg, i + 10);+  }+  *count = j;++  return TMR_SUCCESS;+}++TMR_Status+TMR_SR_cmdGetAntennaReturnLoss(TMR_Reader *reader, TMR_PortValueList *ports)+{+  TMR_Status ret;+  uint8_t msg[TMR_SR_MAX_PACKET_SIZE];+  uint8_t i, j, count;++  count = TMR_SR_MAX_ANTENNA_PORTS;++  i = 2;+  SETU8(msg, i, TMR_SR_OPCODE_GET_ANTENNA_PORT);+  SETU8(msg, i, 6); /* antenna return loss option */+  msg[1] = i - 3; /* Install length */++  ret = TMR_SR_send(reader, msg);+  if (TMR_SUCCESS != ret)+  {+    return ret;+  }+  +  for (i = 1, j = 0; i < msg[1] && j < count; i += 2, j++)+  {+    if (j < ports->max)+    {+      ports->list[j].port = (uint8_t)GETU8AT(msg, i + 5);+      ports->list[j].value = (int16_t)GETU8AT(msg, i + 6);+    }+    else+    {+      /* no sufficent memory, break from here */+      break;+    }+  }+  ports->len = (uint8_t)j;++  return TMR_SUCCESS;+}++TMR_Status+TMR_SR_cmdGetReadTxPower(TMR_Reader *reader, int32_t *power)+{+  TMR_Status ret;+  uint8_t msg[TMR_SR_MAX_PACKET_SIZE];+  uint8_t i;++  i = 2;+  SETU8(msg, i, TMR_SR_OPCODE_GET_READ_TX_POWER);+  SETU8(msg, i, 0); /* just return power */+  msg[1] = i - 3; /* Install length */++  ret = TMR_SR_send(reader, msg);+  if (TMR_SUCCESS != ret)+  {+    return ret;+  }++  *power = (int32_t)GETS16AT(msg, 6);++  return TMR_SUCCESS;+}+++TMR_Status+TMR_SR_cmdGetReadTxPowerWithLimits(TMR_Reader *reader,+                                   TMR_SR_PowerWithLimits *power)+{+  TMR_Status ret;+  uint8_t msg[TMR_SR_MAX_PACKET_SIZE];+  uint8_t i;++  i = 2;+  SETU8(msg, i, TMR_SR_OPCODE_GET_READ_TX_POWER);+  SETU8(msg, i, 1); /* return limits */+  msg[1] = i - 3; /* Install length */++  ret = TMR_SR_send(reader, msg);+  if (TMR_SUCCESS != ret)+  {+    return ret;+  }++  power->setPower = GETU16AT(msg, 6);+  power->maxPower = GETU16AT(msg, 8);+  power->minPower = GETU16AT(msg, 10);++  return TMR_SUCCESS;+}+++TMR_Status+TMR_SR_cmdGetWriteTxPower(TMR_Reader *reader, int32_t *power)+{+  TMR_Status ret;+  uint8_t msg[TMR_SR_MAX_PACKET_SIZE];+  uint8_t i;++  i = 2;+  SETU8(msg, i, TMR_SR_OPCODE_GET_WRITE_TX_POWER);+  SETU8(msg, i, 0); /* just return power */+  msg[1] = i - 3; /* Install length */++  ret = TMR_SR_send(reader, msg);+  if (TMR_SUCCESS != ret)+  {+    return ret;+  }++  *power = (int32_t)GETS16AT(msg, 6);++  return TMR_SUCCESS;+}+++TMR_Status+TMR_SR_cmdGetFrequencyHopTable(TMR_Reader *reader, uint8_t *count,+                               uint32_t *hopTable)+{+  TMR_Status ret;+  uint8_t msg[TMR_SR_MAX_PACKET_SIZE];+  uint8_t i, j, len;++  i = 2;+  SETU8(msg, i, TMR_SR_OPCODE_GET_FREQ_HOP_TABLE);+  msg[1] = i - 3; /* Install length */++  ret = TMR_SR_send(reader, msg);+  if (TMR_SUCCESS != ret)+  {+    return ret;+  }++  len = msg[1] / 4;+  for (j = 0; i < *count && j < len ; j++)+  {+    hopTable[j] = GETU32AT(msg, 5 + 4*j);+  }+  *count = len;++  return TMR_SUCCESS;+}+++TMR_Status+TMR_SR_cmdGetFrequencyHopTime(TMR_Reader *reader, uint32_t *hopTime)+{+  TMR_Status ret;+  uint8_t msg[TMR_SR_MAX_PACKET_SIZE];+  uint8_t i;++  i = 2;+  SETU8(msg, i, TMR_SR_OPCODE_GET_FREQ_HOP_TABLE);+  SETU8(msg, i, 1); /* get time */+  msg[1] = i - 3; /* Install length */++  ret = TMR_SR_send(reader, msg);+  if (TMR_SUCCESS != ret)+  {+    return ret;+  }++  *hopTime = GETU32AT(msg, 6);++  return TMR_SUCCESS;+}+++TMR_Status+TMR_SR_cmdGetGPIO(TMR_Reader *reader, uint8_t *count, TMR_GpioPin *state)+{+  TMR_Status ret;+  uint8_t msg[TMR_SR_MAX_PACKET_SIZE] = {0};+  uint8_t i, j, len, offset;++  i = 2;+  SETU8(msg, i, TMR_SR_OPCODE_GET_USER_GPIO_INPUTS);+  SETU8(msg, i, 0x01);  // option+  msg[1] = i - 3; /* Install length */++  ret = TMR_SR_sendTimeout(reader, msg, reader->u.serialReader.commandTimeout);+  if (TMR_SUCCESS != ret)+    return ret;++  len = (msg[1] - 1)/3;+  if (len > *count)+  {+    len = *count;+  }++  offset = 6;+  for (j = 0; j < len ; j++)+  {+    state[j].id = msg[offset++];+    state[j].output = (1 == msg[offset++]) ? true : false;+    state[j].high = (1 == msg[offset++]) ? true : false;+  }+  *count = len;++  return TMR_SUCCESS;+}++TMR_Status+TMR_SR_cmdGetGPIODirection(TMR_Reader *reader, uint8_t pin, bool *out)+{+  TMR_Status ret;+  uint8_t msg[TMR_SR_MAX_PACKET_SIZE];+  uint8_t i;++  i = 2;+  SETU8(msg, i, TMR_SR_OPCODE_SET_USER_GPIO_OUTPUTS);+  SETU8(msg, i, pin);+  msg[1] = i - 3; /* Install length */++  ret = TMR_SR_send(reader, msg);+  if (TMR_SUCCESS != ret)+    return ret;++  *out = (msg[6] == 1);++  return TMR_SUCCESS;+}+++TMR_Status+TMR_SR_cmdSetGPIODirection(TMR_Reader *reader, uint8_t pin, bool out)+{+  TMR_Status ret;+  uint8_t msg[TMR_SR_MAX_PACKET_SIZE];+  uint8_t i;++  i = 2;+  SETU8(msg, i, TMR_SR_OPCODE_SET_USER_GPIO_OUTPUTS);+  SETU8(msg, i, 1); /* Option flag */+  SETU8(msg, i, pin);+  SETU8(msg, i, (out == true) ? 1 : 0);+  SETU8(msg, i, 0); /* New value if output */+  msg[1] = i - 3; /* Install length */++  ret = TMR_SR_send(reader, msg);+  if (TMR_SUCCESS != ret)+    return ret;++  return TMR_SUCCESS;+}++TMR_Status +TMR_SR_cmdGetCurrentProtocol(TMR_Reader *reader, TMR_TagProtocol *protocol)+{+  TMR_Status ret;+  uint8_t msg[TMR_SR_MAX_PACKET_SIZE];+  uint8_t i;++  i = 2;+  SETU8(msg, i, TMR_SR_OPCODE_GET_TAG_PROTOCOL);+  msg[1] = i - 3; /* Install length */++  ret = TMR_SR_send(reader, msg);+  if (TMR_SUCCESS != ret)+  {+    return ret;+  }+  *protocol = (TMR_TagProtocol)GETU16AT(msg, 5);++  return TMR_SUCCESS;+}++TMR_Status+TMR_SR_cmdGetRegion(TMR_Reader *reader, TMR_Region *region)+{+  TMR_Status ret;+  uint8_t msg[TMR_SR_MAX_PACKET_SIZE];+  uint8_t i;+  +  i = 2;+  SETU8(msg, i, TMR_SR_OPCODE_GET_REGION);+  msg[1] = i - 3; /* Install length */+  +  ret = TMR_SR_send(reader, msg);+  if (TMR_SUCCESS != ret)+  {+    return ret;+  }+  *region = (TMR_Region)GETU8AT(msg, 5);+  +  return TMR_SUCCESS;+}++TMR_Status+TMR_SR_cmdGetRegionConfiguration(TMR_Reader *reader,+                                 TMR_SR_RegionConfiguration key,+                                 void *value)+{+  TMR_Status ret;+  uint8_t msg[TMR_SR_MAX_PACKET_SIZE];+  uint8_t i;++  i = 2;+  SETU8(msg, i, TMR_SR_OPCODE_GET_REGION);+  SETU8(msg, i, 1);+  SETU8(msg, i, key);+  msg[1] = i - 3; /* Install length */++  ret = TMR_SR_send(reader, msg);+  if (TMR_SUCCESS != ret)+  {+    return ret;+  }++  switch (key)+  {+  case TMR_SR_REGION_CONFIGURATION_LBT_ENABLED:+    *(bool *)value = (GETU8AT(msg, 8) == 1);+    break;+  default:+    return TMR_ERROR_NOT_FOUND;+  }++  return TMR_SUCCESS;+}+++TMR_Status+TMR_SR_cmdGetPowerMode(TMR_Reader *reader, TMR_SR_PowerMode *mode)+{+  TMR_Status ret;+  uint8_t msg[TMR_SR_MAX_PACKET_SIZE];+  uint8_t i;++  i = 2;+  SETU8(msg, i, TMR_SR_OPCODE_GET_POWER_MODE);+  msg[1] = i - 3; /* Install length */++  ret = TMR_SR_send(reader, msg);+  if (TMR_SUCCESS != ret)+  {+    return ret;+  }++  *mode = (TMR_SR_PowerMode)GETU8AT(msg, 5);++  return TMR_SUCCESS;+}+++TMR_Status+TMR_SR_cmdGetUserMode(TMR_Reader *reader, TMR_SR_UserMode *mode)+{+  TMR_Status ret;+  uint8_t msg[TMR_SR_MAX_PACKET_SIZE];+  uint8_t i;++  i = 2;+  SETU8(msg, i, TMR_SR_OPCODE_GET_USER_MODE);+  msg[1] = i - 3; /* Install length */++  ret = TMR_SR_send(reader, msg);+  if (TMR_SUCCESS != ret)+  {+    return ret;+  }++  *mode = (TMR_SR_UserMode)GETU8AT(msg, 5);++  return TMR_SUCCESS;+}+++TMR_Status+TMR_SR_cmdGetReaderConfiguration(TMR_Reader *reader, TMR_SR_Configuration key,+                                 void *value)+{+	TMR_SR_SerialReader *sr = &reader->u.serialReader;+  TMR_Status ret;+  uint8_t msg[TMR_SR_MAX_PACKET_SIZE];+  uint8_t i;++  i = 2;+  SETU8(msg, i, TMR_SR_OPCODE_GET_READER_OPTIONAL_PARAMS);+  SETU8(msg, i, 1); /* key-value form of command */+  SETU8(msg, i, key);+  msg[1] = i - 3; /* Install length */++  ret = TMR_SR_send(reader, msg);+  if (TMR_SUCCESS != ret)+  {+    return ret;+  }++  switch (key)+  {+  case TMR_SR_CONFIGURATION_ANTENNA_CONTROL_GPIO:+    *(uint8_t *)value = GETU8AT(msg, 7);+    break;+  case TMR_SR_CONFIGURATION_TRIGGER_READ_GPIO:+    *(uint8_t *)value = GETU8AT(msg, 7);+    break;++  case TMR_SR_CONFIGURATION_UNIQUE_BY_ANTENNA:+  case TMR_SR_CONFIGURATION_UNIQUE_BY_DATA:+  case TMR_SR_CONFIGURATION_UNIQUE_BY_PROTOCOL:+    *(bool *)value = (GETU8AT(msg, 7) == 0);+    break;+  case TMR_SR_CONFIGURATION_TRANSMIT_POWER_SAVE:+		if(TMR_SR_MODEL_MICRO == sr->versionInfo.hardware[0])+		{+			if(GETU8AT(msg, 7) == 2)+			{+				//Open loop power calibration+				*(bool *)value = 1;+			}+			else+			{+				//Closed loop power calibration+				*(bool *)value = 0;+			}+		}+		else+		{+			*(bool *)value = (GETU8AT(msg, 7) == 1);+		}+		break;+  case TMR_SR_CONFIGURATION_EXTENDED_EPC:+  case TMR_SR_CONFIGURATION_SAFETY_ANTENNA_CHECK:+  case TMR_SR_CONFIGURATION_SAFETY_TEMPERATURE_CHECK:+  case TMR_SR_CONFIGURATION_RECORD_HIGHEST_RSSI:+  case TMR_SR_CONFIGURATION_RSSI_IN_DBM:+  case TMR_SR_CONFIGURATION_SELF_JAMMER_CANCELLATION:+  case TMR_SR_CONFIGURATION_ENABLE_READ_FILTER:+  case TMR_SR_CONFIGURATION_SEND_CRC:+    *(bool *)value = (GETU8AT(msg, 7) == 1);+    break;+  case TMR_SR_CONFIGURATION_CURRENT_MSG_TRANSPORT:+    *(uint8_t *)value = GETU8AT(msg, 7) ;+    break;+  case TMR_SR_CONFIGURATION_READ_FILTER_TIMEOUT:+    *(uint32_t *)value = GETU32AT(msg, 7);+    break;++  case TMR_SR_CONFIGURATION_PRODUCT_GROUP_ID:+    *(uint16_t *)value = GETU16AT(msg, 7);+    break;++  case TMR_SR_CONFIGURATION_PRODUCT_ID:+    *(uint16_t *)value = GETU16AT(msg, 7);+    break;++  default:+    return TMR_ERROR_NOT_FOUND;+  }++  return TMR_SUCCESS;+}++TMR_Status+TMR_SR_cmdGetProtocolConfiguration(TMR_Reader *reader, TMR_TagProtocol protocol,+                                   TMR_SR_ProtocolConfiguration key,+                                   void *value)+{+  TMR_Status ret;+  uint8_t msg[TMR_SR_MAX_PACKET_SIZE];+  uint8_t i;++  i = 2;+  SETU8(msg, i, TMR_SR_OPCODE_GET_PROTOCOL_PARAM);+  SETU8(msg, i, protocol);+  if (TMR_TAG_PROTOCOL_GEN2 == key.protocol)+  {+    SETU8(msg, i, key.u.gen2);+  }+#ifdef TMR_ENABLE_ISO180006B+  else if (TMR_TAG_PROTOCOL_ISO180006B == key.protocol +           || TMR_TAG_PROTOCOL_ISO180006B_UCODE == key.protocol)+  {+    SETU8(msg, i, key.u.iso180006b);+  }+#endif+  else+  {+    return TMR_ERROR_INVALID;+  }+  msg[1] = i - 3; /* Install length */++  ret = TMR_SR_send(reader, msg);+  if (TMR_SUCCESS != ret)+  {+    return ret;+  }++  if (TMR_TAG_PROTOCOL_GEN2 == key.protocol)+  {+    switch (key.u.gen2)+    {+    case TMR_SR_GEN2_CONFIGURATION_SESSION:+      *(TMR_GEN2_Session *)value = (TMR_GEN2_Session)GETU8AT(msg, 7);+      break;++    case TMR_SR_GEN2_CONFIGURATION_TAGENCODING:+      *(TMR_GEN2_TagEncoding *)value = (TMR_GEN2_TagEncoding)GETU8AT(msg, 7);+      break;++    case TMR_SR_GEN2_CONFIGURATION_LINKFREQUENCY:+      *(TMR_GEN2_LinkFrequency *)value = (TMR_GEN2_LinkFrequency)GETU8AT(msg, 7);+      break;++    case TMR_SR_GEN2_CONFIGURATION_TARI:+      *(TMR_GEN2_Tari *)value = (TMR_GEN2_Tari)GETU8AT(msg, 7);+      break;++	case TMR_SR_GEN2_CONFIGURATION_PROTCOLEXTENSION:+	  *(TMR_GEN2_ProtocolExtension *)value = (TMR_GEN2_ProtocolExtension)GETU8AT(msg, 7);+      break;++    case TMR_SR_GEN2_CONFIGURATION_BAP:+      {+        TMR_GEN2_Bap *b = value;++        i = 10;+        b->powerUpDelayUs = GETU32(msg,i);+        b->freqHopOfftimeUs = GETU32(msg,i);+        break;+      }++    case TMR_SR_GEN2_CONFIGURATION_TARGET:+      {+        uint16_t target;++        target = GETU16AT(msg, 7);+        switch (target)+        {+        case 0x0100:+          *(TMR_GEN2_Target *)value = TMR_GEN2_TARGET_A;+          break;+        case 0x0101:+          *(TMR_GEN2_Target *)value = TMR_GEN2_TARGET_B;+          break;+        case 0x0000:+          *(TMR_GEN2_Target *)value = TMR_GEN2_TARGET_AB;+          break;+        case 0x0001:+          *(TMR_GEN2_Target *)value = TMR_GEN2_TARGET_BA;+          break;+        default:+          *(TMR_GEN2_Target *)value = TMR_GEN2_TARGET_INVALID;+        }+        break;+      }++    case TMR_SR_GEN2_CONFIGURATION_Q:+      {+        TMR_SR_GEN2_Q *q = value;++        q->type = (TMR_SR_GEN2_QType)GETU8AT(msg, 7);+        if (q->type == TMR_SR_GEN2_Q_DYNAMIC)+        {+          ; /* No further data to get */+        }+        else if (q->type == TMR_SR_GEN2_Q_STATIC)+        {+          q->u.staticQ.initialQ = GETU8AT(msg, 8);+        }+        break;+      }++    default:+      return TMR_ERROR_NOT_FOUND;+    }+  }+#ifdef TMR_ENABLE_ISO180006B+  else if (TMR_TAG_PROTOCOL_ISO180006B == key.protocol +    || TMR_TAG_PROTOCOL_ISO180006B_UCODE == key.protocol)+  {+    switch (key.u.iso180006b)+    {+    case TMR_SR_ISO180006B_CONFIGURATION_LINKFREQUENCY:+      {+    TMR_iso18000BBLFValToInt(GETU8AT(msg, 7), value);+        break;+  }+    case TMR_SR_ISO180006B_CONFIGURATION_MODULATION_DEPTH:+      {+        uint8_t val;+        val = GETU8AT(msg, 7);+        switch (val)+        {+        case 0:+          *(TMR_ISO180006B_ModulationDepth *)value = TMR_ISO180006B_Modulation99percent;+          break;+        case 1:+          *(TMR_ISO180006B_ModulationDepth *)value = TMR_ISO180006B_Modulation11percent;+          break;+        default:+          return TMR_ERROR_NOT_FOUND;+        }+        break;+      }+    case TMR_SR_ISO180006B_CONFIGURATION_DELIMITER:+      {+        uint8_t val;+        val = GETU8AT(msg, 7);+        switch (val)+        {+        case 1:+          *(TMR_ISO180006B_Delimiter *)value = TMR_ISO180006B_Delimiter1;+          break;+        case 4:+          *(TMR_ISO180006B_Delimiter *)value = TMR_ISO180006B_Delimiter4;+          break;+        default:+          return TMR_ERROR_NOT_FOUND;+        }+        break;+      }+    default:+      return TMR_ERROR_NOT_FOUND;+      }+    }  +#endif /* TMR_ENABLE_ISO180006B */+  else+  {+    return TMR_ERROR_INVALID;+  }++  return TMR_SUCCESS;+}++TMR_Status TMR_iso18000BBLFValToInt(int val, void *lf)+{+  switch (val)+  {+    case 1:+	  *(TMR_ISO180006B_LinkFrequency *)lf = TMR_ISO180006B_LINKFREQUENCY_40KHZ;+	  break;+	case 0:+	  *(TMR_ISO180006B_LinkFrequency *)lf = TMR_ISO180006B_LINKFREQUENCY_160KHZ;+	  break;+	default:+      return TMR_ERROR_NOT_FOUND;+  }+  return TMR_SUCCESS;+}++/* Helper function to frame the multiple protocol search command */+TMR_Status +TMR_SR_msgSetupMultipleProtocolSearch(TMR_Reader *reader, uint8_t *msg, TMR_SR_OpCode op, TMR_TagProtocolList *protocols, TMR_TRD_MetadataFlag metadataFlags, TMR_SR_SearchFlag antennas, TMR_TagFilter **filter, uint16_t timeout)+{+  TMR_Status ret;+  uint8_t i;+  uint32_t j;+  uint16_t subTimeout;++  ret = TMR_SUCCESS;+  i=2;++  SETU8(msg, i, TMR_SR_OPCODE_MULTI_PROTOCOL_TAG_OP);  //Opcode+  if(reader->continuousReading)+  {+    /* Timeout should be zero for true continuous reading */+    SETU16(msg, i, 0);+    SETU8(msg, i, (uint8_t)0x1);//TM Option 1, for continuous reading+  }+  else+  {+    SETU16(msg, i, timeout); //command timeout+    SETU8(msg, i, (uint8_t)0x11);//TM Option, turns on metadata+    SETU16(msg, i, (uint16_t)metadataFlags);+  }++  SETU8(msg, i, (uint8_t)op);//sub command opcode++  if (TMR_READ_PLAN_TYPE_MULTI == reader->readParams.readPlan->type)+  {+    reader->isStopNTags = false;+    /**+    * in case of multi read plan look for the stop N trigger option+    **/+    for (j = 0; j < reader->readParams.readPlan->u.multi.planCount; j++)+    {+      if (reader->readParams.readPlan->u.multi.plans[j]->u.simple.stopOnCount.stopNTriggerStatus)+      {+        reader->numberOfTagsToRead += reader->readParams.readPlan->u.multi.plans[j]->u.simple.stopOnCount.noOfTags;+        reader->isStopNTags = true;+      }+    }+  }+  else+  {+    reader->numberOfTagsToRead += reader->readParams.readPlan->u.simple.stopOnCount.noOfTags;+  }++  if (reader->isStopNTags && !reader->continuousReading)+  {+    /**+    * True means atlest one sub read plan has the requested for stop N trigger.+    * Enable the flag and add the total tag count. This is only supported for sync read+    * case.+    */+    SETU16(msg, i, (uint16_t)TMR_SR_SEARCH_FLAG_RETURN_ON_N_TAGS);+    SETU32(msg, i, reader->numberOfTagsToRead);+  }+  else+  {+    SETU16(msg, i, (uint16_t)0x0000);//search flags, only 0x0001 is supported+  }++  /**+  * TODO:add the timeout as requested by the user+  **/+  subTimeout =(uint16_t)(timeout/(protocols->len));+  for (j=0;j<protocols->len;j++) // iterate through the protocol search list+  {+    int PLenIdx;+++    TMR_TagProtocol subProtocol=protocols->list[j];+    SETU8(msg, i, (uint8_t)(subProtocol)); //protocol ID+    PLenIdx = i;+    SETU8(msg, i, 0); //PLEN++    /**+    * in case of multi readplan and the total weight is not zero,+    * we should use the weight as provided by the user.+    **/+    if (TMR_READ_PLAN_TYPE_MULTI == reader->readParams.readPlan->type)+    {+      if (0 != reader->readParams.readPlan->u.multi.totalWeight)+      {+        subTimeout = (uint16_t)(reader->readParams.readPlan->u.multi.plans[j]->weight * timeout+          / reader->readParams.readPlan->u.multi.totalWeight);+      }+    }++    /**+    * In case of Multireadplan, check each simple read plan FastSearch option and+    * stop N trigger option.+    */+    if (TMR_READ_PLAN_TYPE_MULTI == reader->readParams.readPlan->type)+    {+      reader->fastSearch = reader->readParams.readPlan->u.multi.plans[j]->u.simple.useFastSearch;+      reader->triggerRead = reader->readParams.readPlan->u.multi.plans[j]->u.simple.triggerRead.enable;+      reader->isStopNTags = false;+      reader->isStopNTags = reader->readParams.readPlan->u.multi.plans[j]->u.simple.stopOnCount.stopNTriggerStatus;+      reader->numberOfTagsToRead = reader->readParams.readPlan->u.multi.plans[j]->u.simple.stopOnCount.noOfTags;+    }++    switch(op)+    {+    case TMR_SR_OPCODE_READ_TAG_ID_SINGLE :+      {+        ret = TMR_SR_msgSetupReadTagSingle(msg, &i, subProtocol,metadataFlags, filter[j], subTimeout);+        break;+      }+    case TMR_SR_OPCODE_READ_TAG_ID_MULTIPLE:+      {+        /**+        * simple read plan uses this function, only when tagop is NULL,+        * s0, need to check for simple read plan tagop.+        **/+        if (TMR_READ_PLAN_TYPE_MULTI == reader->readParams.readPlan->type)+        {+          /* check for the tagop */+          if (NULL != reader->readParams.readPlan->u.multi.plans[j]->u.simple.tagop)+          {+            uint32_t readTimeMs = (uint32_t)subTimeout;+            uint8_t lenbyte = 0;+            //add the tagoperation here+            ret = TMR_SR_addTagOp(reader,reader->readParams.readPlan->u.multi.plans[j]->u.simple.tagop,+              reader->readParams.readPlan->u.multi.plans[j], msg, &i, readTimeMs, &lenbyte);+          }+          else+          {+            ret = TMR_SR_msgSetupReadTagMultipleWithMetadata(reader, msg, &i, subTimeout, antennas, metadataFlags ,filter[j], subProtocol, 0);+          }+        }+        else+        {+          if (NULL != reader->readParams.readPlan->u.simple.tagop)+          {+            uint32_t readTimeMs = (uint32_t)subTimeout;+            uint8_t lenbyte = 0;+            //add the tagoperation here+            ret = TMR_SR_addTagOp(reader, reader->readParams.readPlan->u.simple.tagop,+              reader->readParams.readPlan, msg, &i, readTimeMs, &lenbyte);+          }+          else+          {+            ret = TMR_SR_msgSetupReadTagMultipleWithMetadata(reader, msg, &i, subTimeout, antennas, metadataFlags ,filter[j], subProtocol, 0);+          }+        }+        break;+      }+    default :+      {+        return TMR_ERROR_INVALID_OPCODE;          +      }+    }++    msg[PLenIdx]= i - PLenIdx - 2; //PLEN+    msg[1]=i - 3;+  }+  return ret;+}++TMR_Status TMR_SR_cmdMultipleProtocolSearch(TMR_Reader *reader,TMR_SR_OpCode op,TMR_TagProtocolList *protocols, TMR_TRD_MetadataFlag metadataFlags,TMR_SR_SearchFlag antennas, TMR_TagFilter **filter, uint16_t timeout, uint32_t *tagsFound)+{+  TMR_Status ret;+  uint8_t msg[TMR_SR_MAX_PACKET_SIZE];+  TMR_SR_SerialReader *sr;++  sr = &reader->u.serialReader;+  *tagsFound = 0 ;++  ret = TMR_SR_msgSetupMultipleProtocolSearch(reader, msg, op, protocols, metadataFlags, antennas, filter, timeout);+  if (ret != TMR_SUCCESS)+  {+    return ret;+  }++  if (op == TMR_SR_OPCODE_READ_TAG_ID_SINGLE)+  {+    uint8_t opcode;++    sr->opCode = op;+    ret = TMR_SR_sendMessage(reader, msg, &opcode, timeout);+    if (TMR_SUCCESS != ret)+    {+      return ret;+    }+    sr->tagsRemaining = 1;+  }++  if (op == TMR_SR_OPCODE_READ_TAG_ID_MULTIPLE)+  {+    sr->opCode = op;+    if(reader->continuousReading)+    {+      uint8_t opcode;+      ret = TMR_SR_sendMessage(reader, msg, &opcode, timeout);+      if (TMR_SUCCESS != ret)+      {+        return ret;+      }+	  reader->hasContinuousReadStarted = true;+      sr->tagsRemaining=1;+    }+    else+    {+      ret = TMR_SR_sendTimeout(reader, msg, timeout);+      if (TMR_ERROR_NO_TAGS_FOUND == ret)+      {+        sr->tagsRemaining = *tagsFound = 0;+        return ret;+      }+      else if ((TMR_ERROR_TM_ASSERT_FAILED == ret) ||+        (TMR_ERROR_TIMEOUT == ret))+      {+        return ret;+      }+      else if (TMR_SUCCESS != ret)+      {+        uint16_t remainingTagsCount;+        TMR_Status ret1;++        /* Check for the tag count (in case of module error)*/+        ret1 = TMR_SR_cmdGetTagsRemaining(reader, &remainingTagsCount);+        if (TMR_SUCCESS != ret1)+        {+          return ret1;+        }++        *tagsFound = remainingTagsCount;+        sr->tagsRemaining = *tagsFound;+        return ret;+      }++      *tagsFound = GETU32AT(msg , 9);+      sr->tagsRemaining = *tagsFound;+    }+  }++  return TMR_SUCCESS;+}++TMR_Status+TMR_SR_cmdGetAvailableProtocols(TMR_Reader *reader,+                                TMR_TagProtocolList *protocols)+{+  TMR_Status ret;+  uint8_t msg[TMR_SR_MAX_PACKET_SIZE];+  uint8_t i;++  i = 2;+  SETU8(msg, i, TMR_SR_OPCODE_GET_AVAILABLE_PROTOCOLS);+  msg[1] = i - 3; /* Install length */++  ret = TMR_SR_send(reader, msg);+  if (TMR_SUCCESS != ret)+  {+    return ret;+  }++  protocols->len = 0;+  for (i = 0; i < msg[1] ; i += 2)+  {+    LISTAPPEND(protocols, (TMR_TagProtocol)GETU16AT(msg, 5 + i)); +  }++  reader->u.serialReader.versionInfo.protocols = 0x0000;+  for (i = 0 ; i < protocols->len; i ++)+  {+    reader->u.serialReader.versionInfo.protocols |= (1 << (protocols->list[i] - 1)); +  }+  +  return TMR_SUCCESS;+}+++TMR_Status+TMR_SR_cmdGetAvailableRegions(TMR_Reader *reader, TMR_RegionList *regions)+{+  TMR_Status ret;+  uint8_t msg[TMR_SR_MAX_PACKET_SIZE];+  uint8_t i;++  i = 2;+  SETU8(msg, i, TMR_SR_OPCODE_GET_AVAILABLE_REGIONS);+  msg[1] = i - 3; /* Install length */++  ret = TMR_SR_send(reader, msg);+  if (TMR_SUCCESS != ret)+  {+    return ret;+  }++  regions->len = 0;+  for (i = 0; i < msg[1] ; i++)+  {+    LISTAPPEND(regions, (TMR_Region)GETU8AT(msg, 5 + i)); +  }++  return TMR_SUCCESS;+}++++TMR_Status+TMR_SR_cmdGetTemperature(TMR_Reader *reader, int8_t *temp)+{+  TMR_Status ret;+  uint8_t msg[TMR_SR_MAX_PACKET_SIZE];+  uint8_t i;++  i = 2;+  SETU8(msg, i, TMR_SR_OPCODE_GET_TEMPERATURE);+  msg[1] = i - 3; /* Install length */++  ret = TMR_SR_send(reader, msg);+  if (TMR_SUCCESS != ret)+  {+    return ret;+  }++  *temp = msg[5];+  return TMR_SUCCESS;+}+++static TMR_Status+filterbytes(TMR_TagProtocol protocol, const TMR_TagFilter *filter, +            uint8_t *option, uint8_t *i, uint8_t *msg,+            uint32_t accessPassword, bool usePassword)+{+  int j;+  if (isSecureAccessEnabled)+  {+    *option = TMR_SR_GEN2_SINGULATION_OPTION_SECURE_READ_DATA;+  }++  if (NULL == filter && 0 == accessPassword)+  {+    *option = 0x00;+    return TMR_SUCCESS;+  }++  if (TMR_TAG_PROTOCOL_GEN2 == protocol)+  {+    if (usePassword)+    {+		if (filter && TMR_FILTER_TYPE_GEN2_SELECT == filter->type)+		{+			if (filter->u.gen2Select.bank != TMR_GEN2_EPC_LENGTH_FILTER)+				SETU32(msg, *i, accessPassword);+		}+		else+		{+			SETU32(msg, *i, accessPassword);+		}+    }+    if (NULL == filter)+    {+      *option |= TMR_SR_GEN2_SINGULATION_OPTION_USE_PASSWORD;+    }+    else if (TMR_FILTER_TYPE_GEN2_SELECT == filter->type)+    {+      const TMR_GEN2_Select *fp;++      fp = &filter->u.gen2Select;++      if (1 == fp->bank)+      {+        *option |= TMR_SR_GEN2_SINGULATION_OPTION_SELECT_ON_ADDRESSED_EPC;+      }+      else /* select based on the bank */+      {+        *option |= fp->bank;+      }++	  if (fp->bank == TMR_GEN2_EPC_LENGTH_FILTER)+	  {+		  SETU16(msg, *i, fp->maskBitLength);+	  }+	  else+	  {+		  if(true == fp->invert)+		  {+			*option |= TMR_SR_GEN2_SINGULATION_OPTION_INVERSE_SELECT_BIT;+		  }++		  if (fp->maskBitLength > 255)+		  {+			*option |= TMR_SR_GEN2_SINGULATION_OPTION_EXTENDED_DATA_LENGTH;+		  }++		  SETU32(msg, *i, fp->bitPointer);++		  if (fp->maskBitLength > 255)+		  {+			SETU8(msg, *i, (fp->maskBitLength >> 8) & 0xFF);+		  }+		  SETU8(msg, *i, fp->maskBitLength & 0xFF);++		  if (*i + 1 + tm_u8s_per_bits(fp->maskBitLength) > TMR_SR_MAX_PACKET_SIZE)+		  {+			return TMR_ERROR_TOO_BIG;+		  }++		  for(j = 0; j < tm_u8s_per_bits(fp->maskBitLength) ; j++)+		  {+			SETU8(msg, *i, fp->mask[j]);+		  }+	  }+    }+    else if (TMR_FILTER_TYPE_TAG_DATA == filter->type)+    {+      const TMR_TagData *fp;+      int bitCount;++      fp = &filter->u.tagData;+      bitCount = fp->epcByteCount * 8;++      /* select on the EPC */+      *option |= 1;+      if (bitCount > 255)+      {+        *option |= TMR_SR_GEN2_SINGULATION_OPTION_EXTENDED_DATA_LENGTH;+        SETU8(msg, *i, (bitCount>>8) & 0xFF);+      }+      SETU8(msg, *i, (bitCount & 0xFF));++      if (*i + 1 + fp->epcByteCount > TMR_SR_MAX_PACKET_SIZE)+      {+        return TMR_ERROR_TOO_BIG;+      }++      for(j = 0 ; j < fp->epcByteCount ; j++)+      {+        SETU8(msg, *i, fp->epc[j]);+      }+    }+    else+    {+      return TMR_ERROR_INVALID;+    }+  }+#ifdef TMR_ENABLE_ISO180006B+  else if (TMR_TAG_PROTOCOL_ISO180006B == protocol)+  {+    if (option)+    {+      *option = 1;+    }+    +    if (NULL == filter)+    {+       /* Set up a match-anything filter, since it isn't the default */+      SETU8(msg, *i, TMR_ISO180006B_SELECT_OP_EQUALS);+      SETU8(msg, *i, 0); /* address */+      SETU8(msg, *i, 0); /* mask - don't compare anything */+      SETU32(msg, *i, 0); /* dummy tag ID bytes 0-3, not compared */+      SETU32(msg, *i, 0); /* dummy tag ID bytes 4-7, not compared */+      return TMR_SUCCESS;+    }+    else if (TMR_FILTER_TYPE_ISO180006B_SELECT == filter->type)+    {+      const TMR_ISO180006B_Select *fp;+      +      fp = &filter->u.iso180006bSelect;+      if (false == fp->invert)+      {+        SETU8(msg, *i, fp->op);+      }+      else+      {+        SETU8(msg, *i, fp->op | 4);+      }+      SETU8(msg, *i, fp->address);+      SETU8(msg, *i, fp->mask);+      for (j = 0 ; j < 8 ; j++)+      {+        SETU8(msg, *i, fp->data[j]);+      }+    }+    else if (TMR_FILTER_TYPE_TAG_DATA == filter->type)+    {+      const TMR_TagData *fp;+      uint8_t mask;++      fp = &filter->u.tagData;++      if (fp->epcByteCount > 8)+      {+        return TMR_ERROR_INVALID;+      }++      /* Convert the byte count to a MSB-based bit mask */+      mask = (0xff00 >> fp->epcByteCount) & 0xff;++      SETU8(msg, *i, TMR_ISO180006B_SELECT_OP_EQUALS);+      SETU8(msg, *i, 0); /* Address - EPC is at the start of memory */+      SETU8(msg, *i, mask);+      for (j = 0 ; j < fp->epcByteCount; j++)+      {+        SETU8(msg, *i, fp->epc[j]);+      }+      for ( ; j < 8 ; j++)+      {+        SETU8(msg, *i, 0); /* EPC data must be 8 bytes */+      }+    }+    else+    {+      return TMR_ERROR_INVALID;+    }+    +  }+#endif /* TMR_ENABLE_ISO180006B */+  else+  {+    return TMR_ERROR_INVALID;+  }++  return TMR_SUCCESS;+}++/** + *  Alien Higgs2 and Higgs3 Specific Commands+ **/++/** Helper routine to form the Higgs2 Partial Load Image command **/+void TMR_SR_msgAddHiggs2PartialLoadImage(uint8_t *msg, uint8_t *i, uint16_t timeout,+      TMR_GEN2_Password accessPassword, TMR_GEN2_Password killPassword, uint8_t len, const uint8_t *epc, TMR_TagFilter* target)+{+  SETU8(msg, *i, TMR_SR_OPCODE_WRITE_TAG_SPECIFIC);+  SETU16(msg, *i, timeout);+  SETU8(msg, *i, (uint8_t)TMR_SR_GEN2_ALIEN_HIGGS_SILICON);  /* Chip - type*/+  SETU8(msg, *i, (uint8_t)0x01);  /* Sub command, partial load image */+  SETU32(msg, *i, killPassword);+  SETU32(msg, *i, accessPassword);+  memcpy(&msg[*i], epc, len);+  *i += len;+}+/**+ * Partial Load Image (only 96-bit EPC with no user memory versions)+ * Chip type = 0x01+ *  + * @param reader The reader+ * @param timeout The timeout of the operation, in milliseconds. Valid range is 0-65535.+ * @param accessPassword The access password to write on the tag+ * @param killPassword The kill password to write on the tag+ * @param len Length of the EPC+ * @param epc The EPC to write to the tag. Maximum of 12 bytes (96 bits)+ * @param target Filter to be applied.+ */+TMR_Status TMR_SR_cmdHiggs2PartialLoadImage(TMR_Reader *reader, uint16_t timeout,+            TMR_GEN2_Password accessPassword, TMR_GEN2_Password killPassword, +            uint8_t len, const uint8_t epc[], TMR_TagFilter* target)+{+  uint8_t msg[TMR_SR_MAX_PACKET_SIZE];+  uint8_t i;+  i = 2;++  if(NULL != target)+  {+    return TMR_ERROR_UNSUPPORTED;+  }+  TMR_SR_msgAddHiggs2PartialLoadImage(msg, &i, timeout, accessPassword, killPassword, len, epc, target);+  msg[1] = i - 3; /* Install length */++  return TMR_SR_sendTimeout(reader, msg, timeout);+}+++/** Helper routine to form the Higgs2 Full Load Image command **/+void TMR_SR_msgAddHiggs2FullLoadImage(uint8_t *msg, uint8_t *i, uint16_t timeout,+      TMR_GEN2_Password accessPassword, TMR_GEN2_Password killPassword, uint16_t lockBits, uint16_t pcWord, uint8_t len, const uint8_t *epc, TMR_TagFilter* target)+{+  SETU8(msg, *i, TMR_SR_OPCODE_WRITE_TAG_SPECIFIC);+  SETU16(msg, *i, timeout);+  SETU8(msg, *i, (uint8_t)TMR_SR_GEN2_ALIEN_HIGGS_SILICON);  /* Chip - type*/+  SETU8(msg, *i, (uint8_t)0x03);  /* Sub command, full load image */+  SETU32(msg, *i, killPassword);+  SETU32(msg, *i, accessPassword);+  SETU16(msg, *i, lockBits);+  SETU16(msg, *i, pcWord);+  memcpy(&msg[*i], epc, len);+  *i += len;+}+/**+ * Full Load Image (only 96-bit EPC with no user memory versions)+ * Chip type = 0x01+ *  + * @param reader The reader+ * @param timeout The timeout of the operation, in milliseconds. Valid range is 0-65535.+ * @param accessPassword The access password to write on the tag+ * @param killPassword The kill password to write on the tag+ * @param lockBits locking the tag according to the Alien Higgs LockBits+ * @param pcWord PC Word in the Tag EPC memBank defined in the Gen2 Specification+ * @param len Length of the EPC+ * @param epc The EPC to write to the tag. Maximum of 12 bytes (96 bits)+ * @param target Filter to be applied.+ */+TMR_Status TMR_SR_cmdHiggs2FullLoadImage(TMR_Reader *reader, uint16_t timeout,+            TMR_GEN2_Password accessPassword, TMR_GEN2_Password killPassword,+            uint16_t lockBits, uint16_t pcWord, uint8_t len,+            const uint8_t epc[], TMR_TagFilter* target)+{+  uint8_t msg[TMR_SR_MAX_PACKET_SIZE];+  uint8_t i;+  i = 2;++  if(NULL != target)+  {+    return TMR_ERROR_UNSUPPORTED;+  }+  TMR_SR_msgAddHiggs2FullLoadImage(msg, &i, timeout, accessPassword, killPassword, lockBits, pcWord, len, epc, target);+  msg[1] = i - 3; /* Install length */++  return TMR_SR_sendTimeout(reader, msg, timeout);+}++/** Helper routine to form the Higgs3 Fast Load Image command **/+void TMR_SR_msgAddHiggs3FastLoadImage(uint8_t *msg, uint8_t *i, uint16_t timeout, TMR_GEN2_Password currentAccessPassword,+      TMR_GEN2_Password accessPassword, TMR_GEN2_Password killPassword, uint16_t pcWord, uint8_t len, const uint8_t *epc, TMR_TagFilter* target)+{+  uint8_t option=0,rec; ++  SETU8(msg, *i, TMR_SR_OPCODE_WRITE_TAG_SPECIFIC);+  SETU16(msg, *i, timeout);+  SETU8(msg, *i, (uint8_t)TMR_SR_GEN2_ALIEN_HIGGS3_SILICON);  /* Chip - type*/+  +  rec=*i;+  SETU8(msg,*i,0x40);//option+  SETU8(msg, *i, (uint8_t)0x00);+  SETU8(msg, *i, (uint8_t)0x01);  /* Sub command, fast load image */+  +  filterbytes(TMR_TAG_PROTOCOL_GEN2, target, &option, i, msg, 0, false); +  msg[rec]=msg[rec]|option;++  SETU32(msg, *i, currentAccessPassword);+  SETU32(msg, *i, killPassword);+  SETU32(msg, *i, accessPassword);+  SETU16(msg, *i, pcWord);+  memcpy(&msg[*i], epc, len);+  *i += len;+}+/**+ * Higgs3 Fast Load Image (only 96-bit EPC)+ * Chip type = 0x05+ *  + * @param reader The reader+ * @param timeout The timeout of the operation, in milliseconds. Valid range is 0-65535.+ * @param currentAccessPassword The access password to use to write to the tag+ * @param accessPassword The access password to write on the tag+ * @param killPassword The kill password to write on the tag+ * @param pcWord PC Word in the Tag EPC memBank defined in the Gen2 Specification+ * @param len Length of the EPC+ * @param epc The EPC to write to the tag. Maximum of 12 bytes (96 bits)+ * @param target Filter to be applied.+ */+TMR_Status +TMR_SR_cmdHiggs3FastLoadImage(TMR_Reader *reader, uint16_t timeout,+            TMR_GEN2_Password currentAccessPassword, TMR_GEN2_Password accessPassword, +            TMR_GEN2_Password killPassword, uint16_t pcWord, uint8_t len, const uint8_t epc[], TMR_TagFilter* target)+{+  uint8_t msg[TMR_SR_MAX_PACKET_SIZE];+  uint8_t i;+  i = 2;++  TMR_SR_msgAddHiggs3FastLoadImage(msg, &i, timeout, currentAccessPassword, accessPassword, killPassword, pcWord, len, epc, target);+  msg[1] = i - 3; /* Install length */++  return TMR_SR_sendTimeout(reader, msg, timeout);+}++/** Helper routine to form the Higgs3 Load Image command **/+void TMR_SR_msgAddHiggs3LoadImage(uint8_t *msg, uint8_t *i, uint16_t timeout, TMR_GEN2_Password currentAccessPassword,+      TMR_GEN2_Password accessPassword, TMR_GEN2_Password killPassword, uint16_t pcWord, uint8_t len, const uint8_t *epcAndUserData, TMR_TagFilter* target)+{+  uint8_t option=0,rec; ++  SETU8(msg, *i, TMR_SR_OPCODE_WRITE_TAG_SPECIFIC);+  SETU16(msg, *i, timeout);+  SETU8(msg, *i, (uint8_t)TMR_SR_GEN2_ALIEN_HIGGS3_SILICON);  /* Chip - type*/+  +  rec=*i;+  SETU8(msg,*i,0x40);//option+  SETU8(msg, *i, (uint8_t)0x00);+  SETU8(msg, *i, (uint8_t)0x03);  /* Sub command, Load image */++  filterbytes(TMR_TAG_PROTOCOL_GEN2, target, &option, i, msg, 0, false); +  msg[rec]=msg[rec]|option;++  SETU32(msg, *i, currentAccessPassword);+  SETU32(msg, *i, killPassword);+  SETU32(msg, *i, accessPassword);+  SETU16(msg, *i, pcWord);+  memcpy(&msg[*i], epcAndUserData, len);+  *i += len;+}++/**+ * Higgs3 Load Image + * Chip type = 0x05+ *  + * @param reader The reader+ * @param timeout The timeout of the operation, in milliseconds. Valid range is 0-65535.+ * @param currentAccessPassword The access password to use to write to the tag+ * @param accessPassword The access password to write on the tag+ * @param killPassword The kill password to write on the tag+ * @param pcWord PC Word in the Tag EPC memBank defined in the Gen2 Specification+ * @param len Length of epcAndUserData+ * @param epcAndUserData The EPC and user data to write to the tag. Must be exactly 76 bytes. + *                       The pcWord specifies which of this is EPC and which is user data.+ * @param target Filter to be applied.+ */+TMR_Status TMR_SR_cmdHiggs3LoadImage(TMR_Reader *reader, uint16_t timeout,+            TMR_GEN2_Password currentAccessPassword,+            TMR_GEN2_Password accessPassword, TMR_GEN2_Password killPassword,+            uint16_t pcWord, uint8_t len, const uint8_t epcAndUserData[], TMR_TagFilter* target)+{+  uint8_t msg[TMR_SR_MAX_PACKET_SIZE];+  uint8_t i;+  i = 2;++  TMR_SR_msgAddHiggs3LoadImage(msg, &i, timeout, currentAccessPassword, accessPassword, +                                killPassword, pcWord, len, epcAndUserData, target);  /* Length of epcAndUserData must be 76 */+  msg[1] = i - 3; /* Install length */++  return TMR_SR_sendTimeout(reader, msg, timeout);+}++/** Helper routine to form the Higgs3 Block Read Lock command**/+void TMR_SR_msgAddHiggs3BlockReadLock(uint8_t *msg, uint8_t *i, uint16_t timeout, +          TMR_GEN2_Password accessPassword, uint8_t lockBits, TMR_TagFilter* target)+{+  uint8_t option=0,rec; ++  SETU8(msg, *i, TMR_SR_OPCODE_WRITE_TAG_SPECIFIC);+  SETU16(msg, *i, timeout);+  SETU8(msg, *i, (uint8_t)TMR_SR_GEN2_ALIEN_HIGGS3_SILICON);  /* Chip - type*/+  +  rec=*i;+  SETU8(msg,*i,0x40);//option+  SETU8(msg, *i, (uint8_t)0x00);+  SETU8(msg, *i, (uint8_t)0x09);  /* Sub command, Block Read Lock */+  +  filterbytes(TMR_TAG_PROTOCOL_GEN2, target, &option, i, msg, 0, false); +  msg[rec]=msg[rec]|option;++  SETU32(msg, *i, accessPassword);+  SETU8(msg, *i, lockBits);+}++/**+ * Higgs3 Block Read Lock + * Chip type = 0x05+ *  + * @param reader The reader+ * @param timeout The timeout of the operation, in milliseconds. Valid range is 0-65535.+ * @param accessPassword The access password to use to write on the tag+ * @param lockBits A bitmask of bits to lock. Valid range 0-255+ * @param target Filter to be applied.+ */+TMR_Status TMR_SR_cmdHiggs3BlockReadLock(TMR_Reader *reader, uint16_t timeout,+            TMR_GEN2_Password accessPassword, uint8_t lockBits, TMR_TagFilter* target)+{+  uint8_t msg[TMR_SR_MAX_PACKET_SIZE];+  uint8_t i;+  i = 2;++  TMR_SR_msgAddHiggs3BlockReadLock(msg, &i, timeout, accessPassword, lockBits, target);+  msg[1] = i - 3; /* Install length */++  return TMR_SR_sendTimeout(reader, msg, timeout);+}++/** + *  NXP Silicon (G2xL and G2iL) Specific Commands+ *  Chip Type = 0x02 and 0x07+ **/++/** Helper routine to form the NXP Set Read Protect command**/+void TMR_SR_msgAddNXPSetReadProtect(uint8_t *msg, uint8_t *i, uint16_t timeout,+                TMR_SR_GEN2_SiliconType chip, TMR_GEN2_Password accessPassword, TMR_TagFilter* target)+{+  uint8_t option=0,rec; ++  SETU8(msg, *i, TMR_SR_OPCODE_WRITE_TAG_SPECIFIC);+  SETU16(msg, *i, timeout);+  SETU8(msg, *i, (uint8_t)chip);  /* Chip - type*/+  +  rec=*i;+  SETU8(msg,*i,0x40);//option+  SETU8(msg, *i, (uint8_t)0x00);+  SETU8(msg, *i, (uint8_t)0x01);  /* Sub command, Set Read Protect */+  filterbytes(TMR_TAG_PROTOCOL_GEN2, target, &option, i, msg, 0, false);+  msg[rec]=msg[rec]|option;+  +  SETU32(msg, *i, accessPassword);+}++/** Helper routine to form the NXP Set Read Protect command**/+void TMR_SR_msgAddNXPResetReadProtect(uint8_t *msg, uint8_t *i, uint16_t timeout,+                TMR_SR_GEN2_SiliconType chip, TMR_GEN2_Password accessPassword, TMR_TagFilter* target)+{+  uint8_t option=0,rec;++  SETU8(msg, *i, TMR_SR_OPCODE_WRITE_TAG_SPECIFIC);+  SETU16(msg, *i, timeout);+  SETU8(msg, *i, (uint8_t)chip);  /* Chip - type*/+  +  rec=*i;+  SETU8(msg,*i,0x40);//option+  SETU8(msg, *i, (uint8_t)0x00);+  SETU8(msg, *i, (uint8_t)0x02);  /* Sub command, Reset Read Protect */+  filterbytes(TMR_TAG_PROTOCOL_GEN2, target, &option, i, msg, 0, false); +  msg[rec]=msg[rec]|option;+  +  SETU32(msg, *i, accessPassword);+}++/**+ * NXP Set Read Protect+ * Chip type = 0x02 or 0x07, Command = 0x01+ *  + * @param reader The reader+ * @param timeout The timeout of the operation, in milliseconds. Valid range is 0-65535.+ * @param chip The NXP Chip type (G2iL or G2xL)+ * @param accessPassword The access password to use to write on the tag+ * @param target Filter to be applied.+ */+TMR_Status TMR_SR_cmdNxpSetReadProtect(TMR_Reader *reader, uint16_t timeout,+            TMR_SR_GEN2_SiliconType chip, TMR_GEN2_Password accessPassword, TMR_TagFilter* target)+{+  uint8_t msg[TMR_SR_MAX_PACKET_SIZE];+  uint8_t i;+  i = 2;+  +  TMR_SR_msgAddNXPSetReadProtect(msg, &i, timeout, chip, accessPassword, target);  /* set read protect */+  msg[1] = i - 3; /* Install length */++  return TMR_SR_sendTimeout(reader, msg, timeout);+}++/**+ * NXP Reset Read Protect+ * Chip type = 0x02 or 0x07, Command = 0x02+ *  + * @param reader The reader+ * @param timeout The timeout of the operation, in milliseconds. Valid range is 0-65535.+ * @param chip The NXP Chip type (G2iL or G2xL)+ * @param accessPassword The access password to use to write on the tag+ * @param target Filter to be applied.+ */+TMR_Status TMR_SR_cmdNxpResetReadProtect(TMR_Reader *reader, uint16_t timeout,+            TMR_SR_GEN2_SiliconType chip, TMR_GEN2_Password accessPassword, TMR_TagFilter* target)+{+  uint8_t msg[TMR_SR_MAX_PACKET_SIZE];+  uint8_t i;+  i = 2;++  TMR_SR_msgAddNXPResetReadProtect(msg, &i, timeout, chip, accessPassword, target);  /* Reset read protect */+  msg[1] = i - 3; /* Install length */++  return TMR_SR_sendTimeout(reader, msg, timeout);+}++/** Helper routine to form the NXP Change EAS command**/+void TMR_SR_msgAddNXPChangeEAS(uint8_t *msg, uint8_t *i, uint16_t timeout, +                TMR_SR_GEN2_SiliconType chip, TMR_GEN2_Password accessPassword, bool reset, TMR_TagFilter* target)+{+  uint8_t option=0,rec; ++  SETU8(msg, *i, TMR_SR_OPCODE_WRITE_TAG_SPECIFIC);+  SETU16(msg, *i, timeout);+  SETU8(msg, *i, (uint8_t)chip);  /* Chip - type*/+  +  rec=*i;+  SETU8(msg,*i,0x40);//option+  SETU8(msg, *i, (uint8_t)0x00);+  SETU8(msg, *i, (uint8_t)0x03);  /* Sub command, Change EAS */+  +  filterbytes(TMR_TAG_PROTOCOL_GEN2, target, &option, i, msg, 0, false); +  msg[rec]=msg[rec]|option;+    +  SETU32(msg, *i, accessPassword);  +  if(reset)+  {+    SETU8(msg, *i, (uint8_t)0x02);  /* reset EAS */+  }+  else+  {+    SETU8(msg, *i, (uint8_t)0x01);  /* set EAS */+  }  +}++/**+ * NXP Change EAS+ * Chip type = 0x02 or 0x07, Command = 0x03+ *  + * @param reader The reader+ * @param timeout The timeout of the operation, in milliseconds. Valid range is 0-65535.+ * @param chip The NXP Chip type (G2iL or G2xL)+ * @param accessPassword The access password to use to write on the tag+ * @param reset Reset or set EAS bit+ * @param target Filter to be applied.+ */+TMR_Status TMR_SR_cmdNxpChangeEas(TMR_Reader *reader, uint16_t timeout,+            TMR_SR_GEN2_SiliconType chip, TMR_GEN2_Password accessPassword, bool reset, TMR_TagFilter* target)+{+  uint8_t msg[TMR_SR_MAX_PACKET_SIZE];+  uint8_t i;+  i = 2;++  TMR_SR_msgAddNXPChangeEAS(msg, &i, timeout, chip, accessPassword, reset, target);+  msg[1] = i - 3; /* Install length */++  return TMR_SR_sendTimeout(reader, msg, timeout);+}++/** Helper routine to form the NXP EAS Alarm command **/+void TMR_SR_msgAddNXPEASAlarm(uint8_t *msg, uint8_t *i, uint16_t timeout, +                TMR_SR_GEN2_SiliconType chip, TMR_GEN2_DivideRatio dr, TMR_GEN2_TagEncoding m, TMR_GEN2_TrExt trExt, TMR_TagFilter* target)+{+  SETU8(msg, *i, TMR_SR_OPCODE_WRITE_TAG_SPECIFIC);+  SETU16(msg, *i, timeout);+  SETU8(msg, *i, (uint8_t)chip);  /* Chip - type*/+  +  SETU8(msg,*i,0x40);//option+  SETU8(msg, *i, (uint8_t)0x00);  +  SETU8(msg, *i, (uint8_t)0x04);  /* Sub command, EAS Alarm */++  SETU8(msg, *i, (uint8_t)dr);    +  SETU8(msg, *i, (uint8_t)m);+  SETU8(msg, *i, (uint8_t)trExt);+}++/**+ * NXP EAS Alarm+ * Chip type = 0x02 or 0x07, Command = 0x04+ *  + * @param reader The reader+ * @param timeout The timeout of the operation, in milliseconds. Valid range is 0-65535.+ * @param chip The NXP Chip type (G2iL or G2xL)+ * @param dr Gen2 divide ratio to use+ * @param m Gen2 M(tag encoding) parameter to use+ * @param trExt Gen2 TrExt value to use+ * @param data 8 bytes of EAS alarm data will be returned, on successful operation+ * @param target Filter to be applied.+ */+TMR_Status TMR_SR_cmdNxpEasAlarm(TMR_Reader *reader, uint16_t timeout,+            TMR_SR_GEN2_SiliconType chip, TMR_GEN2_DivideRatio dr, TMR_GEN2_TagEncoding m, TMR_GEN2_TrExt trExt,+            TMR_uint8List *data, TMR_TagFilter* target)+{+  TMR_Status ret;+  uint8_t msg[TMR_SR_MAX_PACKET_SIZE];+  uint8_t i;+  i = 2;++  if (NULL != target)+  {  /* EAS Alarm command is sent without any singulation of the tag*/+    return TMR_ERROR_UNSUPPORTED;+  }+  TMR_SR_msgAddNXPEASAlarm(msg, &i, timeout, chip, dr, m, trExt, target);+  msg[1] = i - 3; /* Install length */++  ret = TMR_SR_sendTimeout(reader, msg, timeout);+  if (TMR_SUCCESS != ret)+  {+    return ret;+  }+  +  +  /* Alarm data always starts at position 9 */+  /*  FF    0A    2D   00 00    xx        40         00 04            [8 bytes]       ?? ??+   *  SOH Length OpCode Status ChipType  option     SubCommand      [EAS AlarmData]      CRC+   */+  i = 9;+  if (NULL != data)+  {+    uint16_t copyLength;+    +    copyLength = msg[1] + 5 - i;+    memcpy(data->list, &msg[i], copyLength);    +    data->len = copyLength;    +  }++  return TMR_SUCCESS;+}++/** Helper routine to form the NXP Calibrate command **/+void TMR_SR_msgAddNXPCalibrate(uint8_t *msg, uint8_t *i, uint16_t timeout, +                               TMR_SR_GEN2_SiliconType chip, TMR_GEN2_Password accessPassword, TMR_TagFilter* target)+{+  uint8_t option=0,rec; ++  SETU8(msg, *i, TMR_SR_OPCODE_WRITE_TAG_SPECIFIC);+  SETU16(msg, *i, timeout);+  SETU8(msg, *i, (uint8_t)chip);  /* Chip - type*/+  +  rec=*i;+  SETU8(msg,*i,0x40);//option+  SETU8(msg, *i, (uint8_t)0x00);+  SETU8(msg, *i, (uint8_t)0x05);  /* Sub command, Calibrate */++  filterbytes(TMR_TAG_PROTOCOL_GEN2, target, &option, i, msg, 0, false); +  msg[rec]=msg[rec]|option;+  +  SETU32(msg, *i, accessPassword);+}+/**+ * NXP Calibrate (only for G2xL)+ * Chip type = 0x02, Command = 0x05+ *  + * @param reader The reader+ * @param timeout The timeout of the operation, in milliseconds. Valid range is 0-65535.+ * @param chip The NXP Chip type (G2iL or G2xL)+ * @param accessPassword The access password to use to write on the tag+ * @param data  64 bytes of calibration data will be returned on a successful operation+ * @param target Filter to be applied.+ */+TMR_Status TMR_SR_cmdNxpCalibrate(TMR_Reader *reader, uint16_t timeout,+                                  TMR_SR_GEN2_SiliconType chip, TMR_GEN2_Password accessPassword, TMR_uint8List *data, TMR_TagFilter* target)+{+  TMR_Status ret;+  uint8_t msg[TMR_SR_MAX_PACKET_SIZE];+  uint8_t i;+  i = 2;++  TMR_SR_msgAddNXPCalibrate(msg, &i, timeout, chip, accessPassword, target);+  msg[1] = i - 3; /* Install length */++  ret = TMR_SR_sendTimeout(reader, msg, timeout);+  if (TMR_SUCCESS != ret)+  {+    return ret;+  }+  +  +  /* Calibration data always starts at position 9 */+  /* FF    42     2D    00 00     xx     40       00 05         [64 bytes]     ?? ??+   * SOH Length OpCode Status  ChipType  option  SubCommand   [CalibrateData]     CRC+   */+  i = 9;+  if (NULL != data)+  {    +    uint16_t copyLength;+    +    copyLength = msg[1] + 5 - i;+    memcpy(data->list, &msg[i], copyLength);    +    data->len = copyLength;+  }++  return TMR_SUCCESS;+}++/** Helper routine to form the NXP ChangeConfig command **/+void TMR_SR_msgAddNXPChangeConfig(uint8_t *msg, uint8_t *i, uint16_t timeout,+        TMR_SR_GEN2_SiliconType chip, TMR_GEN2_Password accessPassword, TMR_NXP_ConfigWord configWord, TMR_TagFilter* target)+{+  //uint16_t configData;+  uint8_t option=0,rec; ++  SETU8(msg, *i, TMR_SR_OPCODE_WRITE_TAG_SPECIFIC);+  SETU16(msg, *i, timeout);+  SETU8(msg, *i, (uint8_t)chip);  /* Chip - type*/+  rec=*i;+  SETU8(msg,*i,0x40);//option+  SETU8(msg, *i, (uint8_t)0x00);+  SETU8(msg, *i, (uint8_t)0x07);  /* Sub command, ChangeConfig */+  filterbytes(TMR_TAG_PROTOCOL_GEN2, target, &option, i, msg, accessPassword, true); +  msg[rec]=msg[rec]|option;+  SETU8(msg, *i, (uint8_t)0x00); //RFU  +  SETU16(msg, *i, configWord.data);+}++/**+ * NXP ChangeConfig (only for G2iL)+ * Chip type = 0x07, Command = 0x07+ *  + * @param reader The reader+ * @param timeout The timeout of the operation, in milliseconds. Valid range is 0-65535.+ * @param chip The NXP Chip type (G2iL or G2xL)+ * @param accessPassword The access password to use to write on the tag+ * @param configWord (I/O)The config word to write on the tag. + * @param data If the operation is success, this data contains the current configword setting on the tag.+ * @param target Filter to be applied.+ */+TMR_Status TMR_SR_cmdNxpChangeConfig(TMR_Reader *reader, uint16_t timeout,+            TMR_SR_GEN2_SiliconType chip, TMR_GEN2_Password accessPassword, TMR_NXP_ConfigWord configWord,+            TMR_uint8List *data, TMR_TagFilter* target)+{+  TMR_Status ret;+  uint8_t msg[TMR_SR_MAX_PACKET_SIZE];+  uint8_t i;+  i = 2;++  if (chip == TMR_SR_GEN2_NXP_G2X_SILICON)+  {+    /* ChangeConfig works only for G2iL tags*/+    return TMR_ERROR_UNSUPPORTED;  +  }+  +  TMR_SR_msgAddNXPChangeConfig(msg, &i, timeout, chip, accessPassword, configWord, target);+  msg[1] = i - 3; /* Install length */++  ret = TMR_SR_sendTimeout(reader, msg, timeout);+  if (TMR_SUCCESS != ret)+  {+    return ret;+  }++  /* Parse the config data from response back to the user */+  i = 9;  +  /* FF    06     2d    00 00      07     40     00 07         80 46        59 2f+   * SOH Length OpCode Status  ChipType  option  SubCommand  [ConfigData]     CRC+   */+  {+    uint16_t copyLength;+    +    copyLength = msg[1] + 5 - i;+    if (NULL != data)+    {+      memcpy(data->list, &msg[i], copyLength);+      data->len = copyLength;+    }+  }+  return TMR_SUCCESS;+}++void TMR_SR_msgAddGen2v2NxpUntraceable(uint8_t *msg, uint8_t *i, uint16_t timeout,+									   TMR_SR_GEN2_SiliconType chip, TMR_GEN2_Password accessPassword, uint16_t configWord, +									   TMR_TagOp_GEN2_NXP_Untraceable op ,TMR_TagFilter* target)+{+	uint8_t option=0,rec; +	SETU8(msg, *i, TMR_SR_OPCODE_WRITE_TAG_SPECIFIC);+	SETU16(msg, *i, timeout);+	SETU8(msg, *i, (uint8_t)chip);  /* Chip - type*/+	rec=*i;+	SETU8(msg,*i,0x00);//option+	SETU8(msg, *i, (uint8_t)op.subCommand);  /* Sub command, Untraceable */+	filterbytes(TMR_TAG_PROTOCOL_GEN2, target, &option, i, msg, accessPassword, false); +	msg[rec]=msg[rec]|option;+	SETU16(msg, *i, configWord);+	if(op.subCommand == 0x02)// Untraceable with Authentication+	{+		SETU8(msg,*i, op.auth.tam1Auth.Authentication);+		SETU8(msg,*i,op.auth.tam1Auth.CSI);+		SETU8(msg,*i,op.auth.tam1Auth.keyID);+		SETU8(msg,*i,op.auth.tam1Auth.KeyLength);	+		{+			uint32_t iWord;+			for (iWord = 0; iWord < op.auth.tam1Auth.Key.len; iWord++)+			{+				SETU8(msg, *i, (op.auth.tam1Auth.Key.list[iWord]));+				// SETU8(msg, *i, ((op.auth.tam1Auth.Key.list[iWord]>>0)&0xFF));+			}+		}+		SETU8(msg,*i,op.auth.tam1Auth.IchallengeLength);+		{+			uint32_t iWord;+			for (iWord = 0; iWord < op.auth.tam1Auth.Ichallenge.len; iWord++)+			{+				SETU8(msg, *i, (op.auth.tam1Auth.Ichallenge.list[iWord]));+				//SETU8(msg, *i, ((op.auth.tam1Auth.Ichallenge.list[iWord]>>0)&0xFF));+			}+		}+	}+	else //Untraceable with Access +	{+		SETU32(msg, *i,op.auth.accessPassword);+	}+}++TMR_Status TMR_SR_cmdGen2v2NXPUntraceable(TMR_Reader *reader, uint16_t timeout,+										  TMR_SR_GEN2_SiliconType chip, TMR_GEN2_Password accessPassword, uint16_t configWord,+										  TMR_TagOp_GEN2_NXP_Untraceable op,TMR_uint8List *data, TMR_TagFilter* target)+{+	TMR_Status ret;+	uint8_t msg[TMR_SR_MAX_PACKET_SIZE];+	uint8_t i;+	i = 2;++	TMR_SR_msgAddGen2v2NxpUntraceable(msg, &i, timeout, chip, accessPassword, configWord, op ,target);+	msg[1] = i - 3; /* Install length */++	ret = TMR_SR_sendTimeout(reader, msg, timeout);+	if (TMR_SUCCESS != ret)+	{+		return ret;+	}+	return TMR_SUCCESS;+}+uint8_t getCmdProtModeBlockCount(uint8_t protMode, uint8_t blockCount)+{+	uint8_t protModeBlockCount = 0x01; //The UCODE AES Tag only supports ProtMode = "0001b" (CBC encryption)+	uint16_t mask = 0x0F;+	int pos = 4;+	protModeBlockCount |= ((blockCount & mask) << pos);++	return protModeBlockCount;+}+uint16_t getCmdProfileOffset(uint16_t profile, uint16_t offset)+{+	uint16_t profileOffset = 0x0000;+	uint16_t mask;+	int pos;++	mask = 0xF;+	pos = 12;+	profileOffset |= ((profile & mask) << pos);++	mask = 0xFFF;+	pos = 0;+	profileOffset |= ((offset & mask) << pos);++	return profileOffset;+}+void TMR_SR_msgAddGen2v2NxpAuthenticate(uint8_t *msg, uint8_t *i, uint16_t timeout,TMR_SR_GEN2_SiliconType chip,+										TMR_GEN2_Password accessPassword,TMR_TagOp_GEN2_NXP_Authenticate op ,TMR_TagFilter* target)+{+	uint8_t option=0,rec; +	SETU8(msg, *i, TMR_SR_OPCODE_WRITE_TAG_SPECIFIC);+	SETU16(msg, *i, timeout);+	SETU8(msg, *i, (uint8_t)chip);  /* Chip - type*/+	rec=*i;+	SETU8(msg,*i,0x00);//option+	SETU8(msg, *i, (uint8_t)op.subCommand);  /* Sub command, Untraceable */+	filterbytes(TMR_TAG_PROTOCOL_GEN2, target, &option, i, msg, accessPassword, false); +	msg[rec]=msg[rec]|option;+	SETU8(msg,*i, op.tam1Auth.Authentication);+	SETU8(msg,*i,op.tam1Auth.CSI);+	SETU8(msg,*i,op.tam1Auth.keyID);+	SETU8(msg,*i,op.tam1Auth.KeyLength);	+	{+		uint8_t iWord;+		for (iWord = 0; iWord < op.tam1Auth.Key.len; iWord++)+		{+			SETU8(msg, *i, (op.tam1Auth.Key.list[iWord]));+		}+	}+	SETU8(msg,*i,op.tam1Auth.IchallengeLength);+	{+		uint8_t iWord;+		for (iWord = 0; iWord < op.tam1Auth.Ichallenge.len; iWord++)+		{+			SETU8(msg, *i, (op.tam1Auth.Ichallenge.list[iWord]));+		}+	}+	if(op.type == TAM2_AUTHENTICATION)+	{+		SETU16(msg, *i, getCmdProfileOffset(op.tam2Auth.profile,op.tam2Auth.Offset));+		SETU8(msg, *i, getCmdProtModeBlockCount(op.tam2Auth.ProtMode,op.tam2Auth.BlockCount));+	}+}++TMR_Status TMR_SR_cmdGen2v2NXPAuthenticate(TMR_Reader *reader, uint16_t timeout,TMR_SR_GEN2_SiliconType chip,+										   TMR_GEN2_Password accessPassword, TMR_TagOp_GEN2_NXP_Authenticate op, TMR_uint8List *data, TMR_TagFilter* target)+{+	TMR_Status ret;+	uint8_t msg[TMR_SR_MAX_PACKET_SIZE];+	uint8_t i;+	i = 2;++	TMR_SR_msgAddGen2v2NxpAuthenticate(msg, &i, timeout, chip, accessPassword, op ,target);+	msg[1] = i - 3; /* Install length */++	ret = TMR_SR_sendTimeout(reader, msg, timeout);++	if (TMR_SUCCESS != ret)+	{+		return ret;+	}++	if (NULL != data->list)+	{+		i = 8;+		{+			uint16_t dataLength;+			uint16_t copyLength;++			copyLength = dataLength = msg[1] + 5 - i;+			if (copyLength > data->max)+			{+				copyLength = data->max;+			}+			data->len = copyLength;+			memcpy(data->list, &msg[i], copyLength);+			i += dataLength;+		}+	}+	return TMR_SUCCESS;+}+uint16_t getCmdWordPointer(uint16_t wordPointer)+{+	uint16_t rdBufferWordPointer = 0x0000;+	if (wordPointer > 0)+	{+		uint16_t mask = 0x0FFF;+		int pos = 0;+		rdBufferWordPointer |= ((wordPointer & mask) << pos);+	}+	return rdBufferWordPointer;+}+uint16_t getCmdBitCount(uint16_t bitCount)+{+	uint16_t rdBufferBitCount = 0x0000;+	if (bitCount > 0)+	{+		uint16_t mask = 0x0FFF;+		int pos = 0;+		rdBufferBitCount |= ((bitCount & mask) << pos);+	}+	return rdBufferBitCount;+}+void TMR_SR_msgAddGen2v2NxpReadBuffer(uint8_t *msg, uint8_t *i, uint16_t timeout,TMR_SR_GEN2_SiliconType chip,+									  TMR_GEN2_Password accessPassword,TMR_TagOp_GEN2_NXP_Readbuffer op ,TMR_TagFilter* target)+{+	uint8_t option=0,rec; +	SETU8(msg, *i, TMR_SR_OPCODE_WRITE_TAG_SPECIFIC);+	SETU16(msg, *i, timeout);+	SETU8(msg, *i, (uint8_t)chip);  /* Chip - type*/+	rec=*i;+	SETU8(msg,*i,0x00);//option+	SETU8(msg, *i, (uint8_t)op.authenticate.subCommand);  /* Sub command, Untraceable */+	filterbytes(TMR_TAG_PROTOCOL_GEN2, target, &option, i, msg, accessPassword, false); +	msg[rec]=msg[rec]|option;+	SETU16(msg, *i, getCmdWordPointer(op.wordPointer));+	SETU16(msg, *i, getCmdBitCount(op.bitCount));+	SETU8(msg,*i, op.authenticate.tam1Auth.Authentication);+	SETU8(msg,*i,op.authenticate.tam1Auth.CSI);+	SETU8(msg,*i,op.authenticate.tam1Auth.keyID);+	SETU8(msg,*i,op.authenticate.tam1Auth.KeyLength);	+	{+		uint8_t iWord;+		for (iWord = 0; iWord < op.authenticate.tam1Auth.Key.len; iWord++)+		{+			SETU8(msg, *i, (op.authenticate.tam1Auth.Key.list[iWord]));+		}+	}+	SETU8(msg,*i,op.authenticate.tam1Auth.IchallengeLength);+	{+		uint8_t iWord;+		for (iWord = 0; iWord < op.authenticate.tam1Auth.Ichallenge.len; iWord++)+		{+			SETU8(msg, *i, (op.authenticate.tam1Auth.Ichallenge.list[iWord]));+		}+	}+	if(op.authenticate.type == TAM2_AUTHENTICATION)+	{+		SETU16(msg, *i, getCmdProfileOffset(op.authenticate.tam2Auth.profile,op.authenticate.tam2Auth.Offset));+		SETU8(msg, *i, getCmdProtModeBlockCount(op.authenticate.tam2Auth.ProtMode,op.authenticate.tam2Auth.BlockCount));+	}+}++TMR_Status TMR_SR_cmdGen2v2NXPReadBuffer(TMR_Reader *reader, uint16_t timeout,TMR_SR_GEN2_SiliconType chip,+										 TMR_GEN2_Password accessPassword, TMR_TagOp_GEN2_NXP_Readbuffer op, TMR_uint8List *data, TMR_TagFilter* target)+{+	TMR_Status ret;+	uint8_t msg[TMR_SR_MAX_PACKET_SIZE];+	uint8_t i;+	i = 2;++	TMR_SR_msgAddGen2v2NxpReadBuffer(msg, &i, timeout, chip, accessPassword, op ,target);+	msg[1] = i - 3; /* Install length */++	ret = TMR_SR_sendTimeout(reader, msg, timeout);+	if (TMR_SUCCESS != ret)+	{+		return ret;+	}+	if (NULL != data->list)+	{+		i = 8;+		{+			uint16_t dataLength;+			uint16_t copyLength;++			copyLength = dataLength = msg[1] + 5 - i;+			if (copyLength > data->max)+			{+				copyLength = data->max;+			}+			data->len = copyLength;+			memcpy(data->list, &msg[i], copyLength);+			i += dataLength;+		}+	}+	return TMR_SUCCESS;+}+/** + *  Monza4 Silicon Specific Commands+ *  Chip Type = 0x08+ **/++/** Helper routine to form the Monza4 QT Read/Write command **/+void TMR_SR_msgAddMonza4QTReadWrite(uint8_t *msg, uint8_t *i, uint16_t timeout, TMR_GEN2_Password accessPassword,+                                TMR_Monza4_ControlByte controlByte, TMR_Monza4_Payload payload, TMR_TagFilter* target)+{+  uint8_t option=0,rec; ++  SETU8(msg, *i, TMR_SR_OPCODE_WRITE_TAG_SPECIFIC);+  SETU16(msg, *i, timeout);+  SETU8(msg, *i, (uint8_t)TMR_SR_GEN2_IMPINJ_MONZA4_SILICON);  /* Chip - type*/+  rec=*i;+  SETU8(msg,*i,0x40);//option+  SETU8(msg, *i, (uint8_t)0x00);+  SETU8(msg, *i, (uint8_t)0x00);  /* Sub command, QT Read/Write */+  filterbytes(TMR_TAG_PROTOCOL_GEN2, target, &option, i, msg, accessPassword, true); +  msg[rec]=msg[rec]|option;+  SETU8(msg, *i, controlByte.data);+  SETU16(msg, *i, payload.data);+}++/**+ * Impinj Monza4 QT Read/Write+ * Chip type = 0x08, command = 0x00+ *  + * @param reader The reader+ * @param timeout The timeout of the operation, in milliseconds. Valid range is 0-65535.+ * @param accessPassword The access password to use to write on the tag+ * @param controlByte The control byte to write on the tag+ * @param payload The payload + * @param data If the operation is success, this data contains the payload+ *             When Read/Write (bit) = 0, then the payload is the value read,+ *             When Read/Write (bit) = 1, then the payload is the value written.+ * @param target Filter to be applied.+ */+TMR_Status TMR_SR_cmdMonza4QTReadWrite(TMR_Reader *reader, uint16_t timeout, TMR_GEN2_Password accessPassword, +                                       TMR_Monza4_ControlByte controlByte, TMR_Monza4_Payload payload, TMR_uint8List *data, TMR_TagFilter* target)+{+  TMR_Status ret;+  uint8_t msg[TMR_SR_MAX_PACKET_SIZE];+  uint8_t i;+  i = 2;++  TMR_SR_msgAddMonza4QTReadWrite(msg, &i, timeout, accessPassword, controlByte, payload, target);+  msg[1] = i - 3; /* Install length */++  ret = TMR_SR_sendTimeout(reader, msg, timeout);+  if (TMR_SUCCESS != ret)+  {+    return ret;+  }+  +  /* Parse the payload data from response back to the user */+  i = 9;  +  /* FF    06     2d    00 00      08     40     00 00         xx xx        xx xx+   * SOH Length OpCode Status  ChipType  option  SubCommand  [payload]      CRC+   */+  {+    uint16_t copyLength;+    +    copyLength = msg[1] + 5 - i;+    if (NULL != data)+    {+      memcpy(data->list, &msg[i], copyLength);+      data->len = copyLength;+    }+  }+  return TMR_SUCCESS;++}++/**+ * IDS SL900A specific commands+ * chip type 0A+ */++/**+ * Helper routine to form the IDS SL900A get battery level command+ */+void TMR_SR_msgAddIdsSL900aGetBatteryLevel(uint8_t *msg, uint8_t *i, uint16_t timeout, TMR_GEN2_Password accessPassword,+                                           uint8_t CommandCode, uint32_t password, PasswordLevel level, BatteryType batteryType,+                                           TMR_TagFilter* target)+{+  uint8_t option = 0, rec;++  SETU8(msg, *i, TMR_SR_OPCODE_WRITE_TAG_SPECIFIC);+  SETU16(msg, *i, timeout);+  SETU8(msg, *i, (uint8_t)TMR_SR_GEN2_IDS_SL900A_SILICON); /* chip type */+  rec = *i;+  SETU8(msg,*i,0x40);//option+  SETU8(msg, *i, (uint8_t)0x00);+  SETU8(msg, *i, (uint8_t)CommandCode);+  filterbytes(TMR_TAG_PROTOCOL_GEN2, target, &option, i, msg, accessPassword, true);+  msg[rec]=msg[rec]|option;+  SETU8(msg, *i, (uint8_t)level);+  SETU32(msg, *i, password);+  SETU8(msg, *i, batteryType);+}++/**+ * IDS SL900A  Get Battery Level+ * Chip type = 0x0A, command = 0x00 AA+ *+ * @param reader The reader+ * @param timeout The timeout of the operation, in milliseconds. Valid range is 0-65535.+ * @param accessPassword The access password to use to write on the tag+ * @param commandcode to specify the operation+ * @param password to specify SL900A password access level values+ * @param data If the operation is success, this data contains the requested value+ * @param target Filter to be applied.+ */+TMR_Status+TMR_SR_cmdSL900aGetBatteryLevel(TMR_Reader *reader, uint16_t timeout, TMR_GEN2_Password accessPassword,+                                uint8_t CommandCode, uint32_t password, PasswordLevel level,BatteryType type,+                                TMR_uint8List *data, TMR_TagFilter* target)+{+  TMR_Status ret;+  uint8_t msg[TMR_SR_MAX_PACKET_SIZE];+  uint8_t i;+  i = 2;++  TMR_SR_msgAddIdsSL900aGetBatteryLevel(msg, &i, timeout, accessPassword, CommandCode, password, level, type, target);+  msg[1] = i - 3; /* Install length */++  ret = TMR_SR_sendTimeout(reader, msg, timeout);+  if (TMR_SUCCESS != ret)+  {+    return ret;+  }++  /* Parse the battery level data from response back to the user */+  i = 9;+  /* FF    06     2d    00 00      0A     42     00 AD         xx xx        xx xx+   * SOH Length OpCode Status  ChipType  option  SubCommand    [level]       CRC+   */+  {+    uint16_t copyLength;+    +    copyLength = msg[1] + 5 - i;+    if (NULL != data)+    {+      memcpy(data->list, &msg[i], copyLength);+      data->len = copyLength;+    }+  }+  return TMR_SUCCESS;+}++/**+ *  Helper routine to form the IDS SL900A get sensor value command+ */+void TMR_SR_msgAddIdsSL900aGetSensorValue(uint8_t *msg, uint8_t *i, uint16_t timeout, TMR_GEN2_Password accessPassword,+                                          uint8_t CommandCode, uint32_t password, PasswordLevel level, Sensor sensortype,+                                          TMR_TagFilter* target)+{+  uint8_t option = 0, rec;++  SETU8(msg, *i, TMR_SR_OPCODE_WRITE_TAG_SPECIFIC);+  SETU16(msg, *i, timeout);+  SETU8(msg, *i, (uint8_t)TMR_SR_GEN2_IDS_SL900A_SILICON); /* chip type */+  rec = *i;+  SETU8(msg,*i,0x40);//option+  SETU8(msg, *i, (uint8_t)0x00);+  SETU8(msg, *i, (uint8_t)CommandCode);+  filterbytes(TMR_TAG_PROTOCOL_GEN2, target, &option, i, msg, accessPassword, true);+  msg[rec]=msg[rec]|option;+  SETU8(msg, *i, (uint8_t)level);+  SETU32(msg, *i, password);+  SETU8(msg, *i, sensortype);+}++/**+ * IDS SL900A  Get Sensor value+ * Chip type = 0x0A, command = 0x00 AD+ *+ * @param reader The reader+ * @param timeout The timeout of the operation, in milliseconds. Valid range is 0-65535.+ * @param accessPassword The access password to use to write on the tag+ * @param commandcode to specify the operation+ * @param password to specify SL900A password access level values+ * @param data If the operation is success, this data contains the requested value+ * @param target Filter to be applied.+ */+TMR_Status+TMR_SR_cmdSL900aGetSensorValue(TMR_Reader *reader, uint16_t timeout, TMR_GEN2_Password accessPassword,+                               uint8_t CommandCode, uint32_t password, PasswordLevel level,Sensor sensortype,+                                TMR_uint8List *data, TMR_TagFilter* target)+{+  TMR_Status ret;+  uint8_t msg[TMR_SR_MAX_PACKET_SIZE];+  uint8_t i;+  i = 2;++  TMR_SR_msgAddIdsSL900aGetSensorValue(msg, &i, timeout, accessPassword, CommandCode, password, level, sensortype, target);+  msg[1] = i - 3; /* Install length */++  ret = TMR_SR_sendTimeout(reader, msg, timeout);+  if (TMR_SUCCESS != ret)+  {+    return ret;+  }++  /* Parse the sensor type data from response back to the user */+  i = 9;+  /* FF    06     2d    00 00      0A     42     00 AD         xx xx        xx xx+   * SOH Length OpCode Status  ChipType  option  SubCommand    [type]       CRC+   */+  {+    uint16_t copyLength;+    +    copyLength = msg[1] + 5 - i;+    if (NULL != data)+    {+      memcpy(data->list, &msg[i], copyLength);+      data->len = copyLength;+    }+  }+  return TMR_SUCCESS;+}++/**+ *  Helper routine to form the IDS SL900A get measurment setup command+ */+void TMR_SR_msgAddIdsSL900aGetMeasurementSetup(uint8_t *msg, uint8_t *i, uint16_t timeout, TMR_GEN2_Password accessPassword,+                                          uint8_t CommandCode, uint32_t password, PasswordLevel level, TMR_TagFilter* target)+{+  uint8_t option = 0, rec;++  SETU8(msg, *i, TMR_SR_OPCODE_WRITE_TAG_SPECIFIC);+  SETU16(msg, *i, timeout);+  SETU8(msg, *i, (uint8_t)TMR_SR_GEN2_IDS_SL900A_SILICON); /* chip type */+  rec = *i;+  SETU8(msg,*i,0x40);//option+  SETU8(msg, *i, (uint8_t)0x00);+  SETU8(msg, *i, (uint8_t)CommandCode);+  filterbytes(TMR_TAG_PROTOCOL_GEN2, target, &option, i, msg, accessPassword, true);+  msg[rec]=msg[rec]|option;+  SETU8(msg, *i, (uint8_t)level);+  SETU32(msg, *i, password);+}++/**+ * IDS SL900A  Get Sensor value+ * Chip type = 0x0A, command = 0x00 A3+ *+ * @param reader The reader+ * @param timeout The timeout of the operation, in milliseconds. Valid range is 0-65535.+ * @param accessPassword The access password to use to write on the tag+ * @param commandcode to specify the operation+ * @param password to specify SL900A password access level values+ * @param data If the operation is success, this data contains the requested value+ * @param target Filter to be applied.+ */+TMR_Status+TMR_SR_cmdSL900aGetMeasurementSetup(TMR_Reader *reader, uint16_t timeout, TMR_GEN2_Password accessPassword,+                               uint8_t CommandCode, uint32_t password, PasswordLevel level,+                                TMR_uint8List *data, TMR_TagFilter* target)+{+  TMR_Status ret;+  uint8_t msg[TMR_SR_MAX_PACKET_SIZE];+  uint8_t i;+  i = 2;++  TMR_SR_msgAddIdsSL900aGetMeasurementSetup(msg, &i, timeout, accessPassword, CommandCode, password, level, target);+  msg[1] = i - 3; /* Install length */++  ret = TMR_SR_sendTimeout(reader, msg, timeout);+  if (TMR_SUCCESS != ret)+  {+    return ret;+  }++  /* Parse the measurment data from response back to the user */+  i = 9;+  /* FF    06     2d    00 00      0A     42     00 AD         xx xx    xx xx+   * SOH Length OpCode Status  ChipType  option  SubCommand    [data]   CRC+   */+  {+    uint16_t copyLength;+    +    copyLength = msg[1] + 5 - i;+    if (NULL != data)+    {+      memcpy(data->list, &msg[i], copyLength);+      data->len = copyLength;+    }+  }+  return TMR_SUCCESS;+}++/**+ *  Helper routine to form the IDS SL900A get log state command+ */+void TMR_SR_msgAddIdsSL900aGetLogState(uint8_t *msg, uint8_t *i, uint16_t timeout, TMR_GEN2_Password accessPassword,+                                       uint8_t CommandCode, uint32_t password, PasswordLevel level, TMR_TagFilter* target)+{+  uint8_t option = 0, rec;++  SETU8(msg, *i, TMR_SR_OPCODE_WRITE_TAG_SPECIFIC);+  SETU16(msg, *i, timeout);+  SETU8(msg, *i, (uint8_t)TMR_SR_GEN2_IDS_SL900A_SILICON); /* chip type */+  rec = *i;+  SETU8(msg,*i,0x40);//option+  SETU8(msg, *i, (uint8_t)0x00);+  SETU8(msg, *i, (uint8_t)CommandCode);+  filterbytes(TMR_TAG_PROTOCOL_GEN2, target, &option, i, msg, accessPassword, true);+  msg[rec]=msg[rec]|option;+  SETU8(msg, *i, (uint8_t)level);+  SETU32(msg, *i, password);+}++/**+ * IDS SL900A  Get log State+ * Chip type = 0x0A, command = 0x00 AD+ *+ * @param reader The reader+ * @param timeout The timeout of the operation, in milliseconds. Valid range is 0-65535.+ * @param accessPassword The access password to use to write on the tag+ * @param commandcode to specify the operation+ * @param password to specify SL900A password access level values+ * @param to specify SL900A sensor type+ * @param data If the operation is success, this data contains the requested value+ * @param target Filter to be applied.+ */+TMR_Status+TMR_SR_cmdSL900aGetLogState(TMR_Reader *reader, uint16_t timeout, TMR_GEN2_Password accessPassword,+                            uint8_t CommandCode, uint32_t password, PasswordLevel level,TMR_uint8List *data,+                            TMR_TagFilter* target)+{+  TMR_Status ret;+  uint8_t msg[TMR_SR_MAX_PACKET_SIZE];+  uint8_t i;+  i = 2;++  TMR_SR_msgAddIdsSL900aGetLogState(msg, &i, timeout, accessPassword, CommandCode, password, level, target);+  msg[1] = i - 3; /* Install length */++  ret = TMR_SR_sendTimeout(reader, msg, timeout);+  if (TMR_SUCCESS != ret)+  {+    return ret;+  }++  /* Parse the sensor type data from response back to the user */+  i = 9;+  /* FF    06     2d    00 00      0A     42     00 AD         xx xx        xx xx+  * SOH Length OpCode Status  ChipType  option  SubCommand    [type]       CRC+  */+  {+    uint16_t copyLength;++    copyLength = msg[1] + 5 - i;+    if (NULL != data)+    {+      memcpy(data->list, &msg[i], copyLength);+      data->len = copyLength;+    }+  }+  return TMR_SUCCESS;+}++/**+ *  Helper routine to form the IDS SL900A set log mode command+ */+void TMR_SR_msgAddIdsSL900aSetLogMode(uint8_t *msg, uint8_t *i, uint16_t timeout, TMR_GEN2_Password accessPassword,+                                      uint8_t CommandCode, uint32_t password, PasswordLevel level, LoggingForm form,+                                      StorageRule rule, bool Ext1Enable, bool Ext2Enable, bool TempEnable, bool BattEnable,+                                      uint16_t LogInterval, TMR_TagFilter* target)+{+  uint8_t option = 0, rec;+  uint32_t logmode = 0;++  SETU8(msg, *i, TMR_SR_OPCODE_WRITE_TAG_SPECIFIC);+  SETU16(msg, *i, timeout);+  SETU8(msg, *i, (uint8_t)TMR_SR_GEN2_IDS_SL900A_SILICON); /* chip type */+  rec = *i;+  SETU8(msg,*i,0x40);//option+  SETU8(msg, *i, (uint8_t)0x00);+  SETU8(msg, *i, (uint8_t)CommandCode);+  filterbytes(TMR_TAG_PROTOCOL_GEN2, target, &option, i, msg, accessPassword, true);+  msg[rec]=msg[rec]|option;+  SETU8(msg, *i, (uint8_t)level);+  SETU32(msg, *i, password);++  logmode |= (uint32_t)form << 21;+  logmode |= (uint32_t)rule << 20;+  logmode |= (uint32_t)(Ext1Enable ? 1 : 0) << 19;+  logmode |= (uint32_t)(Ext2Enable ? 1 : 0) << 18;+  logmode |= (uint32_t)(TempEnable ? 1 : 0) << 17;+  logmode |= (uint32_t)(BattEnable ? 1 : 0) << 16;+  logmode |= (uint32_t)LogInterval << 1;+  SETU8(msg, *i, (uint8_t)((logmode >> 16) & 0xFF));+  SETU8(msg, *i, (uint8_t)((logmode >> 8) & 0xFF));+  SETU8(msg, *i, (uint8_t)((logmode >> 0) & 0xFF));+}++/**+ * IDS SL900A  Get log State+ * Chip type = 0x0A, command = 0x00 AD+ *+ * @param reader The reader+ * @param timeout The timeout of the operation, in milliseconds. Valid range is 0-65535.+ * @param accessPassword The access password to use to write on the tag+ * @param commandcode to specify the operation+ * @param password to specify SL900A password access level values+ * @param level IDS password level+ * @param form IDS logging form+ * @param rule IDS storage rule+ * @param Ext1Enable to Enable log for EXT1 external sensor+ * @param Ext2Enable to Enable log for EXT2 external sensor+ * @param TempEnable to Enable log for temperature sensor+ * @param BattEnable to Enable log for battery sensor+ * @param LogInterval to Time (seconds) between log readings+ * @param target Filter to be applied.+ */+TMR_Status+TMR_SR_cmdSL900aSetLogMode(TMR_Reader *reader, uint16_t timeout, TMR_GEN2_Password accessPassword,+                           uint8_t CommandCode, uint32_t password, PasswordLevel level, LoggingForm form,+                           StorageRule rule, bool Ext1Enable, bool Ext2Enable, bool TempEnable, bool BattEnable,+                           uint16_t LogInterval, TMR_TagFilter* target)+{+  uint8_t msg[TMR_SR_MAX_PACKET_SIZE];+  uint8_t i;+  i = 2;++  TMR_SR_msgAddIdsSL900aSetLogMode(msg, &i, timeout, accessPassword, CommandCode, password, level, form,+    rule, Ext1Enable, Ext2Enable, TempEnable, BattEnable, LogInterval, target);++  msg[1] = i - 3; /* Install length */++  return TMR_SR_sendTimeout(reader, msg, timeout);+}++/* Helper routine to form the IDS SL900A initialize command */+void TMR_SR_msgAddIdsSL900aInitialize(uint8_t *msg, uint8_t *i, uint16_t timeout, TMR_GEN2_Password accessPassword,+                                      uint8_t CommandCode, uint32_t password, PasswordLevel level, uint16_t delayTime,+                                      uint16_t applicatioData, TMR_TagFilter* target)+{+  uint8_t option = 0, rec;++  SETU8(msg, *i, TMR_SR_OPCODE_WRITE_TAG_SPECIFIC);+  SETU16(msg, *i, timeout);+  SETU8(msg, *i, (uint8_t)TMR_SR_GEN2_IDS_SL900A_SILICON); /* chip type */+  rec = *i;+  SETU8(msg,*i,0x40);//option+  SETU8(msg, *i, (uint8_t)0x00);+  SETU8(msg, *i, (uint8_t)CommandCode);+  filterbytes(TMR_TAG_PROTOCOL_GEN2, target, &option, i, msg, accessPassword, true);+  msg[rec]=msg[rec]|option;+  SETU8(msg, *i, (uint8_t)level);+  SETU32(msg, *i, password);+  SETU16(msg, *i, delayTime);+  SETU16(msg, *i, applicatioData);+}++/**+ * IDS SL900A  initialize command+ * Chip type = 0x0A, command = 0x00 AC+ *+ * @param reader The reader+ * @param timeout The timeout of the operation, in milliseconds. Valid range is 0-65535.+ * @param accessPassword The access password to use to write on the tag+ * @param commandcode to specify the operation+ * @param password to specify SL900A password access level values+ * @param delayTime to secify delayTime+ * @param applicatioData to specify applicationData+ * @param target Filter to be applied.+ */+TMR_Status+TMR_SR_cmdSL900aInitialize(TMR_Reader *reader, uint16_t timeout, TMR_GEN2_Password accessPassword,+                           uint8_t CommandCode, uint32_t password, PasswordLevel level, uint16_t delayTime,+                           uint16_t applicationData, TMR_TagFilter* target)+{+  uint8_t msg[TMR_SR_MAX_PACKET_SIZE];+  uint8_t i;+  i = 2;++  TMR_SR_msgAddIdsSL900aInitialize(msg, &i, timeout, accessPassword, CommandCode, password, level, delayTime,+    applicationData, target);++  msg[1] = i - 3; /* Install length */++  return TMR_SR_sendTimeout(reader, msg, timeout);+}++/**+ *  Helper routine to form the IDS SL900A end log command+ */+void TMR_SR_msgAddIdsSL900aEndLog(uint8_t *msg, uint8_t *i, uint16_t timeout, TMR_GEN2_Password accessPassword,+                                  uint8_t CommandCode, uint32_t password, PasswordLevel level, TMR_TagFilter* target)+{+  uint8_t option = 0, rec;++  SETU8(msg, *i, TMR_SR_OPCODE_WRITE_TAG_SPECIFIC);+  SETU16(msg, *i, timeout);+  SETU8(msg, *i, (uint8_t)TMR_SR_GEN2_IDS_SL900A_SILICON); /* chip type */+  rec = *i;+  SETU8(msg,*i,0x40);//option+  SETU8(msg, *i, (uint8_t)0x00);+  SETU8(msg, *i, (uint8_t)CommandCode);+  filterbytes(TMR_TAG_PROTOCOL_GEN2, target, &option, i, msg, accessPassword, true);+  msg[rec]=msg[rec]|option;+  SETU8(msg, *i, (uint8_t)level);+  SETU32(msg, *i, password);  +}++/**+ * IDS SL900A Initialize command+ * Chip type = 0x0A, command = 0x00 A6+ *+ * @param reader The reader+ * @param timeout The timeout of the operation, in milliseconds. Valid range is 0-65535.+ * @param accessPassword The access password to use to write on the tag+ * @param commandcode to specify the operation+ * @param password to specify SL900A password access level values+ * @param data If the operation is success, this data contains the requested value+ * @param target Filter to be applied.+ */+TMR_Status+TMR_SR_cmdSL900aEndLog(TMR_Reader *reader, uint16_t timeout, TMR_GEN2_Password accessPassword,+                               uint8_t CommandCode, uint32_t password, PasswordLevel level, TMR_TagFilter* target)+{+  uint8_t msg[TMR_SR_MAX_PACKET_SIZE];+  uint8_t i;+  i = 2;++  TMR_SR_msgAddIdsSL900aEndLog(msg, &i, timeout, accessPassword, CommandCode, password, level, target);+  msg[1] = i - 3; /* Install length */++  return TMR_SR_sendTimeout(reader, msg, timeout);+}++/**+ * Helper function to form the IDS SL900A SetPassword command+ */ +void TMR_SR_msgAddIdsSL900aSetPassword(uint8_t *msg, uint8_t *i, uint16_t timeout, TMR_GEN2_Password accessPassword,+                                       uint8_t CommandCode, uint32_t password, PasswordLevel level, uint32_t newPassword,+                                       PasswordLevel newPasswordLevel, TMR_TagFilter* target)+{+  uint8_t option = 0, rec;++  SETU8(msg, *i, TMR_SR_OPCODE_WRITE_TAG_SPECIFIC);+  SETU16(msg, *i, timeout);+  SETU8(msg, *i, (uint8_t)TMR_SR_GEN2_IDS_SL900A_SILICON); /* chip type */+  rec = *i;+  SETU8(msg,*i,0x40);//option+  SETU8(msg, *i, (uint8_t)0x00);+  SETU8(msg, *i, (uint8_t)CommandCode);+  filterbytes(TMR_TAG_PROTOCOL_GEN2, target, &option, i, msg, accessPassword, true);+  msg[rec]=msg[rec]|option;+  SETU8(msg, *i, (uint8_t)level);+  SETU32(msg, *i, password);+  SETU8(msg, *i, (uint8_t)newPasswordLevel);+  SETU32(msg, *i, newPassword);+}++/**+ * IDS SL900A SetPassword command+ * Chip type = 0x0A, command = 0x00 A0+ *+ * @param reader The reader+ * @param timeout The timeout of the operation, in milliseconds. Valid range is 0-65535.+ * @param accessPassword The access password to use to write on the tag+ * @param commandcode to specify the operation+ * @param password to specify SL900A password access level values+ * @param data If the operation is success, this data contains the requested value+ * @param target Filter to be applied.+ */+TMR_Status+TMR_SR_cmdSL900aSetPassword(TMR_Reader *reader, uint16_t timeout, TMR_GEN2_Password accessPassword,+                            uint8_t CommandCode, uint32_t password, PasswordLevel level, uint32_t newPassword,+                            PasswordLevel newPasswordLevel, TMR_TagFilter* target)+{+  uint8_t msg[TMR_SR_MAX_PACKET_SIZE];+  uint8_t i;+  i = 2;++  TMR_SR_msgAddIdsSL900aSetPassword(msg, &i, timeout, accessPassword, CommandCode, password, level, newPassword, newPasswordLevel, target);+  msg[1] = i - 3; /* Install length */++  return TMR_SR_sendTimeout(reader, msg, timeout);+}++/**+ *  Helper routine to form the IDS SL900A AccessFifo Status command+ */+void TMR_SR_msgAddIdsSL900aAccessFifoStatus(uint8_t *msg, uint8_t *i, uint16_t timeout, TMR_GEN2_Password accessPassword,+                                  uint8_t CommandCode, uint32_t password, PasswordLevel level, AccessFifoOperation operation,+                                  TMR_TagFilter* target)+{+  uint8_t option = 0, rec;++  SETU8(msg, *i, TMR_SR_OPCODE_WRITE_TAG_SPECIFIC);+  SETU16(msg, *i, timeout);+  SETU8(msg, *i, (uint8_t)TMR_SR_GEN2_IDS_SL900A_SILICON); /* chip type */+  rec = *i;+  SETU8(msg,*i,0x40);//option+  SETU8(msg, *i, (uint8_t)0x00);+  SETU8(msg, *i, (uint8_t)CommandCode);+  filterbytes(TMR_TAG_PROTOCOL_GEN2, target, &option, i, msg, accessPassword, true);+  msg[rec]=msg[rec]|option;+  SETU8(msg, *i, (uint8_t)level);+  SETU32(msg, *i, password);+  SETU8(msg, *i, (uint8_t)operation);+}++/**+ * IDS SL900A AccessFifo status command+ * Chip type = 0x0A, command = 0x00 AF+ *+ * @param reader The reader+ * @param timeout The timeout of the operation, in milliseconds. Valid range is 0-65535.+ * @param accessPassword The access password to use to write on the tag+ * @param commandcode to specify the operation+ * @param password to specify SL900A password access level values+ * @param data If the operation is success, this data contains the requested value+ * @param target Filter to be applied.+ */+TMR_Status+TMR_SR_cmdSL900aAccessFifoStatus(TMR_Reader *reader, uint16_t timeout, TMR_GEN2_Password accessPassword, uint8_t CommandCode,+                                 uint32_t password, PasswordLevel level, AccessFifoOperation operation,TMR_uint8List *data, TMR_TagFilter* target)+{+  TMR_Status ret;+  uint8_t msg[TMR_SR_MAX_PACKET_SIZE];+  uint8_t i;+  i = 2;++  TMR_SR_msgAddIdsSL900aAccessFifoStatus(msg, &i, timeout, accessPassword, CommandCode, password, level, operation, target);+  msg[1] = i - 3; /* Install length */++  ret = TMR_SR_sendTimeout(reader, msg, timeout);+  if (TMR_SUCCESS != ret)+  {+    return ret;+  }++  /* Parse the sensor type data from response back to the user */+  i = 9;+  /* FF    06     2d    00 00      0A     42     00 AF         xx xx        xx xx+  * SOH Length OpCode Status  ChipType  option  SubCommand    [type]       CRC+  */+  {+    uint16_t copyLength;++    copyLength = msg[1] + 5 - i;+    if (NULL != data)+    {+      memcpy(data->list, &msg[i], copyLength);+      data->len = copyLength;+    }+  }+  return TMR_SUCCESS;+}++/**+ *  Helper routine to form the IDS SL900A AccessFifo Read command+ */+void TMR_SR_msgAddIdsSL900aAccessFifoRead(uint8_t *msg, uint8_t *i, uint16_t timeout, TMR_GEN2_Password accessPassword,+                                  uint8_t CommandCode, uint32_t password, PasswordLevel level, AccessFifoOperation operation,+                                  uint8_t length, TMR_TagFilter* target)+{+  uint8_t option = 0, rec;++  SETU8(msg, *i, TMR_SR_OPCODE_WRITE_TAG_SPECIFIC);+  SETU16(msg, *i, timeout);+  SETU8(msg, *i, (uint8_t)TMR_SR_GEN2_IDS_SL900A_SILICON); /* chip type */+  rec = *i;+  SETU8(msg,*i,0x40);//option+  SETU8(msg, *i, (uint8_t)0x00);+  SETU8(msg, *i, (uint8_t)CommandCode);+  filterbytes(TMR_TAG_PROTOCOL_GEN2, target, &option, i, msg, accessPassword, true);+  msg[rec]=msg[rec]|option;+  SETU8(msg, *i, (uint8_t)level);+  SETU32(msg, *i, password);+  SETU8(msg, *i, (uint8_t)(operation | length));+}++/**+ * IDS SL900A AccessFifo read command+ * Chip type = 0x0A, command = 0x00 AF+ *+ * @param reader The reader+ * @param timeout The timeout of the operation, in milliseconds. Valid range is 0-65535.+ * @param accessPassword The access password to use to write on the tag+ * @param commandcode to specify the operation+ * @param password to specify SL900A password access level values+ * @param data If the operation is success, this data contains the requested value+ * @param target Filter to be applied.+ */+TMR_Status+TMR_SR_cmdSL900aAccessFifoRead(TMR_Reader *reader, uint16_t timeout, TMR_GEN2_Password accessPassword, uint8_t CommandCode,+                               uint32_t password, PasswordLevel level, AccessFifoOperation operation, uint8_t length, TMR_uint8List *data,+                               TMR_TagFilter* target)+{+  TMR_Status ret;+  uint8_t msg[TMR_SR_MAX_PACKET_SIZE];+  uint8_t i;+  i = 2;++  TMR_SR_msgAddIdsSL900aAccessFifoRead(msg, &i, timeout, accessPassword, CommandCode, password, level, operation, length, target);+  msg[1] = i - 3; /* Install length */++  ret = TMR_SR_sendTimeout(reader, msg, timeout);+  if (TMR_SUCCESS != ret)+  {+    return ret;+  }++  /* Parse the sensor type data from response back to the user */+  i = 9;+  /* FF    06     2d    00 00      0A     42     00 AF         xx xx        xx xx+  * SOH Length OpCode Status  ChipType  option  SubCommand    [type]       CRC+  */+  {+    uint16_t copyLength;++    copyLength = msg[1] + 5 - i;+    if (NULL != data)+    {+      memcpy(data->list, &msg[i], copyLength);+      data->len = copyLength;+    }+  }+  return TMR_SUCCESS;+}++/**+ *  Helper routine to form the IDS SL900A AccessFifo Write command+ */+void TMR_SR_msgAddIdsSL900aAccessFifoWrite(uint8_t *msg, uint8_t *i, uint16_t timeout, TMR_GEN2_Password accessPassword,+                                  uint8_t CommandCode, uint32_t password, PasswordLevel level, AccessFifoOperation operation,+                                  TMR_uint8List *payLoad, TMR_TagFilter* target)+{+  uint8_t option = 0, rec;++  SETU8(msg, *i, TMR_SR_OPCODE_WRITE_TAG_SPECIFIC);+  SETU16(msg, *i, timeout);+  SETU8(msg, *i, (uint8_t)TMR_SR_GEN2_IDS_SL900A_SILICON); /* chip type */+  rec = *i;+  SETU8(msg,*i,0x40);//option+  SETU8(msg, *i, (uint8_t)0x00);+  SETU8(msg, *i, (uint8_t)CommandCode);+  filterbytes(TMR_TAG_PROTOCOL_GEN2, target, &option, i, msg, accessPassword, true);+  msg[rec]=msg[rec]|option;+  SETU8(msg, *i, (uint8_t)level);+  SETU32(msg, *i, password);+  SETU8(msg, *i, (uint8_t)(operation | payLoad->len));+  memcpy(&msg[*i], payLoad->list, payLoad->len);+  *i += payLoad->len;+}++/**+ * IDS SL900A AccessFifo Write command+ * Chip type = 0x0A, command = 0x00 AF+ *+ * @param reader The reader+ * @param timeout The timeout of the operation, in milliseconds. Valid range is 0-65535.+ * @param accessPassword The access password to use to write on the tag+ * @param commandcode to specify the operation+ * @param password to specify SL900A password access level values+ * @param data If the operation is success, this data contains the requested value+ * @param target Filter to be applied.+ */+TMR_Status+TMR_SR_cmdSL900aAccessFifoWrite(TMR_Reader *reader, uint16_t timeout, TMR_GEN2_Password accessPassword, uint8_t CommandCode,+                                uint32_t password, PasswordLevel level, AccessFifoOperation operation, TMR_uint8List *payLoad, TMR_uint8List *data,+                                TMR_TagFilter* target)+{+  TMR_Status ret;+  uint8_t msg[TMR_SR_MAX_PACKET_SIZE];+  uint8_t i;+  i = 2;++  TMR_SR_msgAddIdsSL900aAccessFifoWrite(msg, &i, timeout, accessPassword, CommandCode, password, level, operation, payLoad, target);+  msg[1] = i - 3; /* Install length */++  ret = TMR_SR_sendTimeout(reader, msg, timeout);+  if (TMR_SUCCESS != ret)+  {+    return ret;+  }++  /* Parse the sensor type data from response back to the user */+  i = 9;+  /* FF    06     2d    00 00      0A     42     00 AF         xx xx        xx xx+  * SOH Length OpCode Status  ChipType  option  SubCommand    [type]       CRC+  */+  {+    uint16_t copyLength;++    copyLength = msg[1] + 5 - i;+    if (NULL != data)+    {+      memcpy(data->list, &msg[i], copyLength);+      data->len = copyLength;+    }+  }+  return TMR_SUCCESS;+}++/**+ *  Helper routine to form the IDS SL900A Start Log command+ */+void TMR_SR_msgAddIdsSL900aStartLog(uint8_t *msg, uint8_t *i, uint16_t timeout, TMR_GEN2_Password accessPassword,+                                    uint8_t CommandCode, uint32_t password, PasswordLevel level, uint32_t time, TMR_TagFilter* target)+{+  uint8_t option = 0, rec;++  SETU8(msg, *i, TMR_SR_OPCODE_WRITE_TAG_SPECIFIC);+  SETU16(msg, *i, timeout);+  SETU8(msg, *i, (uint8_t)TMR_SR_GEN2_IDS_SL900A_SILICON); /* chip type */+  rec = *i;+  SETU8(msg,*i,0x40);//option+  SETU8(msg, *i, (uint8_t)0x00);+  SETU8(msg, *i, (uint8_t)CommandCode);+  filterbytes(TMR_TAG_PROTOCOL_GEN2, target, &option, i, msg, accessPassword, true);+  msg[rec]=msg[rec]|option;+  SETU8(msg, *i, (uint8_t)level);+  SETU32(msg, *i, password);+  SETU32(msg, *i, time);+}++/**+ * IDS SL900A StartLog command+ * Chip type = 0x0A, command = 0x00 A7+ *+ * @param reader The reader+ * @param timeout The timeout of the operation, in milliseconds. Valid range is 0-65535.+ * @param accessPassword The access password to use to write on the tag+ * @param commandcode to specify the operation+ * @param password to specify SL900A password access level values+ * @param startTime to specify count start time+ * @param target Filter to be applied.+ */+TMR_Status+TMR_SR_cmdSL900aStartLog(TMR_Reader *reader, uint16_t timeout, TMR_GEN2_Password accessPassword, uint8_t CommandCode,+                         uint32_t password, PasswordLevel level, uint32_t time, TMR_TagFilter* target)+{+  uint8_t msg[TMR_SR_MAX_PACKET_SIZE];+  uint8_t i;+  i = 2;++  TMR_SR_msgAddIdsSL900aStartLog(msg, &i, timeout, accessPassword, CommandCode, password, level, time, target);+  msg[1] = i - 3; /* Install length */++  return TMR_SR_sendTimeout(reader, msg, timeout);+}++/**+ *  Helper routine to form the IDS SL900A get calibration data  command+ */+void TMR_SR_msgAddIdsSL900aGetCalibrationData(uint8_t *msg, uint8_t *i, uint16_t timeout, TMR_GEN2_Password accessPassword,+                                          uint8_t CommandCode, uint32_t password, PasswordLevel level, TMR_TagFilter* target)+{+  uint8_t option = 0, rec;++  SETU8(msg, *i, TMR_SR_OPCODE_WRITE_TAG_SPECIFIC);+  SETU16(msg, *i, timeout);+  SETU8(msg, *i, (uint8_t)TMR_SR_GEN2_IDS_SL900A_SILICON); /* chip type */+  rec = *i;+  SETU8(msg,*i,0x40);//option+  SETU8(msg, *i, (uint8_t)0x00);+  SETU8(msg, *i, (uint8_t)CommandCode);+  filterbytes(TMR_TAG_PROTOCOL_GEN2, target, &option, i, msg, accessPassword, true);+  msg[rec]=msg[rec]|option;+  SETU8(msg, *i, (uint8_t)level);+  SETU32(msg, *i, password);+}++/**+ * IDS SL900A  Get Calibration Data+ * Chip type = 0x0A, command = 0x00 A9+ *+ * @param reader The reader+ * @param timeout The timeout of the operation, in milliseconds. Valid range is 0-65535.+ * @param accessPassword The access password to use to write on the tag+ * @param commandcode to specify the operation+ * @param password to specify SL900A password access level values+ * @param data If the operation is success, this data contains the requested value+ * @param target Filter to be applied.+ */+TMR_Status+TMR_SR_cmdSL900aGetCalibrationData(TMR_Reader *reader, uint16_t timeout, TMR_GEN2_Password accessPassword,+                               uint8_t CommandCode, uint32_t password, PasswordLevel level,+                                TMR_uint8List *data, TMR_TagFilter* target)+{+  TMR_Status ret;+  uint8_t msg[TMR_SR_MAX_PACKET_SIZE];+  uint8_t i;+  i = 2;++  TMR_SR_msgAddIdsSL900aGetCalibrationData(msg, &i, timeout, accessPassword, CommandCode, password, level, target);+  msg[1] = i - 3; /* Install length */++  ret = TMR_SR_sendTimeout(reader, msg, timeout);+  if (TMR_SUCCESS != ret)+  {+    return ret;+  }++  /* Parse the  calibration  data from response back to the user */+  i = 9;+  /* FF    06     2d    00 00      0A     42     00 A9         xx xx        xx xx+   * SOH Length OpCode Status  ChipType  option  SubCommand    [data]       CRC+   */+  {+    uint16_t copyLength;++    copyLength = msg[1] + 5 - i;+    if (NULL != data)+    {+      memcpy(data->list, &msg[i], copyLength);+      data->len = copyLength;+    }+  }+  return TMR_SUCCESS;+}++/**+ *  Helper routine to form the IDS SL900A set calibration data  command+ */+void TMR_SR_msgAddIdsSL900aSetCalibrationData(uint8_t *msg, uint8_t *i, uint16_t timeout, TMR_GEN2_Password accessPassword,+                                          uint8_t CommandCode, uint32_t password, PasswordLevel level, uint64_t calibration, +                                          TMR_TagFilter* target)+{+  uint8_t option = 0, rec;+  uint8_t calBytes[8];++  SETU8(msg, *i, TMR_SR_OPCODE_WRITE_TAG_SPECIFIC);+  SETU16(msg, *i, timeout);+  SETU8(msg, *i, (uint8_t)TMR_SR_GEN2_IDS_SL900A_SILICON); /* chip type */+  rec = *i;+  SETU8(msg,*i,0x40);//option+  SETU8(msg, *i, (uint8_t)0x00);+  SETU8(msg, *i, (uint8_t)CommandCode);+  filterbytes(TMR_TAG_PROTOCOL_GEN2, target, &option, i, msg, accessPassword, true);+  msg[rec]=msg[rec]|option;+  SETU8(msg, *i, (uint8_t)level);+  SETU32(msg, *i, password);++  calBytes[0] = (uint8_t) (calibration >> 56);+  calBytes[1] = (uint8_t) (calibration >> 48);+  calBytes[2] = (uint8_t) (calibration >> 40);+  calBytes[3] = (uint8_t) (calibration >> 32);+  calBytes[4] = (uint8_t) (calibration >> 24);+  calBytes[5] = (uint8_t) (calibration >> 16);+  calBytes[6] = (uint8_t) (calibration >> 8);+  calBytes[7] = (uint8_t) (calibration >> 0);++  memcpy(&msg[*i], calBytes + 1, 7);+  *i += 7;++}++/**+ * IDS SL900A  Set Calibration Data+ * Chip type = 0x0A, command = 0x00 A5+ *+ * @param reader The reader+ * @param timeout The timeout of the operation, in milliseconds. Valid range is 0-65535.+ * @param accessPassword The access password to use to write on the tag+ * @param commandcode to specify the operation+ * @param password to specify SL900A password access level values+ * @param calibration to spcify the calibration data+ * @param target Filter to be applied.+ */+TMR_Status+TMR_SR_cmdSL900aSetCalibrationData(TMR_Reader *reader, uint16_t timeout, TMR_GEN2_Password accessPassword, +    uint8_t CommandCode, uint32_t password, PasswordLevel level, uint64_t calibration,+    TMR_TagFilter* target)+{+  uint8_t msg[TMR_SR_MAX_PACKET_SIZE];+  uint8_t i;+  i = 2;++  TMR_SR_msgAddIdsSL900aSetCalibrationData(msg, &i, timeout, accessPassword, CommandCode, password, level, calibration, target);+  msg[1] = i - 3; /* Install length */++  return TMR_SR_sendTimeout(reader, msg, timeout);+}++/**+ *  Helper routine to form the IDS SL900A set sfe parameters command+ */+void TMR_SR_msgAddIdsSL900aSetSfeParameters(uint8_t *msg, uint8_t *i, uint16_t timeout, TMR_GEN2_Password accessPassword,+                                          uint8_t CommandCode, uint32_t password, PasswordLevel level, uint16_t sfe,+                                          TMR_TagFilter* target)+{+  uint8_t option = 0, rec;++  SETU8(msg, *i, TMR_SR_OPCODE_WRITE_TAG_SPECIFIC);+  SETU16(msg, *i, timeout);+  SETU8(msg, *i, (uint8_t)TMR_SR_GEN2_IDS_SL900A_SILICON); /* chip type */+  rec = *i;+  SETU8(msg,*i,0x40);//option+  SETU8(msg, *i, (uint8_t)0x00);+  SETU8(msg, *i, (uint8_t)CommandCode);+  filterbytes(TMR_TAG_PROTOCOL_GEN2, target, &option, i, msg, accessPassword, true);+  msg[rec]=msg[rec]|option;+  SETU8(msg, *i, (uint8_t)level);+  SETU32(msg, *i, password);+  SETU16(msg, *i, sfe);+}++/**+ * IDS SL900A  Set Calibration Data+ * Chip type = 0x0A, command = 0x00 A4+ *+ * @param reader The reader+ * @param timeout The timeout of the operation, in milliseconds. Valid range is 0-65535.+ * @param accessPassword The access password to use to write on the tag+ * @param commandcode to specify the operation+ * @param password to specify SL900A password access level values+ * @param sfe to spcify the sfe parameters+ * @param target Filter to be applied.+ */+TMR_Status+TMR_SR_cmdSL900aSetSfeParameters(TMR_Reader *reader, uint16_t timeout, TMR_GEN2_Password accessPassword, +    uint8_t CommandCode, uint32_t password, PasswordLevel level, uint16_t sfe,+    TMR_TagFilter* target)+{+  uint8_t msg[TMR_SR_MAX_PACKET_SIZE];+  uint8_t i;+  i = 2;++  TMR_SR_msgAddIdsSL900aSetSfeParameters(msg, &i, timeout, accessPassword, CommandCode, password, level, sfe, target);+  msg[1] = i - 3; /* Install length */++  return TMR_SR_sendTimeout(reader, msg, timeout);+}++/**+ * Helper routine to form the IDS Sl900A set log mode command+ */+void TMR_SR_msgAddIdsSL900aSetLogLimit(uint8_t *msg, uint8_t *i, uint16_t timeout, TMR_GEN2_Password accessPassword,+                                       uint8_t CommandCode, uint32_t password, PasswordLevel level, uint16_t exLower,+                                       uint16_t lower, uint16_t upper, uint16_t exUpper, TMR_TagFilter* target)+{+  uint8_t option = 0, rec;+  uint64_t temp = 0;++  SETU8(msg, *i, TMR_SR_OPCODE_WRITE_TAG_SPECIFIC);+  SETU16(msg, *i, timeout);+  SETU8(msg, *i, (uint8_t)TMR_SR_GEN2_IDS_SL900A_SILICON); /* chip type */+  rec = *i;+  SETU8(msg,*i,0x40);//option+  SETU8(msg, *i, (uint8_t)0x00);+  SETU8(msg, *i, (uint8_t)CommandCode);+  filterbytes(TMR_TAG_PROTOCOL_GEN2, target, &option, i, msg, accessPassword, true);+  msg[rec]=msg[rec]|option;+  SETU8(msg, *i, (uint8_t)level);+  SETU32(msg, *i, password);++  temp |= (uint64_t)exLower << 30;+  temp |= (uint64_t)lower << 20;+  temp |= (uint64_t)upper << 10;+  temp |= (uint64_t)exUpper << 0;++  SETU8(msg, *i, (uint8_t)((temp >> 32) & 0xFF));+  SETU8(msg, *i, (uint8_t)((temp >> 24) & 0xFF));+  SETU8(msg, *i, (uint8_t)((temp >> 16) & 0xFF));+  SETU8(msg, *i, (uint8_t)((temp >> 8) & 0xFF));+  SETU8(msg, *i, (uint8_t)((temp >> 0) & 0xFF));+}++/**+ * IDS SL90A SetLogLimit+ * Chip type = 0x0A, command = 0x00 A2+ *+ * @param reader The reader+ * @param timeout The timeout of the operation, in millisecondds. Valid range 0-65535.+ * @param accessPassword The access password to use to write on the tag+ * @param commandcode to specify the operation+ * @param password to specify SL900A password access level values+ * @param level IDS password level+ * @param exLoweer IDS extreamLower limit+ * @param lower IDS lower limit+ * @param upper IDS upper limit+ * @param exUpper IDS extreamUpper limit+ */+TMR_Status+TMR_SR_cmdSL900aSetLogLimit(TMR_Reader *reader, uint16_t timeout, TMR_GEN2_Password accessPassword,+                            uint8_t CommandCode, uint32_t password, PasswordLevel level, uint16_t exLower,+                            uint16_t lower, uint16_t upper, uint16_t exUpper, TMR_TagFilter* target)+{+  uint8_t msg[TMR_SR_MAX_PACKET_SIZE];+  uint8_t i;+  i = 2;++  TMR_SR_msgAddIdsSL900aSetLogLimit(msg, &i, timeout, accessPassword, CommandCode, password, level, exLower,+      lower, upper, exUpper, target);++  msg[1] = i - 3; /* Install length */++  return TMR_SR_sendTimeout(reader, msg, timeout);+}++/**+ *  Helper routine to form the IDS SL900A SetShelfLife command+ */+void TMR_SR_msgAddIdsSL900aSetShelfLife(uint8_t *msg, uint8_t *i, uint16_t timeout, TMR_GEN2_Password accessPassword,+                                        uint8_t CommandCode, uint32_t password, PasswordLevel level, uint32_t block0, uint32_t block1,+                                        TMR_TagFilter* target)+{+  uint8_t option = 0, rec;++  SETU8(msg, *i, TMR_SR_OPCODE_WRITE_TAG_SPECIFIC);+  SETU16(msg, *i, timeout);+  SETU8(msg, *i, (uint8_t)TMR_SR_GEN2_IDS_SL900A_SILICON); /* chip type */+  rec = *i;+  SETU8(msg,*i,0x40);//option+  SETU8(msg, *i, (uint8_t)0x00);+  SETU8(msg, *i, (uint8_t)CommandCode);+  filterbytes(TMR_TAG_PROTOCOL_GEN2, target, &option, i, msg, accessPassword, true);+  msg[rec]=msg[rec]|option;+  SETU8(msg, *i, (uint8_t)level);+  SETU32(msg, *i, password);+  SETU32(msg, *i, block0);+  SETU32(msg, *i, block1);+}++/**+ * IDS SL900A  SetShelfLife+ * Chip type = 0x0A, command = 0x00 AB+ *+ * @param reader The reader+ * @param timeout The timeout of the operation, in milliseconds. Valid range is 0-65535.+ * @param accessPassword The access password to use to write on the tag+ * @param commandcode to specify the operation+ * @param password to specify SL900A password access level values+ * @param data If the operation is success, this data contains the requested value+ * @param target Filter to be applied.+ */+TMR_Status+TMR_SR_cmdSL900aSetShelfLife(TMR_Reader *reader, uint16_t timeout, TMR_GEN2_Password accessPassword,+                             uint8_t CommandCode, uint32_t password, PasswordLevel level, uint32_t block0, uint32_t block1,+                             TMR_TagFilter* target)+{+  uint8_t msg[TMR_SR_MAX_PACKET_SIZE];+  uint8_t i;+  i = 2;++  TMR_SR_msgAddIdsSL900aSetShelfLife(msg, &i, timeout, accessPassword, CommandCode, password, level, block0, block1, target);++  msg[1] = i - 3; /* Install length */++  return TMR_SR_sendTimeout(reader, msg, timeout);+}++/** + *  Gen2 IAVDenatran Custom Commands+ *  Chip Type = 0x0B+ **/+ +/** Helper routine to form the Gen2 IAVDenatran Custom commands **/+void TMR_SR_msgAddIAVDenatranCustomOp(uint8_t *msg, uint8_t *i, uint16_t timeout, TMR_GEN2_Password accessPassword,+                              uint8_t mode, uint8_t payload, TMR_TagFilter* target)+{+  uint8_t option=0,rec; ++  SETU8(msg, *i, TMR_SR_OPCODE_WRITE_TAG_SPECIFIC);+  SETU16(msg, *i, timeout);+  SETU8(msg, *i, (uint8_t)TMR_SR_GEN2_DENATRAN_IAV_SILICON);  /* Chip - type*/+  rec=*i;+  SETU8(msg,*i,0x40);//option+  SETU8(msg, *i, (uint8_t)0x00);+  SETU8(msg, *i, (uint8_t)mode);  /* Sub command */+  filterbytes(TMR_TAG_PROTOCOL_GEN2, target, &option, i, msg, accessPassword, true); +  msg[rec]=msg[rec]|option;+  SETU8(msg, *i, (uint8_t)payload);+}++ /**+ * IAV Denatran Custom Commands+ * Chip type = 0x0B, command = 0x00+ *  + * @param reader The reader+ * @param timeout The timeout of the operation, in milliseconds. Valid range is 0-65535.+ * @param accessPassword The access password to use to write on the tag+ * @param target Filter to be applied.+ */+TMR_Status+TMR_SR_cmdIAVDenatranCustomOp(TMR_Reader *reader, uint16_t timeout, TMR_GEN2_Password accessPassword, uint8_t mode, uint8_t payload,+                      TMR_uint8List *data, TMR_TagFilter* target)+{+  TMR_Status ret;+  uint8_t msg[TMR_SR_MAX_PACKET_SIZE];+  uint8_t i;+  i = 2;++  TMR_SR_msgAddIAVDenatranCustomOp(msg, &i, timeout, accessPassword, mode, payload, target);+  msg[1] = i - 3; /* Install length */++  ret = TMR_SR_sendTimeout(reader, msg, timeout);+  if (TMR_SUCCESS != ret)+  {+    return ret;+  }++  /* Parse the  response back to the user */+  i = 9;  +  /* FF    06     2d    00 00      08     40     00 00         xx xx        xx xx+   * SOH Length OpCode Status  ChipType  option  SubCommand  [payload]      CRC+   */+  {+    uint16_t copyLength;++    copyLength = msg[1] + 5 - i;++    if (copyLength > data->max)+    {+      copyLength = data->max;+    }+    if (NULL != data)+    {+      memcpy(data->list, &msg[i], copyLength);+      data->len = copyLength;+    }+  }+  return TMR_SUCCESS;+}++/** Helper routine to form the Gen2 IAVDenatran Custom commad readFromMemMap */+void TMR_SR_msgAddIAVDenatranCustomReadFromMemMap(uint8_t *msg, uint8_t *i, uint16_t timeout, TMR_GEN2_Password accessPassword,+    uint8_t mode, uint8_t payload, TMR_TagFilter* target, uint16_t wordAddress)+{++  TMR_SR_msgAddIAVDenatranCustomOp(msg, i, timeout, accessPassword, mode, payload, target);+  /* Add the address to be read from user bank */+  SETU16(msg, *i, wordAddress);+}++/** * IAV Denatran Custom Command Read From MemMap+ * Chip type = 0x0B, command = 0x06+ *  + * @param reader The reader+ * @param timeout The timeout of the operation, in milliseconds. Valid range is 0-65535.+ * @param accessPassword The access password to use to write on the tag+ * @param target Filter to be applied.+ * @param wordAddress address to be read from USER bank+ */+TMR_Status+TMR_SR_cmdIAVDenatranCustomReadFromMemMap(TMR_Reader *reader, uint16_t timeout, TMR_GEN2_Password accessPassword, uint8_t mode, uint8_t payload,+                      TMR_uint8List *data, TMR_TagFilter* target, uint16_t wordAddress)+{+  TMR_Status ret;+  uint8_t msg[TMR_SR_MAX_PACKET_SIZE];+  uint8_t i;+  i = 2;++  TMR_SR_msgAddIAVDenatranCustomReadFromMemMap(msg, &i, timeout, accessPassword, mode, payload, target, wordAddress);+  msg[1] = i - 3; /* Install length */++  ret = TMR_SR_sendTimeout(reader, msg, timeout);+  if (TMR_SUCCESS != ret)+  {+    return ret;+  }++  /* Parse the  response back to the user */+  i = 9;+  /* FF    06     2d    00 00      08     40     00 00         xx xx        xx xx+   * SOH Length OpCode Status  ChipType  option  SubCommand  [payload]      CRC+   */+  {+    uint16_t copyLength;++    copyLength = msg[1] + 5 - i;++    if (copyLength > data->max)+    {+      copyLength = data->max;+    }+    if (NULL != data)+    {+      memcpy(data->list, &msg[i], copyLength);+      data->len = copyLength;+    }+  }+  return TMR_SUCCESS;+}++/** Helper routine to form the Gen2 IAVDenatran Custom commad read sec */+void TMR_SR_msgAddIAVDenatranCustomReadSec(uint8_t *msg, uint8_t *i, uint16_t timeout, TMR_GEN2_Password accessPassword,+    uint8_t mode, uint8_t payload, TMR_TagFilter* target, uint16_t wordAddress)+{++  TMR_SR_msgAddIAVDenatranCustomOp(msg, i, timeout, accessPassword, mode, payload, target);+  /* Add the address to be read from user bank */+  SETU16(msg, *i, wordAddress);+}++/** * IAV Denatran Custom Command Read Sec+ * Chip type = 0x0B, command = 0x0A+ *  + * @param reader The reader+ * @param timeout The timeout of the operation, in milliseconds. Valid range is 0-65535.+ * @param accessPassword The access password to use to write on the tag+ * @param target Filter to be applied.+ * @param wordAddress address to be read from USER bank+ */+TMR_Status+TMR_SR_cmdIAVDenatranCustomReadSec(TMR_Reader *reader, uint16_t timeout, TMR_GEN2_Password accessPassword, uint8_t mode, uint8_t payload,+                      TMR_uint8List *data, TMR_TagFilter* target, uint16_t wordAddress)+{+  TMR_Status ret;+  uint8_t msg[TMR_SR_MAX_PACKET_SIZE];+  uint8_t i;+  i = 2;++  TMR_SR_msgAddIAVDenatranCustomReadSec(msg, &i, timeout, accessPassword, mode, payload, target, wordAddress);+  msg[1] = i - 3; /* Install length */++  ret = TMR_SR_sendTimeout(reader, msg, timeout);+  if (TMR_SUCCESS != ret)+  {+    return ret;+  }++  /* Parse the  response back to the user */+  i = 9;+  /* FF    06     2d    00 00      08     40     00 00         xx xx        xx xx+   * SOH Length OpCode Status  ChipType  option  SubCommand  [payload]      CRC+   */+  {+    uint16_t copyLength;++    copyLength = msg[1] + 5 - i;++    if (copyLength > data->max)+    {+      copyLength = data->max;+    }+    if (NULL != data)+    {+      memcpy(data->list, &msg[i], copyLength);+      data->len = copyLength;+    }+  }+  return TMR_SUCCESS;+}++/** Helper routine to form the Gen2 IAVDenatran Custom commad Activate Siniav Mode */+void TMR_SR_msgAddIAVDenatranCustomActivateSiniavMode(uint8_t *msg, uint8_t *i, uint16_t timeout, TMR_GEN2_Password accessPassword,+                                                      uint8_t mode, uint8_t payload, TMR_TagFilter* target, bool tokenDesc, uint8_t *token)+{+  uint8_t j;++  TMR_SR_msgAddIAVDenatranCustomOp(msg, i, timeout, accessPassword, mode, payload, target);+  /* add the token field */+  if (tokenDesc)+  {+    for (j = 0; j < 8; j++)+    {+      SETU8(msg, *i, token[j]);+    }+  }+}++ /**+ * IAV Denatran Custom Commands Activate Siniav Mode+ * Chip type = 0x0B, command = 0x02+ *  + * @param reader The reader+ * @param timeout The timeout of the operation, in milliseconds. Valid range is 0-65535.+ * @param accessPassword The access password to use to write on the tag+ * @param target Filter to be applied.+ * @param token 64bit value to active the tag+ */+TMR_Status+TMR_SR_cmdIAVDenatranCustomActivateSiniavMode(TMR_Reader *reader, uint16_t timeout, TMR_GEN2_Password accessPassword, uint8_t mode, uint8_t payload,+                              TMR_uint8List *data, TMR_TagFilter* target, bool tokenDesc, uint8_t *token)+{+  TMR_Status ret;+  uint8_t msg[TMR_SR_MAX_PACKET_SIZE];+  uint8_t i;+  i = 2;++  TMR_SR_msgAddIAVDenatranCustomActivateSiniavMode(msg, &i, timeout, accessPassword, mode, payload, target, tokenDesc, token);+  msg[1] = i - 3; /* Install length */++  ret = TMR_SR_sendTimeout(reader, msg, timeout);+  if (TMR_SUCCESS != ret)+  {+    return ret;+  }++  /* Parse the  response back to the user */+  i = 9;  +  /* FF    06     2d    00 00      08     40     00 00         xx xx        xx xx+   * SOH Length OpCode Status  ChipType  option  SubCommand  [payload]      CRC+   */+  {+    uint16_t copyLength;++    copyLength = msg[1] + 5 - i;++    if (copyLength > data->max)+    {+      copyLength = data->max;+    }+    if (NULL != data)+    {+      memcpy(data->list, &msg[i], copyLength);+      data->len = copyLength;+    }+  }+  return TMR_SUCCESS;+}++/** Helper routine to form the Gen2 IAVDenatran Custom commad writeToMemMap */+void TMR_SR_msgAddIAVDenatranCustomWriteToMemMap(uint8_t *msg, uint8_t *i, uint16_t timeout, TMR_GEN2_Password accessPassword,+    uint8_t mode, uint8_t payload, TMR_TagFilter* target, uint16_t wordPtr, uint16_t wordData, uint8_t* tagId, uint8_t* dataBuf)+{+  uint8_t j;++  TMR_SR_msgAddIAVDenatranCustomOp(msg, i, timeout, accessPassword, mode, payload, target);+  /* Add the address to be read from user bank */+  SETU16(msg, *i, wordPtr);+  SETU16(msg, *i, wordData);+  for (j = 0; j < 8; j++)+  {+    SETU8(msg, *i, tagId[j]);+  }+  for (j = 0; j < 16; j++)+  {+    SETU8(msg, *i, dataBuf[j]);+  }+}++/** Helper routine to form the Gne2 IAVDenatran Custom command get token Id */+void TMR_SR_msgAddIAVDenatranCustomGetTokenId(uint8_t *msg, uint8_t *i, uint16_t timeout, +    TMR_GEN2_Password accessPassword, uint8_t mode, TMR_TagFilter* target)+{+  uint8_t option = 0,rec; ++  SETU8(msg, *i, TMR_SR_OPCODE_WRITE_TAG_SPECIFIC);+  SETU16(msg, *i, timeout);+  SETU8(msg, *i, (uint8_t)TMR_SR_GEN2_DENATRAN_IAV_SILICON);  /* Chip - type*/+  rec=*i;+  SETU8(msg,*i,0x40);//option+  SETU8(msg, *i, (uint8_t)0x00);+  SETU8(msg, *i, (uint8_t)mode);  /* Sub command */+  filterbytes(TMR_TAG_PROTOCOL_GEN2, target, &option, i, msg, accessPassword, true); +  msg[rec]=msg[rec]|option;+}++/**+ * IAV Denatran Custom Command write to MemMap+ * Chip type = 0x0B, command = 0x06+ *  + * @param reader The reader+ * @param timeout The timeout of the operation, in milliseconds. Valid range is 0-65535.+ * @param accessPassword The access password to use to write on the tag+ * @param target Filter to be applied.+ * @param wordPtr pointer to the USER data+ * @param wordData data to be written+ * @param dataBuf credentials written word+ */+TMR_Status+TMR_SR_cmdIAVDenatranCustomWriteToMemMap(TMR_Reader *reader, uint16_t timeout, TMR_GEN2_Password accessPassword, uint8_t mode, uint8_t payload,+                      TMR_uint8List *data, TMR_TagFilter* target, uint16_t wordPtr, uint16_t wordData, uint8_t* tagId, uint8_t* dataBuf)+{+  TMR_Status ret;+  uint8_t msg[TMR_SR_MAX_PACKET_SIZE];+  uint8_t i;+  i = 2;++  TMR_SR_msgAddIAVDenatranCustomWriteToMemMap(msg, &i, timeout, accessPassword, mode, payload, target, wordPtr, wordData, tagId, dataBuf);+  msg[1] = i - 3; /* Install length */++  ret = TMR_SR_sendTimeout(reader, msg, timeout);+  if (TMR_SUCCESS != ret)+  {+    return ret;+  }++  /* Parse the  response back to the user */+  i = 9;+  /* FF    06     2d    00 00      08     40     00 00         xx xx        xx xx+   * SOH Length OpCode Status  ChipType  option  SubCommand  [payload]      CRC+   */+  {+    uint16_t copyLength;++    copyLength = msg[1] + 5 - i;++    if (copyLength > data->max)+    {+      copyLength = data->max;+    }+    if (NULL != data)+    {+      memcpy(data->list, &msg[i], copyLength);+      data->len = copyLength;+    }+  }+  return TMR_SUCCESS;+}++/** Helper routine to form the Gen2 IAVDenatran Custom commad write Sec */+void TMR_SR_msgAddIAVDenatranCustomWriteSec(uint8_t *msg, uint8_t *i, uint16_t timeout, TMR_GEN2_Password accessPassword,+    uint8_t mode, uint8_t payload, TMR_TagFilter* target, uint8_t* data, uint8_t* dataBuf)+{+  uint8_t j;++  TMR_SR_msgAddIAVDenatranCustomOp(msg, i, timeout, accessPassword, mode, payload, target);++  for (j = 0; j < 6; j++)+  {+    SETU8(msg, *i, data[j]);+  }+  for (j = 0; j < 16; j++)+  {+    SETU8(msg, *i, dataBuf[j]);+  }+}++/**+ * IAV Denatran Custom Command write sec+ * Chip type = 0x0B, command = 0x0B+ *  + * @param reader The reader+ * @param timeout The timeout of the operation, in milliseconds. Valid range is 0-65535.+ * @param accessPassword The access password to use to write on the tag+ * @param target Filter to be applied.+ * @param wordPtr pointer to the USER data+ * @param data data words+ * @param dataBuf credentials written word+ */+TMR_Status+TMR_SR_cmdIAVDenatranCustomWriteSec(TMR_Reader *reader, uint16_t timeout, TMR_GEN2_Password accessPassword, uint8_t mode, uint8_t payload,+                      TMR_uint8List *data, TMR_TagFilter* target, uint8_t* dataWords, uint8_t* dataBuf)+{+  TMR_Status ret;+  uint8_t msg[TMR_SR_MAX_PACKET_SIZE];+  uint8_t i;+  i = 2;++  TMR_SR_msgAddIAVDenatranCustomWriteSec(msg, &i, timeout, accessPassword, mode, payload, target, dataWords, dataBuf);+  msg[1] = i - 3; /* Install length */++  ret = TMR_SR_sendTimeout(reader, msg, timeout);+  if (TMR_SUCCESS != ret)+  {+    return ret;+  }++  /* Parse the  response back to the user */+  i = 9;+  /* FF    06     2d    00 00      08     40     00 00         xx xx        xx xx+   * SOH Length OpCode Status  ChipType  option  SubCommand  [payload]      CRC+   */+  {+    uint16_t copyLength;++    copyLength = msg[1] + 5 - i;++    if (copyLength > data->max)+    {+      copyLength = data->max;+    }+    if (NULL != data)+    {+      memcpy(data->list, &msg[i], copyLength);+      data->len = copyLength;+    }+  }+  return TMR_SUCCESS;+}++/**+ * IAV Denatran Custom Command Get Token Id+ * Chip type = 0x0B, command = 0x09+ *  + * @param reader The reader+ * @param timeout The timeout of the operation, in milliseconds. Valid range is 0-65535.+ * @param accessPassword The access password to use to write on the tag + * @param target Filter to be applied.+ */ +TMR_Status+TMR_SR_cmdIAVDenatranCustomGetTokenId(TMR_Reader *reader, uint16_t timeout, TMR_GEN2_Password accessPassword, uint8_t mode, +                      TMR_uint8List *data, TMR_TagFilter* target)+{+  TMR_Status ret;+  uint8_t msg[TMR_SR_MAX_PACKET_SIZE];+  uint8_t i;+  i = 2;++  TMR_SR_msgAddIAVDenatranCustomGetTokenId(msg, &i, timeout, accessPassword, mode, target);+  msg[1] = i - 3; /* Install length */++  ret = TMR_SR_sendTimeout(reader, msg, timeout);+  if (TMR_SUCCESS != ret)+  {+    return ret;+  }++  /* Parse the  response back to the user */+  i = 9;+  /* FF    06     2d    00 00      08     40     00 00         xx xx        xx xx+   * SOH Length OpCode Status  ChipType  option  SubCommand  [payload]      CRC+   */+  {+    uint16_t copyLength;++    copyLength = msg[1] + 5 - i;++    if (copyLength > data->max)+    {+      copyLength = data->max;+    }+    if (NULL != data)+    {+      memcpy(data->list, &msg[i], copyLength);+      data->len = copyLength;+    }+  }+  return TMR_SUCCESS;+}++/**+ * TMR_SR_cmdGetReaderStatistics+ * Get the current per-port statistics.+ *+ * @param reader [in]The reader+ * @param statFlags [in]The set of statistics together+ * @param stats [out]The ReaderStatistics structure populated with requested per-port values+ */+TMR_Status+TMR_SR_cmdGetReaderStatistics(TMR_Reader *reader, TMR_SR_ReaderStatisticsFlag statFlags,+                                         TMR_SR_ReaderStatistics *stats)+{+  TMR_Status ret;+  uint8_t msg[TMR_SR_MAX_PACKET_SIZE];+  uint8_t i, length, offset;+  i = 2;++  SETU8(msg, i, TMR_SR_OPCODE_GET_READER_STATS);+  SETU8(msg, i, (uint8_t)TMR_SR_READER_STATS_OPTION_GET_PER_PORT); /* Option byte */+  SETU8(msg, i, (uint8_t)statFlags);++  msg[1] = i - 3; /* Install length */++  ret = TMR_SR_sendTimeout(reader, msg, reader->u.serialReader.commandTimeout);+  if (TMR_SUCCESS != ret)+  {+    return ret;+  }++  /* Parse the statistics from response */+  if (NULL != stats)+  {+    uint8_t  port = 0;+    offset = 7;++    length = reader->u.serialReader.txRxMap->len;++    while (offset < (msg[1] + 2))+    {+      if (0 != (msg[offset] & TMR_SR_READER_STATS_FLAG_RF_ON_TIME))+      {+        offset += 2;++        for (i = 0; i < length; i++)+        {+          port = msg[offset];+          if (i == (port-1))+          {+            offset ++;+            stats->rfOnTime[i] = GETU32(msg, offset);+          }+          else+          {+            stats->rfOnTime[i] = 0;+          }+        }+        stats->numPorts = length;+      }+      else if (0 != (msg[offset] & TMR_SR_READER_STATS_FLAG_NOISE_FLOOR))+      {+        offset += 2;++        for (i = 0; i < length; i++)+        {+          port = msg[offset];+          if (i == (port-1))+          {+            offset ++;+            stats->noiseFloor[i] = msg[offset++];+          }+          else+          {+            stats->noiseFloor[i] = 0;+          }+        }+        stats->numPorts = length;+      }+      else if (0 != (msg[offset] & TMR_SR_READER_STATS_FLAG_NOISE_FLOOR_TX_ON))+      {+        offset += 2;++        for (i = 0; i < length; i++)+        {+          port = msg[offset];+          if (i == (port-1))+          {+            offset ++;+            stats->noiseFloorTxOn[i] = msg[offset++];+          }+          else+          {+            stats->noiseFloorTxOn[i] = 0;+          }+        }+        stats->numPorts = length;+      }+    }+  }+  return TMR_SUCCESS;+}++/**+ * TMR_SR_cmdResetReaderStatistics+ * Reset the per-port statistics.+ *+ * @param reader [in]The reader+ * @param statFlags [in]The set of statistics to reset. Only the RF on time statistic may be reset.+ */+TMR_Status+TMR_SR_cmdResetReaderStatistics(TMR_Reader *reader, TMR_SR_ReaderStatisticsFlag statFlags)+{+  TMR_Status ret;+  uint8_t msg[TMR_SR_MAX_PACKET_SIZE];+  uint8_t i;+  i = 2;++  SETU8(msg, i, TMR_SR_OPCODE_GET_READER_STATS);+  SETU8(msg, i, (uint8_t)TMR_SR_READER_STATS_OPTION_RESET); /* Option byte */+  SETU8(msg, i, (uint8_t)statFlags);++  msg[1] = i - 3; /* Install length */++  ret = TMR_SR_sendTimeout(reader, msg, reader->u.serialReader.commandTimeout);+  if (TMR_SUCCESS != ret)+  {+    return ret;+  }+  return TMR_SUCCESS;+}+++/**+ * Helper function to be used in GetReaderStats+ */ +TMR_Status+TMR_fillReaderStats(TMR_Reader *reader, TMR_Reader_StatsValues* stats, uint16_t flag, uint8_t* msg, uint8_t offset)+{+  uint8_t i;+  while (offset < (msg[1] + 2))+  {+    if ((0x80) > msg[offset])+    {+      flag = msg[offset];+    }+    else+    {+      /**+       * the response flag will be in EBV format,+       * convert that to the api enum values+       */+      flag = ((msg[offset] << 8) | (msg[offset + 1]));+      flag &= 0x7fff;+      flag = ((flag >> 1) | (flag & 0x7f));+    }+++    if (flag & TMR_READER_STATS_FLAG_RF_ON_TIME)+    {+      uint8_t tx;++      offset += 2;++      for (i = 0; i < reader->u.serialReader.txRxMap->len; i++)+      {+        tx = GETU8(msg, offset);+        if (tx == reader->u.serialReader.txRxMap->list[i].txPort)+        {+          stats->perAntenna.list[i].antenna = reader->u.serialReader.txRxMap->list[i].antenna;+          stats->perAntenna.list[i].rfOnTime = GETU32(msg, offset);+        }+      }+    }++    else if (flag & TMR_READER_STATS_FLAG_NOISE_FLOOR_SEARCH_RX_TX_WITH_TX_ON)+    {+      uint8_t tx,rx, len;++      offset++;+      len = GETU8(msg, offset);+      while (len)+      {+        tx = GETU8(msg, offset);+        rx = GETU8(msg, offset);+        for (i = 0; i < reader->u.serialReader.txRxMap->len; i++)+        {+          if ((rx == reader->u.serialReader.txRxMap->list[i].rxPort) && (tx == reader->u.serialReader.txRxMap->list[i].txPort))+          {+            stats->perAntenna.list[i].antenna = reader->u.serialReader.txRxMap->list[i].antenna;+            stats->perAntenna.list[i].noiseFloor = GETU8(msg, offset);+            len -= 3;+          }+        }+      }+    }++    else if (flag & TMR_READER_STATS_FLAG_FREQUENCY)+    {+      offset += 3;+      stats->frequency = GETU24(msg, offset);+    }++    else if (flag & TMR_READER_STATS_FLAG_TEMPERATURE)+    {+      offset += 3;+      stats->temperature = GETU8(msg, offset);+    }++    else if (flag & TMR_READER_STATS_FLAG_PROTOCOL)+    {+      offset += 3;+      stats->protocol = (TMR_TagProtocol)GETU8(msg, offset);+    }++    else if (flag & TMR_READER_STATS_FLAG_ANTENNA_PORTS)+    {+      uint8_t tx, rx;++      offset += 3;      +      tx = GETU8(msg, offset);+      rx = GETU8(msg, offset);++      for (i = 0; i < reader->u.serialReader.txRxMap->len; i++)+      {+        if ((rx == reader->u.serialReader.txRxMap->list[i].rxPort) && (tx == reader->u.serialReader.txRxMap->list[i].txPort))+        {+          stats->antenna = reader->u.serialReader.txRxMap->list[i].antenna;+          break;+        }+      }+    }++    else if (flag & TMR_READER_STATS_FLAG_CONNECTED_ANTENNAS)+    {+      offset += 3;+      stats->connectedAntennas.len = msg[offset - 1];+      for (i = 0; i < stats->connectedAntennas.len; i++)+      {+        stats->connectedAntennas.list[i] = msg[offset++];+      }+    }+    else+    {+      return TMR_ERROR_INVALID;+    }+  }/* End of while loop */+  return TMR_SUCCESS;+}+ +/**+ * TMR_SR_cmdGetReaderStats+ * Get the current per-port statistics.+ *   + * @param reader [in]The reader+ * @param statFlags [in]The set of statistics together+ * @param stats [out]The ReaderStatistics structure populated with requested per-port values+ */+TMR_Status +TMR_SR_cmdGetReaderStats(TMR_Reader *reader, TMR_Reader_StatsFlag statFlags,+                                         TMR_Reader_StatsValues *stats)+{+  TMR_Status ret;+  uint8_t msg[TMR_SR_MAX_PACKET_SIZE];+  uint8_t i, offset; +  uint16_t flag = 0, temp = 0;+  i = 2;++  SETU8(msg, i, TMR_SR_OPCODE_GET_READER_STATS);+  SETU8(msg, i, (uint8_t)TMR_SR_READER_STATS_OPTION_GET_PER_PORT); /* Option byte */++  /**+   * To extend the flag byte, an EBV technique is to be used.+   * When the highest order bit of the flag byte is used,+   * it signals the reader’s parser, that another flag byte is to follow+   */+  if ((0x80) > statFlags)+  {+    SETU8(msg, i, (uint8_t)statFlags);+  }+  else+  {+    temp = statFlags & 0x7f;+    statFlags &= 0xFFFE;+    statFlags = (TMR_Reader_StatsFlag)((statFlags << 1) | temp);+    statFlags &= 0xFF7F;+    SETU16(msg, i, ((uint16_t)0x8000 | statFlags));+  }++  msg[1] = i - 3; /* Install length */++  ret = TMR_SR_sendTimeout(reader, msg, reader->u.serialReader.commandTimeout);+  if (TMR_SUCCESS != ret)+  {+    return ret;+  }++  /* Parse the statistics from response */+  if (NULL != stats)+  {+    uint8_t  j;+    offset = 7;++    /**+     * preinitialize the rf ontime and the noise floor value to zero+     * berfore getting the reader stats+     */+    for (i = 0; i < stats->perAntenna.max; i++)+    {+      stats->perAntenna.list[i].antenna = 0;+      stats->perAntenna.list[i].rfOnTime = 0;+      stats->perAntenna.list[i].noiseFloor = 0;+    }++    if ((0x80) > statFlags)+    {+      offset = 7;+    }+    else+    {+      offset = 8;+    }++    ret = TMR_fillReaderStats(reader, stats, flag, msg, offset);+    if (TMR_SUCCESS != ret)+    {+      return ret;+    }++    /**+     * iterate through the per antenna values,+     * If found  any 0-antenna rows, copy the+     * later rows down to compact out the empty space.+     */+    for (i = 0; i < reader->u.serialReader.txRxMap->len; i++)+    {+      if (!stats->perAntenna.list[i].antenna )+      {+        for (j = i + 1; j < reader->u.serialReader.txRxMap->len; j++)+        {+          if (stats->perAntenna.list[j].antenna) +          {+            stats->perAntenna.list[i].antenna = stats->perAntenna.list[j].antenna;+            stats->perAntenna.list[i].rfOnTime = stats->perAntenna.list[j].rfOnTime;+            stats->perAntenna.list[i].noiseFloor = stats->perAntenna.list[j].noiseFloor;+            stats->perAntenna.list[j].antenna = 0;+            stats->perAntenna.list[j].rfOnTime = 0;+            stats->perAntenna.list[j].noiseFloor = 0;++            stats->perAntenna.len++;+            break;+          }+        }+      }+      else+      {+        /* Increment the length */+        stats->perAntenna.len++;+      }+    }+  }/* end of outermost if block */++  /* Store the requested flags for future validation */+  stats->valid = reader->statsFlag;++  return TMR_SUCCESS;+}++/**+ * TMR_SR_cmdResetReaderStats+ * Reset the per-port statistics.+ *   + * @param reader [in]The reader+ * @param statFlags [in]The set of statistics to reset. Only the RF on time statistic may be reset.+ */+TMR_Status +TMR_SR_cmdResetReaderStats(TMR_Reader *reader, TMR_Reader_StatsFlag statFlags)+{+  TMR_Status ret;+  uint8_t msg[TMR_SR_MAX_PACKET_SIZE];+  uint8_t i;+  uint16_t temp = 0;+  i = 2;++  SETU8(msg, i, TMR_SR_OPCODE_GET_READER_STATS);+  SETU8(msg, i, (uint8_t)TMR_SR_READER_STATS_OPTION_RESET); /* Option byte */++ /**+   * To extend the flag byte, an EBV technique is to be used.+   * When the highest order bit of the flag byte is used,+   * it signals the reader’s parser, that another flag byte is to follow+   */+  if ((0x80) > statFlags)+  {+    SETU8(msg, i, (uint8_t)statFlags);+  }+  else+  {+    temp = statFlags & 0x7f;+    statFlags &= 0xFFFE;+    statFlags = (TMR_Reader_StatsFlag)((statFlags << 1) | temp);+    statFlags &= 0xFF7F;+    SETU16(msg, i, ((uint16_t)0x8000 | statFlags));+  }++  msg[1] = i - 3; /* Install length */++  ret = TMR_SR_sendTimeout(reader, msg, reader->u.serialReader.commandTimeout);+  if (TMR_SUCCESS != ret)+  {+    return ret;+  }+  return TMR_SUCCESS;+}++TMR_Status+TMR_SR_receiveAutonomousReading(struct TMR_Reader *reader, TMR_TagReadData *trd, TMR_Reader_StatsValues *stats)+{+  TMR_Status ret;++  ret = TMR_SUCCESS;+  reader->continuousReading = true;++  ret = TMR_SR_hasMoreTags(reader);+  if (TMR_SUCCESS == ret)+  {        +    uint16_t flags;++    if (false == reader->isStatusResponse)+    {+      /* Ignore the fail cases and pass only valid messages */+      flags = GETU16AT(reader->u.serialReader.bufResponse, 8);+      TMR_SR_parseMetadataFromMessage(reader, trd, flags, &reader->u.serialReader.bufPointer, reader->u.serialReader.bufResponse);+      TMR_SR_postprocessReaderSpecificMetadata(trd, &reader->u.serialReader);+      trd->reader = reader;+      reader->u.serialReader.tagsRemainingInBuffer--;+    }+    else+    {+      /* A status stream response */+      uint8_t offset, i,j;+      uint16_t flags = 0;                 ++      TMR_STATS_init(stats);+      offset = reader->u.serialReader.bufPointer;++      /* Get status content flags */+      if ((0x80) > reader->statsFlag)+      {+        offset += 1;+      }+      else+      {+        offset += 2;+      }++      /**+      * preinitialize the rf ontime and the noise floor value to zero+      * berfore getting the reader stats+      */+      for (i = 0; i < stats->perAntenna.max; i++)+      {+        stats->perAntenna.list[i].antenna = 0;+        stats->perAntenna.list[i].rfOnTime = 0;+        stats->perAntenna.list[i].noiseFloor = 0;+      }++      TMR_fillReaderStats(reader, stats, flags, reader->u.serialReader.bufResponse, offset);++      /**+      * iterate through the per antenna values,+      * If found  any 0-antenna rows, copy the+      * later rows down to compact out the empty space.+      */+      for (i = 0; i < reader->u.serialReader.txRxMap->len; i++)+      {+        if (!stats->perAntenna.list[i].antenna)+        {+          for (j = i + 1; j < reader->u.serialReader.txRxMap->len; j++)+          {+            if (stats->perAntenna.list[j].antenna)+            {+              stats->perAntenna.list[i].antenna = stats->perAntenna.list[j].antenna;+              stats->perAntenna.list[i].rfOnTime = stats->perAntenna.list[j].rfOnTime;+              stats->perAntenna.list[i].noiseFloor = stats->perAntenna.list[j].noiseFloor;+              stats->perAntenna.list[j].antenna = 0;+              stats->perAntenna.list[j].rfOnTime = 0;+              stats->perAntenna.list[j].noiseFloor = 0;++              stats->perAntenna.len++;+              break;+            }+          }+        }+        else+        {+          /* Increment the length */+          stats->perAntenna.len++;+        }+      }++      /* store the requested flags for future use */+      stats->valid = reader->statsFlag;+    }+  }+  +  reader->continuousReading = false;+  return ret;  +}++TMR_Status+TMR_SR_cmdStopReading(struct TMR_Reader *reader)+{+  uint8_t msg[TMR_SR_MAX_PACKET_SIZE];+  uint8_t i, op;+  +  reader->hasContinuousReadStarted = false;+  i = 2;+  op = TMR_SR_OPCODE_MULTI_PROTOCOL_TAG_OP;+  SETU8(msg, i, op);+  SETU16(msg, i, 0); /* Timeout, Currently ignored */+  SETU8(msg, i, (uint8_t)0x02); /* option - stop continuous reading */++  msg[1]=i - 3;  /* Install length */++  /* No need to capture the response */+  return TMR_SR_sendMessage(reader, msg, &op, reader->u.serialReader.commandTimeout);+}++TMR_Status+TMR_SR_cmdGetReaderWriteTimeOut (struct TMR_Reader *reader, TMR_TagProtocol protocol,+                                 TMR_SR_Gen2ReaderWriteTimeOut *value)+{+  TMR_Status ret;+  uint8_t msg[TMR_SR_MAX_PACKET_SIZE];+  uint8_t i, op;++  i = 2;+  op = TMR_SR_OPCODE_GET_PROTOCOL_PARAM;+  SETU8(msg, i, op);+  SETU8(msg, i, protocol); +  SETU8(msg, i, (uint8_t)0x3f); /* option - reader write timeout */++  msg[1]=i - 3;  /* Install length */++  ret = TMR_SR_send(reader, msg);+  if (TMR_SUCCESS != ret)+  {+    return ret;+  }++  /* Get the values */+  value->earlyexit =  GETU8AT(msg, 7);+  value->writetimeout = GETU16AT(msg, 8);++  return TMR_SUCCESS;+}++TMR_Status+TMR_SR_cmdSetReaderWriteTimeOut (struct TMR_Reader *reader, TMR_TagProtocol protocol,+                                 TMR_SR_Gen2ReaderWriteTimeOut *value)+{+  uint8_t msg[TMR_SR_MAX_PACKET_SIZE];+  uint8_t i;++  i = 2;+  SETU8(msg, i, TMR_SR_OPCODE_SET_PROTOCOL_PARAM);+  SETU8(msg, i, protocol);+  SETU8(msg, i, (uint8_t)0x3f); /* option - reader write timeout */+  SETU8(msg, i, (uint8_t)value->earlyexit);+  SETU16(msg,i, value->writetimeout);++  msg[1] = i - 3; /* Install length */+  return TMR_SR_send(reader, msg);+}++TMR_Status+TMR_SR_cmdAuthReqResponse(struct TMR_Reader *reader, TMR_TagAuthentication *auth)+{+  uint8_t msg[TMR_SR_MAX_PACKET_SIZE];+  uint8_t i;+  uint8_t opcode;++  i = 2;+  SETU8(msg, i, (uint8_t)TMR_SR_OPCODE_MULTI_PROTOCOL_TAG_OP);+  SETU8(msg, i, (uint8_t)0x00);+  SETU8(msg, i, (uint8_t)0x00);+  SETU8(msg, i, (uint8_t)0x03);+  SETU8(msg, i, (uint8_t)0x00);+  SETU8(msg, i, (uint8_t)0x01);+  SETU8(msg, i, (uint8_t)0x00);++  switch (auth->type)+  {+  default:+	return TMR_ERROR_UNSUPPORTED;++  case TMR_AUTH_TYPE_GEN2_PASSWORD:+	{+	  TMR_GEN2_Password password = auth->u.gen2Password;+	  SETU8(msg, i, (uint8_t)0x20);+	  SETU8(msg, i, (uint8_t)(password>>24));+	  SETU8(msg, i, (uint8_t)(password>>16));+	  SETU8(msg, i, (uint8_t)(password>> 8));+	  SETU8(msg, i, (uint8_t)(password>> 0));+	}+	break;+  }++  msg[1] = i - 3; /* Install length */+  return TMR_SR_sendMessage(reader, msg, &opcode, 0);+}++#endif /* TMR_ENABLE_SERIAL_READER */
+ cbits/api/serial_transport_posix.c view
@@ -0,0 +1,307 @@+/**+ *  @file serial_transport_posix.c+ *  @brief Mercury API - POSIX serial transport implementation+ *  @author Nathan Williams+ *  @date 10/20/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 <sys/types.h>+#include <sys/stat.h>+#include <sys/select.h>+#include <fcntl.h>+#include <termios.h>+#include <unistd.h>+#include <errno.h>+#include <string.h>+#include <sys/ioctl.h>+#include "tm_reader.h"++#ifdef __APPLE__+#include <sys/ioctl.h>+#include <IOKit/serial/ioss.h>+#endif++#ifdef TMR_ENABLE_SERIAL_TRANSPORT_NATIVE++static TMR_Status+s_open(TMR_SR_SerialTransport *this)+{+  int ret;+  struct termios t;+#if TMR_MAX_READER_NAME_LENGTH > 0+  TMR_SR_SerialPortNativeContext *c;++  c = this->cookie;++  c->handle = open(c->devicename, O_RDWR);+  if (c->handle == -1)+    return TMR_ERROR_COMM_ERRNO(errno);+#endif++  /*+   * Set 8N1, disable high-bit stripping, soft flow control, and hard+   * flow control (modem lines).+   */+  ret = tcgetattr(c->handle, &t);+  if (-1 == ret)+    return TMR_ERROR_COMM_ERRNO(errno);+  t.c_iflag &= ~(ICRNL | IGNCR | INLCR | INPCK | ISTRIP | IXANY +                 | IXON | IXOFF | PARMRK);+  t.c_oflag &= ~OPOST;+  t.c_cflag &= ~(CRTSCTS | CSIZE | CSTOPB | PARENB);+  t.c_cflag |= CS8 | CLOCAL | CREAD | HUPCL;+  t.c_lflag &= ~(ECHO | ICANON | IEXTEN | ISIG);+  t.c_cc[VMIN] = 0;+  t.c_cc[VTIME] = 1;+  ret = tcsetattr(c->handle, TCSANOW, &t);+  if (-1 == ret)+    return TMR_ERROR_COMM_ERRNO(errno);++  return TMR_SUCCESS;+}++static TMR_Status+s_sendBytes(TMR_SR_SerialTransport *this, uint32_t length, +            uint8_t* message, const uint32_t timeoutMs)+{+  TMR_SR_SerialPortNativeContext *c;+  int ret;++  c = this->cookie;+  do +  {+    ret = write(c->handle, message, length);+    if (ret == -1)+    {+      if (ENXIO == errno)+      {+        return TMR_ERROR_TIMEOUT; +      }+      else+      {+        return TMR_ERROR_COMM_ERRNO(errno);+      }+    }+    length -= ret;+    message += ret;+  }+  while (length > 0);++  return TMR_SUCCESS;+}++static TMR_Status+s_receiveBytes(TMR_SR_SerialTransport *this, uint32_t length, +               uint32_t *messageLength, uint8_t* message, const uint32_t timeoutMs)+{+  TMR_SR_SerialPortNativeContext *c;+  int ret;+  struct timeval tv;+  fd_set set;+  int status = 0;++  *messageLength = 0;+  c = this->cookie;++  do+  {+    do+    {+      FD_ZERO(&set);+      FD_SET(c->handle, &set);+      tv.tv_sec = timeoutMs / 1000;+      tv.tv_usec = (timeoutMs % 1000) * 1000;+      /* Ideally should reset this timeout value every time through */+      ret = select(c->handle + 1, &set, NULL, NULL, &tv);+    } while (ret == -1 && errno == EINTR);+    if (ret == -1)+    {+      return TMR_ERROR_COMM_ERRNO(errno);+    }+    if (ret < 1)+    {+      return TMR_ERROR_TIMEOUT;+    }+    ret = read(c->handle, message, length);+    if (ret == -1)+    {+      if (ENXIO == errno)+      {+        return TMR_ERROR_TIMEOUT; +      }+      else+      {+        return TMR_ERROR_COMM_ERRNO(errno);+      }+    }++    if (0 == ret)+    {+      /**+       * We should not be here, coming here means the select()+       * is success , but we are not able to read the data.+       * check the serial port connection status.+       **/+      ret = ioctl(c->handle, TIOCMGET, &status);+      if (-1 == ret)+      {+        /* not success. check for errno */+        if (EIO == errno)+        {+          /**+           * EIO means I/O error, may serial port got disconnected,+           * throw the error.+           **/+          return TMR_ERROR_TIMEOUT;+        }+      }+    }++    length -= ret;+    *messageLength += ret;+    message += ret;+  }+  while (length > 0);++  return TMR_SUCCESS;+}++static TMR_Status+s_setBaudRate(TMR_SR_SerialTransport *this, uint32_t rate)+{+  TMR_SR_SerialPortNativeContext *c;+  +  c = this->cookie;++#if defined(__APPLE__)+  {+    speed_t speed = rate;++    if (ioctl(c->handle, IOSSIOSPEED, &speed) == -1)+      return TMR_ERROR_COMM_ERRNO(errno);+  }+#else+  {+    struct termios t;++    tcgetattr(c->handle, &t);++#define BCASE(t,n) case n: cfsetispeed((t),B##n); cfsetospeed((t),B##n); break;+    switch (rate)+    {+      BCASE(&t, 9600);+      BCASE(&t, 19200);+      BCASE(&t, 38400);+      // Believe it or not, speeds beyond 38400 aren't required by POSIX.+#ifdef B57600+      BCASE(&t, 57600);+#endif+#ifdef B115200+      BCASE(&t, 115200);+#endif+#ifdef B230400+      BCASE(&t, 230400);+#endif+#ifdef B460800+      BCASE(&t, 460800);+#endif+#ifdef B921600+      BCASE(&t, 921600);+#endif+    default:+      return TMR_ERROR_INVALID;+    }+#undef BCASE+    if (tcsetattr(c->handle, TCSANOW, &t) != 0)+    {+      return TMR_ERROR_COMM_ERRNO(errno);+    }+  }+#endif /* __APPLE__ */++  return TMR_SUCCESS;+}++static TMR_Status+s_shutdown(TMR_SR_SerialTransport *this)+{+  TMR_SR_SerialPortNativeContext *c;++  c = this->cookie;++  close(c->handle);+  /* What, exactly, would be the point of checking for an error here? */++  return TMR_SUCCESS;+}++static TMR_Status+s_flush(TMR_SR_SerialTransport *this)+{+  TMR_SR_SerialPortNativeContext *c;++  c = this->cookie;++  if (tcflush(c->handle, TCOFLUSH) == -1)+  {+    return TMR_ERROR_COMM_ERRNO(errno);+  }++  return TMR_SUCCESS;+}++TMR_Status+TMR_SR_SerialTransportNativeInit(TMR_SR_SerialTransport *transport,+                                 TMR_SR_SerialPortNativeContext *context,+                                 const char *device)+{++#if TMR_MAX_READER_NAME_LENGTH > 0+  if (strlen(device) + 1 > TMR_MAX_READER_NAME_LENGTH)+  {+    return TMR_ERROR_INVALID;+  }+  strcpy(context->devicename, device);+#else+  /* No space to store the device name, so open it now */+  context->handle = open(device, O_RDWR);+  if (context->handle == -1)+  {+    return TMR_ERROR_COMM_ERRNO(errno);+  }+#endif++  transport->cookie = context;+  transport->open = s_open;+  transport->sendBytes = s_sendBytes;+  transport->receiveBytes = s_receiveBytes;+  transport->setBaudRate = s_setBaudRate;+  transport->shutdown = s_shutdown;+  transport->flush = s_flush;++  return TMR_SUCCESS;+}++#endif
+ cbits/api/serial_transport_win32.c view
@@ -0,0 +1,234 @@+/**+ *  @file serial_transport_win32.c+ *  @brief Mercury API - Serial transport over local serial port on Win32+ *  @author Nathan Williams+ *  @date 10/20/2009+ */+++/*+ * Copyright (c) 2010 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 "tm_config.h"+#include "tmr_status.h"++#if defined(WIN32) || defined(WINCE)+#if !defined(_WINSOCK2API_) && !defined(_WINSOCKAPI_)+#include <winsock2.h>+#endif+#include <stdio.h>++#  if defined(WINCE)+#    define snprintf _snprintf+#  elif !defined(__GNUC__)+#    define snprintf sprintf_s+#  endif++#endif /* WIN32 */++#include "tm_reader.h"++__declspec(dllexport) TMR_Status+s_open(TMR_SR_SerialTransport *this)+{+  TMR_SR_SerialPortNativeContext *c;+  COMMTIMEOUTS timeOuts;+  DCB dcb;++  c = this->cookie;+  +  c->handle = CreateFile((TCHAR*)c->devicename,+                         GENERIC_READ | GENERIC_WRITE,+                         0,             /* not shared */+                         NULL,          /* default security */+                         OPEN_EXISTING, /* don't create a new file */+                         0,             /* flags and attributes */+                         NULL);         /* template file */+                         +  if (INVALID_HANDLE_VALUE == c->handle)+    return TMR_ERROR_INVALID; /* @todo use GetLastError() */++  timeOuts.ReadIntervalTimeout          = 0xFFFFFFFF;+  timeOuts.ReadTotalTimeoutConstant     = 0;+  timeOuts.ReadTotalTimeoutMultiplier   = 0;+  timeOuts.WriteTotalTimeoutConstant    = 5000;+  timeOuts.WriteTotalTimeoutMultiplier  = 0;+  +  SetCommTimeouts(c->handle, &timeOuts);++  dcb.DCBlength = sizeof(DCB);+  GetCommState(c->handle, &dcb);+  dcb.fOutxCtsFlow = 0;+  dcb.fOutxDsrFlow = 0;+  dcb.fDtrControl = DTR_CONTROL_DISABLE;+  dcb.fDsrSensitivity = 0;+  dcb.fOutX = 0;+  dcb.fInX = 0;+  dcb.fNull = 0;+  dcb.fRtsControl = RTS_CONTROL_DISABLE;+  dcb.ByteSize  = 8;+  dcb.fParity = NOPARITY;+  dcb.StopBits = ONESTOPBIT;+  if ((0 == SetCommState(c->handle, &dcb)) ||+      (0 == SetupComm(c->handle, 10000, 10000)))+  {+    return TMR_ERROR_INVALID;  /* @todo use GetLastError() */+  }+  +  return TMR_SUCCESS;+}++__declspec(dllexport) TMR_Status+s_sendBytes(TMR_SR_SerialTransport *this, uint32_t length,+            uint8_t* message, const uint32_t timeoutMs)+{+  TMR_SR_SerialPortNativeContext *c;+  BOOL writeStatus;+  COMMTIMEOUTS timeOuts;++  c = this->cookie;+  GetCommTimeouts(c->handle, &timeOuts);+  timeOuts.WriteTotalTimeoutConstant = timeoutMs;+  SetCommTimeouts(c->handle, &timeOuts);+  +  {+	long numberOfBytesWritten;+	writeStatus = WriteFile(c->handle, message, length, &numberOfBytesWritten, NULL);+  }+  if (0 == writeStatus)+  {+    return TMR_ERROR_TIMEOUT;  /* @todo use GetLastError() */+  }+  return TMR_SUCCESS;+}++__declspec(dllexport) TMR_Status+s_receiveBytes(TMR_SR_SerialTransport *this, uint32_t length,+              uint32_t* messageLength, uint8_t* message, const uint32_t+timeoutMs)+{+ DWORD readLength;+ DWORD errorFlags;+ COMSTAT comStat;+ TMR_SR_SerialPortNativeContext *c;+ BOOL    readStatus;+ COMMTIMEOUTS timeOuts;++ c = this->cookie;+ *messageLength=0;++ GetCommTimeouts(c->handle, &timeOuts);+ timeOuts.ReadTotalTimeoutConstant = timeoutMs;+ SetCommTimeouts(c->handle, &timeOuts);++ ClearCommError(c->handle, &errorFlags, &comStat);+ while (length > 0)+ {+   readLength=0;+   readStatus = ReadFile(c->handle, message, length, &readLength, NULL);+   *messageLength += readLength;+   if (0 == readStatus)+   {+     return TMR_ERROR_TIMEOUT;  /* @todo use GetLastError() */+   }+   if(readLength == 0)+   {+     return TMR_ERROR_TIMEOUT;+   }+   length -= readLength;+   message += readLength;++ }+ return TMR_SUCCESS;+}+++__declspec(dllexport) TMR_Status+s_setBaudRate(TMR_SR_SerialTransport *this, uint32_t rate)+{+  TMR_SR_SerialPortNativeContext *c;+  DCB   dcb;++  c = this->cookie;++  dcb.DCBlength = sizeof(DCB);+  GetCommState(c->handle, &dcb);+  dcb.BaudRate  = rate;++  if (0 == SetCommState(c->handle, &dcb)) /* @todo use GetLastError() */+  {+    return TMR_ERROR_INVALID;+  }++  return TMR_SUCCESS;+}++static TMR_Status+s_shutdown(TMR_SR_SerialTransport *this)+{+  TMR_SR_SerialPortNativeContext *c;++  c = this->cookie;++  CloseHandle(c->handle);+  /* What, exactly, would be the point of checking for an error here? */++  return TMR_SUCCESS;+}++static TMR_Status+s_flush(TMR_SR_SerialTransport *this)+{+  TMR_SR_SerialPortNativeContext *c;++  c = this->cookie;++  if (PurgeComm(c->handle, PURGE_RXCLEAR) == 0)+  {+	  return TMR_ERROR_COMM_ERRNO(errno);+  }+  return TMR_SUCCESS;+}++__declspec(dllexport)TMR_Status+TMR_SR_SerialTransportNativeInit(TMR_SR_SerialTransport *transport,+                                 TMR_SR_SerialPortNativeContext *context,+                                 const char *device)+{+  // Transform COM port name from "/COMnn" to "\\\\.\\COMnn"+  if (strlen(device)-1 + 4 + 1 > TMR_MAX_READER_NAME_LENGTH)+  {+    return TMR_ERROR_INVALID;+  }+  snprintf(context->devicename, sizeof(context->devicename),+    "\\\\.\\%s", device+1);++  transport->cookie = context;+  transport->open = s_open;+  transport->sendBytes = s_sendBytes;+  transport->receiveBytes = s_receiveBytes;+  transport->setBaudRate = s_setBaudRate;+  transport->shutdown = s_shutdown;+  transport->flush = s_flush;++  return TMR_SUCCESS;+}
+ cbits/api/tm_config.h view
@@ -0,0 +1,263 @@+/* ex: set tabstop=2 shiftwidth=2 expandtab cindent: */+#ifndef _TM_CONFIG_H+#define _TM_CONFIG_H++/**+ *  @file tm_config.h+ *  @brief Mercury API - Build Configuration+ *  @author Nathan Williams+ *  @date 10/20/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.+ */++#ifdef  __cplusplus+extern "C" {+#endif++/**+ * API version number+ */+#define TMR_VERSION "1.29.3.34"++/**+ * Define this to enable support for devices that support the serial+ * reader command set (M5e, M6e, Vega, etc.)+ */+#define TMR_ENABLE_SERIAL_READER++/**+ * Define this to enable support for local serial port access via+ * native interfaces (COM1 on Windows, /dev/ttyS0, /dev/ttyUSB0 on+ * Linux, etc.).+ */+#define TMR_ENABLE_SERIAL_TRANSPORT_NATIVE++/**+ * The longest possible name for a reader.+ */+#define TMR_MAX_READER_NAME_LENGTH 256++/**+ * The maximum number of protocols supported in a multiprotocol search command+ */+#define TMR_MAX_SERIAL_MULTIPROTOCOL_LENGTH 5++/**+ * The maximum size of the Queue, used to share the streamed messages+ * between the do_background_reads thread and parse_tag_reads thread.+ */+#define TMR_MAX_QUEUE_SLOTS 20++/** + * Number of bytes to allocate for embedded data return+ * in each TagReadData.+ */+#define TMR_MAX_EMBEDDED_DATA_LENGTH 128 ++/**+ * The maximum length of the probe baudrate list. This list specifies the  + * baudrates which are used while connecting to the serial reader.+ */+#define TMR_MAX_PROBE_BAUDRATE_LENGTH 8++/**+ * Define this to enable support for LLRP readers.+ * (Not yet available for Windows)+ */+#define TMR_ENABLE_LLRP_TRANSPORT+#ifndef WIN32+#define TMR_ENABLE_LLRP_SERIAL_TRANSPORT+#endif++/**+ * LLRP reader keep alive timeout in milli seconds+ */+#define TMR_LLRP_KEEP_ALIVE_TIMEOUT 5000++/**+ * Define this to enable async read using single thread++Note:To run readsync_baremetal codelet you have to +     define it.+	 Otherwise keep it undefined.+ */+#undef SINGLE_THREAD_ASYNC_READ++/**+ * Define this to enable for BARE_METAL API + */+#ifndef BARE_METAL+/**+ * Define this to enable support for the GEN2 Custom Tag Operations parameters+ * and access commands+ */+#define TMR_ENABLE_GEN2_CUSTOM_TAGOPS++/**+ * Define this to enable support for the ISO180006B protocol parameters+ * and access commands+ */+#define TMR_ENABLE_ISO180006B++/**+ * Define this to enable support for small microcontrollers.+ * Enabling this option will reduce the code which is not relevant to + * serial readers in order to minimize the program footprint+ * To compile for Serial Reader only.+ *+ * To compile for Serial Reader only, use one of the following options:+ ** Uncomment the following define+ ** Run make with TMR_ENABLE_SERIAL_READER_ONLY=1 defined+ ** Add -DTMR_ENABLE_SERIAL_READER_ONLY=1 to your compiler flags+ */ +//#define TMR_ENABLE_SERIAL_READER_ONLY++/**+ * Define this to enable support for background reads using native threads.+ * This feature is also available for windows (using pthreads-win32)+ */++#define TMR_ENABLE_BACKGROUND_READS+++/**+ * Define this to include TMR_strerror().+ */+#define TMR_ENABLE_ERROR_STRINGS++/**+ * Define this to include TMR_paramName() and TMR_paramID().+ */+#define TMR_ENABLE_PARAM_STRINGS++/**+ * Enabling  this option will enable the support for the parameters defined + * in stdio.h header file like FILE *. This check is required as stdio.h does not+ * exist in some of the embedded  architectures.+ */+#define  TMR_ENABLE_STDIO+  +/**+ * Enabling  this option will enable the support for the parameters defined + * in string.h header file like strerror(). This check is required as string.h does not+ * exist in some of the embedded  architectures.+ */+#define  TMR_USE_STRERROR+#if defined(WINCE)+#undef TMR_USE_STRERROR+#endif++#else+/**+ * Define this to enable support for the GEN2 Custom Tag Operations parameters+ * and access commands+ */+#undef TMR_ENABLE_GEN2_CUSTOM_TAGOPS++/**+ * Define this to enable support for the ISO180006B protocol parameters+ * and access commands+ */+#undef TMR_ENABLE_ISO180006B++/**+ * Define this to enable support for small microcontrollers.+ * Enabling this option will reduce the code which is not relevant to + * serial readers in order to minimize the program footprint+ * To compile for Serial Reader only.+ *+ * To compile for Serial Reader only, use one of the following options:+ ** Uncomment the following define+ ** Run make with TMR_ENABLE_SERIAL_READER_ONLY=1 defined+ ** Add -DTMR_ENABLE_SERIAL_READER_ONLY=1 to your compiler flags+ */ +#define TMR_ENABLE_SERIAL_READER_ONLY++/**+ * Define this to enable support for background reads using native threads.+ * This feature is also available for windows (using pthreads-win32)+ */++#undef TMR_ENABLE_BACKGROUND_READS+++/**+ * Define this to include TMR_strerror().+ */+#undef TMR_ENABLE_ERROR_STRINGS++/**+ * Define this to include TMR_paramName() and TMR_paramID().+ */+#undef TMR_ENABLE_PARAM_STRINGS++/**+ * Enabling  this option will enable the support for the parameters defined + * in stdio.h header file like FILE *. This check is required as stdio.h does not+ * exist in some of the embedded  architectures.+ */+#undef  TMR_ENABLE_STDIO+  +/**+ * Enabling  this option will enable the support for the parameters defined + * in string.h header file like strerror(). This check is required as string.h does not+ * exist in some of the embedded  architectures.+ */+#undef  TMR_USE_STRERROR++#endif    /*Bare_metal*/++/**+ * Define the largest number serial reader antenna ports that will be supported+ */+#define TMR_SR_MAX_ANTENNA_PORTS (32)++/**+ * Define when compiling on a big-endian host platform to enable some+ * endian optimizations. Without this, no endianness will be assumed.+ */ +#undef TMR_BIG_ENDIAN_HOST++/**+ * Define this to enable API-side tag read deduplication.  Under+ * certain conditions, the module runs out of buffer space to detect+ * reads of a previously-seen EPC.  + */+#define TMR_ENABLE_API_SIDE_DEDUPLICATION++/**+ * Default read filter timeout.+ */+#define TMR_DEFAULT_READ_FILTER_TIMEOUT -1++/**+ * The max length of the custom transport scheme name+ */+#define TMR_MAX_TRANSPORT_SCHEME_NAME 50++#ifdef __cplusplus+}+#endif++#endif /* _TM_CONFIG_H */
+ cbits/api/tm_reader.c view
@@ -0,0 +1,3680 @@+/**+ *  @file tm_reader.c+ *  @brief Mercury API - top 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 <stddef.h>+#include <stdio.h>+#include <stdlib.h>+#include <string.h>++#include "tm_reader.h"+#include "serial_reader_imp.h"+#include "tmr_utils.h"++#define EAPI_PREFIX "eapi://"+#define EAPI_PREFIX_LEN (sizeof(EAPI_PREFIX)-1)++#define TMR_PREFIX "tmr://"+#define TMR_PREFIX_LEN (sizeof(TMR_PREFIX)-1)++#define LLRP_EAPI_PREFIX "llrp+eapi://"+#define LLRP_EAPI_PREFIX_LEN (sizeof(LLRP_EAPI_PREFIX)-1)++#define LLRP_PREFIX "llrp://"+#define LLRP_PREFIX_LEN (sizeof(LLRP_PREFIX)-1)++TMR_Status restart_reading(struct TMR_Reader *reader);++/**+ * Private: Should not be used by user level application.+ * structure containing the transport scheme name  and the+ * pointer to the factory init function.+ **/+static void TMR_initSerialTransportTable();++void* do_background_receiveAutonomousReading(void * arg);++typedef struct TMR_SerialTransportDispatchTableData+{+  char transportScheme[TMR_MAX_TRANSPORT_SCHEME_NAME];+  TMR_TransportNativeInit transportInit;+}TMR_SerialTransportDispatchTableData;++typedef struct TMR_SerialTransportDispatchTable+{+  TMR_SerialTransportDispatchTableData *list;+  uint8_t max;+  uint8_t len;+}TMR_SerialTransportDispatchTable;++static bool transportTableInitialized = false;+static TMR_SerialTransportDispatchTableData tdTableData[10];+static TMR_SerialTransportDispatchTable tdTable;++static void TMR_initSerialTransportTable()+{+  if (false == transportTableInitialized)+  {+    /** +     * We did not get a chance to initialize the transport table.+     * Initialize it now.+     */+    memset(tdTableData, 0, (sizeof(tdTableData)/sizeof(tdTableData[0])));+    tdTable.list = tdTableData;+    tdTable.max = sizeof(tdTableData)/sizeof(tdTableData[0]);+    tdTable.len = 0;++    /* Add default schemes to the table */+    {+      TMR_String str;++      str.max = TMR_MAX_TRANSPORT_SCHEME_NAME;+      str.value = tdTable.list[tdTable.len].transportScheme;+      TMR_stringCopy(&str, "eapi", (int)strlen("eapi"));+      tdTable.list[tdTable.len].transportInit = TMR_SR_SerialTransportNativeInit;+      tdTable.len++;++      str.value = tdTable.list[tdTable.len].transportScheme;+      TMR_stringCopy(&str, "tmr", (int)strlen("tmr"));+      tdTable.list[tdTable.len].transportInit = TMR_SR_SerialTransportNativeInit;+      tdTable.len++;+    }+    transportTableInitialized = true;+  }+}++TMR_Status+TMR_create_alloc(TMR_Reader **reader, const char* deviceUri)+{++  *reader = malloc(sizeof(**reader));+  if (NULL == *reader)+    return TMR_ERROR_OUT_OF_MEMORY;+  return TMR_create(*reader, deviceUri);+}+++TMR_Status+TMR_create(TMR_Reader *reader, const char* deviceUri)+{+  TMR_Status ret;++  ret = TMR_ERROR_INVALID;++#ifdef TMR_ENABLE_BACKGROUND_READS+  /* Because destruction of the readers may rely on the locks, these must be+   * created before any possible error can cause an early exit+   */+  pthread_mutex_init(&reader->backgroundLock, NULL);+  pthread_mutex_init(&reader->parserLock, NULL);+  pthread_cond_init(&reader->backgroundCond, NULL);+  pthread_cond_init(&reader->parserCond, NULL);+  pthread_cond_init(&reader->readCond, NULL);+  pthread_mutex_init(&reader->listenerLock, NULL);+  pthread_mutex_init(&reader->queue_lock, NULL);+  reader->authReqListeners = NULL;+  reader->readExceptionListeners = NULL;+  reader->statsListeners = NULL;+  reader->statusListeners = NULL;+  reader->readState = TMR_READ_STATE_IDLE;+  reader->backgroundSetup = false;+  reader->parserSetup = false;+#endif+  reader->readListeners = NULL;+  reader->dutyCycle = false;+  reader->paramWait = false;+  reader->hasContinuousReadStarted = false;++#ifdef TMR_ENABLE_SERIAL_READER+#ifdef TMR_ENABLE_SERIAL_TRANSPORT_NATIVE+if ((strncmp(deviceUri, EAPI_PREFIX, EAPI_PREFIX_LEN) == 0)+    || ((strncmp(deviceUri, TMR_PREFIX, TMR_PREFIX_LEN) == 0)+      && *(deviceUri + TMR_PREFIX_LEN) == '/'))+{+  uint8_t i;+  char  *scheme;+  char devname[TMR_MAX_READER_NAME_LENGTH];+  bool scheme_exists = false;++  TMR_initSerialTransportTable();++  strcpy(devname, deviceUri);+  scheme = strtok((char *)devname, ":");++  for (i = 0; i < tdTable.len; i++)+  {+    if (0 == strcmp(scheme, tdTable.list[i].transportScheme))+    {+      if ('e' == deviceUri[0])+      {+        scheme = (char *)deviceUri + EAPI_PREFIX_LEN;+      }+      else+      {+        scheme = (char *)deviceUri + TMR_PREFIX_LEN;+      }+      strncpy(reader->uri, deviceUri, TMR_MAX_READER_NAME_LENGTH);++        /* Entry exists */+        ret = tdTable.list[i].transportInit(&reader->u.serialReader.transport,+            &reader->u.serialReader.+            transportContext.nativeContext,+            scheme);+      if (TMR_SUCCESS != ret)+      {+        return ret;+      }++      scheme_exists = true;+      break;+    }+  }++  if (false == scheme_exists)+  {+    /* No entry found */+    return TMR_ERROR_INVALID;+  }+  return TMR_SR_SerialReader_init(reader);+}+else+#endif /* TMR_ENABLE_SERIAL_TRANSPORT_NATIVE */+  if ((strncmp(deviceUri, LLRP_PREFIX, LLRP_PREFIX_LEN) == 0)+      || (strncmp(deviceUri, TMR_PREFIX, TMR_PREFIX_LEN) == 0))+{+#ifdef TMR_ENABLE_LLRP_READER+  const char *host, *port;+  char hostCopy[256];++  if ('t' == deviceUri[0])+  {+    host = deviceUri + TMR_PREFIX_LEN;+  }+  else+  {+    host = deviceUri + LLRP_PREFIX_LEN;+  }+  port = strchr(host, ':');+  strcpy(hostCopy, host);+  if (port == NULL)+  {+    char *slash;+    reader->u.llrpReader.portNum = TMR_LLRP_READER_DEFAULT_PORT;+    slash = strchr(hostCopy, '/');+    if (slash)+    {+      *slash = '\0';+    }+  }+  else+  {+    reader->u.llrpReader.portNum = atoi(port + 1);+    hostCopy[port - host] = '\0';+  }++  strncpy(reader->uri, hostCopy, TMR_MAX_READER_NAME_LENGTH); +  return TMR_LLRP_LlrpReader_init(reader);++#else+  return TMR_ERROR_UNSUPPORTED_READER_TYPE;+#endif /* TMR_ENABLE_LLRP_READER */+}+else+{+  /**+   * we are here means user requested for custom transport+   * scheme.+   **/+  uint8_t i;+  char* scheme;+  bool scheme_exists = false;++  scheme = strtok((char *)deviceUri, ":");++  for (i = 0; i < tdTable.len; i++)+  {+    if (0 == strcmp(scheme, tdTable.list[i].transportScheme))+    {+      deviceUri += strlen(scheme) + 2;+      strncpy(reader->uri, deviceUri, TMR_MAX_READER_NAME_LENGTH);++      /* Entry exists */+      ret = tdTable.list[i].transportInit(&reader->u.serialReader.transport,+          &reader->u.serialReader.+          transportContext.nativeContext,+          reader->uri);+      if (TMR_SUCCESS != ret)+      {+        return ret;+      }++      scheme_exists = true;+      break;+    }+  }++  if (false == scheme_exists)+  {+    /* No entry found */+    return TMR_ERROR_INVALID;+  }+  return TMR_SR_SerialReader_init(reader);+}+++#else /* TMR_ENABLE_SERIAL_READER */+/* No readers supported! */+return TMR_ERROR_INVALID;+#endif+}++TMR_Status+TMR_reader_init_internal(struct TMR_Reader *reader)+{+  reader->connected = false;+  reader->pSupportsResetStats = NULL;+  reader->transportListeners = NULL;+++  TMR_RP_init_simple(&reader->readParams.defaultReadPlan, 0, NULL, +                     TMR_TAG_PROTOCOL_GEN2, 1);+  reader->readParams.readPlan = &reader->readParams.defaultReadPlan;+#ifdef SINGLE_THREAD_ASYNC_READ+  reader->readParams.asyncOnTime = 250;+  reader->readParams.asyncOffTime = 0;+#endif+#ifdef TMR_ENABLE_BACKGROUND_READS+  reader->readParams.asyncOnTime = 250;  +  reader->readParams.asyncOffTime = 0;+#if 0+  pthread_mutex_init(&reader->backgroundLock, NULL);+  pthread_mutex_init(&reader->parserLock, NULL);+  pthread_cond_init(&reader->backgroundCond, NULL);+  pthread_cond_init(&reader->parserCond, NULL);+  pthread_cond_init(&reader->readCond, NULL);+  pthread_mutex_init(&reader->listenerLock, NULL);+  pthread_mutex_init(&reader->queue_lock, NULL);+  reader->readListeners = NULL;+  reader->authReqListeners = NULL;+  reader->readExceptionListeners = NULL;+  reader->statsListeners = NULL;+  reader->statusListeners = NULL;+  reader->readState = TMR_READ_STATE_IDLE;+  reader->backgroundSetup = false;+  reader->parserSetup = false;+#endif+  reader->backgroundEnabled = false;+  reader->trueAsyncflag = false;+  reader->parserEnabled = false;+  reader->tagQueueHead = NULL;+  reader->tagQueueTail = NULL;+  reader->isStatusResponse = false;  +  reader->statsFlag = TMR_READER_STATS_FLAG_NONE;+  reader->streamStats = TMR_SR_STATUS_NONE;+  reader->finishedReading = true;+#endif+  reader->continuousReading = false;+  reader->searchStatus = false;+  reader->fastSearch = false;+  reader->backgroundThreadCancel = false;+  reader->isStopNTags = false;+  reader->numberOfTagsToRead = 0;+  reader->userMetadataFlag = TMR_TRD_METADATA_FLAG_ALL;+  reader->portmask = 0;++  return TMR_SUCCESS;+}++TMR_Status+TMR_setSerialTransport(char* scheme, TMR_TransportNativeInit nativeInit)+{+  bool scheme_exists = false;+  uint8_t i;++  TMR_initSerialTransportTable();++  if ((0 == strcmp("llrp", scheme))+      || (0 == strcmp("llrp", scheme)))+  {+    /**+     * Currently set serial transport is only supported for+     * serial readers only.+     **/+    return TMR_ERROR_UNSUPPORTED;+  }++  for (i = 0; i < tdTable.len; i++)+  {+    if (0 == strcmp(scheme, tdTable.list[i].transportScheme))+    {+      /* Entry exists already, just update it */+      if (NULL != nativeInit)+      {+        tdTable.list[i].transportInit = nativeInit;+      }+      scheme_exists = true;+      break;+    }+  }++  if (false == scheme_exists)+  {++    TMR_String str;+    /* Its a new entry, add it to table */++    str.max = TMR_MAX_TRANSPORT_SCHEME_NAME;+    str.value = tdTable.list[tdTable.len].transportScheme;+    TMR_stringCopy(&str, scheme, (int)strlen(scheme));+    tdTable.list[tdTable.len].transportInit = nativeInit;+    tdTable.len++;+  }+  return TMR_SUCCESS;+}+#ifdef TMR_ENABLE_API_SIDE_DEDUPLICATION++static int+TMR_findDupTag(TMR_Reader *reader,+               TMR_TagReadData* newRead,+               TMR_TagReadData oldReads[], int32_t oldLength,+               bool uniqueByAntenna, bool uniqueByData, bool uniqueByProtocol)+{+  int i;++  for (i=0; i<oldLength; i++)+  {+    TMR_TagReadData* oldRead = &oldReads[i];+    TMR_TagData* oldTag = &oldRead->tag;+    TMR_TagData* newTag = &newRead->tag;++    if ((oldTag->epcByteCount != newTag->epcByteCount) ||+        (0 != memcmp(oldTag->epc, newTag->epc,+                     (oldTag->epcByteCount)*sizeof(uint8_t))))+    {+      continue;+    }+    if (uniqueByAntenna)+    {+      if (oldRead->antenna != newRead->antenna)+      {+        continue;+      }+    }+    if (uniqueByData)+    {+      if ((oldRead->data.len != newRead->data.len) ||+          (0 != memcmp(oldRead->data.list, newRead->data.list,+                       (oldRead->data.len)*sizeof(uint8_t))))+      {+        continue;+      }+    }+    if (uniqueByProtocol)+    {+      if (oldRead->tag.protocol != newRead->tag.protocol)+      {+        continue;+      }+    }+    /* No fields mismatched; this tag is a match */+    break;+  }++  return (i < oldLength) ? i : -1;+}++static void+TMR_updateDupTag(TMR_Reader* reader,+                 TMR_TagReadData* oldRead, TMR_TagReadData* newRead,+                 bool highestRssi)+{+  oldRead->readCount += newRead->readCount;++  if (highestRssi)+  {+    if (newRead->rssi > oldRead->rssi)+    {+      uint32_t saveCount = oldRead->readCount;++      memcpy(oldRead, newRead, sizeof(TMR_TagReadData));+      /* TODO: TagReadData.data field not yet supported, pending a+       * comprehensive strategy for dynamic memory allocation. */++      oldRead->readCount = saveCount;+    }+  }+}++#endif /* TMR_ENABLE_API_SIDE_DEDUPLICATION */++TMR_Status+TMR_readIntoArray(struct TMR_Reader *reader, uint32_t timeoutMs,+                  int32_t *tagCount, TMR_TagReadData *result[])+{+  int32_t tagsRead, count, alloc;+  TMR_TagReadData *results;+  TMR_Status ret;+  uint32_t startHi, startLo, nowHi, nowLo;+#ifdef TMR_ENABLE_API_SIDE_DEDUPLICATION+  bool uniqueByAntenna, uniqueByData, recordHighestRssi, uniqueByProtocol;+#endif /* TMR_ENABLE_API_SIDE_DEDUPLICATION */++#ifdef TMR_ENABLE_API_SIDE_DEDUPLICATION+  {+    bool bval;++    ret = TMR_paramGet(reader, TMR_PARAM_TAGREADDATA_UNIQUEBYANTENNA, &bval);+    if (TMR_ERROR_NOT_FOUND == ret) { bval = false; }+    else if (TMR_SUCCESS != ret) { return ret; }+    uniqueByAntenna = bval;++    ret = TMR_paramGet(reader, TMR_PARAM_TAGREADDATA_UNIQUEBYDATA, &bval);+    if (TMR_ERROR_NOT_FOUND == ret) { bval = false; }+    else if (TMR_SUCCESS != ret) { return ret; }+    uniqueByData = bval;++    ret = TMR_paramGet(reader, TMR_PARAM_TAGREADDATA_UNIQUEBYPROTOCOL, &bval);+    if (TMR_ERROR_NOT_FOUND == ret) { bval = false; }+    else if (TMR_SUCCESS != ret) { return ret; }+    uniqueByProtocol = bval;++    ret = TMR_paramGet(reader, TMR_PARAM_TAGREADDATA_RECORDHIGHESTRSSI, &bval);+    if (TMR_ERROR_NOT_FOUND == ret) { bval = false; }+    else if (TMR_SUCCESS != ret) { return ret; }+    recordHighestRssi = bval;+  }+#endif /* TMR_ENABLE_API_SIDE_DEDUPLICATION */++  tagsRead = 0;+  alloc = 0;+  results = NULL;++  tm_gettime_consistent(&startHi, &startLo);+  do +  {++    ret = TMR_read(reader, timeoutMs, &count);+    if ((TMR_SUCCESS != ret) && (TMR_ERROR_TAG_ID_BUFFER_FULL != ret))+    {+      goto out;+    }++    if (0 == count)+    {+      goto out;+    }+    else if (-1 == count) /* Unknown - streaming */+    {+      alloc += 4;+    }+    else+    {+      alloc += count;+    }++    {+      TMR_TagReadData *newResults;+      newResults = realloc(results, alloc * sizeof(*results));+      if (NULL == newResults)+      {+        ret = TMR_ERROR_OUT_OF_MEMORY;+        goto out;+      }+      results = newResults;+    }+    while (TMR_SUCCESS == TMR_hasMoreTags(reader))+    {+      if (tagsRead == alloc)+      {+        TMR_TagReadData *newResults;+        alloc *= 2;+        newResults = realloc(results, alloc * sizeof(*results));+        if (NULL == newResults)+        {+          ret = TMR_ERROR_OUT_OF_MEMORY;+          goto out;+        }+        results = newResults;+      }+      TMR_TRD_init(&results[tagsRead]);+      ret = TMR_getNextTag(reader, &results[tagsRead]);+      if (TMR_SUCCESS != ret)+      {+        goto out;+      }+#ifndef TMR_ENABLE_API_SIDE_DEDUPLICATION+      tagsRead++;+#else+      /* Search array for record duplicating the one just fetched.+       * If no dup found, commit fetched tag by incrementing tag count.+       * If dup found, copy last record to found position, don't advance count.+       */+      if (true == reader->u.serialReader.enableReadFiltering)+      {+        TMR_TagReadData* last = &results[tagsRead];+        int dupIndex = TMR_findDupTag(reader, last, results, tagsRead,+                        uniqueByAntenna, uniqueByData, uniqueByProtocol);+        if (-1 == dupIndex)+          {+            tagsRead++;+          }+        else+          {+            TMR_updateDupTag(reader, &results[dupIndex], last,+                             recordHighestRssi);+          }+      }+      else+      {+        tagsRead++;+      }+#endif /* TMR_ENABLE_API_SIDE_DEDUPLICATION */+    }++    tm_gettime_consistent(&nowHi, &nowLo);+  }+  while (tm_time_subtract(nowLo, startLo) < timeoutMs);++out:+  if (NULL != tagCount)+    *tagCount = tagsRead;+  *result = results;+  return ret;+}++TMR_Status+validateReadPlan(TMR_Reader *reader, TMR_ReadPlan *plan,+                  TMR_AntennaMapList *txRxMap, uint32_t protocols)+{+  TMR_Status ret;+  int i, j;++  if (TMR_READ_PLAN_TYPE_MULTI == plan->type)+  {+    plan->u.multi.totalWeight = 0;+    for (i = 0; i < plan->u.multi.planCount; i++)+    {+      ret = validateReadPlan(reader, plan->u.multi.plans[i], txRxMap, protocols);+      if (TMR_SUCCESS != ret)+      {+        return ret;+      }+      plan->u.multi.totalWeight += plan->u.multi.plans[i]->weight;+    }+    }+  else if (TMR_READ_PLAN_TYPE_SIMPLE == plan->type)+  {+    if (0 == ((1 << (plan->u.simple.protocol - 1)) & protocols))+    {+      return TMR_ERROR_INVALID_PROTOCOL_SPECIFIED;+    }+    for (i = 0 ; i < plan->u.simple.antennas.len; i++)+    {+      for (j = 0; j < txRxMap->len; j++)+      { +        if (plan->u.simple.antennas.list[i] == txRxMap->list[j].antenna)+        {+          break;+        }+      }+      if (j == txRxMap->len)+      {+        return TMR_ERROR_INVALID_ANTENNA_CONFIG;+      }+    }+    if (NULL != plan->u.simple.tagop)+    {+      if (TMR_TAGOP_LIST == plan->u.simple.tagop->type)+        return TMR_ERROR_UNSUPPORTED; /* not yet supported */+    }+  }++  return TMR_SUCCESS;+}++TMR_Status+TMR_paramSet(struct TMR_Reader *reader, TMR_Param key, const void *value)+{+  TMR_Status ret;++  ret = TMR_SUCCESS;++  switch (key)+  {+#if defined(TMR_ENABLE_BACKGROUND_READS)|| defined(SINGLE_THREAD_ASYNC_READ)+  case TMR_PARAM_READ_ASYNCOFFTIME:+      {+        if (TMR_READER_TYPE_LLRP != reader->readerType)+        {+			if (reader->readParams.asyncOffTime != *(uint32_t *)value)+			{+				uint32_t asyncOffTime = reader->readParams.asyncOffTime;+				reader->readParams.asyncOffTime = *(uint32_t *)value;+				if (reader->continuousReading)+				{+					ret = restart_reading(reader);+					if(ret != TMR_SUCCESS)+					{+						reader->readParams.asyncOffTime = asyncOffTime;+					}+				}+			}+        }+        else+        {+          goto LEVEL1;+        }+      }+    break;+  case TMR_PARAM_READ_ASYNCONTIME:+	  {+		  if (reader->readParams.asyncOnTime != *(uint32_t *)value)+		  {+			  uint32_t asyncOnTime = reader->readParams.asyncOnTime;+			  reader->readParams.asyncOnTime = *(uint32_t *)value;+			  if (reader->continuousReading)+			  {+				  ret = restart_reading(reader);+				  if(ret != TMR_SUCCESS)+				  {+					  reader->readParams.asyncOnTime = asyncOnTime;+				  }+			  }+		  }+	  }+    break;+LEVEL1:+#endif+  default:+    ret = reader->paramSet(reader, key, value);+  }+  return ret;+}+++TMR_Status+TMR_paramGet(struct TMR_Reader *reader, TMR_Param key, void *value)+{+  TMR_Status ret;++  ret = TMR_SUCCESS;++  switch (key)+  {+  case TMR_PARAM_READ_PLAN:+  {+    TMR_ReadPlan *plan = value;+    *plan = *reader->readParams.readPlan;+    break;+  }+#if defined(TMR_ENABLE_BACKGROUND_READS)|| defined(SINGLE_THREAD_ASYNC_READ) +  case TMR_PARAM_READ_ASYNCOFFTIME:+  {+    if (TMR_READER_TYPE_LLRP != reader->readerType)+    {+    *(uint32_t *)value = reader->readParams.asyncOffTime;+    }+    else+    {+      goto LEVEL;+    }+    break;+  }+  case TMR_PARAM_READ_ASYNCONTIME:+    *(uint32_t *)value = reader->readParams.asyncOnTime;+    break;+LEVEL:+#endif+  default:+    ret = reader->paramGet(reader, key, value);+  }+  return ret;+}+++TMR_Status+TMR_addTransportListener(TMR_Reader *reader, TMR_TransportListenerBlock *b)+{++  b->next = reader->transportListeners;+  reader->transportListeners = b;++  return TMR_SUCCESS;+}+++TMR_Status+TMR_removeTransportListener(TMR_Reader *reader, TMR_TransportListenerBlock *b)+{+  TMR_TransportListenerBlock *block, **prev;++  prev = &reader->transportListeners;+  block = reader->transportListeners;+  while (NULL != block)+  {+    if (block == b)+    {+      *prev = block->next;+      break;+    }+    prev = &block->next;+    block = block->next;+  }+  if (block == NULL)+  {+    return TMR_ERROR_INVALID;+  }++  return TMR_SUCCESS;+}+++void+TMR__notifyTransportListeners(TMR_Reader *reader, bool tx, +                              uint32_t dataLen, uint8_t *data,+                              int timeout)+{+  TMR_TransportListenerBlock *block;++  block = reader->transportListeners;+  while (NULL != block)+  {+    block->listener(tx, dataLen, data, timeout, block->cookie);+    block = block->next;+  }+}++bool+TMR_memoryProvider(void *cookie, uint16_t *size, uint8_t *data)+{+  TMR_memoryCookie *mc;+  int len;++  mc = cookie;++  if (0 == mc->firmwareSize)+  {+    return false;+  }++  if (*size > mc->firmwareSize)+  {+    *size =(uint16_t) mc->firmwareSize;+  }++  len = *size;++  memcpy(data, mc->firmwareStart, len);+  +  mc->firmwareSize -= len;+  mc->firmwareStart += len;++  return true;+}++#ifdef TMR_ENABLE_STDIO+bool+TMR_fileProvider(void *cookie, uint16_t *size, uint8_t *data)+{+  FILE *fp;+  size_t len;++  fp = cookie;++  len = fread(data, 1, *size, fp);+  if (0 == len)+  {+    return false;+  }+  +  *size = (uint16_t) len;+  return true;+}+#endif++/**+ * Initialize TMR_TagReadData with default values.+ * The tagData buffer will be initialized to TMR_MAX_EMBEDDED_DATA_LENGTH+ * which can be found in tm_config.h.  + * If this value is zero, then the buffer is pointed to NULL.+ * @param trd Pointer to the TMR_TagReadData structure to initialize+ */+TMR_Status+TMR_TRD_init(TMR_TagReadData *trd)+{+  trd->tag.protocol = TMR_TAG_PROTOCOL_NONE;+  trd->tag.epcByteCount = 0;+  trd->tag.crc = 0;+  trd->metadataFlags = 0;+  trd->phase = 0;+  memset(trd->gpio, 0, sizeof(trd->gpio));+  trd->gpioCount = 0;+  trd->readCount = 0;+  trd->rssi = 0;+  trd->frequency = 0;+  trd->dspMicros = 0;+  trd->timestampLow = 0;+  trd->timestampHigh = 0;++#if TMR_MAX_EMBEDDED_DATA_LENGTH+  trd->data.list = trd->_dataList;+  trd->epcMemData.list = trd->_epcMemDataList;+  trd->tidMemData.list = trd->_tidMemDataList;+  trd->userMemData.list = trd->_userMemDataList;+  trd->reservedMemData.list = trd->_reservedMemDataList;++  trd->data.max = TMR_MAX_EMBEDDED_DATA_LENGTH;+  trd->epcMemData.max = TMR_MAX_EMBEDDED_DATA_LENGTH;+  trd->userMemData.max = TMR_MAX_EMBEDDED_DATA_LENGTH;+  trd->reservedMemData.max = TMR_MAX_EMBEDDED_DATA_LENGTH;+  trd->tidMemData.max = TMR_MAX_EMBEDDED_DATA_LENGTH;+#else+  trd->data.list = NULL;+  trd->epcMemData.list = NULL;+  trd->userMemData.list = NULL;+  trd->tidMemData.list = NULL;+  trd->reservedMemData.list = NULL;++  trd->data.max = 0;+  trd->epcMemData.max = 0;+  trd->userMemData.max = 0;+  trd->reservedMemData.max = 0;+  trd->tidMemData.max = 0;+#endif+  trd->data.len = 0;+  trd->epcMemData.len = 0;+  trd->userMemData.len = 0;+  trd->tidMemData.len = 0;+  trd->reservedMemData.len = 0;++  return TMR_SUCCESS;+}++/**+ * Initialize a TMR_TagReadData with the provided data storage area.+ *+ * @param trd Pointer to the TMR_TagReadData structure to initialize+ * @param size The number of bytes pointed to+ * @param buf Pointer to the uint8_t storage area+ */+TMR_Status+TMR_TRD_init_data(TMR_TagReadData *trd, uint16_t size, uint8_t *buf)+{+  trd->data.max = size;+  trd->data.len = 0;+  trd->data.list = buf;++  return TMR_SUCCESS;+}++/**+ * Initialize a TMR_TagReadDataMemBank with provided data storage area+ *+ * @param data to the TMR_uint8List structure to initialize+ * @param size The nuber of bytes pointed to+ * @param buf pointer to the uint8_t storage area+ **/+TMR_Status+TMR_TRD_MEMBANK_init_data(TMR_uint8List *data, uint16_t size, uint8_t *buf)+{+  data->max = size;+  data->len = 0;+  data->list = buf;++  return TMR_SUCCESS;+}++/**+ * Initialize a TMR_GEN2_Bap with the provided parameters+ *+ * @param bapVal pointer to the TMR_GEN2_Bap structure+ * @param powerUpDelayUs the power up delay time+ * @param freqHopOfftimeUs the offtime for frequencyHop+ **/+TMR_Status+TMR_GEN2_init_BapParams(TMR_GEN2_Bap *bapVal, int32_t powerUpDelayUs, int32_t freqHopOfftimeUs)+{++  bapVal->powerUpDelayUs = powerUpDelayUs;+  bapVal->freqHopOfftimeUs=freqHopOfftimeUs;++  return TMR_SUCCESS;+}++/**+ * Initialize a TMR_Filter structure as tag data (EPC) filter with the+ * provided tag (which is copied).+ * + * @param filter Pointer to the filter structure to initialize+ * @param tag TMR_TagData to use as the filter value+ */+TMR_Status+TMR_TF_init_tag(TMR_TagFilter *filter, TMR_TagData *tag)+{+  +  filter->type = TMR_FILTER_TYPE_TAG_DATA;+  filter->u.tagData = *tag;+  +  return TMR_SUCCESS;+}++/**+ * Initialize a TMR_Filter structure as a Gen2 select filter with the+ * provided parameters.+ * + * @param filter Pointer to the filter structure to initialize+ * @param invert Whether to invert the result of the select+ * @param bank The memory bank on the tag to compare with the data+ * @param bitPointer The bit address of the tag data to compare+ * @param maskBitLength The length of the data to compare+ * @param mask The data to compare+ */+TMR_Status+TMR_TF_init_gen2_select(TMR_TagFilter *filter, bool invert, TMR_GEN2_Bank bank,+                        uint32_t bitPointer, uint16_t maskBitLength,+                        uint8_t *mask)+{+  +  filter->type = TMR_FILTER_TYPE_GEN2_SELECT;+  filter->u.gen2Select.invert = invert;+  filter->u.gen2Select.bank = bank;+  filter->u.gen2Select.bitPointer = bitPointer;+  filter->u.gen2Select.maskBitLength = maskBitLength;+  filter->u.gen2Select.mask = mask;++  return TMR_SUCCESS;+}+++#ifdef TMR_ENABLE_ISO180006B+/**+ * Initialize a TMR_Filter structure as an ISO180006B select filter with the+ * provided parameters.+ * + * @param filter Pointer to the filter structure to initialize+ * @param invert Whether to invert the result of the select+ * @param op The operation to use to compare the provided data with the tag data+ * @param address The address of the 8 bytes of data on the tag to compare + * @param mask 8-bit mask of the bytes to compare+ * @param wordData The data to compare to the tag data+ */+TMR_Status TMR_TF_init_ISO180006B_select(TMR_TagFilter *filter, bool invert,+                                         TMR_ISO180006B_SelectOp op,+                                         uint8_t address, uint8_t mask,+                                         uint8_t wordData[8])+{++  filter->type = TMR_FILTER_TYPE_ISO180006B_SELECT;+  filter->u.iso180006bSelect.invert = invert;+  filter->u.iso180006bSelect.op = op;+  filter->u.iso180006bSelect.address = address;+  filter->u.iso180006bSelect.mask = mask;+  memcpy(filter->u.iso180006bSelect.data, wordData, 8);+  +  return TMR_SUCCESS;+}+#endif /* TMR_ENABLE_ISO180006B */+++bool+TMR_TF_match(TMR_TagFilter *filter, TMR_TagData *tag)+{+  int32_t i, bitAddr;+  bool match;+  TMR_GEN2_Select *sel;++  if (TMR_FILTER_TYPE_GEN2_SELECT != filter->type)+  {+    return false;+  }++  if (TMR_TAG_PROTOCOL_GEN2 != tag->protocol)+  {+    return false;+  }++  sel = &filter->u.gen2Select;++  if (TMR_GEN2_BANK_EPC != sel->bank)+  {+    /*+     * Can't perform non-EPC matches, since we don't have the rest of+     * the tag data.+     */+    return false;+  }++  i = 0;+  bitAddr = sel->bitPointer;+  /*+   * Matching against the CRC and PC does not have defined+   * behavior; see section 6.3.2.11.1.1 of Gen2 version 1.2.0.+   * We choose to let it match, because that's simple.+   */+  bitAddr -= 32;+  if (bitAddr < 0)+  {+    i -= bitAddr;+    bitAddr = 0;+  }++  match = true;+  for (; i < sel->maskBitLength; i++, bitAddr++)+  {+    if (bitAddr >(int32_t) (tag->epcByteCount * 8))+    {+      match = false;+      break;+    }+    /* Extract the relevant bit from both the EPC and the mask. */+    if (((tag->epc[bitAddr / 8] >> (7 - (bitAddr & 7))) & 1) !=+        ((sel->mask[i / 8] >> (7 - (i & 7))) & 1))+    {+      match = false;+      break;+    }+  }+  if (sel->invert)+    match = match ? false : true;++  return match;+}+++/**+ * Initialize a TMR_TagAuthentication structure as a Gen2 password.+ *+ * @param auth Pointer to the structure to initialize.+ * @param password The password 32-bit Gen2 password value.+ */+TMR_Status+TMR_TA_init_gen2(TMR_TagAuthentication *auth, TMR_GEN2_Password password)+{++  auth->type = TMR_AUTH_TYPE_GEN2_PASSWORD;+  auth->u.gen2Password = password;++  return TMR_SUCCESS;+}++/**+ * Initialize a TMR_TagAuthentication structure as Denatran IAV write credential+ *+ * @param auth Pointer to the structure to initialize.+ * @param data Gen2 Denatran IAV write credential+ */+TMR_Status+TMR_TA_init_gen2_Denatran_IAV_writeCredentials(TMR_TagAuthentication *auth, uint8_t idLength, uint8_t* tagId, uint8_t len, uint8_t *data)+{+  uint8_t i;+  auth->type = TMR_AUTH_TYPE_GEN2_DENATRAN_IAV_WRITE_CREDENTIALS;++  /* The length should be 16 byte */+  auth->u.writeCreds.credentialLength = len;+  if (16 != auth->u.writeCreds.credentialLength)+  {+    return TMR_ERROR_INVALID;+  }++  /* The length for tag ID should be 8 bytes */+  auth->u.writeCreds.tagIdLength = idLength;+  if (8 != auth->u.writeCreds.tagIdLength)+  {+    return TMR_ERROR_INVALID;+  }++  /* Copy the data */+  for (i = 0; i < auth->u.writeCreds.tagIdLength; i++)+  {+    memcpy(auth->u.writeCreds.tagId, tagId, auth->u.writeCreds.tagIdLength);+  }++  /* Copy the data */+  for (i = 0; i < auth->u.writeCreds.credentialLength; i++)+  {+    memcpy(auth->u.writeCreds.value, data, auth->u.writeCreds.credentialLength);+  }++  return TMR_SUCCESS;+}++/**+ * Initialize a TMR_TagAuthentication structure as Denatran IAV write credential+ *+ * @param auth Pointer to the structure to initialize.+ * @param data Gen2 Denatran IAV write credential+ */+TMR_Status+TMR_TA_init_gen2_Denatran_IAV_writeSecCredentials(TMR_TagAuthentication *auth, uint8_t length, uint8_t* data, uint8_t len, uint8_t* credentials)+{+  uint8_t i;+  auth->type = TMR_AUTH_TYPE_GEN2_DENATRAN_IAV_WRITE_SEC_CREDENTIALS;++  /* The length should be 16 byte */+  auth->u.writeSecCreds.credentialLength = len;+  if (16 != auth->u.writeSecCreds.credentialLength)+  {+    return TMR_ERROR_INVALID;+  }++  /* The length for data words should be 6 bytes */+  auth->u.writeSecCreds.dataLength = length;+  if (6 != auth->u.writeSecCreds.dataLength)+  {+    return TMR_ERROR_INVALID;+  }++  /* Copy the data */+  for (i = 0; i < auth->u.writeSecCreds.dataLength; i++)+  {+    memcpy(auth->u.writeSecCreds.data, data, auth->u.writeSecCreds.dataLength);+  }++  /* Copy the data */+  for (i = 0; i < auth->u.writeSecCreds.credentialLength; i++)+  {+    memcpy(auth->u.writeSecCreds.value, credentials, auth->u.writeSecCreds.credentialLength);+  }++  return TMR_SUCCESS;+}++/** Initialize a TMR_StatValues structure with the default vales+ *+ * @param stats Pointer to the TMR_StatValues structure to initialize.+ */+TMR_Status+TMR_STATS_init(TMR_Reader_StatsValues *stats)+{+  if (NULL != stats)+  {+    stats->valid = TMR_READER_STATS_FLAG_NONE;+    /* Allocate space for the parameters */+    stats->connectedAntennas.len = 0;+    stats->connectedAntennas.max = TMR_SR_MAX_ANTENNA_PORTS;+    stats->connectedAntennas.list = stats->_connectedAntennasStorage;+    stats->perAntenna.len = 0;+    stats->perAntenna.max = TMR_SR_MAX_ANTENNA_PORTS;+    stats->perAntenna.list = stats->_perAntStorage;+  }+  return TMR_SUCCESS;+}++/**+ * Initialize a TMR_GPITriggerRead structure with default values.+ *+ * @param triggerRead Pointer to the read plan to initialize.+ * @param enable Option to enable trigger read.+ */+TMR_Status+TMR_GPITR_init_enable(TMR_GPITriggerRead *triggerRead, bool enable)+{+  triggerRead->enable = enable;++  return TMR_SUCCESS;+}++/**+ * Initialize a TMR_ReadPlan structure as a simple read plan with the+ * provided parameters.  + *+ * Only the mandatory elements are parameters to+ * this function. The optional elements, filters and tag operations,+ * can be set with TMR_RP_set_filter() and TMR_RP_set_tagop().+ *+ * @param plan Pointer to the read plan to initialize.+ * @param antennaCount Number of antennas in antenna list. A+ * zero-length list requests the reader to use all antennas known to+ * be connected at the time of the read operation.+ * @param antennaList Pointer to antenna numbers.+ * @param protocol Protocol+ * @param weight Weight.+ */+TMR_Status+TMR_RP_init_simple(TMR_ReadPlan *plan, uint8_t antennaCount,+                   uint8_t *antennaList, TMR_TagProtocol protocol,+                   uint32_t weight) +{+  +  plan->type = TMR_READ_PLAN_TYPE_SIMPLE;+  plan->u.simple.antennas.max = antennaCount;+  plan->u.simple.antennas.len = antennaCount;+  plan->u.simple.antennas.list = antennaList;+  plan->u.simple.protocol = protocol;+  plan->u.simple.filter = NULL;+  plan->u.simple.tagop = NULL;+  plan->weight = weight;+  plan->u.simple.useFastSearch = false;+  plan->u.simple.stopOnCount.stopNTriggerStatus = false;+  plan->u.simple.stopOnCount.noOfTags = 0;+  plan->u.simple.triggerRead.enable = false;+  plan->u.simple.triggerRead.gpiList.len = 0;+  plan->u.simple.triggerRead.gpiList.list = NULL;+  plan->u.simple.triggerRead.gpiList.max = 0;+  plan->enableAutonomousRead = false;+  +  return TMR_SUCCESS;+}++/**+ * Set the stop on N tags  option of a read plan+ *+ * @param plan Pointer to the read plan+ * @param nCount the number of tags user requested to search.+ */+TMR_Status+TMR_RP_set_stopTrigger(TMR_ReadPlan *plan, uint32_t nCount)+{++  if (TMR_READ_PLAN_TYPE_SIMPLE != plan->type)+    return TMR_ERROR_INVALID;++  plan->u.simple.stopOnCount.stopNTriggerStatus = true;+  plan->u.simple.stopOnCount.noOfTags = nCount;++  return TMR_SUCCESS;+}++/**+ * Set the filter of a simple read plan.+ *+ * @param plan Pointer to the read plan+ * @param filter Pointer to the filter + */+TMR_Status+TMR_RP_set_filter(TMR_ReadPlan *plan, TMR_TagFilter *filter)+{++  if (TMR_READ_PLAN_TYPE_SIMPLE != plan->type)+    return TMR_ERROR_INVALID;++  plan->u.simple.filter = filter;++  return TMR_SUCCESS;+}++/**+ * Set the fast search option of a read plan+ *+ * @param plan Pointer to the read plan+ * @param useFastSearch Option for FastSearch+ */ +TMR_Status+TMR_RP_set_useFastSearch(TMR_ReadPlan *plan, bool useFastSearch)+{++  if (TMR_READ_PLAN_TYPE_SIMPLE != plan->type)+    return TMR_ERROR_INVALID;++  plan->u.simple.useFastSearch = useFastSearch;++  return TMR_SUCCESS;+}++/**+ * Set the autonomous read option of a read plan+ *+ * @param plan Pointer to the read plan+ * @param autonomousRead Option for autonomous read.+ */ +TMR_Status+TMR_RP_set_enableAutonomousRead(TMR_ReadPlan *plan, bool autonomousRead)+{+  plan->enableAutonomousRead = autonomousRead;+  return TMR_SUCCESS;+}++/**+ * Set the trigger read option of a read plan+ *+ * @param plan Pointer to the read plan+ * @param triggerRead Pointer for trigger read+ */+TMR_Status+TMR_RP_set_enableTriggerRead(TMR_ReadPlan *plan, TMR_GPITriggerRead *triggerRead)+{+  if (TMR_READ_PLAN_TYPE_SIMPLE != plan->type)+    return TMR_ERROR_INVALID;++  plan->u.simple.triggerRead.enable = triggerRead->enable;+  /*+   * TODO: extent the set_enableTriggerRead() method to accept the GPI list directly+           as a part of read plan. Current the GPI list can be set through TMR_paramSet().+   */+  plan->u.simple.triggerRead.gpiList.list = NULL;+  plan->u.simple.triggerRead.gpiList.len = 0;+  plan->u.simple.triggerRead.gpiList.max = 0;  ++  return TMR_SUCCESS;+}++/**+ * Set the tagop of a simple read plan.+ *+ * @param plan Pointer to the read plan+ * @param tagop Pointer to the tagop + */+TMR_Status+TMR_RP_set_tagop(TMR_ReadPlan *plan, TMR_TagOp *tagop)+{++  if (TMR_READ_PLAN_TYPE_SIMPLE != plan->type)+    return TMR_ERROR_INVALID;++  plan->u.simple.tagop = tagop;++  return TMR_SUCCESS;+}++/**+ * Initialize a TMR_ReadPlan structure as a multi-read plan with the+ * provided parameters.+ *+ * @param plan Pointer to the read plan to initialize.+ * @param plans Array of pointers to read plans to include+ * @param planCount Number of elements in array+ * @param weight Weight.+ */+TMR_Status+TMR_RP_init_multi(TMR_ReadPlan *plan, TMR_ReadPlan **plans, uint8_t planCount,+                  uint32_t weight)+{+  plan->type = TMR_READ_PLAN_TYPE_MULTI;+  plan->u.multi.plans = plans;+  plan->u.multi.planCount = planCount;+  plan->u.multi.totalWeight = 0;+  plan->weight = weight;++  return TMR_SUCCESS;+}+++/**+ * Initialize a TMR_TagLockAction as a Gen2 lock action with the+ * provided parameters.+ *+ * @param lockAction Pointer to the structure to initialize.+ * @param mask mask+ * @param action action+ */+TMR_Status+TMR_TLA_init_gen2(TMR_TagLockAction *lockAction, uint16_t mask, uint16_t action)+{++  lockAction->type = TMR_LOCK_ACTION_TYPE_GEN2_LOCK_ACTION;+  lockAction->u.gen2LockAction.mask = mask;+  lockAction->u.gen2LockAction.action = action;++  return TMR_SUCCESS;+}+++#ifdef TMR_ENABLE_ISO180006B+/**+ * Initialize a TMR_TagLockAction as an ISO180006B lock action with the+ * provided parameters.+ *+ * @param lockAction Pointer to the structure to initialize.+ * @param address The byte to lock+ */+TMR_Status+TMR_TLA_init_ISO180006B(TMR_TagLockAction *lockAction, uint8_t address)+{++  lockAction->type = TMR_LOCK_ACTION_TYPE_ISO180006B_LOCK_ACTION;+  lockAction->u.iso180006bLockAction.address = address;++  return TMR_SUCCESS;+}++#endif /* TMR_ENABLE_ISO180006B */+++/**+ * Initialize a TMR_TagOp as a GEN2 EPC write operation with the+ * provided parameters.+ * + * @param tagop Pointer to the tagop structure to initialize.+ * @param epc EPC to write+ */+TMR_Status+TMR_TagOp_init_GEN2_WriteTag(TMR_TagOp *tagop, TMR_TagData* epc)+{+  tagop->type = TMR_TAGOP_GEN2_WRITETAG;+  tagop->u.gen2.u.writeTag.epcptr = epc;  /* Takes pointer to EPC; doesn't make an actual copy */++  return TMR_SUCCESS;+}++/**+ * Initialize a TMR_TagOp as a GEN2 data read operation with the+ * provided parameters.+ * + * @param tagop Pointer to the tagop structure to initialize.+ * @param bank Memory bank from which to read+ * @param wordAddress Word address of location in bank from which to read+ * @param len Number of words to read+ */+TMR_Status+TMR_TagOp_init_GEN2_ReadData(TMR_TagOp *tagop, TMR_GEN2_Bank bank,+                             uint32_t wordAddress, uint8_t len)+{++  tagop->type = TMR_TAGOP_GEN2_READDATA;+  tagop->u.gen2.u.readData.bank = bank;+  tagop->u.gen2.u.readData.wordAddress = wordAddress;+  tagop->u.gen2.u.readData.len = len;++  return TMR_SUCCESS;+}++/** + * Initialize a TMR_TagOp as a GEN2 Secure data read operation with the+ * provided parameters.+ *+ * @param tagop Pointer to the tagop structure to initialize.+ * @param bank Memory bank from which to read+ * @param wordAddress Word address of location in bank from which to read+ * @param len Number of words to read+ * @param tagtype to select Alien Higgs 3 secure access and Monza 4 secure access+ * @param passwordType specifying the mode of password + */+TMR_Status+TMR_TagOp_init_GEN2_SecureReadData(TMR_TagOp *tagop, TMR_GEN2_Bank bank, uint32_t wordAddress,+                                   uint8_t len, uint8_t tagtype, uint8_t passwordType)+{+  tagop->type = TMR_TAGOP_GEN2_SECURE_READDATA;+  tagop->u.gen2.u.secureReadData.passwordType = (SecurePasswordType)passwordType;+  tagop->u.gen2.u.secureReadData.readData.bank = bank;+  tagop->u.gen2.u.secureReadData.readData.wordAddress = wordAddress;+  tagop->u.gen2.u.secureReadData.readData.len = len;+  tagop->u.gen2.u.secureReadData.type = (SecureTagType)tagtype;++  return TMR_SUCCESS;+}++/**+ * Initialize a TMR_TagOp as a Gen2 Secure Password with the + * provided parameters.+ *+ * @param tagop Pointer to the tagop structure to initialize+ * @param passwordType specifying the mode of password + * @param gen2PassWord Gen2 access password+ * @param addressLength Number of bits used to address the AP list+ * @param addressOffset EPC word offset+ * @param flashOffset User flash offset+ */+TMR_Status+TMR_TagOp_init_GEN2_SecurePassWord(TMR_TagOp *tagop, uint8_t passwordType, uint32_t gen2PassWord,+                                   uint8_t addressLength, uint8_t addressOffset, uint16_t flashOffset)+{+  +  tagop->u.gen2.u.secureReadData.passwordType = (SecurePasswordType)passwordType;+  tagop->u.gen2.u.secureReadData.password.gen2PassWord.u.gen2Password = gen2PassWord;+  tagop->u.gen2.u.secureReadData.password.secureAddressLength = addressLength;+  tagop->u.gen2.u.secureReadData.password.secureAddressOffset = addressOffset;+  tagop->u.gen2.u.secureReadData.password.secureFlashOffset = flashOffset;++  return TMR_SUCCESS;+}++/**+ * Initialize a TMR_TagOp as a ISO18000B data read operation with the+ * provided parameters.+ * + * @param tagop Pointer to the tagop structure to initialize.+ * @param byteAddress Address of location in bank from which to read+ * @param len Number of bytes to read+ */+TMR_Status+TMR_TagOp_init_ISO180006B_ReadData(TMR_TagOp *tagop, uint8_t byteAddress, uint8_t len)+{++  tagop->type = TMR_TAGOP_ISO180006B_READDATA;+  tagop->u.iso180006b.u.readData.byteAddress = byteAddress;+  tagop->u.iso180006b.u.readData.len = len;++  return TMR_SUCCESS;+}+++/**+ * Initialize a TMR_TagOp as a GEN2 data write operation with the+ * provided parameters.+ * + * @param tagop Pointer to the tagop structure to initialize.+ * @param bank Memory bank to write into+ * @param wordAddress Word address of location to begin write+ * @param data Data to write+ */+TMR_Status+TMR_TagOp_init_GEN2_WriteData(TMR_TagOp *tagop, TMR_GEN2_Bank bank,+                              uint32_t wordAddress, TMR_uint16List *data)+{+  tagop->type = TMR_TAGOP_GEN2_WRITEDATA;+  tagop->u.gen2.u.writeData.bank = bank;+  tagop->u.gen2.u.writeData.wordAddress = wordAddress;+  tagop->u.gen2.u.writeData.data = *data; /* Copies pointer to the words adata but not data */++  return TMR_SUCCESS;+}++/**+ * Initialize a TMR_TagOp as a ISO180006B data write operation with the+ * provided parameters.+ * + * @param tagop Pointer to the tagop structure to initialize.+ * @param byteAddress  address of location to begin write+ * @param data Data to write+ */+TMR_Status+TMR_TagOp_init_ISO180006B_WriteData(TMR_TagOp *tagop, uint8_t byteAddress, TMR_uint8List *data)+{+  tagop->type = TMR_TAGOP_ISO180006B_WRITEDATA;+  tagop->u.iso180006b.u.writeData.byteAddress = byteAddress;+  tagop->u.iso180006b.u.writeData.data = *data;+  return TMR_SUCCESS;+}++/**+ * Initialize a TMR_TagOp as a GEN2 lock operation with the provided parameters.+ * @param tagop Pointer to the tagop structure to initialize.+ * @param mask mask+ * @param action action+ * @param accessPassword The password to use to lock the tag.+ */+TMR_Status+TMR_TagOp_init_GEN2_Lock(TMR_TagOp *tagop, uint16_t mask, uint16_t action, TMR_GEN2_Password accessPassword)+{++  tagop->type = TMR_TAGOP_GEN2_LOCK;+  tagop->u.gen2.u.lock.mask = mask;+  tagop->u.gen2.u.lock.action = action;+  tagop->u.gen2.u.lock.accessPassword = accessPassword;++  return TMR_SUCCESS;+}++/**+ * Initialize a TMR_TagOp as a ISO180006B lock operation with the provided parameters.+ * @param tagop Pointer to the tagop structure to initialize.+ * @param address The memory address of the byte to lock.+ */+TMR_Status+TMR_TagOp_init_ISO180006B_Lock(TMR_TagOp *tagop,  uint8_t address)+{++  tagop->type = TMR_TAGOP_ISO180006B_LOCK;+  tagop->u.iso180006b.u.lock.address = address;++  return TMR_SUCCESS;+}++/**+ * Initialize a TMR_TagOp as a GEN2 kill operation with the provided parameters.+ * @param tagop Pointer to the tagop structure to initialize.+ * @param killPassword tag kill password+ */+TMR_Status+TMR_TagOp_init_GEN2_Kill(TMR_TagOp *tagop, TMR_GEN2_Password killPassword)+{++  tagop->type = TMR_TAGOP_GEN2_KILL;+  tagop->u.gen2.u.kill.password = killPassword;++  return TMR_SUCCESS;+}+++/**+ * Initialize a TMR_TagOp as a GEN2 BlockWrite operation with the provided parameters.+ * @param tagop Pointer to the tagop structure to initialize.+ * @param bank bank+ * @param wordPtr word pointer+ * @param data data (The length of the data specifies the word count)+ */+TMR_Status+TMR_TagOp_init_GEN2_BlockWrite(TMR_TagOp *tagop, TMR_GEN2_Bank bank, uint32_t wordPtr, TMR_uint16List *data)+{+  tagop->type = TMR_TAGOP_GEN2_BLOCKWRITE;+  tagop->u.gen2.u.blockWrite.bank = bank;+  tagop->u.gen2.u.blockWrite.wordPtr = wordPtr;+  tagop->u.gen2.u.blockWrite.data.len = data->len;+  tagop->u.gen2.u.blockWrite.data.list = data->list;+  tagop->u.gen2.u.blockWrite.data.max = data->max;+  return TMR_SUCCESS;+}++/**+ * Initialize a TMR_TagOp as a GEN2 BlockPermaLock operation with the provided parameters.+ * @param tagop Pointer to the tagop structure to initialize.+ * @param readLock readLock+ * @param bank bank+ * @param blockPtr block pointer+ * @param mask mask (The length of the mask specifies the block range)+ */+TMR_Status+TMR_TagOp_init_GEN2_BlockPermaLock(TMR_TagOp *tagop, uint8_t readLock, TMR_GEN2_Bank bank, uint32_t blockPtr, TMR_uint16List *mask)+{+  tagop->type = TMR_TAGOP_GEN2_BLOCKPERMALOCK;+  tagop->u.gen2.u.blockPermaLock.readLock = readLock;+  tagop->u.gen2.u.blockPermaLock.bank = bank;+  tagop->u.gen2.u.blockPermaLock.blockPtr = blockPtr;+  tagop->u.gen2.u.blockPermaLock.mask.len = mask->len;+  tagop->u.gen2.u.blockPermaLock.mask.list = mask->list;+  tagop->u.gen2.u.blockPermaLock.mask.max = mask->max;+  return TMR_SUCCESS;++}++/**+ * Initialize a TMR_TagOp as a GEN2 BlockErase operation with the provided parameters.+ * @param tagop Pointer to the tagop structure to initialize.+ * @param bank bank+ * @param wordPtr The starting word address to erase+ * @param wordCount Number of words to erase+ */+TMR_Status +TMR_TagOp_init_GEN2_BlockErase(TMR_TagOp *tagop, TMR_GEN2_Bank bank, uint32_t wordPtr, uint8_t wordCount)+{+  tagop->type = TMR_TAGOP_GEN2_BLOCKERASE;+  tagop->u.gen2.u.blockErase.bank = bank;+  tagop->u.gen2.u.blockErase.wordCount = wordCount;+  tagop->u.gen2.u.blockErase.wordPtr = wordPtr;+  return TMR_SUCCESS;+}++/**+ * Initialize a TMR_TagOp as a Higgs2 Partial Load Image operation with the provided parameters.+ * @param tagop Pointer to the tagop structure to initialize.+ * @param killPassword kill password+ * @param accessPassword access password+ * @param epc EPC to write+ */++#ifdef TMR_ENABLE_GEN2_CUSTOM_TAGOPS++TMR_Status +TMR_TagOp_init_GEN2_Alien_Higgs2_PartialLoadImage(TMR_TagOp *tagop, TMR_GEN2_Password killPassword,+                                       TMR_GEN2_Password accessPassword, TMR_TagData *epc)+{+  tagop->type = TMR_TAGOP_GEN2_ALIEN_HIGGS2_PARTIALLOADIMAGE;+  tagop->u.gen2.u.custom.chipType = TMR_SR_GEN2_ALIEN_HIGGS_SILICON;+  tagop->u.gen2.u.custom.u.alien.u.higgs2.u.partialLoadImage.accessPassword = accessPassword;+  tagop->u.gen2.u.custom.u.alien.u.higgs2.u.partialLoadImage.killPassword = killPassword;+  tagop->u.gen2.u.custom.u.alien.u.higgs2.u.partialLoadImage.epcptr = epc; /* Takes pointer to EPC; doesn't make an actual copy */++  return TMR_SUCCESS;+}++/**+ * Initialize a TMR_TagOp as a Higgs2 Full Load Image operation with the provided parameters.+ * @param tagop Pointer to the tagop structure to initialize.+ * @param killPassword kill password+ * @param accessPassword access password+ * @param lockBits Lock bits to write to the tag+ * @param pcWord PC word to write to the tag+ * @param epc EPC to write+ */+TMR_Status+TMR_TagOp_init_GEN2_Alien_Higgs2_FullLoadImage(TMR_TagOp *tagop, TMR_GEN2_Password killPassword,+                                    TMR_GEN2_Password accessPassword, uint16_t lockBits, +                                    uint16_t pcWord, TMR_TagData *epc)+{+  tagop->type = TMR_TAGOP_GEN2_ALIEN_HIGGS2_FULLLOADIMAGE;+  tagop->u.gen2.u.custom.chipType = TMR_SR_GEN2_ALIEN_HIGGS_SILICON;+  tagop->u.gen2.u.custom.u.alien.u.higgs2.u.fullLoadImage.accessPassword = accessPassword;+  tagop->u.gen2.u.custom.u.alien.u.higgs2.u.fullLoadImage.killPassword = killPassword;+  tagop->u.gen2.u.custom.u.alien.u.higgs2.u.fullLoadImage.lockBits = lockBits;+  tagop->u.gen2.u.custom.u.alien.u.higgs2.u.fullLoadImage.pcWord = pcWord;+  tagop->u.gen2.u.custom.u.alien.u.higgs2.u.fullLoadImage.epcptr = epc; /* Takes pointer to EPC; doesn't make an actual copy */++  return TMR_SUCCESS;+}++/**+ * Initialize a TMR_TagOp as a Higgs3 Fast Load Image operation with the provided parameters.+ * @param tagop Pointer to the tagop structure to initialize.+ * @param currentAccessPassword The access password used to write to the tag+ * @param accessPassword access password+ * @param killPassword kill password+ * @param pcWord PC word to write to the tag+ * @param epc EPC to write+ */+TMR_Status TMR_TagOp_init_GEN2_Alien_Higgs3_FastLoadImage(TMR_TagOp *tagop, TMR_GEN2_Password currentAccessPassword,+                                    TMR_GEN2_Password accessPassword, TMR_GEN2_Password killPassword, +                                    uint16_t pcWord, TMR_TagData *epc)+{+  tagop->type = TMR_TAGOP_GEN2_ALIEN_HIGGS3_FASTLOADIMAGE;+  tagop->u.gen2.u.custom.chipType = TMR_SR_GEN2_ALIEN_HIGGS3_SILICON;+  tagop->u.gen2.u.custom.u.alien.u.higgs3.u.fastLoadImage.currentAccessPassword = currentAccessPassword;+  tagop->u.gen2.u.custom.u.alien.u.higgs3.u.fastLoadImage.killPassword = killPassword;+  tagop->u.gen2.u.custom.u.alien.u.higgs3.u.fastLoadImage.accessPassword = accessPassword;+  tagop->u.gen2.u.custom.u.alien.u.higgs3.u.fastLoadImage.pcWord = pcWord;+  tagop->u.gen2.u.custom.u.alien.u.higgs3.u.fastLoadImage.epcptr = epc; /* Takes pointer to EPC; doesn't make an actual copy */++  return TMR_SUCCESS;+}++/**+ * Initialize a TMR_TagOp as a Higgs3 Load Image operation with the provided parameters.+ * @param tagop Pointer to the tagop structure to initialize.+ * @param currentAccessPassword The access password used to write to the tag+ * @param accessPassword access password+ * @param killPassword kill password+ * @param pcWord PC word to write to the tag+ * @param epcAndUserData Tag EPC and user data to write to the tag (76 bytes)+ */+TMR_Status TMR_TagOp_init_GEN2_Alien_Higgs3_LoadImage(TMR_TagOp *tagop, TMR_GEN2_Password currentAccessPassword,+                                    TMR_GEN2_Password accessPassword, TMR_GEN2_Password killPassword, +                                    uint16_t pcWord, TMR_uint8List *epcAndUserData)+{+  tagop->type = TMR_TAGOP_GEN2_ALIEN_HIGGS3_LOADIMAGE;+  tagop->u.gen2.u.custom.chipType = TMR_SR_GEN2_ALIEN_HIGGS3_SILICON;+  tagop->u.gen2.u.custom.u.alien.u.higgs3.u.loadImage.currentAccessPassword = currentAccessPassword;+  tagop->u.gen2.u.custom.u.alien.u.higgs3.u.loadImage.killPassword = killPassword;+  tagop->u.gen2.u.custom.u.alien.u.higgs3.u.loadImage.accessPassword = accessPassword;+  tagop->u.gen2.u.custom.u.alien.u.higgs3.u.loadImage.pcWord = pcWord;+  tagop->u.gen2.u.custom.u.alien.u.higgs3.u.loadImage.epcAndUserData = epcAndUserData; /* Takes pointer epcAndUserData; doesn't make an actual copy */++  return TMR_SUCCESS;+}++/**+ * Initialize a TMR_TagOp as a Higgs3 Block Read Lock operation with the provided parameters.+ * @param tagop Pointer to the tagop structure to initialize.+ * @param accessPassword access password+ * @param lockBits A bitmask of bits to lock+ */+TMR_Status TMR_TagOp_init_GEN2_Alien_Higgs3_BlockReadLock(TMR_TagOp *tagop, TMR_GEN2_Password accessPassword, uint8_t lockBits)+{+  tagop->type = TMR_TAGOP_GEN2_ALIEN_HIGGS3_BLOCKREADLOCK;+  tagop->u.gen2.u.custom.chipType = TMR_SR_GEN2_ALIEN_HIGGS3_SILICON;+  tagop->u.gen2.u.custom.u.alien.u.higgs3.u.blockReadLock.accessPassword = accessPassword;+  tagop->u.gen2.u.custom.u.alien.u.higgs3.u.blockReadLock.lockBits = lockBits;+  +  return TMR_SUCCESS;+}++/**+ * Initialize a TMR_TagOp as a NXP G2I set read protect operation with the provided parameters.+ * @param tagop Pointer to the tagop structure to initialize.+ * @param accessPassword access password+ */+TMR_Status TMR_TagOp_init_GEN2_NXP_G2I_SetReadProtect(TMR_TagOp *tagop, TMR_GEN2_Password accessPassword)+{+  tagop->type = TMR_TAGOP_GEN2_NXP_SETREADPROTECT;+  tagop->u.gen2.u.custom.chipType = TMR_SR_GEN2_NXP_G2I_SILICON;+  tagop->u.gen2.u.custom.u.nxp.u.setReadProtect.accessPassword = accessPassword;+  return TMR_SUCCESS;+}++/**+ * Initialize a TMR_TagOp as a NXP G2X set read protect operation with the provided parameters.+ * @param tagop Pointer to the tagop structure to initialize.+ * @param accessPassword access password+ */+TMR_Status TMR_TagOp_init_GEN2_NXP_G2X_SetReadProtect(TMR_TagOp *tagop, TMR_GEN2_Password accessPassword)+{+  tagop->type = TMR_TAGOP_GEN2_NXP_SETREADPROTECT;+  tagop->u.gen2.u.custom.chipType = TMR_SR_GEN2_NXP_G2X_SILICON;+  tagop->u.gen2.u.custom.u.nxp.u.setReadProtect.accessPassword = accessPassword;+  return TMR_SUCCESS;+}++/**+ * Initialize a TMR_TagOp as a NXP G2I reset read protect operation with the provided parameters.+ * @param tagop Pointer to the tagop structure to initialize.+ * @param accessPassword access password+ */+TMR_Status TMR_TagOp_init_GEN2_NXP_G2I_ResetReadProtect(TMR_TagOp *tagop, TMR_GEN2_Password accessPassword)+{+  tagop->type = TMR_TAGOP_GEN2_NXP_RESETREADPROTECT;+  tagop->u.gen2.u.custom.chipType = TMR_SR_GEN2_NXP_G2I_SILICON;+  tagop->u.gen2.u.custom.u.nxp.u.resetReadProtect.accessPassword = accessPassword;+  return TMR_SUCCESS;+}++/**+ * Initialize a TMR_TagOp as a NXP G2X reset read protect operation with the provided parameters.+ * @param tagop Pointer to the tagop structure to initialize.+ * @param accessPassword access password+ */+TMR_Status TMR_TagOp_init_GEN2_NXP_G2X_ResetReadProtect(TMR_TagOp *tagop, TMR_GEN2_Password accessPassword)+{+  tagop->type = TMR_TAGOP_GEN2_NXP_RESETREADPROTECT;+  tagop->u.gen2.u.custom.chipType = TMR_SR_GEN2_NXP_G2X_SILICON;+  tagop->u.gen2.u.custom.u.nxp.u.resetReadProtect.accessPassword = accessPassword;+  return TMR_SUCCESS;+}++/**+ * Initialize a TMR_TagOp as a NXP G2I Change EAS operation with the provided parameters.+ * @param tagop Pointer to the tagop structure to initialize.+ * @param accessPassword access password+ * @param resetEAS   -  if true, Reset EAS+ *                      if false, Set EAS+ */+TMR_Status TMR_TagOp_init_GEN2_NXP_G2I_ChangeEAS(TMR_TagOp *tagop, TMR_GEN2_Password accessPassword, bool resetEAS)+{+  tagop->type = TMR_TAGOP_GEN2_NXP_CHANGEEAS;+  tagop->u.gen2.u.custom.chipType = TMR_SR_GEN2_NXP_G2I_SILICON;+  tagop->u.gen2.u.custom.u.nxp.u.changeEAS.accessPassword = accessPassword;+  tagop->u.gen2.u.custom.u.nxp.u.changeEAS.reset = resetEAS;++  return TMR_SUCCESS;+}++/**+ * Initialize a TMR_TagOp as a NXP G2X Change EAS operation with the provided parameters.+ * @param tagop Pointer to the tagop structure to initialize.+ * @param accessPassword access password+ * @param resetEAS   -  if true, Reset EAS+ *                      if false, Set EAS+ */+TMR_Status TMR_TagOp_init_GEN2_NXP_G2X_ChangeEAS(TMR_TagOp *tagop, TMR_GEN2_Password accessPassword, bool resetEAS)+{+  tagop->type = TMR_TAGOP_GEN2_NXP_CHANGEEAS;+  tagop->u.gen2.u.custom.chipType = TMR_SR_GEN2_NXP_G2X_SILICON;+  tagop->u.gen2.u.custom.u.nxp.u.changeEAS.accessPassword = accessPassword;+  tagop->u.gen2.u.custom.u.nxp.u.changeEAS.reset = resetEAS;++  return TMR_SUCCESS;+}++/**+ * Initialize a TMR_TagOp as a NXP G2I EAS alarm operation with the provided parameters.+ * @param tagop Pointer to the tagop structure to initialize.+ * @param dr Gen2 divide ratio to use+ * @param m Gen2 M(tag encoding) parameter to use+ * @param trExt txExt Gen2 TrExt value to use+ */+TMR_Status TMR_TagOp_init_GEN2_NXP_G2I_EASAlarm(TMR_TagOp *tagop, TMR_GEN2_DivideRatio dr, TMR_GEN2_TagEncoding m, TMR_GEN2_TrExt trExt)+{+  tagop->type = TMR_TAGOP_GEN2_NXP_EASALARM;+  tagop->u.gen2.u.custom.chipType = TMR_SR_GEN2_NXP_G2I_SILICON;+  tagop->u.gen2.u.custom.u.nxp.u.EASAlarm.dr = dr;+  tagop->u.gen2.u.custom.u.nxp.u.EASAlarm.m = m;+  tagop->u.gen2.u.custom.u.nxp.u.EASAlarm.trExt = trExt;+  return TMR_SUCCESS;+}++TMR_Status TMR_TagOp_init_GEN2_NXP_AES_Untraceable(TMR_TagOp *tagop,TMR_GEN2_UNTRACEABLE_Epc epc, int epclen , TMR_GEN2_UNTRACEABLE_Tid tid, TMR_GEN2_UNTRACEABLE_UserMemory user,+																									 TMR_GEN2_UNTRACEABLE_Range range, TMR_TagOp_GEN2_NXP_Untraceable *untraceable)+{+	tagop->type = TMR_TAGOP_GEN2_NXP_UNTRACEABLE;+	tagop->u.gen2.u.custom.chipType = TMR_SR_GEN2_NXP_AES_UCODE;+	tagop->u.gen2.u.custom.u.nxp.u.untraceable.epc = epc;+	tagop->u.gen2.u.custom.u.nxp.u.untraceable.epcLength = epclen;+	tagop->u.gen2.u.custom.u.nxp.u.untraceable.tid = tid;+	tagop->u.gen2.u.custom.u.nxp.u.untraceable.userMemory = user;+	tagop->u.gen2.u.custom.u.nxp.u.untraceable.range = range;+	if(untraceable->auth.authType == UNTRACEABLE_WITH_AUTHENTICATION)+	{+		tagop->u.gen2.u.custom.u.nxp.u.untraceable.subCommand = 0x02;+		tagop->u.gen2.u.custom.u.nxp.u.untraceable.auth.tam1Auth = untraceable->auth.tam1Auth;+		tagop->u.gen2.u.custom.u.nxp.u.untraceable.auth.tam1Auth.Authentication |= 0x03;+	}+	else+	{+		tagop->u.gen2.u.custom.u.nxp.u.untraceable.subCommand = 0x03;+		tagop->u.gen2.u.custom.u.nxp.u.untraceable.auth.accessPassword = untraceable->auth.accessPassword;+	}+	return TMR_SUCCESS;+}++TMR_Status TMR_TagOp_init_GEN2_NXP_AES_Authenticate(TMR_TagOp *tagop, TMR_TagOp_GEN2_NXP_Authenticate *authenticate)+{+	tagop->type = TMR_TAGOP_GEN2_NXP_AUTHENTICATE;+	tagop->u.gen2.u.custom.chipType = TMR_SR_GEN2_NXP_AES_UCODE;+	if(authenticate->type == TAM1_AUTHENTICATION)+	{+		tagop->u.gen2.u.custom.u.nxp.u.authenticate.type = authenticate->type;+		tagop->u.gen2.u.custom.u.nxp.u.authenticate.subCommand = 0x01;+		tagop->u.gen2.u.custom.u.nxp.u.authenticate.tam1Auth = authenticate->tam1Auth;+		tagop->u.gen2.u.custom.u.nxp.u.authenticate.tam1Auth.Authentication |= 0x03;+	}+	else+	{+		tagop->u.gen2.u.custom.u.nxp.u.authenticate.tam1Auth = authenticate->tam2Auth.tam1Auth;+		tagop->u.gen2.u.custom.u.nxp.u.authenticate.type = authenticate->type;+		tagop->u.gen2.u.custom.u.nxp.u.authenticate.subCommand = 0x01;+		tagop->u.gen2.u.custom.u.nxp.u.authenticate.tam2Auth = authenticate->tam2Auth;+		tagop->u.gen2.u.custom.u.nxp.u.authenticate.tam1Auth.Authentication |= 0x07;+	}+	return TMR_SUCCESS;+}++TMR_Status TMR_TagOp_init_GEN2_NXP_AES_Tam2authentication(TMR_TagOp_GEN2_NXP_Tam2Authentication *auth, TMR_NXP_KeyId keyid, TMR_uint8List *key, +																		TMR_uint8List *ichallenge, TMR_NXP_Profile profile, uint16_t Offset,uint8_t blockCount,bool sendRawData)+{+	auth->tam1Auth.Authentication = sendRawData ? 0x80 : 0x00;+	auth->tam1Auth.CSI = 0x00;+	auth->tam1Auth.KeyLength = 0x10;+	auth->tam1Auth.IchallengeLength = 0x0A;+	auth->tam1Auth.Ichallenge.len = ichallenge->len;+	auth->tam1Auth.Ichallenge.list = ichallenge->list;+	auth->tam1Auth.Ichallenge.max = ichallenge->max;+	auth->tam1Auth.Key.len = key->len;+	auth->tam1Auth.Key.list = key->list;+	auth->tam1Auth.Key.max = key->max;+	auth->tam1Auth.keyID = keyid;+	auth->Offset = Offset;+	auth->BlockCount = blockCount;+	auth->ProtMode = 0x0001;+	auth->profile = profile;+	return TMR_SUCCESS;+}+TMR_Status TMR_TagOp_init_GEN2_NXP_AES_ReadBuffer(TMR_TagOp *tagop, uint16_t wordPointer, uint16_t bitCount, TMR_TagOp_GEN2_NXP_Readbuffer *readbuffer)+{+	tagop->type = TMR_TAGOP_GEN2_NXP_READBUFFER;+	tagop->u.gen2.u.custom.chipType = TMR_SR_GEN2_NXP_AES_UCODE;+	tagop->u.gen2.u.custom.u.nxp.u.readBuffer.wordPointer = wordPointer;+	tagop->u.gen2.u.custom.u.nxp.u.readBuffer.bitCount = bitCount;+	if(readbuffer->authenticate.type == TAM1_AUTHENTICATION)+	{+		tagop->u.gen2.u.custom.u.nxp.u.readBuffer.authenticate.type = readbuffer->authenticate.type;+		tagop->u.gen2.u.custom.u.nxp.u.readBuffer.authenticate.subCommand = 0x04;+		tagop->u.gen2.u.custom.u.nxp.u.readBuffer.authenticate.tam1Auth = readbuffer->authenticate.tam1Auth;+		tagop->u.gen2.u.custom.u.nxp.u.readBuffer.authenticate.tam1Auth.Authentication |= 0x00;+	}+	else+	{+		tagop->u.gen2.u.custom.u.nxp.u.readBuffer.authenticate.tam1Auth = readbuffer->authenticate.tam2Auth.tam1Auth;+		tagop->u.gen2.u.custom.u.nxp.u.readBuffer.authenticate.type = readbuffer->authenticate.type;+		tagop->u.gen2.u.custom.u.nxp.u.readBuffer.authenticate.subCommand = 0x04;+		tagop->u.gen2.u.custom.u.nxp.u.readBuffer.authenticate.tam2Auth = readbuffer->authenticate.tam2Auth;+		tagop->u.gen2.u.custom.u.nxp.u.readBuffer.authenticate.tam1Auth.Authentication |= 0x04;+	}+	return TMR_SUCCESS;+}++TMR_Status TMR_TagOp_init_GEN2_NXP_AES_Tam1authentication(TMR_TagOp_GEN2_NXP_Tam1Authentication *auth, TMR_NXP_KeyId keyid, TMR_uint8List *key, +																													TMR_uint8List *ichallenge ,bool sendRawData )+{+	auth->Authentication = sendRawData ? 0x80 : 0x00;+	auth->CSI = 0x00;+	auth->KeyLength = 0x10;+	auth->IchallengeLength = 0x0A;+	auth->Ichallenge.len = ichallenge->len;+	auth->Ichallenge.list = ichallenge->list;+	auth->Ichallenge.max = ichallenge->max;+	auth->Key.len = key->len;+	auth->Key.list = key->list;+	auth->Key.max = key->max;+	auth->keyID = keyid;+	return TMR_SUCCESS;+}++/**+ * Initialize a TMR_TagOp as a NXP G2X EAS alarm operation with the provided parameters.+ * @param tagop Pointer to the tagop structure to initialize.+ * @param dr Gen2 divide ratio to use+ * @param m Gen2 M(tag encoding) parameter to use+ * @param trExt txExt Gen2 TrExt value to use+ */+TMR_Status TMR_TagOp_init_GEN2_NXP_G2X_EASAlarm(TMR_TagOp *tagop, TMR_GEN2_DivideRatio dr, TMR_GEN2_TagEncoding m, TMR_GEN2_TrExt trExt)+{+  tagop->type = TMR_TAGOP_GEN2_NXP_EASALARM;+  tagop->u.gen2.u.custom.chipType = TMR_SR_GEN2_NXP_G2X_SILICON;+  tagop->u.gen2.u.custom.u.nxp.u.EASAlarm.dr = dr;+  tagop->u.gen2.u.custom.u.nxp.u.EASAlarm.m = m;+  tagop->u.gen2.u.custom.u.nxp.u.EASAlarm.trExt = trExt;+  +  return TMR_SUCCESS;+}++/**+ * Initialize a TMR_TagOp as a NXP G2i Calibrate operation with the provided parameters.+ *+ * @param tagop Pointer to the tagop structure to initialize.+ * @param accessPassword access password+ */+TMR_Status TMR_TagOp_init_GEN2_NXP_G2I_Calibrate(TMR_TagOp *tagop, TMR_GEN2_Password accessPassword)+{+  tagop->type = TMR_TAGOP_GEN2_NXP_CALIBRATE;+  tagop->u.gen2.u.custom.chipType = TMR_SR_GEN2_NXP_G2I_SILICON;+  tagop->u.gen2.u.custom.u.nxp.u.calibrate.accessPassword = accessPassword;++  return TMR_SUCCESS;+}++/**+ * Initialize a TMR_TagOp as a NXP G2x Calibrate operation with the provided parameters.+ *+ * @param tagop Pointer to the tagop structure to initialize.+ * @param accessPassword access password+ */+TMR_Status TMR_TagOp_init_GEN2_NXP_G2X_Calibrate(TMR_TagOp *tagop, TMR_GEN2_Password accessPassword)+{+  tagop->type = TMR_TAGOP_GEN2_NXP_CALIBRATE;+  tagop->u.gen2.u.custom.chipType = TMR_SR_GEN2_NXP_G2X_SILICON;+  tagop->u.gen2.u.custom.u.nxp.u.calibrate.accessPassword = accessPassword;++  return TMR_SUCCESS;+}++/**+ * Initialize a TMR_TagOp as a NXP G2i Change Config operation with the provided parameters.+ * @param tagop Pointer to the tagop structure to initialize.+ * @param accessPassword access password+ * @param configWord ConfigWord to write to the tag.+ */+TMR_Status TMR_TagOp_init_GEN2_NXP_G2I_ChangeConfig(TMR_TagOp *tagop, TMR_GEN2_Password accessPassword, TMR_NXP_ConfigWord configWord)+{+  tagop->type = TMR_TAGOP_GEN2_NXP_CHANGECONFIG;+  tagop->u.gen2.u.custom.chipType = TMR_SR_GEN2_NXP_G2I_SILICON;+  tagop->u.gen2.u.custom.u.nxp.u.changeConfig.accessPassword = accessPassword;+  tagop->u.gen2.u.custom.u.nxp.u.changeConfig.configWord = configWord;++  return TMR_SUCCESS;+}++/**+ * Initialize a TMR_TagOp as a NXP G2x Change Config operation with the provided parameters.+ * @param tagop Pointer to the tagop structure to initialize.+ * @param accessPassword access password+ * @param configWord ConfigWord to write to the tag.+ */+TMR_Status TMR_TagOp_init_GEN2_NXP_G2X_ChangeConfig(TMR_TagOp *tagop, TMR_GEN2_Password accessPassword, TMR_NXP_ConfigWord configWord)+{+  tagop->type = TMR_TAGOP_GEN2_NXP_CHANGECONFIG;+  tagop->u.gen2.u.custom.chipType = TMR_SR_GEN2_NXP_G2X_SILICON;+  tagop->u.gen2.u.custom.u.nxp.u.changeConfig.accessPassword = accessPassword;+  tagop->u.gen2.u.custom.u.nxp.u.changeConfig.configWord = configWord;++  return TMR_SUCCESS;+}++/**+ * Initialize a TMR_TagOp as a Monza4 QT Read/Write operation with the provided parameters.+ * @param tagop Pointer to the tagop structure to initialize.+ * @param accessPassword access password+ * @param controlByte The QT control Byte + * @param payload The QT payload+ */+TMR_Status +TMR_TagOp_init_GEN2_Impinj_Monza4_QTReadWrite(TMR_TagOp *tagop, TMR_GEN2_Password accessPassword,+                                  TMR_Monza4_ControlByte controlByte, TMR_Monza4_Payload payload)+{+  tagop->type = TMR_TAGOP_GEN2_IMPINJ_MONZA4_QTREADWRITE;+  tagop->u.gen2.u.custom.chipType = TMR_SR_GEN2_IMPINJ_MONZA4_SILICON;+  tagop->u.gen2.u.custom.u.impinj.u.monza4.u.qtReadWrite.accessPassword = accessPassword;+  tagop->u.gen2.u.custom.u.impinj.u.monza4.u.qtReadWrite.controlByte = controlByte;+  tagop->u.gen2.u.custom.u.impinj.u.monza4.u.qtReadWrite.payload = payload;++  return TMR_SUCCESS;+}++ /**+ * Initialize a TMR_TagOp as a Gen2 IAVDenatran ActivateSecureMode operation with the provided parameter+ * @param tagop Pointer to the tagop structure to initialize+ * @param payload 1byte->[TC(Transmission Count) 1bit + RFFU(Reserved For Furture Use) 7bits]+ */+TMR_Status+TMR_TagOp_init_GEN2_Denatran_IAV_Activate_Secure_Mode(TMR_TagOp *tagop, uint8_t payload)+{+  tagop->type = TMR_TAGOP_GEN2_DENATRAN_IAV_ACTIVATESECUREMODE;+  tagop->u.gen2.u.custom.chipType = TMR_SR_GEN2_DENATRAN_IAV_SILICON; +  tagop->u.gen2.u.custom.u.IavDenatran.u.secureMode.mode = GEN2_ACTIVATE_SECURE_MODE;+  tagop->u.gen2.u.custom.u.IavDenatran.u.secureMode.payload = payload;++  return TMR_SUCCESS;+}++/**+ * Initialize a TMR_TagOp as a Gen2 IAVDenatran AuthenticateOBU operation with the provided parameter+ * @param tagop Pointer to the tagop structure to initialize + * @param payload 1byte->[TC(Transmission Count) 1bit + RFFU(Reserved For Furture Use) 7bits]+ */+TMR_Status+TMR_TagOp_init_GEN2_Denatran_IAV_Authenticate_OBU(TMR_TagOp *tagop, uint8_t payload)+{+  tagop->type = TMR_TAGOP_GEN2_DENATRAN_IAV_AUTHENTICATEOBU;+  tagop->u.gen2.u.custom.chipType = TMR_SR_GEN2_DENATRAN_IAV_SILICON; +  tagop->u.gen2.u.custom.u.IavDenatran.u.authenticateOBU.mode = GEN2_AUTHENTICATE_OBU;+  tagop->u.gen2.u.custom.u.IavDenatran.u.authenticateOBU.payload = payload;++  return TMR_SUCCESS;+}++/**+ * Initialize a TMR_TagOp as a Gen2 IAVDenatran ACTIVATE_SINIAV_MODE operation with the provided parameter+ * @param tagop Pointer to the tagop structure to initialize + * @param payload 1byte->[TC(Transmission Count) 1bit + RFFU(Reserved For Furture Use) 7bits]+ * @param data 64 bits of token number to activate the tag+ */+TMR_Status+TMR_TagOp_init_GEN2_Denatran_IAV_Activate_Siniav_Mode(TMR_TagOp *tagop, uint8_t payload, TMR_uint8List *token)+{+  uint8_t tokenDesc;++  tagop->type = TMR_TAGOP_GEN2_ACTIVATE_SINIAV_MODE;+  tagop->u.gen2.u.custom.chipType = TMR_SR_GEN2_DENATRAN_IAV_SILICON; +  tagop->u.gen2.u.custom.u.IavDenatran.u.activateSiniavMode.mode = GEN2_ACTIVATE_SINIAV_MODE;+  tagop->u.gen2.u.custom.u.IavDenatran.u.activateSiniavMode.payload = payload;++  /**+   * Currently last two bits of the payload is used as TokenDesc+   * (Token Descriptor): 2 bits parameter indicating the presence and format of Token+   * 00 : No Token.+   * 01 : Token of 64 bits.+   */+  tokenDesc = 0x03 & payload;+  if (0x01 == tokenDesc)+  { +    /* the token field is always 64 bits in this case */    +    if (0x08 != token->len)+    {+      return TMR_ERROR_INVALID;+    }+    memcpy(tagop->u.gen2.u.custom.u.IavDenatran.u.activateSiniavMode.token, token->list, token->len);+    tagop->u.gen2.u.custom.u.IavDenatran.u.activateSiniavMode.isTokenDesc = true;  +  }+  else+  {+    tagop->u.gen2.u.custom.u.IavDenatran.u.activateSiniavMode.isTokenDesc = false;+  }++  return TMR_SUCCESS;+}++/**+ * Initialize a TMR_TagOp as a Gen2 IAVDenatran OBU_Auth_ID operation with the provided parameter+ * @param tagop Pointer to the tagop structure to initialize + * @param payload 1byte->[TC(Transmission Count) 1bit + RFFU(Reserved For Furture Use) 7bits] + */+TMR_Status+TMR_TagOp_init_GEN2_Denatran_IAV_OBU_Auth_ID(TMR_TagOp *tagop, uint8_t payload)+{+  tagop->type = TMR_TAGOP_GEN2_OBU_AUTH_ID;+  tagop->u.gen2.u.custom.chipType = TMR_SR_GEN2_DENATRAN_IAV_SILICON; +  tagop->u.gen2.u.custom.u.IavDenatran.u.obuAuthId.mode = GEN2_OBU_AUTH_ID;+  tagop->u.gen2.u.custom.u.IavDenatran.u.obuAuthId.payload = payload;++  return TMR_SUCCESS;+}++/**+ * Initialize a TMR_TagOp as a Gen2 IAVDenatran OBU_Auth_Full_Pass1 operation with the provided parameter+ * @param tagop Pointer to the tagop structure to initialize + * @param payload 1byte->[TC(Transmission Count) 1bit + RFFU(Reserved For Furture Use) 7bits] + */+TMR_Status+TMR_TagOp_init_GEN2_Denatran_IAV_OBU_Auth_Full_Pass1(TMR_TagOp *tagop, uint8_t payload)+{+  tagop->type = TMR_TAGOP_GEN2_AUTHENTICATE_OBU_FULL_PASS1;+  tagop->u.gen2.u.custom.chipType = TMR_SR_GEN2_DENATRAN_IAV_SILICON; +  tagop->u.gen2.u.custom.u.IavDenatran.u.obuAuthFullPass1.mode = GEN2_AUTHENTICATE_OBU_FULL_PASS1;+  tagop->u.gen2.u.custom.u.IavDenatran.u.obuAuthFullPass1.payload = payload;++  return TMR_SUCCESS;+}++/**+ * Initialize a TMR_TagOp as a Gen2 IAVDenatran OBU_Auth_Full_Pass2 operation with the provided parameter+ * @param tagop Pointer to the tagop structure to initialize + * @param payload 1byte->[TC(Transmission Count) 1bit + RFFU(Reserved For Furture Use) 7bits] + */+TMR_Status+TMR_TagOp_init_GEN2_Denatran_IAV_OBU_Auth_Full_Pass2(TMR_TagOp *tagop, uint8_t payload)+{+  tagop->type = TMR_TAGOP_GEN2_AUTHENTICATE_OBU_FULL_PASS2;+  tagop->u.gen2.u.custom.chipType = TMR_SR_GEN2_DENATRAN_IAV_SILICON; +  tagop->u.gen2.u.custom.u.IavDenatran.u.obuAuthFullPass2.mode = GEN2_AUTHENTICATE_OBU_FULL_PASS2;+  tagop->u.gen2.u.custom.u.IavDenatran.u.obuAuthFullPass2.payload = payload;++  return TMR_SUCCESS;+}++/**+ * Initialize a TMR_TagOp as a Gen2 IAVDenatran OBU_ReadFromMemMap operation with the provided parameter+ * @param tagop Pointer to the tagop structure to initialize + * @param payload The OBU_ReadFromMemMap Payload+ * @param wordAddress pointer indicating the address to be read from USER memory bank+ */+TMR_Status+TMR_TagOp_init_GEN2_Denatran_IAV_OBU_ReadFromMemMap(TMR_TagOp *tagop, uint8_t payload, uint16_t wordAddress)+{+  tagop->type = TMR_TAGOP_GEN2_OBU_READ_FROM_MEM_MAP;+  tagop->u.gen2.u.custom.chipType = TMR_SR_GEN2_DENATRAN_IAV_SILICON;+  tagop->u.gen2.u.custom.u.IavDenatran.u.obuReadFromMemMap.mode = GEN2_OBU_READ_FROM_MEM_MAP;+  tagop->u.gen2.u.custom.u.IavDenatran.u.obuReadFromMemMap.payload = payload;+  tagop->u.gen2.u.custom.u.IavDenatran.u.obuReadFromMemMap.readPtr = wordAddress;++  return TMR_SUCCESS;+}++/**+ * Initialize a TMR_TagOp as a Gen2 IAVDenatran OBU_WriteToMemMap operation with the provided parameter+ * @param tagop Pointer to the tagop structure to initialize + * @param payload The OBU_WriteToMemMap Payload+ * @param wordAddress pointer to the USER data+ * @param word data to be written+ * @param data credentials written word+ */+TMR_Status+TMR_TagOp_init_GEN2_Denatran_IAV_OBU_WriteToMemMap(TMR_TagOp *tagop, uint8_t payload, uint16_t wordAddress, uint16_t word, uint8_t* tagId, uint8_t* data)+{+  tagop->type = TMR_TAGOP_GEN2_OBU_WRITE_TO_MEM_MAP;+  tagop->u.gen2.u.custom.chipType = TMR_SR_GEN2_DENATRAN_IAV_SILICON;+  tagop->u.gen2.u.custom.u.IavDenatran.u.obuWriteToMemMap.mode = GEN2_OBU_WRITE_TO_MEM_MAP;+  tagop->u.gen2.u.custom.u.IavDenatran.u.obuWriteToMemMap.payload = payload;+  tagop->u.gen2.u.custom.u.IavDenatran.u.obuWriteToMemMap.writePtr = wordAddress;+  tagop->u.gen2.u.custom.u.IavDenatran.u.obuWriteToMemMap.wordData = word;+  tagop->u.gen2.u.custom.u.IavDenatran.u.obuWriteToMemMap.tagIdentification = tagId;+  tagop->u.gen2.u.custom.u.IavDenatran.u.obuWriteToMemMap.dataBuf = data;++  return TMR_SUCCESS;+}++/**+ * Initialize a TMR_TagOp as a Gen2 IAVDenatran Write Sec operation with the provided parameter+ * @param tagop Pointer to the tagop structure to initialize + * @param payload The OBU_WriteToMemMap Payload+ * @param wordAddress pointer to the USER data+ * @param dataWords 4 data words+ * @param data credentials written word+ */+TMR_Status+TMR_TagOp_init_GEN2_Denatran_IAV_WriteSec(TMR_TagOp *tagop, uint8_t payload, uint8_t* data, uint8_t* credentials)+{+  tagop->type = TMR_TAGOP_GEN2_DENATRAN_IAV_WRITE_SEC;+  tagop->u.gen2.u.custom.chipType = TMR_SR_GEN2_DENATRAN_IAV_SILICON;+  tagop->u.gen2.u.custom.u.IavDenatran.u.writeSec.mode = GEN2_WRITE_SEC;+  tagop->u.gen2.u.custom.u.IavDenatran.u.writeSec.payload = payload;+  tagop->u.gen2.u.custom.u.IavDenatran.u.writeSec.dataWords = data;+  tagop->u.gen2.u.custom.u.IavDenatran.u.writeSec.dataBuf = credentials;++  return TMR_SUCCESS;+}++/**+ * Initialize a TMR_TagOp as a Gen2 IAVDenatran OBU_Auth_Full_Pass operation with the provided parameter+ * @param tagop Pointer to the tagop structure to initialize + * @param payload 1byte->[TC(Transmission Count) 1bit + RFFU(Reserved For Furture Use) 7bits] + */+TMR_Status+TMR_TagOp_init_GEN2_Denatran_IAV_OBU_Auth_Full_Pass(TMR_TagOp *tagop, uint8_t payload)+{+  tagop->type = TMR_TAGOP_GEN2_DENATRAN_IAV_AUTHENTICATE_OBU_FULL_PASS;+  tagop->u.gen2.u.custom.chipType = TMR_SR_GEN2_DENATRAN_IAV_SILICON; +  tagop->u.gen2.u.custom.u.IavDenatran.u.obuAuthFullPass.mode = GEN2_AUTHENTICATE_OBU_FULL_PASS;+  tagop->u.gen2.u.custom.u.IavDenatran.u.obuAuthFullPass.payload = payload;++  return TMR_SUCCESS;+}++/**+ * Initialize a TMR_TagOp as a Gen2 IAVDenatran G0_PA_OBU_Auth_ID operation with the provided parameter+ * @param tagop Pointer to the tagop structure to initialize + * @param payload 1byte->[TC(Transmission Count) 1bit + RFFU(Reserved For Furture Use) 7bits] + */+TMR_Status+TMR_TagOp_init_GEN2_Denatran_IAV_G0_PA_OBU_Auth(TMR_TagOp *tagop, uint8_t payload)+{+  tagop->type = TMR_TAGOP_GEN2_DENATRAN_IAV_G0_PA_OBU_AUTHENTICATE_ID;+  tagop->u.gen2.u.custom.chipType = TMR_SR_GEN2_DENATRAN_IAV_SILICON; +  tagop->u.gen2.u.custom.u.IavDenatran.u.g0paobuauthid.mode = GEN2_PA_G0_AUTHENTICATE;+  tagop->u.gen2.u.custom.u.IavDenatran.u.g0paobuauthid.payload = payload;++  return TMR_SUCCESS;+}++/**+ * Initialize a TMR_TagOp as a Gen2 IAVDenatran Get Token Id operation with the provided parameter+ * @param tagop Pointer to the tagop structure to initialize + */+TMR_Status+TMR_TagOp_init_GEN2_Denatran_IAV_GetTokenId(TMR_TagOp *tagop)+{+  tagop->type = TMR_TAGOP_GEN2_DENATRAN_IAV_GET_TOKEN_ID;+  tagop->u.gen2.u.custom.chipType = TMR_SR_GEN2_DENATRAN_IAV_SILICON;+  tagop->u.gen2.u.custom.u.IavDenatran.u.getTokenId.mode = GEN2_GET_TOKEN_ID;++  return TMR_SUCCESS;+}++/**+ * Initialize a TMR_TagOp as a Gen2 IAVDenatran read sec operation with the provided parameter+ * @param tagop Pointer to the tagop structure to initialize+ * @param payLoad 8 bits for future use+ * @param wordAddress pointer indicating the sector to be read from USER memory bank+ */+TMR_Status+TMR_TagOp_init_GEN2_Denatran_IAV_ReadSec(TMR_TagOp *tagop, uint8_t payload, uint16_t wordAddress)+{+  tagop->type = TMR_TAGOP_GEN2_DENATRAN_IAV_READ_SEC;+  tagop->u.gen2.u.custom.chipType = TMR_SR_GEN2_DENATRAN_IAV_SILICON;+  tagop->u.gen2.u.custom.u.IavDenatran.u.readSec.mode = GEN2_READ_SEC;+  tagop->u.gen2.u.custom.u.IavDenatran.u.readSec.payload = payload;+  tagop->u.gen2.u.custom.u.IavDenatran.u.readSec.readPtr = wordAddress;++  return TMR_SUCCESS;+}++/**+ * Initialize a TMR_TagOp as a Gen2 Ids SL900A GetCalibrationData value operation with the provided parameters.+ * @param tagop Pointer to the tagop structure to initialize.+ * @param accessPassword Gen2 accessPassword+ * @param password IDS password+ * @param level IDS passwordlevel+ */+TMR_Status+TMR_TagOp_init_GEN2_IDS_SL900A_GetCalibrationData(TMR_TagOp *tagop, TMR_GEN2_Password accessPassword,+                                                  PasswordLevel level, uint32_t password)+{+  tagop->type = TMR_TAGOP_GEN2_IDS_SL900A_GETCALIBRATIONDATA;+  tagop->u.gen2.u.custom.chipType = TMR_SR_GEN2_IDS_SL900A_SILICON;+  tagop->u.gen2.u.custom.u.ids.u.calibrationData.AccessPassword = accessPassword;+  tagop->u.gen2.u.custom.u.ids.u.calibrationData.CommandCode = 0xA9;+  tagop->u.gen2.u.custom.u.ids.u.calibrationData.Password = password;+  tagop->u.gen2.u.custom.u.ids.u.calibrationData.sl900A.level = level;++  return TMR_SUCCESS;+}++/**+ * Initialize  a TMR_TagOp as a GEn2 IDs SL900A SetPassword value with+ * @param tagop pointer to the tagop struture to SetPassword+ * @param accessPassword Gen2 accessPassword+ * @param level IDS passwordLevel+ * @param password IDS password+ * @param newPasswordLevel IDS NewPasswordLevel+ * @param newPassword IDS NewPassword+ */ +TMR_Status+TMR_TagOp_init_GEN2_IDS_SL900A_SetPassword(TMR_TagOp *tagop, TMR_GEN2_Password accessPassword, PasswordLevel level,+                                           uint32_t password, PasswordLevel newPasswordLevel, uint32_t newPassword)+{+  tagop->type = TMR_TAGOP_GEN2_IDS_SL900A_SETPASSWORD;+  tagop->u.gen2.u.custom.chipType = TMR_SR_GEN2_IDS_SL900A_SILICON;+  tagop->u.gen2.u.custom.u.ids.u.setPassword.AccessPassword = accessPassword;+  tagop->u.gen2.u.custom.u.ids.u.setPassword.CommandCode = 0xA0;+  tagop->u.gen2.u.custom.u.ids.u.setPassword.sl900A.level = level;+  tagop->u.gen2.u.custom.u.ids.u.setPassword.Password = password;+  tagop->u.gen2.u.custom.u.ids.u.setPassword.NewPasswordLevel = newPasswordLevel;+  tagop->u.gen2.u.custom.u.ids.u.setPassword.NewPassword = newPassword;+  +  return TMR_SUCCESS;+}+/**+ * Initialize a TMR_TagOp as a Gen2 Ids SL900A SetCalibrationData value operation with the provided parameters.+ * @param tagop Pointer to the tagop structure to initialize.+ * @param accessPassword Gen2 accessPassword+ * @param password IDS password+ * @param level IDS passwordlevel+ * @param data IDS calibration data+ */+TMR_Status+TMR_TagOp_init_GEN2_IDS_SL900A_SetCalibrationData(TMR_TagOp *tagop, TMR_GEN2_Password accessPassword, PasswordLevel level, +                                                  uint32_t password, TMR_TagOp_GEN2_IDS_SL900A_CalibrationData *data)+{+  tagop->type = TMR_TAGOP_GEN2_IDS_SL900A_SETCALIBRATIONDATA;+  tagop->u.gen2.u.custom.chipType = TMR_SR_GEN2_IDS_SL900A_SILICON;+  tagop->u.gen2.u.custom.u.ids.u.setCalibration.AccessPassword = accessPassword;+  tagop->u.gen2.u.custom.u.ids.u.setCalibration.CommandCode = 0xA5;+  tagop->u.gen2.u.custom.u.ids.u.setCalibration.Password = password;+  tagop->u.gen2.u.custom.u.ids.u.setCalibration.sl900A.level = level;+  tagop->u.gen2.u.custom.u.ids.u.setCalibration.cal.raw = data->raw;++  return TMR_SUCCESS;+}++/**+ * Initialize a TMR_TagOp as a Gen2 Ids SL900A SetSfeParameters value operation with the provided parameters.+ * @param tagop Pointer to the tagop structure to initialize.+ * @param accessPassword Gen2 accessPassword+ * @param password IDS password+ * @param level IDS passwordlevel+ * @param data IDS sfe parameters+ */+TMR_Status+TMR_TagOp_init_GEN2_IDS_SL900A_SetSfeParameters(TMR_TagOp *tagop, TMR_GEN2_Password accessPassword, PasswordLevel level,+                                                uint32_t password, TMR_TagOp_GEN2_IDS_SL900A_SfeParameters *data)+{+  tagop->type = TMR_TAGOP_GEN2_IDS_SL900A_SETSFEPARAMETERS;+  tagop->u.gen2.u.custom.chipType = TMR_SR_GEN2_IDS_SL900A_SILICON;+  tagop->u.gen2.u.custom.u.ids.u.setSfeParameters.AccessPassword = accessPassword;+  tagop->u.gen2.u.custom.u.ids.u.setSfeParameters.CommandCode = 0xA4;+  tagop->u.gen2.u.custom.u.ids.u.setSfeParameters.Password = password;+  tagop->u.gen2.u.custom.u.ids.u.setSfeParameters.sl900A.level = level;+  tagop->u.gen2.u.custom.u.ids.u.setSfeParameters.sfe = data;++  return TMR_SUCCESS;+}++/**+ * Initialize a TMR_TagOp as a Gen2 Ids SL900A GetSensor value operation with the provided parameters.+ * @param tagop Pointer to the tagop structure to initialize.+ * @param accessPassword Gen2 accessPassword+ * @param password IDS password+ * @param level IDS passwordlevel+ * @param type IDS sensor type+ */+TMR_Status+TMR_TagOp_init_GEN2_IDS_SL900A_GetSensorValue(TMR_TagOp *tagop, TMR_GEN2_Password accessPassword,+                                              PasswordLevel level, uint32_t password, Sensor type)+{+  tagop->type = TMR_TAGOP_GEN2_IDS_SL900A_GETSENSOR;+  tagop->u.gen2.u.custom.chipType = TMR_SR_GEN2_IDS_SL900A_SILICON;+  tagop->u.gen2.u.custom.u.ids.u.sensor.AccessPassword = accessPassword;+  tagop->u.gen2.u.custom.u.ids.u.sensor.CommandCode = 0xAD;+  tagop->u.gen2.u.custom.u.ids.u.sensor.Password = password;+  tagop->u.gen2.u.custom.u.ids.u.sensor.sl900A.level = level;+  tagop->u.gen2.u.custom.u.ids.u.sensor.sl900A.sensortype = type;++  return TMR_SUCCESS;+}++/**+ * Initialize a TMR_TagOp as a Gen2 Ids SL900A GetMeasurementSetup operation with the provided parameters.+ * @param tagop Pointer to the tagop structure to initialize.+ * @param accessPassword Gen2 accessPassword+ * @param password IDS password+ * @param level IDS passwordlevel+ */+TMR_Status+TMR_TagOp_init_GEN2_IDS_SL900A_GetMeasurementSetup(TMR_TagOp *tagop, TMR_GEN2_Password accessPassword,+                                                   PasswordLevel level, uint32_t password)+{+  tagop->type =TMR_TAGOP_GEN2_IDS_SL900A_GETMEASUREMENTSETUP;+  tagop->u.gen2.u.custom.chipType = TMR_SR_GEN2_IDS_SL900A_SILICON;+  tagop->u.gen2.u.custom.u.ids.u.measurementSetup.AccessPassword = accessPassword;+  tagop->u.gen2.u.custom.u.ids.u.measurementSetup.CommandCode = 0xA3;+  tagop->u.gen2.u.custom.u.ids.u.measurementSetup.Password = password;+  tagop->u.gen2.u.custom.u.ids.u.measurementSetup.sl900A.level = level;++  return TMR_SUCCESS;+}++/**+ * Initialize a TMR_TagOp as a Gen2 Ids SL900A GetLogState operation with the provided parameters.+ * @param tagop Pointer to the tagop structure to initialize.+ * @param accessPassword Gen2 accessPassword+ * @param password IDS password+ * @param level IDS passwordlevel+ */+TMR_Status+TMR_TagOp_init_GEN2_IDS_SL900A_GetLogState(TMR_TagOp *tagop, TMR_GEN2_Password accessPassword,+                                           PasswordLevel level, uint32_t password)+{+  tagop->type = TMR_TAGOP_GEN2_IDS_SL900A_GETLOGSTATE;+  tagop->u.gen2.u.custom.chipType = TMR_SR_GEN2_IDS_SL900A_SILICON;+  tagop->u.gen2.u.custom.u.ids.u.getLog.AccessPassword = accessPassword;+  tagop->u.gen2.u.custom.u.ids.u.getLog.CommandCode = 0xA8;+  tagop->u.gen2.u.custom.u.ids.u.getLog.Password = password;+  tagop->u.gen2.u.custom.u.ids.u.getLog.sl900A.level = level;++  return TMR_SUCCESS;+}++/**+ * Initialize a TMR_TagOp as a Gen2 Ids SL900A Set Log Mode operation with the provided parameters.+ * @param tagop Pointer to the tagop structure to initialize.+ * @param accessPassword Gen2 accessPassword+ * @param password IDS password+ * @param level IDS passwordlevel+ * @param form IDS logging form+ * @param rule IDS storage rule+ * @param Ext1Enable to Enable log for EXT1 external sensor+ * @param Ext2Enable to Enable log for EXT2 external sensor+ * @param TempEnable to Enable log for temperature sensor+ * @param BattEnable to Enable log for battery sensor+ * @param LogInterval to Time (seconds) between log readings+ */+TMR_Status+TMR_TagOp_init_GEN2_IDS_SL900A_SetLogMode(TMR_TagOp *tagop, TMR_GEN2_Password accessPassword, PasswordLevel level,+                                          uint32_t password, LoggingForm form, StorageRule rule, bool Ext1Enable,+                                          bool Ext2Enable,  bool TempEnable, bool BattEnable, uint16_t LogInterval)+{+  tagop->type = TMR_TAGOP_GEN2_IDS_SL900A_SETLOGMODE;+  tagop->u.gen2.u.custom.chipType = TMR_SR_GEN2_IDS_SL900A_SILICON;+  tagop->u.gen2.u.custom.u.ids.u.setLogMode.AccessPassword = accessPassword;+  tagop->u.gen2.u.custom.u.ids.u.setLogMode.CommandCode = 0xA1;+  tagop->u.gen2.u.custom.u.ids.u.setLogMode.Password = password;+  tagop->u.gen2.u.custom.u.ids.u.setLogMode.sl900A.level = level;+  tagop->u.gen2.u.custom.u.ids.u.setLogMode.sl900A.dataLog = form;+  tagop->u.gen2.u.custom.u.ids.u.setLogMode.sl900A.rule = rule;+  tagop->u.gen2.u.custom.u.ids.u.setLogMode.Ext1Enable = Ext1Enable;+  tagop->u.gen2.u.custom.u.ids.u.setLogMode.Ext2Enable = Ext2Enable;+  tagop->u.gen2.u.custom.u.ids.u.setLogMode.TempEnable = TempEnable;+  tagop->u.gen2.u.custom.u.ids.u.setLogMode.BattEnable = BattEnable;+  tagop->u.gen2.u.custom.u.ids.u.setLogMode.LogInterval = LogInterval;++  return TMR_SUCCESS;+}++/**+ * Initialize a TMR_TagOp as a Gen2 Ids SL900A EndLog operation with the provided parameters.+ * @param tagop Pointer to the tagop structure to initialize.+ * @param accessPassword Gen2 accessPassword+ * @param password IDS password+ * @param level IDS passwordlevel+ */+TMR_Status+TMR_TagOp_init_GEN2_IDS_SL900A_EndLog(TMR_TagOp *tagop, TMR_GEN2_Password accessPassword,+                                      PasswordLevel level, uint32_t password)+{+  tagop->type = TMR_TAGOP_GEN2_IDS_SL900A_ENDLOG;+  tagop->u.gen2.u.custom.chipType = TMR_SR_GEN2_IDS_SL900A_SILICON;+  tagop->u.gen2.u.custom.u.ids.u.endLog.AccessPassword = accessPassword;+  tagop->u.gen2.u.custom.u.ids.u.endLog.CommandCode = 0xA6;+  tagop->u.gen2.u.custom.u.ids.u.endLog.Password = password;+  tagop->u.gen2.u.custom.u.ids.u.endLog.sl900A.level = level;++  return TMR_SUCCESS;+}++/**+ * Initialize a TMR_TagOp as a Gen2 Ids SL900A initialize operation with the provided parameters.+ * @param tagop Pointer to the tagop structure to initialize.+ * @param accessPassword Gen2 accessPassword+ * @param level IDS passwordlevel+ * @param password IDS password+ * @param delayMode IDS delaymode+ * @param delayTime specifying IDS Delay time+ * @param timeEnable IDS timeenable+ * @param numberOfWords specifying Number of user bank memory words to reserve+ * @param BrokenWordPointer IDS broken word pointer+ */+TMR_Status+TMR_TagOp_init_GEN2_IDS_SL900A_Initialize(TMR_TagOp *tagop, TMR_GEN2_Password accessPassword,+                                          PasswordLevel level, uint32_t password, uint8_t delayMode, +                                          uint16_t delayTime, bool timeEnable, uint16_t numberOfWords, +                                          uint8_t BrokenWordPointer)+{+  uint16_t mask = 0x1 << 1;++  tagop->type = TMR_TAGOP_GEN2_IDS_SL900A_INITIALIZE;+  tagop->u.gen2.u.custom.chipType = TMR_SR_GEN2_IDS_SL900A_SILICON;+  tagop->u.gen2.u.custom.u.ids.u.initialize.AccessPassword = accessPassword;+  tagop->u.gen2.u.custom.u.ids.u.initialize.CommandCode = 0xAC;+  tagop->u.gen2.u.custom.u.ids.u.initialize.Password = password;+  tagop->u.gen2.u.custom.u.ids.u.initialize.sl900A.level = level;++  if (TMR_GEN2_IDS_SL900A_DELAYMODE_TIMER == delayMode)+  {   +   uint16_t raw = 0;+   raw &= (uint16_t)~mask;+   tagop->u.gen2.u.custom.u.ids.u.initialize.delayTime.raw = raw;+   tagop->u.gen2.u.custom.u.ids.u.initialize.delayTime.Mode = (DelayMode)delayMode;+  }+  else+  {+    tagop->u.gen2.u.custom.u.ids.u.initialize.delayTime.raw |= mask;+    tagop->u.gen2.u.custom.u.ids.u.initialize.delayTime.Mode = (DelayMode)delayMode;+  }++  if (delayTime)+  {+    uint16_t maskDelayTime = 0xFFF << 4;+    tagop->u.gen2.u.custom.u.ids.u.initialize.delayTime.raw &= (uint16_t)~maskDelayTime;+    tagop->u.gen2.u.custom.u.ids.u.initialize.delayTime.raw |= (uint16_t)(delayTime << 4);+    tagop->u.gen2.u.custom.u.ids.u.initialize.delayTime.Time = delayTime;+  }+  mask = 0x1;+  if(timeEnable)+  {+    tagop->u.gen2.u.custom.u.ids.u.initialize.delayTime.raw |= mask;+    tagop->u.gen2.u.custom.u.ids.u.initialize.delayTime.IrqTimerEnable = timeEnable;+  }+  else+  {+    tagop->u.gen2.u.custom.u.ids.u.initialize.delayTime.raw &= (uint16_t)~mask;+    tagop->u.gen2.u.custom.u.ids.u.initialize.delayTime.IrqTimerEnable = timeEnable;+  }++  mask = 0x1FF;+  if (numberOfWords)+  {+    tagop->u.gen2.u.custom.u.ids.u.initialize.applicationData.raw &= (uint16_t)~mask;+    tagop->u.gen2.u.custom.u.ids.u.initialize.applicationData.raw |= (uint16_t)(numberOfWords << 7);+    tagop->u.gen2.u.custom.u.ids.u.initialize.applicationData.NumberOfWords = numberOfWords;+  }++  mask = 0x7;+  if (BrokenWordPointer)+  {+    tagop->u.gen2.u.custom.u.ids.u.initialize.applicationData.raw &= (uint16_t)~mask;+    tagop->u.gen2.u.custom.u.ids.u.initialize.applicationData.raw |= (uint16_t)(BrokenWordPointer);+    tagop->u.gen2.u.custom.u.ids.u.initialize.applicationData.BrokenWordPointer = BrokenWordPointer;+  }++  return TMR_SUCCESS;+}+++/**+ * Initialize a TMR_TagOp as a Gen2 Ids SL900A AcessFifo Status operation with the provided parameters.+ * @param tagop Pointer to the tagop structure to initialize.+ * @param accessPassword Gen2 accessPassword+ * @param password IDS password+ * @param level IDS passwordlevel+ */+TMR_Status+TMR_TagOp_init_GEN2_IDS_SL900A_AccessFifoStatus(TMR_TagOp *tagop, TMR_GEN2_Password accessPassword,+                                                 PasswordLevel level, uint32_t password)+{+  tagop->type = TMR_TAGOP_GEN2_IDS_SL900A_ACCESSFIFOSTATUS;+  tagop->u.gen2.u.custom.chipType = TMR_SR_GEN2_IDS_SL900A_SILICON;+  tagop->u.gen2.u.custom.u.ids.u.accessFifoStatus.status.AccessPassword = accessPassword;+  tagop->u.gen2.u.custom.u.ids.u.accessFifoStatus.status.CommandCode = 0xAF;+  tagop->u.gen2.u.custom.u.ids.u.accessFifoStatus.status.Password = password;+  tagop->u.gen2.u.custom.u.ids.u.accessFifoStatus.status.sl900A.level = level;+  tagop->u.gen2.u.custom.u.ids.u.accessFifoStatus.status.operation = TMR_GEN2_IDS_SL900A_ACCESSFIFO_STATUS;++  return TMR_SUCCESS;+}++/**+ * Initialize a TMR_TagOp as a Gen2 Ids SL900A AcessFifo Read operation with the provided parameters.+ * @param tagop Pointer to the tagop structure to initialize.+ * @param accessPassword Gen2 accessPassword+ * @param password IDS password+ * @param level IDS passwordlevel+ * @param readLength specify no of data to be read from fifo+ */+TMR_Status+TMR_TagOp_init_GEN2_IDS_SL900A_AccessFifoRead(TMR_TagOp *tagop, TMR_GEN2_Password accessPassword,+                                               PasswordLevel level, uint32_t password, uint8_t readLength)+{+  tagop->type = TMR_TAGOP_GEN2_IDS_SL900A_ACCESSFIFOREAD;+  tagop->u.gen2.u.custom.chipType = TMR_SR_GEN2_IDS_SL900A_SILICON;+  tagop->u.gen2.u.custom.u.ids.u.accessFifoRead.read.AccessPassword = accessPassword;+  tagop->u.gen2.u.custom.u.ids.u.accessFifoRead.read.CommandCode = 0xAF;+  tagop->u.gen2.u.custom.u.ids.u.accessFifoRead.read.Password = password;+  tagop->u.gen2.u.custom.u.ids.u.accessFifoRead.read.sl900A.level = level;+  tagop->u.gen2.u.custom.u.ids.u.accessFifoRead.read.operation = TMR_GEN2_IDS_SL900A_ACCESSFIFO_READ;+  +  if (readLength != (readLength & 0xF))+  {+    return TMR_ERROR_MSG_INVALID_PARAMETER_VALUE;+  }+  tagop->u.gen2.u.custom.u.ids.u.accessFifoRead.length = readLength;++  return TMR_SUCCESS;+}++/**+ * Initialize a TMR_TagOp as a Gen2 Ids SL900A AcessFifo Write operation with the provided parameters.+ * @param tagop Pointer to the tagop structure to initialize.+ * @param accessPassword Gen2 accessPassword+ * @param password IDS password+ * @param level IDS passwordlevel+ * @param payLoad specify  data to be written into fifo+ */+TMR_Status+TMR_TagOp_init_GEN2_IDS_SL900A_AccessFifoWrite(TMR_TagOp *tagop, TMR_GEN2_Password accessPassword,+                                               PasswordLevel level, uint32_t password, TMR_uint8List *payLoad)+{+  tagop->type = TMR_TAGOP_GEN2_IDS_SL900A_ACCESSFIFOWRITE;+  tagop->u.gen2.u.custom.chipType = TMR_SR_GEN2_IDS_SL900A_SILICON;+  tagop->u.gen2.u.custom.u.ids.u.accessFifoWrite.write.AccessPassword = accessPassword;+  tagop->u.gen2.u.custom.u.ids.u.accessFifoWrite.write.CommandCode = 0xAF;+  tagop->u.gen2.u.custom.u.ids.u.accessFifoWrite.write.Password = password;+  tagop->u.gen2.u.custom.u.ids.u.accessFifoWrite.write.sl900A.level = level;+  tagop->u.gen2.u.custom.u.ids.u.accessFifoWrite.write.operation = TMR_GEN2_IDS_SL900A_ACCESSFIFO_WRITE;+  +  if (payLoad->len != (payLoad->len & 0xF))+  {+    return TMR_ERROR_MSG_INVALID_PARAMETER_VALUE;+  }+  tagop->u.gen2.u.custom.u.ids.u.accessFifoWrite.payLoad = payLoad;++  return TMR_SUCCESS;+}++/**+ * Initialize a TMR_TagOp as a Gen2 Ids SL900A  StartLog operation with the provided parameters.+ * @param tagop Pointer to the tagop structure to initialize.+ * @param accessPassword Gen2 accessPassword+ * @param level IDS passwordlevel+ * @param password IDS password+ * @param timestamp pointer to TMR_TimeStructure (timestamp structure) + */+TMR_Status+TMR_TagOp_init_GEN2_IDS_SL900A_StartLog(TMR_TagOp *tagop, TMR_GEN2_Password accessPassword,+                                        PasswordLevel level, uint32_t password, TMR_TimeStructure *timestamp)+{+  tagop->type = TMR_TAGOP_GEN2_IDS_SL900A_STARTLOG;+  tagop->u.gen2.u.custom.chipType = TMR_SR_GEN2_IDS_SL900A_SILICON;+  tagop->u.gen2.u.custom.u.ids.u.startLog.AccessPassword = accessPassword;+  tagop->u.gen2.u.custom.u.ids.u.startLog.CommandCode = 0xA7;+  tagop->u.gen2.u.custom.u.ids.u.startLog.Password = password;+  tagop->u.gen2.u.custom.u.ids.u.startLog.sl900A.level = level;+  if (NULL == timestamp)+  {+    /** in case user not providing the time stamp+    * use current system time+    */+    return TMR_ERROR_TIMESTAMP_NULL;+  }+  +  tagop->u.gen2.u.custom.u.ids.u.startLog.startTime = 0;+  tagop->u.gen2.u.custom.u.ids.u.startLog.startTime |= (uint32_t)((timestamp->tm_year - 2010) << 26);+  tagop->u.gen2.u.custom.u.ids.u.startLog.startTime |= (uint32_t)((timestamp->tm_mon) << 22);+  tagop->u.gen2.u.custom.u.ids.u.startLog.startTime |= (uint32_t)(timestamp->tm_mday << 17);+  tagop->u.gen2.u.custom.u.ids.u.startLog.startTime |= (uint32_t)(timestamp->tm_hour << 12);+  tagop->u.gen2.u.custom.u.ids.u.startLog.startTime |= (uint32_t)(timestamp->tm_min << 6);+  tagop->u.gen2.u.custom.u.ids.u.startLog.startTime |= (uint32_t)(timestamp->tm_sec);++  return TMR_SUCCESS;+}++/**+ * Initialize a TMR_TagOp as a Gen2 Ids SL900A GetBatteryLevel operation with the provided parameters.+ * @param tagop Pointer to the tagop structure to initialize.+ * @param accessPassword Gen2 accessPassword+ * @param level IDS passwordlevel+ * @param password IDS password+ * @param type IDS batterytype+ */+TMR_Status+TMR_TagOp_init_GEN2_IDS_SL900A_GetBatteryLevel(TMR_TagOp *tagop, TMR_GEN2_Password accessPassword,+                                               PasswordLevel level, uint32_t password, BatteryType type)+{+  tagop->type = TMR_TAGOP_GEN2_IDS_SL900A_GETBATTERYLEVEL;+  tagop->u.gen2.u.custom.chipType = TMR_SR_GEN2_IDS_SL900A_SILICON;+  tagop->u.gen2.u.custom.u.ids.u.batteryLevel.AccessPassword = accessPassword;+  tagop->u.gen2.u.custom.u.ids.u.batteryLevel.CommandCode = 0xAA;+  tagop->u.gen2.u.custom.u.ids.u.batteryLevel.Password = password;+  tagop->u.gen2.u.custom.u.ids.u.batteryLevel.sl900A.level = level;+  tagop->u.gen2.u.custom.u.ids.u.batteryLevel.batteryType = type;++  return TMR_SUCCESS;+}++/**+ * Initialize a TMR_TagOp as a Gen2 Ids SL900A Set Log Limits operation with+ * @param tagop Pointer to the tagop struture to initialize.+ * @param accessPassword Gen2 accessPassword+ * @param level IDS apsswordlevel+ * @param passowrd IDS password+ * @param logLimits pointer to IDS LogLimits+ */+TMR_Status+TMR_TagOp_init_GEN2_IDS_SL900A_SetLogLimit(TMR_TagOp *tagop, TMR_GEN2_Password accessPassword, PasswordLevel level,+                                           uint32_t password, LogLimits *logLimits)+{+  tagop->type = TMR_TAGOP_GEN2_IDS_SL900A_SETLOGLIMITS;+  tagop->u.gen2.u.custom.chipType = TMR_SR_GEN2_IDS_SL900A_SILICON;+  tagop->u.gen2.u.custom.u.ids.u.setLogLimit.AccessPassword = accessPassword;+  tagop->u.gen2.u.custom.u.ids.u.setLogLimit.CommandCode = 0xA2;+  tagop->u.gen2.u.custom.u.ids.u.setLogLimit.Password = password;+  tagop->u.gen2.u.custom.u.ids.u.setLogLimit.sl900A.level = level;++  /**+   * LogLimit values are only 10 bit long,+   */+  if (0x03FF < logLimits->extremeLower)+  {+    return TMR_ERROR_MSG_INVALID_PARAMETER_VALUE; +  }++  tagop->u.gen2.u.custom.u.ids.u.setLogLimit.limit.extremeLower = logLimits->extremeLower;++  if (0x03FF < logLimits->lower)+  {+    return TMR_ERROR_MSG_INVALID_PARAMETER_VALUE;+  }+  tagop->u.gen2.u.custom.u.ids.u.setLogLimit.limit.lower = logLimits->lower;++  if (0x03FF < logLimits->upper)+  {+    return TMR_ERROR_MSG_INVALID_PARAMETER_VALUE;+  }+  tagop->u.gen2.u.custom.u.ids.u.setLogLimit.limit.upper = logLimits->upper;++  if (0x03FF < logLimits->extremeUpper)+  {+    return TMR_ERROR_MSG_INVALID_PARAMETER_VALUE;+  }+  tagop->u.gen2.u.custom.u.ids.u.setLogLimit.limit.extremeUpper = logLimits->extremeUpper;++  return TMR_SUCCESS;++}++/**+ * Initialize the Gen2 IDS SL900A SetShelfLifeBlock0 with+ * @param block0 pointer to the TMR_TagOp_GEN2_IDS_SL900A_ShelfLifeBlock0,+ * @param tmax SetShelfLife Tmax+ * @param tmin SetShelfLife Tmin+ * @param tstd SetshelfLIfe Tstd;+ * @param ea   SetshelfLife Ea;+ */ +TMR_Status+TMR_TagOp_init_GEN2_IDS_SL900A_ShelfLifeBlock0(TMR_TagOp_GEN2_IDS_SL900A_ShelfLifeBlock0 *block0,+                                               uint8_t tmax, uint8_t tmin, uint8_t tstd, uint8_t ea)+{+  uint64_t mask;+  block0->raw = 0;++  /* Copying the tmax to  block0 raw value */ +  {+    block0->Tmax = tmax;+    mask = TMR_makeBitMask(24, 8);+    block0->raw &= ~mask;+    block0->raw |= (uint32_t)((uint32_t)tmax << 24);+  }++  /* Copying the tmin to  block0 raw value */ +  {+    block0->Tmin = tmin;+    mask = TMR_makeBitMask(16, 8);+    block0->raw &= ~mask;+    block0->raw |= (uint32_t)((uint32_t)tmin << 16);+  }++  /* Copying the tstd to  block0 raw value */ +  {+    block0->Tstd = tstd;+    mask = TMR_makeBitMask(8, 8);+    block0->raw &= ~mask;+    block0->raw |= (uint32_t)((uint32_t)tstd << 8);+  }++  /* Copying the ea to  block0 raw value */ +  {+    block0->Ea = ea;+    mask = TMR_makeBitMask(0, 8);+    block0->raw &= ~mask;+    block0->raw |= (uint32_t)((uint32_t)ea << 0);+  }++  return TMR_SUCCESS;+}+++/**+ * Initialize the Gen2 IDS SL900A SetShelfLifeBlock1 with+ * @param block1 pointer to the TMR_TagOp_GEN2_IDS_SL900A_ShelfLifeBlock1,+ * @param slinit SetShelfLife SLinit+ * @param tint SetShelfLife Tint+ * @param sensorid SetshelfLIfe sensorID+ * @param negative SetshelfLife enableNegative+ * @param algorithm SetShelfLife algorithmEnable+ */ +TMR_Status+TMR_TagOp_init_GEN2_IDS_SL900A_ShelfLifeBlock1(TMR_TagOp_GEN2_IDS_SL900A_ShelfLifeBlock1 *block1,+                                               uint16_t slinit, uint16_t tint, uint8_t sensorid,+                                               bool negative, bool algorithm)+{+  uint64_t mask;+  block1->raw = 0;++  /* Copying the SLinit value to block1 raw value */+  {+    block1->SLinit = slinit;+    mask = TMR_makeBitMask(16, 16);+    block1->raw &= ~mask;+    block1->raw |= (uint32_t)((uint32_t)slinit << 16);+  }++  /* Copying the tint value to block1 raw value */+  {+    block1->Tint = tint;+    mask = TMR_makeBitMask(6, 10);+    block1->raw &= ~mask;+    block1->raw |= (uint32_t)((uint32_t)tint << 6);+  }++  /* Copying the sensorID to block1 raw value */+  {+    block1->sensorID = sensorid;+    mask = TMR_makeBitMask(4, 2);+    block1->raw &= ~mask;+    block1->raw |= (uint32_t)((uint32_t)sensorid << 4);+  }++  /* Copying the enableNegative value to block1 raw value */+  {+    block1->enableNegative = negative;+    mask = TMR_makeBitMask(3, 1);+    block1->raw &= ~mask;+    block1->raw |= (uint32_t)(negative << 3);+  }++  /* Copying the algorithemEnable value to block1 raw value */+  {+    block1->algorithmEnable = algorithm;+    mask = TMR_makeBitMask(2, 1);+    block1->raw &= ~mask;+    block1->raw |= (uint32_t)(negative << 2);+  }++  /* Setting the RFU bytes to zero */+  block1->rfu = 0;+  mask = TMR_makeBitMask(0, 2);+  block1->raw &= ~mask;+  block1->raw |= (uint32_t)(0 << 0);++  return TMR_SUCCESS;+}++/**+ * Initialize a TMR_TagOp as a Gen2 Ids SL900A Set Shelf Life operation with+ * @param tagop pointer to the tagop struture to setShelfLife+ * @param accessPassword Gen2 accessPassword+ * @param level IDS passwordlevel+ * @param password IDS password+ * @param block0 pointer to the TMR_TagOp_GEN2_IDS_SL900A_ShelfLifeBlock0,+ * @param block1 pointer to the TMR_TagOp_GEN2_IDS_SL900A_ShelfLifeBlock1,+ */+TMR_Status+TMR_TagOp_init_GEN2_IDS_SL900A_SetShelfLife(TMR_TagOp *tagop, TMR_GEN2_Password accessPassword, PasswordLevel level,+                                            uint32_t password,TMR_TagOp_GEN2_IDS_SL900A_ShelfLifeBlock0 *block0,+                                            TMR_TagOp_GEN2_IDS_SL900A_ShelfLifeBlock1 *block1)+{+  tagop->type = TMR_TAGOP_GEN2_IDS_SL900A_SETSHELFLIFE;+  tagop->u.gen2.u.custom.chipType = TMR_SR_GEN2_IDS_SL900A_SILICON;+  tagop->u.gen2.u.custom.u.ids.u.setShelfLife.AccessPassword = accessPassword;+  tagop->u.gen2.u.custom.u.ids.u.setShelfLife.CommandCode = 0xAB;+  tagop->u.gen2.u.custom.u.ids.u.setShelfLife.Password = password;+  tagop->u.gen2.u.custom.u.ids.u.setShelfLife.sl900A.level = level;+  tagop->u.gen2.u.custom.u.ids.u.setShelfLife.shelfLifeBlock0 = block0;+  tagop->u.gen2.u.custom.u.ids.u.setShelfLife.shelfLifeBlock1 = block1;++  return TMR_SUCCESS;+}++/**+ * Initialize TMR_UserConfigOp to set the default category.+ * @param config pointer to the TMR_UserConfigOp structure to initialize+ * @param op user configuration opeartion (save, restore or clear)+ */+TMR_Status+TMR_init_UserConfigOp(TMR_SR_UserConfigOp *config, TMR_SR_UserConfigOperation op)+{+  config->category = TMR_SR_ALL;+  config->op       = op;++  return TMR_SUCCESS;+}++/**+ *  Initialize TMR_NXP_ConfigWord to set the default value.+ *  If the instance of the above structure is created as 'static',+ *  then no need to call this constructor.+ *  @param configWord Instance of TMR_NXP_ConfigWord+ */+TMR_Status +TMR_init_GEN2_NXP_G2I_ConfigWord(TMR_NXP_ConfigWord *configWord)+{+  configWord->data = 0x0000;+  return TMR_SUCCESS;+}++/**+ *  Initialize TMR_Monza4_ControlByte to set the default value to 0.+ *  If the instance of the above structure is created as 'static' or+ *  if it is already initialized to 0, then no need to call this constructor.+ *  @param controlByte Instance of TMR_Monza4_ControlByte+ */+TMR_Status+TMR_init_GEN2_Impinj_Monza4_ControlByte(TMR_Monza4_ControlByte *controlByte)+{+  controlByte->data = 0x00;+  return TMR_SUCCESS;+}++/**+ *  Initialize TMR_Monza4_Payload to set the default value to 0.+ *  If the instance of the above structure is created as 'static' or+ *  if it is already initialized to 0, then no need to call this constructor.+ *  @param payload Instance of TMR_Monza4_Payload+ */+TMR_Status+TMR_init_GEN2_Impinj_Monza4_Payload(TMR_Monza4_Payload *payload)+{+  payload->data = 0x0000;+  return TMR_SUCCESS;+}++/**+ * Helper function to update or modifying the sfe parameters+ */+TMR_Status+TMR_update_GEN2_IDS_SL900A_SfeParameters(TMR_TagOp_GEN2_IDS_SL900A_SfeParameters *sfe)+{+  uint64_t mask;+  /* Update the raw value as per the  field set by the user */+  switch (sfe->type)+  {+    case TMR_GEN2_IDS_SL900A_SFE_RANG:+      {+        mask = TMR_makeBitMask(11, 5);+        sfe->raw &= ~mask;+        sfe->raw |= ((uint64_t)(((uint64_t)sfe->Rang) << 11));++        break;+      }+    case TMR_GEN2_IDS_SL900A_SFE_SETI:+      {+        mask = TMR_makeBitMask(6, 5);+        sfe->raw &= ~mask;+        sfe->raw |= ((uint64_t)(((uint64_t)sfe->Seti) << 6));++        break;+      }+    case TMR_GEN2_IDS_SL900A_SFE_EXT1:+      {+        mask = TMR_makeBitMask(4, 2);+        sfe->raw &= ~mask;+        sfe->raw |= ((uint64_t)(((uint64_t)sfe->Ext1) << 4));++        break;+      }+    case TMR_GEN2_IDS_SL900A_SFE_EXT2:+      {+        mask = TMR_makeBitMask(3, 1);+        sfe->raw &= ~mask;+        sfe->raw |= ((uint64_t)(((uint64_t)sfe->Ext2) << 3));++        break;+      }+    case TMR_GEN2_IDS_SL900A_SFE_AUTORANGEDISABLE:+      {+        mask = TMR_makeBitMask(2, 1);+        sfe->raw &= ~mask;+        sfe->raw |= ((uint64_t)(((uint64_t)sfe->AutorangeDisable) << 2));++        break;+      }+    case TMR_GEN2_IDS_SL900A_SFE_VERIFYSENSORID:+      {+        mask = TMR_makeBitMask(0, 2);+        sfe->raw &= ~mask;+        sfe->raw |= ((uint64_t)(((uint64_t)sfe->VerifySensorID) << 0));++        break;+      }+    default: +      break;+  }+  return TMR_SUCCESS;+}++/**+ * Helper function to update or modifying the calibration Data+ */+TMR_Status+TMR_update_GEN2_IDS_SL900A_CalibrationData(TMR_TagOp_GEN2_IDS_SL900A_CalibrationData *cal)+{+  uint64_t mask;+  /* Update the raw value as per the  field set by the user */+  switch (cal->type)+  {+    case TMR_GEN2_IDS_SL900A_CALIBRATION_COARSE1:+      {+        mask = TMR_makeBitMask(48, 3);+        cal->raw &= ~mask;+        cal->raw |= ((uint64_t)(((uint64_t)cal->Coarse1) << 48));+        cal->raw = cal->raw;++        break;+      }+    case TMR_GEN2_IDS_SL900A_CALIBRATION_COARSE2:+      {+        mask = TMR_makeBitMask(40, 3);+        cal->raw &= ~mask;+        cal->raw |= ((uint64_t)(((uint64_t)cal->Coarse2) << 40));+        cal->raw = cal->raw;++        break;+      }+    case TMR_GEN2_IDS_SL900A_CALIBRATION_GNDSWITCH:+      {+        mask = TMR_makeBitMask(39, 1);+        cal->raw &= ~mask;+        cal->raw |= ((uint64_t)(((uint64_t)cal->GndSwitch) << 39));+        cal->raw = cal->raw;++        break;+      }+    case TMR_GEN2_IDS_SL900A_CALIBRATION_SELP12:+      {+        mask = TMR_makeBitMask(37, 2);+        cal->raw &= ~mask;+        cal->raw |= ((uint64_t)(((uint64_t)cal->Selp12) << 37));+        cal->raw = cal->raw;++        break;+      }+    case TMR_GEN2_IDS_SL900A_CALIBRATION_DF:+      {+        mask = TMR_makeBitMask(24, 8);+        cal->raw &= ~mask;+        cal->raw |= ((uint64_t)(((uint64_t)cal->Df) << 24));+        cal->raw = cal->raw;++        break;+      }+    case TMR_GEN2_IDS_SL900A_CALIBRATION_SWEXTEN:+      {+        mask = TMR_makeBitMask(23, 1);+        cal->raw &= ~mask;+        cal->raw |= ((uint64_t)(((uint64_t)cal->SwExtEn) << 23));+        cal->raw = cal->raw;++        break;+      }+    case TMR_GEN2_IDS_SL900A_CALIBRATION_SELP22:+      {+        mask = TMR_makeBitMask(21, 2);+        cal->raw &= ~mask;+        cal->raw |= ((uint64_t)(((uint64_t)cal->Selp22) << 21));+        cal->raw = cal->raw;++        break;+      }+    case TMR_GEN2_IDS_SL900A_CALIBRATION_IRLEV:+      {+        mask = TMR_makeBitMask(19, 2);+        cal->raw &= ~mask;+        cal->raw |= ((uint64_t)(((uint64_t)cal->Irlev) << 19));+        cal->raw = cal->raw;++        break;+      }+    case TMR_GEN2_IDS_SL900A_CALIBRATION_EXCRES:+      {+        mask = TMR_makeBitMask(2, 1);+        cal->raw &= ~mask;+        cal->raw |= ((uint64_t)(((uint64_t)cal->ExcRes) << 2));+        cal->raw = cal->raw;++        break;+      }+    default: +      break;+  }+  return TMR_SUCCESS;+}++/**+ * Helper function to set the calibration Data+ */+TMR_Status+TMR_init_GEN2_IDS_SL900A_CalibrationData(uint8_t byte[7], TMR_TagOp_GEN2_IDS_SL900A_CalibrationData *cal)+{+  if (NULL != byte)+  {+    /**+     * ToU64 requires 8 bytes of input, but CalibrationData is only 7 bytes long+     * Create a temporary array to provide the necessary padding.+     */+    uint8_t tmp[] = {0,0,0,0,0,0,0,0,};+    memcpy(tmp+1, byte, 7);+    cal->raw = (uint64_t)(0+        | ((uint64_t)(tmp[ 0]) << 56)+        | ((uint64_t)(tmp[ 1]) << 48)+        | ((uint64_t)(tmp[ 2]) << 40)+        | ((uint64_t)(tmp[3]) << 32)+        | ((uint64_t)(tmp[4]) << 24)+        | ((uint64_t)(tmp[5]) << 16)+        | ((uint64_t)(tmp[ 6]) << 8)+        | ((uint64_t)(tmp[7]) << 0));++    cal->raw &= (uint64_t)0x00FFFFFFFFFFFFFFLL;+  }++  return TMR_SUCCESS;+}++/**+ * Helper function to set the sfe parameters+ */+TMR_Status+TMR_init_GEN2_IDS_SL900A_SfeParameters(uint8_t byte[2], TMR_TagOp_GEN2_IDS_SL900A_SfeParameters *sfe)+{+  /* Create SFEParameters object from raw 2-byte reply */+  int hi, lo;+  hi = (uint16_t)(byte[0]) << 8;+  lo = (uint16_t)(byte[1]);+  sfe->raw = (hi | lo);++  return TMR_SUCCESS;+}++/**+ * Initialize TMR_GEN2_SL900A_SensorReading to Get Sensor Value response.+ * @param reply instance of TMR_uint8List+ * @param sensor instance of TMR_TagOp_GEN2_IDS_SL900A_SensorReading,+ * response for sl900A getSensorvalue command.+ */+TMR_Status+TMR_init_GEN2_IDS_SL900A_SensorReading(TMR_uint8List *reply, TMR_TagOp_GEN2_IDS_SL900A_SensorReading *sensor)+{  ++  if (2 != reply->len)+  {+    /* Sensor Reading value must be exactly 2 bytes long */+    return TMR_ERROR_MSG_INVALID_PARAMETER_VALUE;+  }+  sensor->reply = reply->list[0] << 8 | reply->list[1];+  sensor->Raw = sensor->reply;+  sensor->ADError = (((sensor->reply >> 15) & 0x1) != 0);+  sensor->RangeLimit = (uint8_t) ((sensor->reply >> 10) & 0x1F);+  sensor->Value = ((sensor->reply >> 0 ) & 0x3FF);++  return TMR_SUCCESS;+}++/**+ * Initialize TMR_GEN2_SL900A_CalSfe to Get getcalibration response.+ * @param reply instance of TMR_uint8List+ * @param calSfe instance of TMR_TagOp_GEN2_IDS_SL900A_CalSfe,+ * response for CalibrationData and SfeParameters.+ */+TMR_Status+TMR_init_GEN2_IDS_SL900A_CalSfe(TMR_uint8List *reply, TMR_TagOp_GEN2_IDS_SL900A_CalSfe *calSfe)+{+  uint64_t mask;+  TMR_init_GEN2_IDS_SL900A_CalibrationData(reply->list, &calSfe->Cal);+  TMR_init_GEN2_IDS_SL900A_SfeParameters(reply->list + 7, &calSfe->Sfe);++  mask = TMR_makeBitMask(51, 5);+  calSfe->Cal.Ad1 = (uint8_t)((calSfe->Cal.raw & mask) >> 51);++  mask = TMR_makeBitMask(48, 3);+  calSfe->Cal.Coarse1 = (uint8_t)((calSfe->Cal.raw & mask) >> 48);++  mask = TMR_makeBitMask(43, 5);+  calSfe->Cal.Ad2 = (uint8_t)((calSfe->Cal.raw & mask) >> 43);++  mask = TMR_makeBitMask(40, 3);+  calSfe->Cal.Coarse2 = (uint8_t)((calSfe->Cal.raw & mask) >> 40);++  mask = TMR_makeBitMask(39, 1);+  calSfe->Cal.GndSwitch = (uint8_t)((calSfe->Cal.raw & mask) >> 39);++  mask = TMR_makeBitMask(37, 2);+  calSfe->Cal.Selp12 = (uint8_t)((calSfe->Cal.raw & mask) >> 37);++  mask = TMR_makeBitMask(32, 5);+  calSfe->Cal.Adf = (uint8_t)((calSfe->Cal.raw & mask) >> 32);++  mask = TMR_makeBitMask(24, 8);+  calSfe->Cal.Df = (uint8_t)((calSfe->Cal.raw & mask) >> 24);++  mask = TMR_makeBitMask(23, 1);+  calSfe->Cal.SwExtEn = (uint8_t)((calSfe->Cal.raw & mask) >> 23);++  mask = TMR_makeBitMask(21, 2);+  calSfe->Cal.Selp22 = (uint8_t)((calSfe->Cal.raw & mask) >> 21);++  mask = TMR_makeBitMask(19, 2);+  calSfe->Cal.Irlev = (uint8_t)((calSfe->Cal.raw & mask) >> 19);++  mask = TMR_makeBitMask(14, 5);+  calSfe->Cal.RingCal = (uint8_t)((calSfe->Cal.raw & mask) >> 14);++  mask = TMR_makeBitMask(7, 7);+  calSfe->Cal.OffInt = (uint8_t)((calSfe->Cal.raw & mask) >> 7);++  mask = TMR_makeBitMask(3, 4);+  calSfe->Cal.Reftc = (uint8_t)((calSfe->Cal.raw & mask) >> 3);++  mask = TMR_makeBitMask(2, 1);+  calSfe->Cal.ExcRes = (uint8_t)((calSfe->Cal.raw & mask) >> 2);++  mask = TMR_makeBitMask(0, 2);+  calSfe->Cal.RFU = (uint8_t)((calSfe->Cal.raw & mask) >> 0);++  mask = TMR_makeBitMask(11, 5);+  calSfe->Sfe.Rang = (uint8_t)((calSfe->Sfe.raw & mask) >> 11);++  mask = TMR_makeBitMask(6, 5);+  calSfe->Sfe.Seti = (uint8_t)((calSfe->Sfe.raw & mask) >> 6);++  mask = TMR_makeBitMask(4, 2);+  calSfe->Sfe.Ext1 = (uint8_t)((calSfe->Sfe.raw & mask) >> 4);++  mask = TMR_makeBitMask(3, 1);+  calSfe->Sfe.Ext2 = (uint8_t)((calSfe->Sfe.raw & mask) >> 3);++  mask = TMR_makeBitMask(2, 1);+  calSfe->Sfe.AutorangeDisable = (uint8_t)((calSfe->Sfe.raw & mask) >> 2);++  mask = TMR_makeBitMask(0, 2);+  calSfe->Sfe.VerifySensorID = (uint8_t)((calSfe->Sfe.raw & mask) >> 0);++  return TMR_SUCCESS;+}++/**+ * Initialize TMR_GEN2_SL900A_BatteryLevelReading to get the getBatteryLevel response.+ * @param reply instance of TMR_uint8List+ * @param battery instance of TMR_TagOp_GEN2_IDS_SL900A_BatteryLevelReading,+ * the reply structure of getBatteryLevel+ */ ++TMR_Status+TMR_init_GEN2_IDS_SL900A_BatteryLevelReading(TMR_uint8List *reply, TMR_TagOp_GEN2_IDS_SL900A_BatteryLevelReading *battery)+{  ++  if (2 != reply->len)+  {+    /* Sensor Reading value must be exactly 2 bytes long */+    return TMR_ERROR_MSG_INVALID_PARAMETER_VALUE;+  }+  battery->reply = (uint16_t)(reply->list[0] << 8 | reply->list[1]);+  battery->ADError = (bool)(((battery->reply >> 15) & 0x1) != 0);+  battery->BatteryType = (uint8_t) ((battery->reply >> 14) & 0x1);+  battery->Value = (uint16_t)((battery->reply >> 0 ) & 0x3FF);++  return TMR_SUCCESS;+}+/**+ * Initialize TMR_GEN2_SL900A_FifoStatus to Get status of fifo reply+ * @param statusReply instance of TMR_uint8List+ * @param status instance of TMR_TagOp_GEN2_IDS_SL900A_FifoStatus,+ * the reply structure of sl900A fifistatus command. + */+TMR_Status+TMR_init_GEN2_IDS_SL900A_FifoStatus(TMR_uint8List *statusReply, TMR_TagOp_GEN2_IDS_SL900A_FifoStatus *status)+{++  uint8_t reply;+  if (1 != statusReply->len)+  {+    /* Fifo Status value must be exactly 1 byte long */+    return TMR_ERROR_MSG_INVALID_PARAMETER_VALUE;+  }+  status->raw = statusReply->list[0];+  reply = statusReply->list[0];+  status->fifoBusy = (0 != ((reply >> 7) & 1));+  status->dataReady = (0 != ((reply >> 6) & 1));+  status->noData = (0 != ((reply >> 5) & 1));+  status->numValidBytes = (uint8_t)(reply & 0xF);++  return TMR_SUCCESS;+}++/**+ * Initialize TMR_GEN2_SL900A_LogState to Get get log state Value response.+ * @param reply instance of TMR_uint8List+ * @param log instance of TMR_TagOp_GEN2_IDS_SL900A_LogState,+ * sl900A logging parameters.+ */+TMR_Status+TMR_init_GEN2_IDS_SL900A_LogState(TMR_uint8List *reply, TMR_TagOp_GEN2_IDS_SL900A_LogState *log)+{  ++  uint32_t offset = 0;+  uint32_t raw;  +  if ((9 != reply->len) && (20 != reply->len))+  {+    /* GetLogState replies must be 9 or 21 bytes in length */+    return TMR_ERROR_MSG_INVALID_PARAMETER_VALUE;+  }++  if (9 == reply->len)+  {+    log->limitCount.extremeLower = reply->list[offset + 0];    +    log->limitCount.lower = reply->list[offset + 1];+    log->limitCount.upper = reply->list[offset + 2];+    log->limitCount.extremeUpper = reply->list[offset + 3];++    offset += 4;+    raw = TMR_byteArrayToInt(reply->list, offset);+    log->statStatus.MeasurementAddressPointer = (uint16_t)((raw >> 22) & 0x1FF);+    log->statStatus.NumMemReplacements = (uint8_t) ((raw >> 16) & 0x3F);+    log->statStatus.NumMeasurements = (uint16_t) ((raw >> 1) & 0x7FFF);+    log->statStatus.Active = (bool)(0 != (raw & 0x1));+    offset += 4;+  }+  if (20 == reply->len)+  {+    /* @todo Fully support shelf life arguments.  For now, just skip over them */+    offset += 8;+    offset += 4;+  }+  raw = TMR_byteArrayToInt(reply->list, offset);+  log->statFlag.Active = (bool)(0 != ((raw >> 7) & 1));+  log->statFlag.Full = (bool)(0 != ((raw >> 6) & 1));+  log->statFlag.Overwritten = (bool)(0 != ((raw >> 5) & 1));+  log->statFlag.ADError = (bool) (0 != ((raw >> 4) & 1));+  log->statFlag.LowBattery = (bool) (0 != ((raw >> 3) & 1));+  log->statFlag.ShelfLifeLow = (bool) (0 != ((raw >> 2) & 1));+  log->statFlag.ShelfLifeHigh = (bool)(0 != ((raw >> 1) & 1));+  log->statFlag.ShelfLifeExpired = (bool)(0 != ((raw >> 0) & 1));+  +  return TMR_SUCCESS;+}++/**+ * Initialize TMR_TagOp_GEN2_IDS_SL900A_MeasurementSetupData to Get measurment setup data + * Value response.+ * @param reply instance of TMR_uint8List+ * @param measurement instance of TMR_TagOp_GEN2_IDS_SL900A_MeasurementSetupData,+ * response structure for sl900A getMeasurementSetupData command.+ */+TMR_Status+TMR_init_GEN2_IDS_SL900A_MeasurementSetupData(TMR_uint8List *reply, TMR_TagOp_GEN2_IDS_SL900A_MeasurementSetupData *measurement)+{+  if(16 != reply->len)+  {+    /* MeasurementSetupData value must be exactly 16 byte long */+    return TMR_ERROR_MSG_INVALID_PARAMETER_VALUE;+  }++  memcpy(measurement->Raw, reply->list, reply->len);++  //get the start time+  {+    uint32_t temp;+    temp = TMR_byteArrayToInt(reply->list, 0);+    measurement->startTime.tm_year = (int)(2010+((temp >> 26) & 0x3F));+    measurement->startTime.tm_mon = (int)((temp >> 22) & 0xF);+    measurement->startTime.tm_mday = (int)((temp >> 17) & 0x1F);+    measurement->startTime.tm_hour = (int)((temp >> 12) & 0x1F);+    measurement->startTime.tm_min = (int)((temp >> 6) & 0x3F);+    measurement->startTime.tm_sec = (int)((temp >> 0) & 0x3F);+  }+  //get the log limits+  {+    int offset = 4;+    uint64_t value = 0;+    /* LogLimits value is of 40 bits+     * extract that from the response+     */+    value = TMR_byteArrayToLong(reply->list, offset);+    /* +     * Indivisual field in LogLimits is of 10 bits+     * masking each of them to a 16 bit value for convinence+     */+    measurement->loglimit.extremeLower = (uint16_t) ((value >> 54) & 0x03FF);+    measurement->loglimit.lower = (uint16_t) ((value >> 44) & 0x03FF);+    measurement->loglimit.upper = (uint16_t) ((value >> 34) & 0x03FF);+    measurement->loglimit.extremeUpper = (uint16_t) ((value >> 24) & 0x03FF);+  }+  //get log mode+  {+    uint8_t temp = (uint8_t)reply->list[9];+    measurement->logModeData.Raw = temp;+    measurement->logModeData.Form = (LoggingForm)((temp >> 5) & 7);+    measurement->logModeData.Storage = (StorageRule)(((temp >> 4) & 1));+    measurement->logModeData.Ext1Enable = (0 != ((temp >> 3) & 1));+    measurement->logModeData.Ext2Enable = (0 != ((temp >> 2) & 1));+    measurement->logModeData.TempEnable = (0 != ((temp >> 1) & 1));+    measurement->logModeData.BattEnable = (0 != ((temp>> 0) & 1));+  }+  //log interval+  {+    uint16_t temp;+    temp = TMR_byteArrayToShort(reply->list, 10);+    temp = ((temp >> 1) & 0x0001);+    measurement->logInterval = temp;+  }+  //delay time+  {+    uint16_t temp;+    temp = TMR_byteArrayToShort(reply->list, 12);+    measurement->delyTime.raw = temp;+    measurement->delyTime.Mode = (0 == ((temp >> 1) & 0x1)) ? TMR_GEN2_IDS_SL900A_DELAYMODE_TIMER+                                                           : TMR_GEN2_IDS_SL900A_DELAYMODE_EXTSWITCH;+    measurement->delyTime.Time = (uint16_t)((temp >> 4) & 0xFFF);+    measurement->delyTime.IrqTimerEnable = (0 != (temp & 0x1));+  }+  //application data+  {+    uint16_t temp;+    temp = TMR_byteArrayToShort(reply->list, 14);+    measurement->addData.raw = temp;+    measurement->addData.NumberOfWords = (uint16_t)((temp >> 7) & 0x1FF);+    measurement->addData.BrokenWordPointer = (uint8_t)(temp & 0x7);+  }++  return TMR_SUCCESS;+}++#endif /* TMR_ENABLE_GEN2_CUSTOM_TAGOPS  */+void+TMR_paramProbe(struct TMR_Reader *reader, TMR_Param key)+{++  /* buf is at least as large as the largest parameter, with all values 0+   * (NULL pointers and 0 lengths).+   */+  uint32_t buf[] = {0, 0, 0, 0, 0, 0, 0, 0};+  TMR_Status ret;++  ret = TMR_paramGet(reader, key, &buf);+  if (TMR_SUCCESS == ret)+  {+    if (TMR_READER_TYPE_SERIAL == reader->readerType)+    {+      BITSET(reader->u.serialReader.paramPresent, key);+      BITSET(reader->u.serialReader.paramConfirmed, key);+    }+#ifdef TMR_ENABLE_LLRP_READER+    if (TMR_READER_TYPE_LLRP == reader->readerType)+    {+      BITSET(reader->u.llrpReader.paramPresent, key);+      BITSET(reader->u.llrpReader.paramConfirmed, key);+    }+#endif+  }+}+++/**+ * Get a list of the parameters available+ * @reader pointer of reader object+ * @key pointer of TMR_Param+ * @len pointer to uint32_t+ */++TMR_Status+TMR_paramList(struct TMR_Reader *reader, TMR_Param *keys, uint32_t *len)+{+  int i, count, max;++  max = *len;+  count = 0;+  for (i = TMR_PARAM_MIN; i <= TMR_PARAM_MAX ; i++)+  {+    if (TMR_READER_TYPE_SERIAL == reader->readerType)+    {+      if (0 == BITGET(reader->u.serialReader.paramConfirmed, i))+      {+        /* Fix me */+        TMR_paramProbe(reader, (TMR_Param)i);+      }++      if (BITGET(reader->u.serialReader.paramPresent, i))+      {+        if (count < max)+          keys[count] = (TMR_Param)i;+        count++;+      }+    }+#ifdef TMR_ENABLE_LLRP_READER+    if (TMR_READER_TYPE_LLRP == reader->readerType)+    {+      if (0 == BITGET(reader->u.llrpReader.paramConfirmed, i))+      {+        TMR_paramProbe(reader, i);+      }++      if (BITGET(reader->u.llrpReader.paramPresent, i))+      {+        if (count < max)+          keys[count] = i;+        count++;+      }+    }+#endif+  }++  *len = count;++  return TMR_SUCCESS;+}++  TMR_Status+TMR_receiveAutonomousReading(struct TMR_Reader *reader, TMR_TagReadData *trd, TMR_Reader_StatsValues *stats)+{+  TMR_Status ret;++  ret = TMR_SUCCESS;++  if (TMR_READER_TYPE_SERIAL != reader->readerType)+  {+    /* Currently supporting only serial reader */+    return TMR_ERROR_UNSUPPORTED;+  }++#ifdef TMR_ENABLE_BACKGROUND_READS+  {+    /**+     *      *     * create the thread+     *           *         */+    ret = pthread_create(&reader->autonomousBackgroundReader, NULL,+        do_background_receiveAutonomousReading, reader);+    if (0 != ret)+    {+      return TMR_ERROR_NO_THREADS;+    }+    pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL);+    pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);+    pthread_detach(reader->autonomousBackgroundReader);+  }+#else+  {+    /* This will add support for non thread platform */+    ret =  TMR_SR_receiveAutonomousReading(reader, trd, stats);+  }+#endif++  return ret;+}+
+ cbits/api/tm_reader.h view
@@ -0,0 +1,1289 @@+/* ex: set tabstop=2 shiftwidth=2 expandtab cindent: */+#ifndef _TM_READER_H+#define _TM_READER_H+/**+ *  @file tm_reader.h+ *  @brief Mercury API Reader Interface+ *  @author Brian Fiegel+ *  @date 4/18/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.+ */++/* Due to incompatibilities between winsock.h and winsock2.h (plus interactions+ * with windows.h) you're in for a storm of "redefinition" errors if you don't+ * include winsock2.h first.+ * + * This is surprisingly hard, because lots of other headers include winsock.h+ * themselves.  So include winsock2.h as early as possible.+ */+#if defined(WIN32) || defined(WINCE)+#include <winsock2.h>+#endif++#include "tm_config.h"++/**+ * TMR_ENABLE_JNI_SERIAL_READER_ONLY is used for building JNI project, and is defined from+ * Makefile.jni+ **/+#if !defined(TMR_ENABLE_SERIAL_READER_ONLY) && !defined(TMR_ENABLE_JNI_SERIAL_READER_ONLY)  && defined(TMR_ENABLE_LLRP_TRANSPORT)+#define TMR_ENABLE_LLRP_READER+#endif++#ifdef TMR_ENABLE_BACKGROUND_READS+#include <pthread.h>+#include <semaphore.h>+#endif++typedef struct TMR_Reader TMR_Reader;++#include "tmr_types.h"+#include "tmr_status.h"++#include "tmr_gpio.h"+#include "tmr_params.h"+#include "tmr_read_plan.h"+#include "tmr_tag_auth.h"+#include "tmr_tag_data.h"+#include "tmr_tag_lock_action.h"+#include "tmr_tag_protocol.h"+#include "tmr_tagop.h"++#include "tmr_serial_reader.h"+#ifdef TMR_ENABLE_LLRP_READER+#include "tmr_llrp_reader.h"+#endif++#ifdef  __cplusplus+extern "C" {+#endif+++#ifndef DOXYGEN_IGNORE+typedef TMR_Status (*TMR_TransportNativeInit)(TMR_SR_SerialTransport *transport, TMR_SR_SerialPortNativeContext *context,+    const char *device);++typedef struct TMR_readParams+{+#if defined(TMR_ENABLE_BACKGROUND_READS)|| defined(SINGLE_THREAD_ASYNC_READ)+  uint32_t asyncOnTime;+  uint32_t asyncOffTime;+#endif+  TMR_ReadPlan defaultReadPlan;+  TMR_ReadPlan *readPlan;+} TMR_readParams;++typedef struct TMR_tagOpParams+{+  uint8_t antenna;+  TMR_TagProtocol protocol;+}TMR_tagOpParams;++typedef enum TMR_ReaderType+{+  TMR_READER_TYPE_INVALID,+  TMR_READER_TYPE_RQL,+  TMR_READER_TYPE_SERIAL,+  TMR_READER_TYPE_LLRP,+} TMR_ReaderType;++typedef enum TMR_ReadState+{+  TMR_READ_STATE_IDLE,+  TMR_READ_STATE_STARTING,+  TMR_READ_STATE_STARTED,+  TMR_READ_STATE_ACTIVE,+  TMR_READ_STATE_DONE,+} TMR_ReadState;+++#endif /* DOXYGEN_IGNORE */++/**+ *  Reader Stats Flag Enum+ */+typedef enum TMR_Reader_StatsFlag+{+  TMR_READER_STATS_FLAG_NONE = 0x00,+	/** Total time the port has been transmitting, in milliseconds. Resettable */+  TMR_READER_STATS_FLAG_RF_ON_TIME = (1 << 0),+  /** Noise floor with the TX on for the antennas were last configured for searching */+  TMR_READER_STATS_FLAG_NOISE_FLOOR_SEARCH_RX_TX_WITH_TX_ON = (1 << 6),+  /** Current frequency in units of Khz */+  TMR_READER_STATS_FLAG_FREQUENCY = (1 << 7),+  /** Current temperature of the device in units of Celsius */+  TMR_READER_STATS_FLAG_TEMPERATURE = (1 << 8),+  /** Current antenna */+  TMR_READER_STATS_FLAG_ANTENNA_PORTS = (1 << 9),+  /** Current protocol */ +  TMR_READER_STATS_FLAG_PROTOCOL = (1 << 10),+  /** Current connected antennas */+  TMR_READER_STATS_FLAG_CONNECTED_ANTENNAS = (1 << 11),+  /* ALL */+  TMR_READER_STATS_FLAG_ALL = (TMR_READER_STATS_FLAG_RF_ON_TIME |+      TMR_READER_STATS_FLAG_NOISE_FLOOR_SEARCH_RX_TX_WITH_TX_ON |+      TMR_READER_STATS_FLAG_TEMPERATURE |+      TMR_READER_STATS_FLAG_PROTOCOL |+      TMR_READER_STATS_FLAG_ANTENNA_PORTS |+      TMR_READER_STATS_FLAG_FREQUENCY |+      TMR_READER_STATS_FLAG_CONNECTED_ANTENNAS),+}TMR_Reader_StatsFlag;++/**+ * Per Antenna stats+ */+typedef struct TMR_StatsPerAntennaValues+{+	/** Antenna number */+	uint8_t antenna;+	/** Current RF on time (since start of search) (milliseconds) */+	uint32_t rfOnTime;+	/** Noise Floor (TX on, all connected antennas) (dBm) */+	int8_t noiseFloor;+} TMR_StatsPerAntennaValues;++/**+ * Object to hold the per antenna stats+ */+typedef struct TMR_StatsPerAntennaValuesList+{+	TMR_StatsPerAntennaValues *list;+	uint16_t max;+	uint16_t len;+} TMR_StatsPerAntennaValuesList;++/**+ * This object is returned from TMR_cmdGetReaderStats+ */+typedef struct TMR_Reader_StatsValues+{+	TMR_Reader_StatsFlag valid;+	/** Current temperature (degrees C) */+	int8_t temperature;+	/** Current tag protocol */+	TMR_TagProtocol protocol;+	/** Current antenna */+	uint16_t antenna;+	/** Current RF carrier frequency (KHZ) */+	uint32_t frequency;+	/** Current connected antennas */+	TMR_uint8List connectedAntennas;+	uint8_t _connectedAntennasStorage[TMR_SR_MAX_ANTENNA_PORTS];+	/** Per-antenna values */+	TMR_StatsPerAntennaValuesList perAntenna;+	TMR_StatsPerAntennaValues _perAntStorage[TMR_SR_MAX_ANTENNA_PORTS];+}TMR_Reader_StatsValues;++/** Type of functions to be registered as read callbacks */+typedef void (*TMR_ReadListener)(TMR_Reader *reader, const TMR_TagReadData *t,+                                 void *cookie);+/**+ * User-allocated structure containing the callback pointer and the+ * value to pass to that callback.+ */+typedef struct TMR_ReadListenerBlock+{+  /** Pointer to callback function */+  TMR_ReadListener listener;+  /** Value to pass to callback function */+  void *cookie;+  /** @private */+  struct TMR_ReadListenerBlock *next;+} TMR_ReadListenerBlock;++/** Type of functions to be registered as tagauth request callbacks + * @param reader  Reader object+ * @param trd  TagReadData object+ * @param cookie  Arbitrary data structure to be passed to callback+ * @param auth  [OUTPUT] Tag authentication value to initialize based on inputs+ */+typedef void (*TMR_AuthReqListener)(TMR_Reader *reader, const TMR_TagReadData *trd,+									void *cookie, TMR_TagAuthentication *auth);+/**+ * User-allocated structure containing the callback pointer and the+ * value to pass to that callback.+ */+typedef struct TMR_AuthReqListenerBlock+{+  /** Pointer to callback function */+  TMR_AuthReqListener listener;+  /** Value to pass to callback function */+  void *cookie;+  /** @private */+  struct TMR_AuthReqListenerBlock *next;+} TMR_AuthReqListenerBlock;++/** Type of functions to be registered as read error callbacks */+typedef void (*TMR_ReadExceptionListener)(TMR_Reader *reader, TMR_Status error, void *cookie);+/**+ * User-allocated structure containing the callback pointer and the+ * value to pass to that callback.+ */+typedef struct TMR_ReadExceptionListenerBlock+{+  /** Pointer to callback function */+  TMR_ReadExceptionListener listener;+  /** Value to pass to callback function */+  void *cookie;+  /** @private */+  struct TMR_ReadExceptionListenerBlock *next;+} TMR_ReadExceptionListenerBlock;++/** Type of functions to be registered as transport callbacks */+typedef void (*TMR_TransportListener) (bool tx, uint32_t dataLen,+                                       const uint8_t data[], uint32_t timeout,+                                       void *cookie);+/**+ * User-allocated structure containing the callback pointer and the+ * value to pass to that callback.+ */+typedef struct TMR_TransportListenerBlock+{+  /** Pointer to callback function */+  TMR_TransportListener listener;+  /** Value to pass to callback function */+  void *cookie;+  /** @private */+  struct TMR_TransportListenerBlock *next;+} TMR_TransportListenerBlock;++/** Type of functions to be registered as Status read callbacks */+typedef void (*TMR_StatsListener)(TMR_Reader *reader, const TMR_Reader_StatsValues* value,+                                void *cookie);+typedef void (*TMR_StatusListener)(TMR_Reader *reader, const TMR_SR_StatusReport report[],+                                 void *cookie);+/**+ * User-allocated structure containing the callback pointer and the+ * value to pass to that callback.+ */+typedef struct TMR_StatsListenerBlock+{+  /** Pointer to callback function */+  TMR_StatsListener listener;+  /** Value to pass to callback function */+  void *cookie;+  /** @private */+  struct TMR_StatsListenerBlock *next;+} TMR_StatsListenerBlock;++/**+ * User-allocated structure containing the callback pointer and the+ * value to pass to that callback.+ */+typedef struct TMR_StatusListenerBlock+{+  /** Pointer to callback function */+  TMR_StatusListener listener;+  /** Value to pass to callback function */+  void *cookie;+  /** @private */+  struct TMR_StatusListenerBlock *next;+} TMR_StatusListenerBlock;++/**+ * Private: should not be used by user level application.+ */+typedef struct TMR_Queue_tagReads+{+  union+  {+    /* Buffer to hold serial message response */+    uint8_t *sMsg;+#ifdef TMR_ENABLE_LLRP_READER+    /* Buffer to hold LLRP message response */+    LLRP_tSMessage *lMsg;+#endif+  } tagEntry;++  uint8_t bufPointer;+  /* Object to hold tag results */+  TMR_TagReadData trd;+  bool isStatusResponse;+  struct TMR_Queue_tagReads  *next;+}TMR_Queue_tagReads;++typedef TMR_SR_GEN2_QType TMR_GEN2_QType;+typedef TMR_SR_GEN2_QStatic TMR_GEN2_QStatic;+typedef TMR_SR_GEN2_Q TMR_GEN2_Q;++/**+ * @defgroup reader Reader+ *+ * TMR_Reader encapsulates a connection to a ThingMagic RFID reader+ * device and provides an interface to perform RFID operations such as+ * reading tags and writing tag IDs.  + *+ * Reads can be done on demand, with the TMR_read() function, or+ * continuously in the background with the TMR_startReading()+ * function.  Background reads notify registered listeners of tags+ * that are read.+ *+ * Operations which take an argument for a tag to operate on may+ * optionally be passed a @c NULL argument. This lets the reader choose+ * what tag to use, but may not work if multiple tags are+ * present. This use is recommended only when exactly one tag is known+ * to be in range.+ */++/**+ * @ingroup reader+ * @struct TMR_Reader+ * + * The structure that represents a RFID reader. The user should+ * allocate a TMR_Reader structure and initialize it with+ * TMR_create().+ */+struct TMR_Reader+{+  /** @privatesection */++  enum TMR_ReaderType readerType;+  bool connected;+  TMR_TransportListenerBlock *transportListeners;++  TMR_readParams readParams;+  TMR_tagOpParams tagOpParams;+  char uri[TMR_MAX_READER_NAME_LENGTH];+  +  bool continuousReading;+  bool trueAsyncflag;+  bool searchStatus;+  /* Statistics response indicator */+  bool isStatusResponse;+  /* Option for Fast Search */+  bool fastSearch;+  /* Option for Trigger Read */+  bool triggerRead;+  /* Option for Duty cycle*/+  bool dutyCycle;+  /* Option for stop N tag trigger */+  bool isStopNTags;+  /* Param wait indicator for Reader and protocol param control during continuous read */+  bool paramWait;+  /* Param response for Reader and protocol param control during continuous read */+  uint8_t paramMessage[256];+  /* True Continuous Read Start indicator */+  bool hasContinuousReadStarted;+  /* Total tag count for sto N trigger */+  uint32_t numberOfTagsToRead;+  /* Does ResetStats feature work on this reader?+   * Unknown: NULL == pSupportsResetStats+   * Yes: (NULL != pSupportsResetStats) && (true == *pSupportsResetStats)+   * No: (NULL != pSupportsResetStats) && (false == *pSupportsResetStats)+   */+  bool* pSupportsResetStats/* = NULL*/;+  bool _storeSupportsResetStats;+  /* the option to request for background thread cancel */+  bool backgroundThreadCancel;++  union+  {+    TMR_SR_SerialReader serialReader;+    /*+     *TMR_RQL_RqlReader rqlReader;+     */+#ifdef TMR_ENABLE_LLRP_READER+    TMR_LLRP_LlrpReader llrpReader;+#endif+  }u;++#ifdef TMR_ENABLE_BACKGROUND_READS+  bool backgroundSetup, backgroundEnabled, backgroundRunning;+  bool parserSetup, parserEnabled, parserRunning;+#endif+  bool finishedReading;+#ifdef TMR_ENABLE_BACKGROUND_READS+  enum TMR_ReadState readState;+  unsigned int queue_depth;+  sem_t queue_slots, queue_length;+  pthread_mutex_t queue_lock;+  pthread_mutex_t backgroundLock;+  pthread_mutex_t parserLock;+  pthread_mutex_t listenerLock;  +  pthread_cond_t backgroundCond;+  pthread_cond_t parserCond;+  pthread_cond_t readCond;+  pthread_t backgroundReader;+  pthread_t backgroundParser;+  pthread_t autonomousBackgroundReader;+  TMR_AuthReqListenerBlock *authReqListeners;+#endif+  TMR_ReadListenerBlock *readListeners;+  TMR_ReadExceptionListenerBlock *readExceptionListeners;+  TMR_StatsListenerBlock *statsListeners;+#ifdef TMR_ENABLE_BACKGROUND_READS+  TMR_StatusListenerBlock *statusListeners;+  TMR_Queue_tagReads *tagQueueTail;+  TMR_Queue_tagReads *tagQueueHead;+#endif+  TMR_Reader_StatsFlag statsFlag;+  TMR_SR_StatusType streamStats;+  TMR_TRD_MetadataFlag userMetadataFlag;+  uint8_t portmask;+++  /* Level 1 */+#ifndef TMR_ENABLE_SERIAL_READER_ONLY+  TMR_Status (*connect)(struct TMR_Reader *reader);+  TMR_Status (*destroy)(struct TMR_Reader *reader);+  TMR_Status (*read)(struct TMR_Reader *reader, uint32_t timeoutMs, int32_t *tagCount);+  TMR_Status (*hasMoreTags)(struct TMR_Reader *reader);+  TMR_Status (*getNextTag)(struct TMR_Reader *reader, TMR_TagReadData *read);+  TMR_Status (*writeTag)(struct TMR_Reader *reader, const TMR_TagFilter *filter, const TMR_TagData *data);+#endif /* TMR_ENABLE_SERIAL_READER_ONLY  */+  TMR_Status (*paramGet)(struct TMR_Reader *reader, TMR_Param key, void *value);+  TMR_Status (*paramSet)(struct TMR_Reader *reader, TMR_Param key, const void *value);+  +  /* Level 2 */+#ifndef TMR_ENABLE_SERIAL_READER_ONLY+  TMR_Status (*killTag)(struct TMR_Reader *reader, const TMR_TagFilter *filter, const TMR_TagAuthentication *auth);+  TMR_Status (*lockTag)(struct TMR_Reader *reader, const TMR_TagFilter *filter, TMR_TagLockAction *action);+  TMR_Status (*executeTagOp)(struct TMR_Reader *reader, TMR_TagOp *tagop, TMR_TagFilter *filter, TMR_uint8List *data);+  TMR_Status (*readTagMemBytes)(struct TMR_Reader *reader, const TMR_TagFilter *filter, +                               uint32_t bank, uint32_t address,+                               uint16_t count, uint8_t data[]);+  TMR_Status (*readTagMemWords)(struct TMR_Reader *reader, const TMR_TagFilter *filter,+                               uint32_t bank, uint32_t address,+                               uint16_t count, uint16_t *data);+  TMR_Status (*writeTagMemBytes)(struct TMR_Reader *reader, const TMR_TagFilter *filter,+                               uint32_t bank, uint32_t address,+                               uint16_t count, const uint8_t data[]);+  TMR_Status (*writeTagMemWords)(struct TMR_Reader *reader, const TMR_TagFilter *filter,+                               uint32_t bank, uint32_t address,+                               uint16_t count, const uint16_t data[]);+  TMR_Status (*gpoSet)(struct TMR_Reader *reader, uint8_t count, const TMR_GpioPin state[]);+  TMR_Status (*gpiGet)(struct TMR_Reader *reader, uint8_t *count, TMR_GpioPin state[]);+  TMR_Status (*firmwareLoad)(TMR_Reader *reader, void *cookie, TMR_FirmwareDataProvider provider);+  TMR_Status (*modifyFlash) (TMR_Reader *reader, uint8_t sector, uint32_t address, uint32_t password,+                             uint8_t length, const uint8_t data[], uint32_t offset);+  TMR_Status (*reboot) (TMR_Reader *reader);+#endif /* TMR_ENABLE_SERIAL_READER_ONLY  */++  /* Level 3 */+#ifdef TMR_ENABLE_BACKGROUND_READS+  TMR_Status (*cmdAutonomousReading)(struct TMR_Reader *reader, TMR_TagReadData *trd, TMR_Reader_StatsValues *stats);+#endif+  TMR_Status (*cmdStopReading)(struct TMR_Reader *reader);+};++/**+ * @ingroup reader+ * The TMR_Reader struct being initialized should be preallocated by+ * the user.  No memory is allocated during the initialization+ * process, and the reader is not contacted at this point.+ *+ * @param reader The TMR_Reader structure to initialize+ * @param deviceUri an identifier for the reader to connect to, with+ * a URI syntax. The scheme can be \c eapi for the embedded+ * module protocol, \c rql for the request query language, or+ * \c tmr to guess. The remainder of the URI identifies the+ * stream that the protocol will be spoken over, either a local host+ * serial port device or a TCP network port.+ * Example URIs are:+ *  - tmr://192.168.10.8/ - Reader at TCP/IP address 192.168.10.8, RQL assumed+ *  - rql://192.168.10.8/ - RQL reader at TCP/IP address 192.168.10.8+ *  - tmr:///dev/ttyS1    - reader on serial port /dev/ttyS1, EAPI (serial) assumed+ *  - eapi:///COM2        - EAPI (serial) reader on serial port COM2+ *  - llrp+eapi://192.168.10.8 - EAPI tunneled over LLRP to a reader at+ * TCP/IP address 192.168.10.8+ *+ * @test Call with valid URI should not fail.+ * @test Call with invalid URI should fail.+ */+TMR_Status TMR_create(TMR_Reader *reader, const char* deviceUri);++ /**+ * @ingroup reader+  *+  * This function is a version of TMR_create() that dynamically+  * allocates the TMR_Reader structure and stores the pointer in+  * *reader.+  * +  * @param[out] readerPointer Pointer to the TMR_Reader* in which to place the+  * pointer to the newly allocated reader structure.+  @ @param deviceUri As described in TMR_create().+  *+  * @test Call with valid URI should not fail.+  * @test Call with invalid URI should fail.+  * @test Multiple calls with different URIs should return distinct objects.+  */+TMR_Status TMR_create_alloc(TMR_Reader **readerPointer, const char* deviceUri);+++/**+ * @ingroup reader+ * Establishes the connection to the reader at the URI specified in+ * the TMR_create() call. The existence of a reader at the address is+ * verified and the reader is brought into a state appropriate for+ * performing RF operations.+ *+ * @param reader The reader to connect + *+ * + * @test Connecting to existing reader should succeed.+ * @test Connecting to nonexisting reader should fail.+ */+TMR_Status TMR_connect(struct TMR_Reader *reader);++/**+ * @ingroup reader+ * Closes the connection to the reader and releases any resources+ * that have been consumed by the reader structure.+ *+ * @param reader The reader to shut down.+ *+ * @test Destroying existing connected reader should succed.+ * @test Destroying existing unconnected reader should succeed.+ * @test Destroying already-destroyed reader should fail.+ * @test Destroying reader allocated by TMR_create_alloc() should+ * free the allocated memory.+ */+TMR_Status TMR_destroy(TMR_Reader *reader);++/**+ * @ingroup reader+ * Search for tags for a fixed duration. Once this returns, the tags+ * are retrieved by calling TMR_getNextTag() until TMR_hasMoreTags()+ * returns false.+ *+ * @param reader The reader being operated on+ * @param timeoutMs The number of milliseconds to search for tags+ * @param[out] tagCount The number of tags read, or -1 if the number+ * is unknown. If NULL, no value will be stored.+ *+ * @test Call should fail if reader is not connected.+ * @test If call is successful as per TMR_Error, *tagCount should be+ * modified and contain a positive value.+ */+TMR_Status TMR_read(TMR_Reader *reader, uint32_t timeoutMs, int32_t *tagCount);++/**+ * @ingroup reader+ * @retval TMR_SUCCESS if there are more tags to be retrieved from the most recent TMR_read() operation.+ * @retval TMR_ERROR_NO_TAGS if no more tags are available for retrieval.+ * @retval Other TMR_ERRORs when appropriate.+ *+ * @param reader The reader being operated on+ * + * @test Call should return false before a read() call.+ * @test Call should return false after a read() call that set+ * *tagCount to zero.+ * @test Call should return true after a read() call that set+ * *tagCount to a nonzero value.+ * @test Call should return true through exactly as many getNextTag()+ * calls as specified by *tagCount.+ */+TMR_Status TMR_hasMoreTags(TMR_Reader *reader);++/**+ * @ingroup reader+ * Fetches the next tag from the last TMR_read() operation.+ *+ * @param reader The reader being operated on+ * @param[out] tagData The TMR_TagReadData structure to fill.+ * + * @test Call should fail before a read() call.+ * @test Call should fail after a read() call that set *tagCount to+ * zero.+ * @test Call should fill in a tag after a read() call that set+ * *tagCount to a nonzero value.+ * @test Call should succeed exactly as many times as specified by+ * *tagCount.+ */+TMR_Status TMR_getNextTag(TMR_Reader *reader, TMR_TagReadData *tagData);++/**+ * @ingroup reader+ * This method provides the direct execution of TagOp commands+ * Reader operates on the first tag found, with applicable tag filtering+ * Reader stops and the call returns immediately after finding one tag+ * and operating on it, unless the command timeout expires first+ * The operation is performed on the antenna specified in+ * /reader/tagop/antenna parameter+ * /reader/tagop/protocol specifies the protocol to be used+ *+ * @param reader The reader being operated on+ * @param tagop Pointer to the TMR_TagOp which needs to be executed+ * @param filter Tag Filter to be used+ * @param[out] data Data returned as a result of tag operation+ */+TMR_Status TMR_executeTagOp(struct TMR_Reader *reader, TMR_TagOp *tagop, TMR_TagFilter *filter, TMR_uint8List *data);++/**+ * @ingroup reader+ * Wrapper routine that searches for tags, allocates space for the+ * results, and returns the results in a single array.+ * + * @param reader The reader being operated on+ * @param timeoutMs The number of milliseconds to search for tags+ * @param[out] tagCount The number of tags found and the size of the allocated array.+ * @param[out] result The array of tag read data.+ *+ * @test Call should fail if reader is not connected.+ * @test If call is successful as per TMR_Error, *tagCount should be+ * modified and contain a positive value, and *result should be+ * modified and contain the corresponding number of tag read values.+ *+ * Out param "result" should be freed after using it.+ */++TMR_Status TMR_readIntoArray(struct TMR_Reader *reader, uint32_t timeoutMs, int32_t *tagCount, TMR_TagReadData *result[]);++/**+ * @deprecated This method is deprecated + *+ * Write a new EPC to an existing tag.  + * + * The @c /reader/tagop/antenna parameter controls which antenna will+ * be used for the write operation. The @c /reader/tagop/protocol+ * parameter controls which protocol will be used.+ * + * @param reader The reader being operated on+ * @param target The existing tag to write.+ * @param data The EPC to write to the tag+ * @note target is not supported on serial or Astra readers and only+ * TagData filters are supported on other fixed readers.+ *+ * @return TMR_ERROR_NO_TAG_FOUND if no tag matching the filter could be found.+ *+ * @test Call should fail if reader is not connected.+ * @test Upon success, a subsequent TMR_read() should find the new tag ID.+ */+TMR_Status TMR_writeTag(TMR_Reader *reader, const TMR_TagFilter *target, TMR_TagData *data);++/**+ * @deprecated This method is deprecated+ *+ * Sends a kill command to a tag.+ *+ * @param reader The reader being operated on.+ * @param target The tag to kill, or @c NULL to kill the first tag seen.+ * @param auth The authentication needed to kill the tag.+ *+ * @return TMR_ERROR_NO_TAG_FOUND if no tag matching the filter could be found.+ */+TMR_Status TMR_killTag(TMR_Reader *reader, TMR_TagFilter *target, TMR_TagAuthentication *auth);+++/**+ * @deprecated This method is deprecated+ *+ * Sends a lock command to a tag.+ *+ * @param reader The reader being operated on.+ * @param target The tag to kill, or @c NULL to kill the first tag seen.+ * @param action The locking action to apply.+ *+ * @return TMR_ERROR_NO_TAG_FOUND if no tag matching the filter could be found.+ */+TMR_Status TMR_lockTag(TMR_Reader *reader, TMR_TagFilter *target, TMR_TagLockAction *action);+++/**+ * @ingroup reader+ * Read 8-bit bytes from the memory bank of a tag.+ *+ * @param reader The reader being operated on.+ * @param target The tag to read from, or @c NULL.+ * @param bank The tag memory bank to read from.+ * @param byteAddress The byte address to start reading at.+ * @param byteCount The number of bytes to read+ * @param[out] data The read data.+ */+TMR_Status TMR_readTagMemBytes(TMR_Reader *reader, TMR_TagFilter *target, +                               uint32_t bank, uint32_t byteAddress, +                               uint16_t byteCount, uint8_t data[]);++/**+ * @ingroup reader+ * Read 16-bit words from the memory bank of a tag.+ *+ * @param reader The reader being operated on.+ * @param target The tag to read from, or @c NULL.+ * @param bank The tag memory bank to read from.+ * @param wordAddress The word address to start reading at.+ * @param wordCount The number of words to read+ * @param[out] data The read data.+ */+TMR_Status TMR_readTagMemWords(TMR_Reader *reader, TMR_TagFilter *target, +                               uint32_t bank, uint32_t wordAddress, +                               uint16_t wordCount, uint16_t data[]);++/**+ * @deprecated This method is deprecated+ *+ * Write 8-bit bytes to the memory bank of a tag. If the tag's+ * fundamental memory unit is larger than 8 bits, trying to write+ * sub-unit quantities will produce an error.+ *+ * @param reader The reader to operate on.+ * @param target The tag to write to, or @c NULL.+ * @param bank The tag memory bank to write to.+ * @param byteAddress The byte address to start writing to.+ * @param byteCount The number of bytes to write.+ * @param data The bytes to write.+ */+TMR_Status TMR_writeTagMemBytes(TMR_Reader *reader, TMR_TagFilter *target,+                                uint32_t bank, uint32_t byteAddress,+                                uint16_t byteCount, const uint8_t data[]);++/**+ * @deprecated This method is deprecated+ *+ * Write 16-bit words to the memory bank of a tag. If the tag's+ * fundamental memory unit is larger than 16 bits, trying to write+ * sub-unit quantities will produce an error.+ *+ * @param reader The reader to operate on.+ * @param target The tag to write to, or @c NULL.+ * @param bank The tag memory bank to write to.+ * @param wordAddress The word address to start writing to.+ * @param wordCount The number of words to write.+ * @param data The words to write.+ */+TMR_Status TMR_writeTagMemWords(TMR_Reader *reader, TMR_TagFilter *target,+                                uint32_t bank, uint32_t wordAddress,+                                uint16_t wordCount, const uint16_t data[]);+++/**+ * @ingroup reader+ * Set the state of some GPO pins.+ *+ * @param reader The reader to operate on.+ * @param count The length of the state array.+ * @param state Array of reader pins and the state to set them to.+ */+TMR_Status TMR_gpoSet(TMR_Reader *reader, uint8_t count, const TMR_GpioPin state[]);++/**+ * @ingroup reader+ * Get the state of all GPI pins.+ *+ * @param reader The reader to operate on.+ * @param[in] count Pointer to the allocated length of the state array.+ * @param[out] count Pointer to the number of entries in the state array.+ * @param[out] state Array of reader pins and the state to set them to.+ */+TMR_Status TMR_gpiGet(TMR_Reader *reader, uint8_t *count, TMR_GpioPin state[]);++/**+ * @ingroup reader+ * The TMR_firmwareLoad() method attempts to install firmware on the+ * reader, then restart and reinitialize.+ * + * @param reader The reader to operate on+ * @param cookie Value to pass to the callback function.+ * @param provider Callback function to provide firmware data.+ */+TMR_Status TMR_firmwareLoad(TMR_Reader *reader, void *cookie, TMR_FirmwareDataProvider provider);++/**+ * Cookie for state storage of a TMR_memoryProvider.+ */+typedef struct TMR_memoryCookie {+  /** Pointer to the start of the firmware image in memory */+  uint8_t *firmwareStart;+  /** Size of the firmware image */+  uint32_t firmwareSize;+} TMR_memoryCookie;++/**+ * This function can be used as a callback to TMR_firmwareLoad when+ * the firmware image exists in system memory. The cookie is a pointer+ * to a TMR_memoryCookie that is initialized with the start of the firmware+ * image in memory and its size.+ *+ * @param cookie TMR_memoryCookie value.+ * @param[in] size The number of bytes requested.+ * @param[out] size The number of bytes returned.+ * @param data Pointer to buffer to fill.+ * @return true if there is more firmware data to return.+ */+bool TMR_memoryProvider(void *cookie, uint16_t *size, uint8_t *data);++/**+ * This function can be used as a callback to TMR_firmwareLoad when+ * the firmware image exists as a file. + *+ * @param cookie FILE * pointing to the file to read from.+ * @param[in] size The number of bytes requested.+ * @param[out] size The number of bytes returned.+ * @param data Pointer to buffer to fill.+ * @return true if there is more firmware data to return.+ */+bool TMR_fileProvider(void *cookie, uint16_t *size, uint8_t *data);++/**+ * @ingroup reader+ * Set the value of a reader parameter.+ * + * @param reader The reader to operate on.+ * @param key The string identifying the parameter.+ * @param value The new value to use for the parameter. The caller may+ * not alter the value after passing it to this function.+ *+ * @test Call should fail if key is an invalid parameter name.+ * @test Call should fail if key is valid but unsupported by connected reader.+ * @test Call should succeed if key matches parameter name, independent of case.+ */+TMR_Status TMR_paramSet(struct TMR_Reader *reader, TMR_Param key, const void *value);++/**+ * @ingroup reader+ * Get the value of a reader parameter.+ *+ * @param reader The reader to operate on.+ * @param key The string identifying the parameter.++ * @param[out] value Pointer to the parameter value. For list types+ * (including TMR_String), the caller must allocate the pointed-to+ * space and set the size of the allocated space in the max field, and+ * the function will write into that space and set the actual length+ * of the data. If the list or string is larger than will fit in the+ * pointed-to space, the length will be larger than the allocated+ * space - be careful iterating over the results if there is a chance+ * of not passing in a large enough structure.+ *+ * @test Call should fail if key is an invalid parameter name.+ * @test Call should fail if key is valid but unsupported by connected reader.+ * @test Call should succeed if key matches parameter name, independent of case.+ */+TMR_Status TMR_paramGet(struct TMR_Reader *reader, TMR_Param key, void *value);++/**+ * @ingroup reader+ * Reboot the reader+ *+ * @param reader The reader to operate on.+ **/ +TMR_Status TMR_reboot(struct TMR_Reader *reader);++/**+ * Get a list of the parameters available+ *+ * Supported Parameters:+ * @li /reader/antenna/checkPort+ * @li /reader/antenna/connectedPortList+ * @li /reader/antenna/portList+ * @li /reader/antenna/portSwitchGpos+ * @li /reader/antenna/returnLoss+ * @li /reader/antenna/settlingTimeList+ * @li /reader/antenna/txRxMap+ * @li /reader/asyncofftime+ * @li /reader/baudRate+ * @li /reader/commandTimeout+ * @li /reader/currentTime+ * @li /reader/description+ * @li /reader/extendedEpc+ * @li /reader/gen2/BLF+ * @li /reader/gen2/accessPassword+ * @li /reader/gen2/bap+ * @li /reader/gen2/protocolExtension+ * @li /reader/gen2/q+ * @li /reader/gen2/session+ * @li /reader/gen2/tagEncoding+ * @li /reader/gen2/target+ * @li /reader/gen2/tari+ * @li /reader/gen2/writeEarlyExit+ * @li /reader/gen2/writeMode+ * @li /reader/gen2/writeReplyTimeout+ * @li /reader/gpio/inputList+ * @li /reader/gpio/outputList+ * @li /reader/hostname+ * @li /reader/iso180006b/BLF+ * @li /reader/iso180006b/delimiter+ * @li /reader/iso180006b/modulationDepth+ * @li /reader/licenseKey+ * @li /reader/licensedFeatures+ * @li /reader/metadataflags+ * @li /reader/powerMode+ * @li /reader/probeBaudRates+ * @li /reader/radio/enablePowerSave+ * @li /reader/radio/enableSJC+ * @li /reader/radio/portReadPowerList+ * @li /reader/radio/portWritePowerList+ * @li /reader/radio/powerMax+ * @li /reader/radio/powerMin+ * @li /reader/radio/readPower+ * @li /reader/radio/temperature+ * @li /reader/radio/writePower+ * @li /reader/read/asyncOffTime+ * @li /reader/read/asyncOnTime+ * @li /reader/read/plan+ * @li /reader/region/hopTable+ * @li /reader/region/hopTime+ * @li /reader/region/id+ * @li /reader/region/lbt/enable+ * @li /reader/region/supportedRegions+ * @li /reader/selectedProtocols+ * @li /reader/statistics+ * @li /reader/stats+ * @li /reader/stats/enable+ * @li /reader/status/antennaEnable+ * @li /reader/status/frequencyEnable+ * @li /reader/status/temperatureEnable+ * @li /reader/tagReadData/enableReadFilter+ * @li /reader/tagReadData/readFilterTimeout+ * @li /reader/tagReadData/recordHighestRssi+ * @li /reader/tagReadData/reportRssiInDbm+ * @li /reader/tagReadData/tagopFailures+ * @li /reader/tagReadData/tagopSuccesses+ * @li /reader/tagReadData/uniqueByAntenna+ * @li /reader/tagReadData/uniqueByData+ * @li /reader/tagReadData/uniqueByProtocol+ * @li /reader/tagop/antenna+ * @li /reader/tagop/protocol+ * @li /reader/transportTimeout+ * @li /reader/trigger/read/Gpi+ * @li /reader/uri+ * @li /reader/userConfig+ * @li /reader/userMode+ * @li /reader/version/hardware+ * @li /reader/version/model+ * @li /reader/version/productGroup+ * @li /reader/version/productGroupID+ * @li /reader/version/productID+ * @li /reader/version/serial+ * @li /reader/version/software+ * @li /reader/version/supportedProtocols+ *+ * @ingroup reader+ *+ * @param reader The reader to operate on.+ * @param[out] keys Pointer to the list of parameters. The caller must+ * allocate space for the parameters.+ * @param[in] len Pointer to the allocated length of the space pointed to by keys.+ * @param[out] len Pointer to the number of parameters supported by+ * the reader, which may be larger or smaller than the provided+ * array. If it is larger than the provided array, the list is+ * truncated.+ */+TMR_Status TMR_paramList(struct TMR_Reader *reader, TMR_Param *keys, uint32_t *len);+/**+ * @reader pointer to TMR_Reader+ * @key pointer to TMR_Param+ */ +void TMR_paramProbe (struct TMR_Reader *reader, TMR_Param key);++/**+ * @ingroup reader+ * Return the string name corresponding to a TMR_Param value.+ * Only present if TMR_ENABLE_PARAM_STRINGS is set.+ *+ * @param key The parameter ID.+ * @return The corresponding string name.+ */+const char* TMR_paramName(TMR_Param key);++/**+ * @ingroup reader+ * Return the TMR_Param ID corresponding to a string name.+ * Only present if TMR_ENABLE_PARAM_STRINGS is set.+ *+ * @param name the parameter + * @return The TMR_Param value of the name, or TMR_PARAM_NONE if no such+ * parameter exists.+ */+TMR_Param TMR_paramID(const char *name);+++/**+ * @ingroup reader+ * + * Add a listener to the list of functions that will be called for+ * each message sent to or received from the reader.+ *+ * @param reader The reader to operate on.+ * @param block A structure containing a pointer to the listener+ * function and a user-supplied cookie value to pass to the function+ * when called.+ */+TMR_Status TMR_addTransportListener(TMR_Reader *reader, TMR_TransportListenerBlock *block);+++/**+ * @ingroup reader+ * + * Remove a listener from the list of functions that will be called+ * for each message sent to or received from the reader.+ *+ * @param reader The reader to operate on.+ * @param block A structure containing a pointer to the listener+ * function and a user-supplied cookie value to pass to the function+ * when called.+ */+TMR_Status TMR_removeTransportListener(TMR_Reader *reader, TMR_TransportListenerBlock *block);++/**+ * @ingroup reader+ * Add a listener to the list of functions that will be called for+ * each background tag read.+ *+ * @param reader The reader to operate on.+ * @param block A structure containing a pointer to the listener+ * function and a user-supplied cookie value to pass to the function+ * when called.+ */+TMR_Status TMR_addReadListener(struct TMR_Reader *reader,+                               TMR_ReadListenerBlock *block);++/**+ * @ingroup reader+ * Add a listener to the list of functions that will be called for+ * each background tag read.+ *+ * @param reader The reader to operate on.+ * @param block A structure containing a pointer to the listener+ * function and a user-supplied cookie value to pass to the function+ * when called.+ */+TMR_Status TMR_addAuthReqListener(struct TMR_Reader *reader,+                                  TMR_AuthReqListenerBlock *block);++/**+ * @ingroup reader+ * Remove a listener from the list of functions that will be called+ * for each background tag read.+ *+ * @param reader The reader to operate on.+ * @param block A structure containing a pointer to the listener+ * function and a user-supplied cookie value to pass to the function+ * when called.+ */+TMR_Status TMR_removeReadListener(struct TMR_Reader *reader,+                                  TMR_ReadListenerBlock *block);++/**+ * @ingroup reader+ * Add a listener to the list of functions that will be called for+ * each error that occurs during background tag reading.+ *+ * @param reader The reader to operate on.+ * @param block A structure containing a pointer to the listener+ * function and a user-supplied cookie value to pass to the function+ * when called.+ */+TMR_Status TMR_addReadExceptionListener(struct TMR_Reader *reader,+                                        TMR_ReadExceptionListenerBlock *block);++/**+ * @ingroup reader+ * Remove a listener from the list of functions that will be called+ * for each error that occurs during background tag reading.+ *+ * @param reader The reader to operate on.+ * @param block A structure containing a pointer to the listener+ * function and a user-supplied cookie value to pass to the function+ * when called.+ */+TMR_Status TMR_removeReadExceptionListener(struct TMR_Reader *reader,+                                           TMR_ReadExceptionListenerBlock *block);++/**+ * @ingroup reader+ * Add a listener to the list of functions that will be called for+ * each background status response.+ *+ * @param reader The reader to operate on.+ * @param block A structure containing a pointer to the listener+ * function and a user-supplied cookie value to pass to the function+ * when called.+ */+TMR_Status TMR_addStatusListener(struct TMR_Reader *reader,+                               TMR_StatusListenerBlock *block);++/**+ * @ingroup reader+ * Remove a listener from the list of functions that will be called+ * for each background status response.+ *+ * @param reader The reader to operate on.+ * @param block A structure containing a pointer to the listener+ * function and a user-supplied cookie value to pass to the function+ * when called.+ */+TMR_Status TMR_removeStatusListener(struct TMR_Reader *reader,+                                  TMR_StatusListenerBlock *block);+++/**+ * @ingroup reader+ * Add a listener to the list of functions that will be called for+ * each background status response.+ *+ * @param reader The reader to operate on.+ * @param block A structure containing a pointer to the listener+ * function and a user-supplied cookie value to pass to the function+ * when called.+ */+TMR_Status TMR_addStatsListener(struct TMR_Reader *reader,+                               TMR_StatsListenerBlock *block);++/**+ * @ingroup reader+ * Remove a listener from the list of functions that will be called+ * for each background status response.+ *+ * @param reader The reader to operate on.+ * @param block A structure containing a pointer to the listener+ * function and a user-supplied cookie value to pass to the function+ * when called.+ */+TMR_Status TMR_removeStatsListener(struct TMR_Reader *reader,+                                  TMR_StatsListenerBlock *block);+++/**+ * @ingroup reader+ * Start reading tags in the background. The tags found will be passed+ * to the registered read listeners, and any errors that occur during+ * reading will be passed to the registered exception+ * listeners. Reading will continue until stopReading() is called.+ * The read listeners will be called from a background thread.+ *+ * @param reader The reader to operate on.+ */++TMR_Status TMR_startReading(struct TMR_Reader *reader);+TMR_Status TMR_receiveAutonomousReading(struct TMR_Reader *reader, TMR_TagReadData *trd, TMR_Reader_StatsValues *stats);+/**+ * @ingroup reader+ * Stop reading tags in the background. This function will wait until+ * the reader has stopped.+ *+ * @param reader The reader to operate on.+ */+TMR_Status TMR_stopReading(struct TMR_Reader *reader);++/**+ * @ingroup reader+ * Stores the transport init function against the provided scheme.+ *+ * @param scheme the transport scheme name.+ * @param nativeInit reference to the init function.+ */ +TMR_Status TMR_setSerialTransport(char* scheme, TMR_TransportNativeInit nativeInit);++/**+ * @ingroup reader+ * This function will convert the error codes into proper error messages.+ *+ * @param reader The reader which resulted in error+ * @param status The status code which is to be converted+ */+const char *TMR_strerr(TMR_Reader *reader, TMR_Status status);++/**+ * @ingroup reader+ * This function will initialize the+ * TMR_StatValues structure with the default values+ */+TMR_Status TMR_STATS_init(TMR_Reader_StatsValues *stats);++/**+ * @ingroup reader+ * This function loads the reader configuration parameters from file and applies to module.+ *+ * @param reader The reader to operate on.+ * @param filePath load reader configurations from filepath.+ */+TMR_Status TMR_loadConfig(struct TMR_Reader *reader, char *filePath);++/**+ * @ingroup reader+ * This function saves the current reader configuration parameters and its values to a file.+ *+ * @param reader The reader to operate on.+ * @param filePath  save reader configurations from filepath.+ */+TMR_Status TMR_saveConfig(struct TMR_Reader *reader, char *filePath);++#ifndef DOXYGEN_IGNORE++TMR_Status TMR_reader_init_internal(struct TMR_Reader *reader);+/*TMR_Status TMR_init_statusListenerBlock(TMR_StatusListenerBlock *slb, TMR_StatusListener listener,+                                        void *cookie, TMR_SR_StatusContentFlags statusFlags);*/+TMR_Status validateReadPlan(TMR_Reader *reader, TMR_ReadPlan *plan, TMR_AntennaMapList *txRxMap, uint32_t protocols);++void TMR__notifyTransportListeners(TMR_Reader *reader, bool tx, +                                   uint32_t dataLen, uint8_t *data,+                                   int timeout);++void notify_exception_listeners(TMR_Reader *reader, TMR_Status status);+void cleanup_background_threads(TMR_Reader *reader);++#ifdef TMR_ENABLE_SERIAL_READER_ONLY++#define TMR_connect(reader) (TMR_SR_connect(reader))+#define TMR_destroy(reader) (TMR_SR_destroy(reader))+#define TMR_read(reader, timeoutMs, tagCount) (TMR_SR_read((reader),(timeoutMs),(tagCount)))+#define TMR_hasMoreTags(reader) (TMR_SR_hasMoreTags(reader))+#define TMR_getNextTag(reader, read) (TMR_SR_getNextTag((reader),(read)))+#define TMR_writeTag(reader, filter, data) (TMR_SR_writeTag((reader),(filter),(data)))+#define TMR_readTagMemWords(reader, target, bank, address, count, data) (TMR_SR_readTagMemWords((reader),(target),(bank),(address),(count),(data)))+#define TMR_readTagMemBytes(reader, target, bank, address, count, data) (TMR_SR_readTagMemBytes((reader),(target),(bank),(address),(count),(data)))+#define TMR_writeTagMemWords(reader, target, bank, address, count, data) (TMR_SR_writeTagMemWords((reader),(target),(bank),(address),(count),(data)))+#define TMR_writeTagMemBytes(reader, target, bank, address, count, data) (TMR_SR_writeTagMemBytes((reader),(target),(bank),(address),(count),(data)))+#define TMR_killTag(reader, filter, auth) (TMR_SR_killTag((reader),(filter),(auth)))+#define TMR_lockTag(reader, filter, action) (TMR_SR_lockTag((reader),(filter),(action)))+#define TMR_executeTagOp(reader, tagop, filter, data) (TMR_SR_executeTagOp((reader), (tagop), (filter), (data)))+#define TMR_gpoSet(reader, count, state) (TMR_SR_gpoSet((reader),(count),(state)))+#define TMR_gpiGet(reader, count, state) (TMR_SR_gpiGet((reader),(count),(state)))+#define TMR_firmwareLoad(reader, cookie, provider) (TMR_SR_firmwareLoad((reader),(cookie),(provider)))+#define TMR_reboot(reader) (TMR_SR_reboot((reader)))++#else+/** + * The fact that these functions are implemented via macros is an+ * implementation detail, not something for the public API+ * documentation.+ */+#define TMR_connect(reader) ((reader)->connect(reader))+#define TMR_destroy(reader) ((reader)->destroy(reader))+#define TMR_read(reader, timeoutMs, tagCount) ((reader)->read((reader),(timeoutMs),(tagCount)))+#define TMR_hasMoreTags(reader) ((reader)->hasMoreTags(reader))+#define TMR_getNextTag(reader, read) ((reader)->getNextTag((reader),(read)))+#define TMR_writeTag(reader, filter, data) ((reader)->writeTag((reader),(filter),(data)))+#define TMR_readTagMemWords(reader, target, bank, address, count, data) ((reader)->readTagMemWords((reader),(target),(bank),(address),(count),(data)))+#define TMR_readTagMemBytes(reader, target, bank, address, count, data) ((reader)->readTagMemBytes((reader),(target),(bank),(address),(count),(data)))+#define TMR_writeTagMemWords(reader, target, bank, address, count, data) ((reader)->writeTagMemWords((reader),(target),(bank),(address),(count),(data)))+#define TMR_writeTagMemBytes(reader, target, bank, address, count, data) ((reader)->writeTagMemBytes((reader),(target),(bank),(address),(count),(data)))+#define TMR_killTag(reader, filter, auth) ((reader)->killTag((reader),(filter),(auth)))+#define TMR_lockTag(reader, filter, action) ((reader)->lockTag((reader),(filter),(action)))+#define TMR_executeTagOp(reader, tagop, filter, data) ((reader)->executeTagOp((reader), (tagop), (filter), (data)))+#define TMR_gpoSet(reader, count, state) ((reader)->gpoSet((reader),(count),(state)))+#define TMR_gpiGet(reader, count, state) ((reader)->gpiGet((reader),(count),(state)))+#define TMR_firmwareLoad(reader, cookie, provider) ((reader)->firmwareLoad((reader),(cookie),(provider)))+#define TMR_modifyFlash(reader, sector, address, password, length, data, offset)  ((reader->modifyFlash((reader),(sector),(address),(password),(length),(data),(offset)))+#define TMR_reboot(reader) ((reader)->reboot(reader))+#endif /* TMR_ENABLE_SERIAL_READER_ONLY  */++#endif /* DOXYGEN_IGNORE */++#ifdef  __cplusplus+}+#endif++#endif /* _TM_READER_H_ */
+ cbits/api/tm_reader_async.c view
@@ -0,0 +1,1599 @@+/**+ *  @file tm_reader_async.c+ *  @brief Mercury API - background reading implementation+ *  @author Nathan Williams+ *  @date 11/18/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 "tm_config.h"+#include "tm_reader.h"+#include "serial_reader_imp.h"+#include <stdio.h>++bool IsDutyCycleEnabled(TMR_Reader *reader);+TMR_Status restart_reading(struct TMR_Reader *reader);+#ifdef TMR_ENABLE_BACKGROUND_READS++#include <stdlib.h>+#include <pthread.h>+#include <semaphore.h>+#include <time.h>+#include <stdio.h>+#include <string.h>++#ifndef WIN32+#include <sys/time.h>+#endif++#ifdef TMR_ENABLE_LLRP_READER+#include "llrp_reader_imp.h"+#endif+#include "osdep.h"+#include "tmr_utils.h"++static void *do_background_reads(void *arg);+static void *parse_tag_reads(void *arg);+static void process_async_response(TMR_Reader *reader);+bool isBufferOverFlow = false;+#endif /* TMR_ENABLE_BACKGROUND_READS */++TMR_Status+TMR_startReading(struct TMR_Reader *reader)+{+#ifdef SINGLE_THREAD_ASYNC_READ+  TMR_Status ret;+  uint32_t ontime;+  +  TMR_paramGet(reader, TMR_PARAM_READ_ASYNCONTIME, &ontime);+  reader->continuousReading = true; +  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_MICRO == reader->u.serialReader.versionInfo.hardware[0]) ||+	(TMR_SR_MODEL_M6E_NANO == reader->u.serialReader.versionInfo.hardware[0])) &&+	(reader->readParams.asyncOffTime == 0 || (reader->readParams.asyncOffTime != 0 && IsDutyCycleEnabled(reader)) ) &&+	((TMR_READ_PLAN_TYPE_SIMPLE == reader->readParams.readPlan->type) ||+	((TMR_READ_PLAN_TYPE_MULTI == reader->readParams.readPlan->type)  &&+	(compareAntennas(&reader->readParams.readPlan->u.multi))))+	)+  {+	if (reader->readParams.asyncOffTime == 0)+	{+		reader->dutyCycle = false;+	}+	else+	{+		reader->dutyCycle = true;+	}+  }+  else+  {+	reader->dutyCycle = false;+  }+  ret = TMR_read(reader, ontime, NULL);+  if(TMR_SUCCESS != ret)+	return ret;+	 +#else+#ifdef TMR_ENABLE_BACKGROUND_READS+  int ret;+  bool createParser = true;++  if (TMR_READER_TYPE_SERIAL == reader->readerType)+  {+#ifdef TMR_ENABLE_SERIAL_READER+    /**+     * Currently we are not supporting stop N trigger for async read case.+     * This is also true for pseudo continuous case as well. Pop up the error+     * if user is trying to do so.+     **/+    if (TMR_READ_PLAN_TYPE_MULTI == reader->readParams.readPlan->type)+    {+      uint8_t loop = 0;+      TMR_MultiReadPlan *multi;++      multi = &reader->readParams.readPlan->u.multi;++      for (loop = 0; loop < multi->planCount; loop++)+      {+        if (multi->plans[loop]->u.simple.stopOnCount.stopNTriggerStatus)+        {+          /* Not supporting stop N trigger */+          return TMR_ERROR_UNSUPPORTED; +        }+      }+    }+    else if (TMR_READ_PLAN_TYPE_SIMPLE == reader->readParams.readPlan->type)+    {+      if (reader->readParams.readPlan->u.simple.stopOnCount.stopNTriggerStatus)+      {+        /* Not supporting stop N trigger */+        return TMR_ERROR_UNSUPPORTED;+      }+    }+    else+    {+      /* do nothing */+    }++    /**+	  * if model is M6e and it's varient+	  * asyncOffTime == 0+	  * only then use streaming+	  */+    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_MICRO == reader->u.serialReader.versionInfo.hardware[0]) ||+         (TMR_SR_MODEL_M6E_NANO == reader->u.serialReader.versionInfo.hardware[0])) &&+        (reader->readParams.asyncOffTime == 0 || (reader->readParams.asyncOffTime != 0 && IsDutyCycleEnabled(reader)) ) &&+        ((TMR_READ_PLAN_TYPE_SIMPLE == reader->readParams.readPlan->type) || +         ((TMR_READ_PLAN_TYPE_MULTI == reader->readParams.readPlan->type)  && +          (compareAntennas(&reader->readParams.readPlan->u.multi))))+       )+    {+		if (reader->readParams.asyncOffTime == 0)+		{+			reader->dutyCycle = false;+		}+		else+		{+			reader->dutyCycle = true;+		}+    }+    else+    {+      createParser = false;+	  reader->dutyCycle = false;+    }+#else+    return TMR_ERROR_UNSUPPORTED;+#endif/* TMR_ENABLE_SERIAL_READER */    +  }+#ifdef TMR_ENABLE_LLRP_READER+  if (TMR_READER_TYPE_LLRP == reader->readerType)+  {+    /**+     * In case of LLRP reader and continuous reading, disable the+     * LLRP background receiver.+     **/+    TMR_LLRP_setBackgroundReceiverState(reader, false);+    /**+     * Note the keepalive start time+     * Keepalive monitoring happens only +     * for async reads.+     **/+    reader->u.llrpReader.ka_start = tmr_gettime();+  }+#endif++  /**+   * Initialize read_started semaphore+   **/+  pthread_mutex_lock(&reader->backgroundLock);+  reader->readState = TMR_READ_STATE_STARTING;+  pthread_cond_broadcast(&reader->readCond);+  pthread_mutex_unlock(&reader->backgroundLock);++  if (true == createParser)+  {+    /** Background parser thread initialization+     *+     * Only M6e supports Streaming, and in case of other readers+     * we still use pseudo-async mechanism for continuous read.+     * To achieve continuous reading, create a parser thread+     */+    pthread_mutex_lock(&reader->parserLock);+    +    if (false == reader->parserSetup)+    {+      ret = pthread_create(&reader->backgroundParser, NULL,+                       parse_tag_reads, reader);+      if (0 != ret)+      {+        pthread_mutex_unlock(&reader->parserLock);+        return TMR_ERROR_NO_THREADS;+      }+      pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL);+      pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);+      pthread_detach(reader->backgroundParser);+    /** Initialize semaphores only for the first time+     *  These semaphores are used only in case of streaming+     */+      reader->queue_depth = 0;+      sem_init(&reader->queue_length, 0, 0);+      sem_init(&reader->queue_slots, 0, TMR_MAX_QUEUE_SLOTS);+      reader->parserSetup = true;+    }++    reader->parserEnabled = true;+++    /* Enable streaming */+    reader->continuousReading = true;+    reader->finishedReading = false;+    pthread_cond_signal(&reader->parserCond);+    pthread_mutex_unlock(&reader->parserLock);+  }++  /* Background reader thread initialization */+  pthread_mutex_lock(&reader->backgroundLock);++  if (false == reader->backgroundSetup)+  {+    ret = pthread_create(&reader->backgroundReader, NULL,+                         do_background_reads, reader);+    if (0 != ret)+    {+      pthread_mutex_unlock(&reader->backgroundLock);+      return TMR_ERROR_NO_THREADS;+    }+    pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL);+    pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);+    reader->backgroundSetup = true;+  }++  reader->backgroundEnabled = true;+  reader->searchStatus = true;++#ifdef TMR_ENABLE_SERIAL_READER    +  if (TMR_READER_TYPE_SERIAL == reader->readerType)+  {+    reader->u.serialReader.tagopFailureCount = 0;+    reader->u.serialReader.tagopSuccessCount = 0;+  }+#endif/* TMR_ENABLE_SERIAL_READER */    +  pthread_cond_signal(&reader->backgroundCond);+  pthread_mutex_unlock(&reader->backgroundLock);++  /* End of Background reader thread initialization */+  /**+   * Wait for the Background thread to send the read command.+   * This will prevent of adding extra sleep in the application+   * after TMR_startReading() call.+   **/ +  pthread_mutex_lock(&reader->backgroundLock);+  while (TMR_READ_STATE_STARTING == reader->readState)+  {+    pthread_cond_wait(&reader->readCond, &reader->backgroundLock);+  }+  pthread_mutex_unlock(&reader->backgroundLock);+#endif /* TMR_ENABLE_BACKGROUND_READS */+#endif++  return TMR_SUCCESS;+}++#if defined(TMR_ENABLE_BACKGROUND_READS)|| defined(SINGLE_THREAD_ASYNC_READ)+bool IsDutyCycleEnabled(struct TMR_Reader *reader)+{+	uint16_t i; +	uint8_t *readerVersion = reader->u.serialReader.versionInfo.fwVersion ;+	uint8_t checkVersion[4];+	switch (reader->u.serialReader.versionInfo.hardware[0])+	{+		case TMR_SR_MODEL_M6E:+		case TMR_SR_MODEL_M6E_I:+			checkVersion[0] = 0x01; checkVersion[1] = 0x21; checkVersion[2] = 0x01; checkVersion[3] = 0x07;+			break;+		case TMR_SR_MODEL_MICRO:+			checkVersion[0] = 0x01; checkVersion[1] = 0x09; checkVersion[2] = 0x00; checkVersion[3] = 0x02;+			break;+		case TMR_SR_MODEL_M6E_NANO:+			checkVersion[0] = 0x01; checkVersion[1] = 0x07; checkVersion[2] = 0x00; checkVersion[3] = 0x02;+			break;+		default:+			checkVersion[0] = 0xFF; checkVersion[1] = 0xFF; checkVersion[2] = 0xFF; checkVersion[3] = 0xFF;+	}+	for (i = 0; i < 4; i++)+	{+		if (readerVersion[i] < checkVersion[i])+			return false;+		else if (readerVersion[i] > checkVersion[i])+			return true;+	}+	return true;+}++#endif /* TMR_ENABLE_BACKGROUND_READS */++void+reset_continuous_reading(struct TMR_Reader *reader, bool dueToError)+{+  if (true == reader->continuousReading)+  {+#ifndef SINGLE_THREAD_ASYNC_READ+#ifdef TMR_ENABLE_LLRP_READER+    if (TMR_READER_TYPE_LLRP == reader->readerType)+    {+      /**+       * In case of LLRP reader, re-enable the+       * LLRP background receiver as continuous reading is finished+       **/+      TMR_LLRP_setBackgroundReceiverState(reader, true);+    }+#endif++#ifdef TMR_ENABLE_SERIAL_READER      +    if ((false == dueToError) && (TMR_READER_TYPE_SERIAL == reader->readerType))+    {+      /**+       * Disable filtering on module+       **/+      TMR_Status ret;+      bool value = reader->u.serialReader.enableReadFiltering;+	  reader->hasContinuousReadStarted = false;+      ret = TMR_SR_cmdSetReaderConfiguration(reader, TMR_SR_CONFIGURATION_ENABLE_READ_FILTER, &value);+      if (TMR_SUCCESS != ret)+      {+#ifndef BARE_METAL+        notify_exception_listeners(reader, ret);+#endif+      }+    }+#endif/* TMR_ENABLE_SERIAL_READER */      +#endif /*SINGLE_THREAD_ASYNC_READ*/+    /* disable streaming */+    reader->continuousReading = false;+  }+}++TMR_Status+TMR_stopReading(struct TMR_Reader *reader)+{+  reader->hasContinuousReadStarted = false;+#ifdef SINGLE_THREAD_ASYNC_READ+  reader->cmdStopReading(reader);+#else+#ifdef TMR_ENABLE_BACKGROUND_READS++  /* Check if background setup is active */+  pthread_mutex_lock(&reader->backgroundLock);++  if (false == reader->backgroundSetup)+  {+    pthread_mutex_unlock(&reader->backgroundLock);+    return TMR_SUCCESS;+  }++  if (false == reader->searchStatus)+  {+    /**+     * searchStatus is false, i.e., reading is already+     * stopped. Returen success.+     **/+    pthread_mutex_unlock(&reader->backgroundLock);+    return TMR_SUCCESS;+  }+  /**+   * Else, read is in progress. Set+   * searchStatus to false;+   **/+  reader->searchStatus = false;+  pthread_mutex_unlock(&reader->backgroundLock);++  /**+   * Wait until the reading has started+   **/+  pthread_mutex_lock(&reader->backgroundLock);+  while (TMR_READ_STATE_STARTING == reader->readState)+  {+    pthread_cond_wait(&reader->readCond, &reader->backgroundLock);+    }+  pthread_mutex_unlock(&reader->backgroundLock);++  if ((true == reader->continuousReading) && (true == reader->trueAsyncflag))+    {+      /**+     * In case of true continuous reading, we need to send+     * stop reading message immediately.+       **/+    if(!isBufferOverFlow)+    {+      reader->cmdStopReading(reader);+    }++    /**+     * Wait logic has been changed in case of continuous reading.+     * Wait while the background reader is still reading.+     **/+    pthread_mutex_lock(&reader->backgroundLock);+    while (TMR_READ_STATE_DONE != reader->readState)+    {+      pthread_cond_wait(&reader->readCond, &reader->backgroundLock);+    }+    pthread_mutex_unlock(&reader->backgroundLock);+    /**+     * By this time, reader->backgroundEnabled is+     * already set to false. i.e., background reader thread+     * is suspended.+     **/+  }++  /**+   * wait until background reader thread finishes.+   * This is needed for pseudo-async reads and also+   * worst case of continuous reading, when read isn't success+   **/+  pthread_mutex_lock(&reader->backgroundLock);+  reader->backgroundEnabled = false;+  while (true == reader->backgroundRunning)+  {+    pthread_cond_wait(&reader->backgroundCond, &reader->backgroundLock);+  }+  pthread_mutex_unlock(&reader->backgroundLock);++  /**+   * Reset continuous reading settings, so that+   * the subsequent startReading() call doesn't have+   * any surprises.+   **/+#else+	reader->cmdStopReading(reader);+#endif+  reset_continuous_reading(reader, false);+#endif+  return TMR_SUCCESS;+}++void+notify_read_listeners(TMR_Reader *reader, TMR_TagReadData *trd)+{+  TMR_ReadListenerBlock *rlb;++  /* notify tag read to listener */+  if (NULL != reader)+  {+#ifndef SINGLE_THREAD_ASYNC_READ+    pthread_mutex_lock(&reader->listenerLock);+#endif+	rlb = reader->readListeners;+    while (rlb)+    {+      rlb->listener(reader, trd, rlb->cookie);+      rlb = rlb->next;+    }+#ifndef SINGLE_THREAD_ASYNC_READ+    pthread_mutex_unlock(&reader->listenerLock);+#endif+  }+}++void+notify_stats_listeners(TMR_Reader *reader, TMR_Reader_StatsValues *stats)+{+  TMR_StatsListenerBlock *slb;++  /* notify stats to the listener */+#ifndef SINGLE_THREAD_ASYNC_READ+  pthread_mutex_lock(&reader->listenerLock);+#endif+  slb = reader->statsListeners;+  while (slb)+  {+    slb->listener(reader, stats, slb->cookie);+    slb = slb->next;+  }+#ifndef SINGLE_THREAD_ASYNC_READ+  pthread_mutex_unlock(&reader->listenerLock);+#endif+}+++TMR_Status restart_reading(struct TMR_Reader *reader)+{+	TMR_Status ret = TMR_SUCCESS;++	//Stop continuous reading+	ret = TMR_stopReading(reader);+	if(ret != TMR_SUCCESS)+	{+		return ret;+	}++	#ifdef SINGLE_THREAD_ASYNC_READ+	//Receive all tags from the previous reading+	{+		TMR_TagReadData trd;+		while(true)+		{+			ret = TMR_hasMoreTags(reader);+			if (TMR_SUCCESS == ret)+			{+				TMR_getNextTag(reader, &trd);+				notify_read_listeners(reader, &trd);+			}+			else if(ret == TMR_ERROR_END_OF_READING)+			break;+		}+	}+	#endif+	//Restart reading+	ret = TMR_startReading(reader);++	return ret;+}+++#ifdef TMR_ENABLE_BACKGROUND_READS+/* NOTE: There is only one auth object for all the authreq listeners, so whichever listener touches it last wins.+ * For now (2012 Jul 20) we only anticipate having a single authreq listener, but there may be future cases which + * require multiples.  Revise this design if necessary. */+void+notify_authreq_listeners(TMR_Reader *reader, TMR_TagReadData *trd, TMR_TagAuthentication *auth)+{+  TMR_AuthReqListenerBlock *arlb;++  /* notify tag read to listener */+  pthread_mutex_lock(&reader->listenerLock);+  arlb = reader->authReqListeners;+  while (arlb)+  {+    arlb->listener(reader, trd, arlb->cookie, auth);+    arlb = arlb->next;+  }+  pthread_mutex_unlock(&reader->listenerLock);+}+#endif /* TMR_ENABLE_BACKGROUND_READS */++TMR_Status+TMR_addReadExceptionListener(TMR_Reader *reader,+                             TMR_ReadExceptionListenerBlock *b)+{+#ifndef SINGLE_THREAD_ASYNC_READ+  if (0 != pthread_mutex_lock(&reader->listenerLock))+    return TMR_ERROR_TRYAGAIN;+#endif+  b->next = reader->readExceptionListeners;+  reader->readExceptionListeners = b;++#ifndef SINGLE_THREAD_ASYNC_READ+  pthread_mutex_unlock(&reader->listenerLock);+#endif+  return TMR_SUCCESS;+}++#ifdef TMR_ENABLE_BACKGROUND_READS+TMR_Status+TMR_removeReadExceptionListener(TMR_Reader *reader,+                                TMR_ReadExceptionListenerBlock *b)+{+  TMR_ReadExceptionListenerBlock *block, **prev;++  if (0 != pthread_mutex_lock(&reader->listenerLock))+    return TMR_ERROR_TRYAGAIN;++  prev = &reader->readExceptionListeners;+  block = reader->readExceptionListeners;+  while (NULL != block)+  {+    if (block == b)+    {+      *prev = block->next;+      break;+    }+    prev = &block->next;+    block = block->next;+  }++  pthread_mutex_unlock(&reader->listenerLock);++  if (block == NULL)+  {+    return TMR_ERROR_INVALID;+  }++  return TMR_SUCCESS;+}+#endif++void+notify_exception_listeners(TMR_Reader *reader, TMR_Status status)+{+  TMR_ReadExceptionListenerBlock *relb;++  if (NULL != reader)+  {+#ifndef SINGLE_THREAD_ASYNC_READ+    pthread_mutex_lock(&reader->listenerLock);+#endif+    relb = reader->readExceptionListeners;+    while (relb)+    {+      relb->listener(reader, status, relb->cookie);+      relb = relb->next;+    }+#ifndef SINGLE_THREAD_ASYNC_READ+    pthread_mutex_unlock(&reader->listenerLock);+#endif+  }+}++#ifdef TMR_ENABLE_BACKGROUND_READS+TMR_Queue_tagReads *+dequeue(TMR_Reader *reader)+{+  TMR_Queue_tagReads *tagRead = NULL;+  pthread_mutex_lock(&reader->queue_lock);+  if (NULL != reader->tagQueueHead)+  {+    /* Fetch the head always */+    tagRead = reader->tagQueueHead;+    reader->tagQueueHead = reader->tagQueueHead->next;+  }+  reader->queue_depth --;+  pthread_mutex_unlock(&reader->queue_lock);+  return(tagRead);+}+++void enqueue(TMR_Reader *reader, TMR_Queue_tagReads *tagRead)+{+  pthread_mutex_lock(&reader->queue_lock);+  if (NULL == reader->tagQueueHead)+  {+    /* first tag */+    reader->tagQueueHead = tagRead;+    reader->tagQueueHead->next = NULL;+    reader->tagQueueTail = reader->tagQueueHead;+  }+  else+  {+    reader->tagQueueTail->next = tagRead;+    reader->tagQueueTail = tagRead;+    tagRead->next = NULL;+  }+  reader->queue_depth ++;+  pthread_mutex_unlock(&reader->queue_lock);+}++static void *+parse_tag_reads(void *arg)+{+  TMR_Reader *reader;+  TMR_Queue_tagReads *tagRead;+  reader = arg;  ++  while (1)+  {+    pthread_mutex_lock(&reader->parserLock);+    reader->parserRunning = false;+    pthread_cond_broadcast(&reader->parserCond);+    while (false == reader->parserEnabled)+    {+      pthread_cond_wait(&reader->parserCond, &reader->parserLock);+    }++    reader->parserRunning = true;+    pthread_mutex_unlock(&reader->parserLock);++    /**+     * Wait until queue_length is more than zero,+     * i.e., Queue should have atleast one tagRead to process+     */+    sem_wait(&reader->queue_length);++    if (NULL != reader->tagQueueHead)+    {+      /**+       * At this point there is a tagEntry in the queue+       * dequeue it and parse it.+       */          +      tagRead = dequeue(reader);+      if (false == tagRead->isStatusResponse)+      {+        /* Tag Buffer stream response */++#ifdef TMR_ENABLE_SERIAL_READER          +        if (TMR_READER_TYPE_SERIAL == reader->readerType)+        {+          /**+          * For serial readers, the tags results are already processed+          * and placed in the queue. Just notify that to the listener.+          */+          notify_read_listeners(reader, &tagRead->trd);+        }+#endif/* TMR_ENABLE_SERIAL_READER */           +#ifdef TMR_ENABLE_LLRP_READER+        if (TMR_READER_TYPE_LLRP == reader->readerType)+        {+          /* Else it is LLRP message, parse it */+          LLRP_tSRO_ACCESS_REPORT *pReport;+          LLRP_tSTagReportData *pTagReportData;++          pReport = (LLRP_tSRO_ACCESS_REPORT *)tagRead->tagEntry.lMsg;++          for(pTagReportData = pReport->listTagReportData;+              NULL != pTagReportData;+              pTagReportData = (LLRP_tSTagReportData *)pTagReportData->hdr.pNextSubParameter)+          {+            TMR_TagReadData trd;++            TMR_TRD_init(&trd);+            TMR_LLRP_parseMetadataFromMessage(reader, &trd, pTagReportData);+          +            trd.reader = reader;+            notify_read_listeners(reader, &trd);+        }+        }+#endif+        }+      else+      {+       /* A status stream response */++        if (TMR_READER_TYPE_SERIAL == reader->readerType)+        {+          TMR_Reader_StatsValues stats;+          uint8_t offset, i,j;+          uint16_t flags = 0;                 ++          TMR_STATS_init(&stats);+          offset = tagRead->bufPointer;++          if (NULL != reader->statusListeners && NULL== reader->statsListeners)+          {+            /* A status stream response */+            TMR_StatusListenerBlock *slb;+            uint8_t index = 0, j;+            TMR_SR_StatusReport report[TMR_SR_STATUS_MAX];+++            /* Get status content flags */+            flags = GETU16(tagRead->tagEntry.sMsg, offset);++            if (0 != (flags & TMR_SR_STATUS_FREQUENCY))+            {+              report[index].type = TMR_SR_STATUS_FREQUENCY;+              report[index].u.fsr.freq = (uint32_t)(GETU24(tagRead->tagEntry.sMsg, offset));+              index ++;+            }+            if (0 != (flags & TMR_SR_STATUS_TEMPERATURE))+            {+              report[index].type = TMR_SR_STATUS_TEMPERATURE;+              report[index].u.tsr.temp = GETU8(tagRead->tagEntry.sMsg, offset);+              index ++;+            }+            if (0 != (flags & TMR_SR_STATUS_ANTENNA))+            {+              uint8_t tx, rx;+              report[index].type = TMR_SR_STATUS_ANTENNA;+              tx = GETU8(tagRead->tagEntry.sMsg, offset);+              rx = GETU8(tagRead->tagEntry.sMsg, offset);++              for (j = 0; j < reader->u.serialReader.txRxMap->len; j++)+              {+                if ((rx == reader->u.serialReader.txRxMap->list[j].rxPort) && (tx == reader->u.serialReader.txRxMap->list[j].txPort))+                {+                  report[index].u.asr.ant = reader->u.serialReader.txRxMap->list[j].antenna;+                  break;+                }+              }+              index ++;+            }++            report[index].type = TMR_SR_STATUS_NONE;+            /* notify status response to listener */+            pthread_mutex_lock(&reader->listenerLock);+            slb = reader->statusListeners;+            while (slb)+            {+              slb->listener(reader, report, slb->cookie);+              slb = slb->next;+            }+            pthread_mutex_unlock(&reader->listenerLock);++          }+          else if (NULL != reader->statsListeners && NULL== reader->statusListeners)+          {+            /* Get status content flags */+            if ((0x80) > reader->statsFlag)+            {+              offset += 1;+            }+            else+            {+              offset += 2;+            }++            /**+             * preinitialize the rf ontime and the noise floor value to zero+             * berfore getting the reader stats+             */+            for (i = 0; i < stats.perAntenna.max; i++)+            {+              stats.perAntenna.list[i].antenna = 0;+              stats.perAntenna.list[i].rfOnTime = 0;+              stats.perAntenna.list[i].noiseFloor = 0;+            }++            TMR_fillReaderStats(reader, &stats, flags, tagRead->tagEntry.sMsg, offset);++            /**+             * iterate through the per antenna values,+             * If found  any 0-antenna rows, copy the+             * later rows down to compact out the empty space.+             */+            for (i = 0; i < reader->u.serialReader.txRxMap->len; i++)+            {+              if (!stats.perAntenna.list[i].antenna)+              {+                for (j = i + 1; j < reader->u.serialReader.txRxMap->len; j++)+                {+                  if (stats.perAntenna.list[j].antenna)+                  {+                    stats.perAntenna.list[i].antenna = stats.perAntenna.list[j].antenna;+                    stats.perAntenna.list[i].rfOnTime = stats.perAntenna.list[j].rfOnTime;+                    stats.perAntenna.list[i].noiseFloor = stats.perAntenna.list[j].noiseFloor;+                    stats.perAntenna.list[j].antenna = 0;+                    stats.perAntenna.list[j].rfOnTime = 0;+                    stats.perAntenna.list[j].noiseFloor = 0;++                    stats.perAntenna.len++;+                    break;+                  }+                }+              }+              else+              {+                /* Increment the length */+                stats.perAntenna.len++;+              }+            }++            /* store the requested flags for future use */+            stats.valid = reader->statsFlag;++            /* notify status response to listener */+            notify_stats_listeners(reader, &stats);+          }+          else+          {+            /**+             * Control comes here when, user added both the listeners,+             * We should pop up error for that+             **/+            TMR_Status ret;+            ret = TMR_ERROR_UNSUPPORTED;+            notify_exception_listeners(reader, ret);+          }+        }+#ifdef TMR_ENABLE_LLRP_READER+        else+        {+          /**+           * TODO: Handle RFSurveyReports in case of+           * async read+           **/+        }+#endif+      }++      /* Free the memory */+      if (TMR_READER_TYPE_SERIAL == reader->readerType)+      {+      	free(tagRead->tagEntry.sMsg);+      }+#ifdef TMR_ENABLE_LLRP_READER+      else+      {+      	TMR_LLRP_freeMessage(tagRead->tagEntry.lMsg);+      }+#endif+      free(tagRead);++      /* Now, increment the queue_slots as we have removed one entry */+      sem_post(&reader->queue_slots);+    }+  }+  return NULL;+}+++static void+process_async_response(TMR_Reader *reader)+{+  TMR_Queue_tagReads *tagRead;+  uint16_t flags = 0;++  /* Decrement Queue slots */+  sem_wait(&reader->queue_slots);++  tagRead = (TMR_Queue_tagReads *) malloc(sizeof(TMR_Queue_tagReads));+  if (TMR_READER_TYPE_SERIAL == reader->readerType)+  {+    tagRead->tagEntry.sMsg = (uint8_t *) malloc(TMR_SR_MAX_PACKET_SIZE); /* size of bufResponse */+    memcpy(tagRead->tagEntry.sMsg, reader->u.serialReader.bufResponse, TMR_SR_MAX_PACKET_SIZE);+    tagRead->bufPointer = reader->u.serialReader.bufPointer;+  }+#ifdef TMR_ENABLE_LLRP_READER+  else+  {+    tagRead->tagEntry.lMsg = reader->u.llrpReader.bufResponse[0];+    reader->u.llrpReader.bufResponse[0] = NULL;+  }+#endif++  tagRead->isStatusResponse = reader->isStatusResponse;+  /**+   * Process the tag results here. The stats responses will be extracted+   * later by the parser thread.+   */+  if (TMR_READER_TYPE_SERIAL == reader->readerType)+  {+    if (false == tagRead->isStatusResponse)+    {+      TMR_TRD_init(&tagRead->trd);+      flags = GETU16AT(tagRead->tagEntry.sMsg, 8);+      TMR_SR_parseMetadataFromMessage(reader, &tagRead->trd, flags, &tagRead->bufPointer, tagRead->tagEntry.sMsg);+      TMR_SR_postprocessReaderSpecificMetadata(&tagRead->trd, &reader->u.serialReader);+      tagRead->trd.reader = reader;+    }+  }++  /* Enqueue the tagRead into Queue */+  enqueue(reader, tagRead);+  /* Increment queue_length */+  sem_post(&reader->queue_length);++  if ((false == reader->isStatusResponse) && (TMR_READER_TYPE_SERIAL == reader->readerType))+  {+    reader->u.serialReader.tagsRemainingInBuffer--;+  }+}++static void *+do_background_reads(void *arg)+{+  TMR_Status ret;+  TMR_Reader *reader;+  uint32_t onTime, offTime;+  int32_t sleepTime;+  uint64_t end, now, difftime;++  reader = arg;+  reader->trueAsyncflag = false;++  TMR_paramGet(reader, TMR_PARAM_READ_ASYNCOFFTIME, &offTime);++  while (1)+  {+    /* Wait for reads to be enabled */+    pthread_mutex_lock(&reader->backgroundLock);+    reader->backgroundRunning = false;++    pthread_cond_broadcast(&reader->backgroundCond);+    while (false == reader->backgroundEnabled)+    {+      reader->trueAsyncflag = false;+      pthread_cond_wait(&reader->backgroundCond, &reader->backgroundLock);+      if (true == reader->backgroundThreadCancel)+      {+        /**+         * thread is no more, required,+         * hence, making it terminated+         **/ +        goto EXIT;+      }+    }++    TMR_paramGet(reader, TMR_PARAM_READ_ASYNCONTIME, &onTime);++    if (!reader->trueAsyncflag)+    {+      ret = TMR_read(reader, onTime, NULL);+      if (TMR_SUCCESS != ret)+      {+        if ((TMR_ERROR_TIMEOUT == ret) || (TMR_ERROR_CRC_ERROR == ret) ||+              (TMR_ERROR_SYSTEM_UNKNOWN_ERROR == ret) || (TMR_ERROR_TM_ASSERT_FAILED == ret))+        {+          if (TMR_READER_TYPE_SERIAL == reader->readerType)+          {+            reader->u.serialReader.transport.flush(&reader->u.serialReader.transport);+          }+          reader->backgroundEnabled = false;+        }++        /**+         * M5e and its variants hardware does not have a real PA protection.So, doing the read with out+         * antenna may cause the damage to the reader.+         *+         * it's okay to let M6e and its variants continue to operate because it has a PA protection mechanism.+         **/+        if (((TMR_ERROR_HIGH_RETURN_LOSS == ret) || (TMR_ERROR_NO_ANTENNA == ret))+            &&+            ((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])))+        {+          reader->backgroundEnabled = false;+          reader->readState = TMR_READ_STATE_DONE;+          pthread_mutex_unlock(&reader->backgroundLock);+          notify_exception_listeners(reader, ret);+          break;+        }++        notify_exception_listeners(reader, ret);+        if(false == reader->searchStatus)+        {+          /**+           * There could be something wrong in initiating a search, continue the+           * effort to initiate a search. But meanwhile if stopReading()+           * is called, it will be blocked as the search itself is not started.+           * sem_post on read_started will unblock it.+           **/+          reader->readState = TMR_READ_STATE_STARTED;+          pthread_cond_broadcast(&reader->readCond);+          reader->backgroundEnabled = false;+        }+        pthread_mutex_unlock(&reader->backgroundLock);+        continue;+      }+      if(reader->continuousReading)+      {+        /**+         * Set this flag, In case of true async reading+         * we have to send the command only once.+         */+        reader->trueAsyncflag = true;+      }++      /**+       * Set an indication that the reading is started+       **/+      reader->readState = TMR_READ_STATE_ACTIVE;+      pthread_cond_broadcast(&reader->readCond);+    }++    reader->backgroundRunning = true;+    pthread_mutex_unlock(&reader->backgroundLock);++    if (true == reader->continuousReading)+    {+      /**  +       * Streaming is enabled only in case of M6e, +       * read till the end of stream.+       */+      /* Make the time stamp zero for serial reader */+      while (true)+      {+        if (TMR_READER_TYPE_SERIAL == reader->readerType)+        {+          if (false == reader->u.serialReader.isBasetimeUpdated)+          {+            /* Update the base time stamp */+            TMR_SR_updateBaseTimeStamp(reader);+            reader->u.serialReader.isBasetimeUpdated = true;+          }+        }+        ret = TMR_hasMoreTags(reader);+        if (TMR_SUCCESS == ret)+        {+          /* Got a valid message, before posting it to queue+           * check whether we have slots free in the queue or+           * not. Validate this only for Serial reader.+           */+          if (TMR_READER_TYPE_SERIAL == reader->readerType)+          {+            int slotsFree = 0;+            int semret;+            /* Get the semaphore value */+            semret = sem_getvalue(&reader->queue_slots, &slotsFree);+            if (0 == semret)+            {+              if (10 > slotsFree)+              {+                tmr_sleep(20);+              }+              if (0 >= slotsFree)+              {+                /* In a normal case we should not come here.+                 * we are here means there is no place to+                 * store the tags. May be the read listener+                 * is not fast enough.+                 * In this case stop the read and exit.+                 */+                if (true == reader->searchStatus)+                {+                  isBufferOverFlow = true;+                  ret = TMR_ERROR_BUFFER_OVERFLOW;+                  notify_exception_listeners(reader, ret);+                  ret = verifySearchStatus(reader);+                  /*isBufferOverFlow = false;+                  pthread_mutex_lock(&reader->backgroundLock);+                  reader->backgroundEnabled = false;+                  reader->readState = TMR_READ_STATE_DONE;+                  pthread_cond_broadcast(&reader->readCond);+                  pthread_mutex_unlock(&reader->backgroundLock);+                  reader->searchStatus = false;*/+				  /* Waiting till all slots are free */+				  while(slotsFree < TMR_MAX_QUEUE_SLOTS)+				  {+					  tmr_sleep(20);+					  semret = sem_getvalue(&reader->queue_slots, &slotsFree);+				  }+				  reader->trueAsyncflag = false;+                  break;+                }+              }+            }+          }++          /* There is place to store the response. Post it */+          process_async_response(reader);+        }+        else if (TMR_ERROR_CRC_ERROR == ret)+        {+          /* Currently, just drop the corrupted packet,+           * inform the user about the error and move on.+           *+           * TODO: Fix the error by tracing the exact reason of failour+           */+          notify_exception_listeners(reader, ret);+        }+        else if (TMR_ERROR_TAG_ID_BUFFER_FULL == ret)+        {+          /* In case of buffer full error, notify the exception */+          notify_exception_listeners(reader, ret);++          /**+           * If stop read is already called, no need to resumbit the seach again.+           * Just spin in the curent loop and wait for the stop read command response.+           **/ +          if (true == reader->searchStatus)+          {+            /**+             * Stop read is not called. Resubmit the search immediately, without user interaction+             * Resetting the trueAsyncFlag will send the continuous read command again.+             */++            ret = TMR_hasMoreTags(reader);+            reader->trueAsyncflag = false;+			reader->hasContinuousReadStarted = false;+            break;+          }+        }+        else+        {+          if ((TMR_ERROR_TIMEOUT == ret) || (TMR_ERROR_SYSTEM_UNKNOWN_ERROR == ret) || +            (TMR_ERROR_TM_ASSERT_FAILED == ret) || (TMR_ERROR_LLRP_READER_CONNECTION_LOST == ret))+          {+            notify_exception_listeners(reader, ret);+            /** +             * In case of timeout error or CRC error, flush the transport buffer.+             * this avoids receiving of junk response.+             */+            if (TMR_READER_TYPE_SERIAL == reader->readerType)+            {+              /* Handling this fix for serial reader now */+		          reader->u.serialReader.transport.flush(&reader->u.serialReader.transport);+            }++            /**+             * Check if reading is finished.+             * If not, send stop command.+             **/+            if (!reader->finishedReading)+            {+              reader->cmdStopReading(reader);+            }++            pthread_mutex_lock(&reader->backgroundLock);+            reader->backgroundEnabled = false;+            reader->readState = TMR_READ_STATE_DONE;+            pthread_cond_broadcast(&reader->readCond);+            pthread_mutex_unlock(&reader->backgroundLock);+++            /**+             * Forced stop +             * Reset continuous reading settings, so that+             * the subsequent startReading() call doesn't have+             * any surprises.+             **/+            reader->searchStatus = false;+            reset_continuous_reading(reader, true);+          }+          else if (TMR_ERROR_END_OF_READING == ret)+          {+            while(0 < reader->queue_depth)+            {+              /**+               * reader->queue_depth is greater than zero. i.e.,+               * there are still some tags left in queue.+               * Give some time for the parser to parse all of them.+               * 5 ms sleep shouldn't cause much delay.+               **/+              tmr_sleep(5);+            }++            /**+             * Since the reading is finished, disable this+             * thread.+             **/+            pthread_mutex_lock(&reader->backgroundLock);+            reader->backgroundEnabled = false;+            reader->readState = TMR_READ_STATE_DONE;+            pthread_cond_broadcast(&reader->readCond);+            pthread_mutex_unlock(&reader->backgroundLock);+            break;+          }+          else if ((TMR_ERROR_NO_TAGS_FOUND != ret) && (TMR_ERROR_NO_TAGS != ret) && (TMR_ERROR_TAG_ID_BUFFER_AUTH_REQUEST != ret) && (TMR_ERROR_TOO_BIG != ret))+          {+            /* Any exception other than 0x400 should be notified */+            notify_exception_listeners(reader, ret);+          }+          break;+        }+      }+    }+    else+    {+      /** +       * On M5e and its variants, streaming is not supported+       * So still, retain the pseudo-async mechanism+       * Also, when asyncOffTime is non-zero the API should fallback to +       * pseudo async mode.+       */++      end = tmr_gettime();++      while (TMR_SUCCESS == TMR_hasMoreTags(reader))+      {+        TMR_TagReadData trd;+        TMR_ReadListenerBlock *rlb;++        TMR_TRD_init(&trd);++        ret = TMR_getNextTag(reader, &trd);+        if (TMR_SUCCESS != ret)+        {+          pthread_mutex_lock(&reader->backgroundLock);+          reader->backgroundEnabled = false;+          pthread_mutex_unlock(&reader->backgroundLock);+          notify_exception_listeners(reader, ret);+          break;+        }++        pthread_mutex_lock(&reader->listenerLock);+        rlb = reader->readListeners;+        while (rlb)+        { +          rlb->listener(reader, &trd, rlb->cookie);+          rlb = rlb->next;+        }+        pthread_mutex_unlock(&reader->listenerLock);+      }++      /* Wait for the asyncOffTime duration to pass */+      now = tmr_gettime();+      difftime = now - end;++      sleepTime = offTime - (uint32_t)difftime;+      if(sleepTime > 0)+      {+        tmr_sleep(sleepTime);+      }+    }+EXIT:+    if (reader->backgroundThreadCancel)+    {+      /**+       * oops.. time to exit+       **/ +      pthread_exit(NULL);+    }+  }+  return NULL;+}+#endif /* TMR_ENABLE_BACKGROUND_READS */++TMR_Status+TMR_addReadListener(TMR_Reader *reader, TMR_ReadListenerBlock *b)+{+#ifndef SINGLE_THREAD_ASYNC_READ+  if (0 != pthread_mutex_lock(&reader->listenerLock))+    return TMR_ERROR_TRYAGAIN;+#endif+  b->next = reader->readListeners;+  reader->readListeners = b;+#ifndef SINGLE_THREAD_ASYNC_READ+  pthread_mutex_unlock(&reader->listenerLock);+#endif+  return TMR_SUCCESS;+}+#ifdef TMR_ENABLE_BACKGROUND_READS++TMR_Status+TMR_removeReadListener(TMR_Reader *reader, TMR_ReadListenerBlock *b)+{+  TMR_ReadListenerBlock *block, **prev;++  if (0 != pthread_mutex_lock(&reader->listenerLock))+    return TMR_ERROR_TRYAGAIN;++  prev = &reader->readListeners;+  block = reader->readListeners;+  while (NULL != block)+  {+    if (block == b)+    {+      *prev = block->next;+      break;+    }+    prev = &block->next;+    block = block->next;+  }++  pthread_mutex_unlock(&reader->listenerLock);++  if (block == NULL)+  {+    return TMR_ERROR_INVALID;+  }++  return TMR_SUCCESS;+}+++TMR_Status+TMR_addAuthReqListener(TMR_Reader *reader, TMR_AuthReqListenerBlock *b)+{++  if (0 != pthread_mutex_lock(&reader->listenerLock))+    return TMR_ERROR_TRYAGAIN;++  b->next = reader->authReqListeners;+  reader->authReqListeners = b;++  pthread_mutex_unlock(&reader->listenerLock);++  return TMR_SUCCESS;+}+++TMR_Status+TMR_removeAuthReqListener(TMR_Reader *reader, TMR_AuthReqListenerBlock *b)+{+  TMR_AuthReqListenerBlock *block, **prev;++  if (0 != pthread_mutex_lock(&reader->listenerLock))+    return TMR_ERROR_TRYAGAIN;++  prev = &reader->authReqListeners;+  block = reader->authReqListeners;+  while (NULL != block)+  {+    if (block == b)+    {+      *prev = block->next;+      break;+    }+    prev = &block->next;+    block = block->next;+  }++  pthread_mutex_unlock(&reader->listenerLock);++  if (block == NULL)+  {+    return TMR_ERROR_INVALID;+  }++  return TMR_SUCCESS;+}++TMR_Status+TMR_addStatusListener(TMR_Reader *reader, TMR_StatusListenerBlock *b)+{++  if (0 != pthread_mutex_lock(&reader->listenerLock))+    return TMR_ERROR_TRYAGAIN;++  b->next = reader->statusListeners;+  reader->statusListeners = b;++  /*reader->streamStats |= b->statusFlags & TMR_SR_STATUS_CONTENT_FLAGS_ALL;*/++  pthread_mutex_unlock(&reader->listenerLock);++  return TMR_SUCCESS;+}+#endif /* TMR_ENABLE_BACKGROUND_READS */++TMR_Status+TMR_addStatsListener(TMR_Reader *reader, TMR_StatsListenerBlock *b)+{+#ifndef SINGLE_THREAD_ASYNC_READ+  if (0 != pthread_mutex_lock(&reader->listenerLock))+    return TMR_ERROR_TRYAGAIN;+#endif+  b->next = reader->statsListeners;+  reader->statsListeners = b;++  /*reader->streamStats |= b->statusFlags & TMR_SR_STATUS_CONTENT_FLAGS_ALL; */+#ifndef SINGLE_THREAD_ASYNC_READ+  pthread_mutex_unlock(&reader->listenerLock);+#endif+  return TMR_SUCCESS;+}+#ifdef TMR_ENABLE_BACKGROUND_READS++TMR_Status+TMR_removeStatsListener(TMR_Reader *reader, TMR_StatsListenerBlock *b)+{+  TMR_StatsListenerBlock *block, **prev;++  if (0 != pthread_mutex_lock(&reader->listenerLock))+    return TMR_ERROR_TRYAGAIN;++  prev = &reader->statsListeners;+  block = reader->statsListeners;+  while (NULL != block)+  {+    if (block == b)+    {+      *prev = block->next;+      break;+    }+    prev = &block->next;+    block = block->next;+  }++  /* Remove the status flags requested by this listener and reframe */+  /*reader->streamStats = TMR_SR_STATUS_CONTENT_FLAG_NONE;+  {+    TMR_StatusListenerBlock *current;+    current = reader->statusListeners;+    while (NULL != current)+    {+      reader->streamStats |= current->statusFlags;+      current = current->next;+    }    +  }*/+  +  pthread_mutex_unlock(&reader->listenerLock);++  if (block == NULL)+  {+    return TMR_ERROR_INVALID;+  }++  return TMR_SUCCESS;+}++TMR_Status+TMR_removeStatusListener(TMR_Reader *reader, TMR_StatusListenerBlock *b)+{+  TMR_StatusListenerBlock *block, **prev;++  if (0 != pthread_mutex_lock(&reader->listenerLock))+    return TMR_ERROR_TRYAGAIN;++  prev = &reader->statusListeners;+  block = reader->statusListeners;+  while (NULL != block)+  {+    if (block == b)+    {+      *prev = block->next;+      break;+    }+    prev = &block->next;+    block = block->next;+  }++  /* Remove the status flags requested by this listener and reframe */+  /*reader->streamStats = TMR_SR_STATUS_CONTENT_FLAG_NONE;+    {+    TMR_StatusListenerBlock *current;+    current = reader->statusListeners;+    while (NULL != current)+    {+    reader->streamStats |= current->statusFlags;+    current = current->next;+    }+    }*/++  pthread_mutex_unlock(&reader->listenerLock);++  if (block == NULL)+  {+    return TMR_ERROR_INVALID;+  }++  return TMR_SUCCESS;+}++void cleanup_background_threads(TMR_Reader *reader)+{+  if (NULL != reader)+  {+    pthread_mutex_lock(&reader->backgroundLock);+    pthread_mutex_lock(&reader->listenerLock);+    reader->readExceptionListeners = NULL;+    reader->statsListeners = NULL;+    if (true == reader->backgroundSetup)+    {+      /**+       * Signal for the thread exit by +       * removing all the pthread lock dependency+       **/+      reader->backgroundThreadCancel = true;+      pthread_cond_broadcast(&reader->backgroundCond);+    }+    pthread_mutex_unlock(&reader->listenerLock);+    pthread_mutex_unlock(&reader->backgroundLock);++    if (true == reader->backgroundSetup)+    {+      /**+       * Wait for the back ground thread to exit+       **/ +      pthread_join(reader->backgroundReader, NULL);+    }++    pthread_mutex_lock(&reader->parserLock);+    pthread_mutex_lock(&reader->listenerLock);+    reader->readListeners = NULL;+    if (true == reader->parserSetup)+    {+      pthread_cancel(reader->backgroundParser);+    }+    pthread_mutex_unlock(&reader->listenerLock);+    pthread_mutex_unlock(&reader->parserLock);+  }+}++void*+do_background_receiveAutonomousReading(void * arg)+{+  TMR_Status ret;+  TMR_TagReadData trd;+  TMR_Reader *reader;+  TMR_Reader_StatsValues stats;  ++  reader = arg;+  TMR_TRD_init(&trd);++  while (1)+  {+    ret = TMR_SR_receiveAutonomousReading(reader, &trd, &stats);+    if (TMR_SUCCESS == ret)+    {+      if (false == reader->isStatusResponse)+      {+        /* Notify the read listener */+        notify_read_listeners(reader, &trd);+      }+      else+      {+        notify_stats_listeners(reader, &stats);+      }+    }+  }+  return NULL;+}+#endif /* TMR_ENABLE_BACKGROUND_READS */+
+ cbits/api/tmr_filter.h view
@@ -0,0 +1,102 @@+/* ex: set tabstop=2 shiftwidth=2 expandtab cindent: */+#ifndef _TMR_FILTER_H+#define _TMR_FILTER_H+/**+ *  @file tmr_filter.h+ *  @brief Mercury API - Tag Filter Interface+ *  @author Brian Fiegel+ *  @date 4/18/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 "tmr_tag_data.h"+#include "tmr_gen2.h"+#include "tmr_iso180006b.h"++/**+ * @defgroup filter Tag filters+ *+ * Tag filters cause the reader to limit an inventory to a subset of+ * tags (in a TMR_ReadPlan) or a tag operation to an individual tag+ * (as a parameter to a tag operation function).+ */++#ifdef  __cplusplus+extern "C" {+#endif++/** Type of a TMR_TagFilter structure */+typedef enum TMR_FilterType+{+  /** Tag data filter - non-protocol-specific */+  TMR_FILTER_TYPE_TAG_DATA          = 0,+  /** Gen2 Select filter */+  TMR_FILTER_TYPE_GEN2_SELECT       = 1, +  /** ISO180006B Select filter */+  TMR_FILTER_TYPE_ISO180006B_SELECT = 2+} TMR_FilterType;++/**+ * Structure representing a filter or subset of avaliable tags.+ * @ingroup filter+ */+typedef struct TMR_TagFilter+{+  TMR_FilterType type;+  union+  {+    /** A particular tag EPC */+    TMR_TagData     tagData;+    /** A Gen2 select operation */+    TMR_GEN2_Select gen2Select;+    /** An ISO180006B select operation */+    TMR_ISO180006B_Select iso180006bSelect;+  } u;+} TMR_TagFilter;++/**+ * Test if a tag matches this filter. Only applies to selects based+ * on the EPC.+ * + * @param filter The filter to test with.+ * @param tag The tag to test.+ * @return true if the tag matches the filter.+ */+bool TMR_TF_match(TMR_TagFilter *filter, TMR_TagData *tag);++TMR_Status TMR_TF_init_tag(TMR_TagFilter *filter, TMR_TagData *tag);++TMR_Status TMR_TF_init_gen2_select(TMR_TagFilter *filter, bool invert,+                                   TMR_GEN2_Bank bank, uint32_t bitPointer,+                                   uint16_t maskBitLength, uint8_t *mask);++TMR_Status TMR_TF_init_ISO180006B_select(TMR_TagFilter *filter, bool invert,+                                         TMR_ISO180006B_SelectOp op,+                                         uint8_t address, uint8_t mask,+                                         uint8_t wordData[8]);+#ifdef  __cplusplus+}+#endif++#endif /* _TMR_FILTER_H_ */
+ cbits/api/tmr_gen2.h view
@@ -0,0 +1,537 @@+/* ex: set tabstop=2 shiftwidth=2 expandtab cindent: */+#ifndef _TMR_GEN2_H+#define _TMR_GEN2_H+/** + *  @file tmr_gen2.h  + *  @brief Mercury API - Gen2 tag information and interfaces+ *  @author Brian Fiegel+ *  @date 5/7/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.+ */++#ifdef  __cplusplus+extern "C" {+#endif++/** Memory lock bits */+typedef enum TMR_GEN2_LockBits+{+  /** User memory bank lock permalock bit */+  TMR_GEN2_LOCK_BITS_USER_PERM    = (1 << 0),+  /** User memory bank lock bit */+  TMR_GEN2_LOCK_BITS_USER         = (1 << 1),+  /** TID memory bank lock permalock bit */+  TMR_GEN2_LOCK_BITS_TID_PERM     = (1 << 2),+  /** TID memory bank lock bit */+  TMR_GEN2_LOCK_BITS_TID          = (1 << 3),+  /** EPC memory bank lock permalock bit */+  TMR_GEN2_LOCK_BITS_EPC_PERM     = (1 << 4),+  /** EPC memory bank lock bit */+  TMR_GEN2_LOCK_BITS_EPC          = (1 << 5),+  /** Access password lock permalock bit */+  TMR_GEN2_LOCK_BITS_ACCESS_PERM  = (1 << 6),+  /** Access password lock bit */+  TMR_GEN2_LOCK_BITS_ACCESS       = (1 << 7),+  /** Kill password lock permalock bit */+  TMR_GEN2_LOCK_BITS_KILL_PERM    = (1 << 8),+  /** Kill password lock bit */+  TMR_GEN2_LOCK_BITS_KILL         = (1 << 9)+} TMR_GEN2_LockBits;++/**+ * The arguments to a TMR_lockTag() method for Gen2 tags. + */+typedef struct TMR_GEN2_LockAction+{+  /** The gen2 lock mask bits */+  uint16_t mask;+  /** The gen2 lock action bits */+  uint16_t action;+}TMR_GEN2_LockAction;++/**+ * @ingroup tagauth+ * A 32-bit password (access or kill) in the Gen2 protocol.+ */+typedef uint32_t TMR_GEN2_Password;++/**+ * @ingroup tagauth+ * a 16 byte(128 bit) Gen2 Denatran IAV write credentials+ */+typedef struct TMR_GEN2_DENATRAN_IAV_WriteCredentials+{+  uint8_t value[16];+  uint8_t tagId[8];+  uint8_t credentialLength;+  uint8_t tagIdLength;+}TMR_GEN2_DENATRAN_IAV_WriteCredentials;++/**+ * @ingroup tagauth+ * a 16 byte(128 bit) Gen2 Denatran IAV write sec credentials+ */+typedef struct TMR_GEN2_DENATRAN_IAV_WriteSecCredentials+{+  uint8_t value[16];+  uint8_t data[6];+  uint8_t credentialLength;+  uint8_t dataLength;+}TMR_GEN2_DENATRAN_IAV_WriteSecCredentials;++/** Gen2 memory banks */+typedef enum TMR_GEN2_Bank+{+  /** Reserved bank (kill and access passwords) */+  TMR_GEN2_BANK_RESERVED  = 0x0,+  /** EPC memory bank */+  TMR_GEN2_BANK_EPC       = 0x1,+  /** TID memory bank */+  TMR_GEN2_BANK_TID       = 0x2,+  /** User memory bank */+  TMR_GEN2_BANK_USER      = 0x3,+  /** Used to enable the read of additional membanks - reserved mem bank */+  TMR_GEN2_BANK_RESERVED_ENABLED = 0x4,+  /** Used to Filter Gen2 Tag with specified EPC length */+  TMR_GEN2_EPC_LENGTH_FILTER = 0x6,+  /** Gen2 Truncate Option */+  TMR_GEN2_EPC_TRUNCATE = 0x7,+  /** Used to enable the read of additional membanks - epc mem bank */+  TMR_GEN2_BANK_EPC_ENABLED = 0x8,+  /** Used to enable the read of additional membanks - tid mem bank */+  TMR_GEN2_BANK_TID_ENABLED = 0x10,+  /** Used to enable the read of additional membanks - user mem bank */+  TMR_GEN2_BANK_USER_ENABLED = 0x20+} TMR_GEN2_Bank;++/**+ * A single selection operation in the Gen2 protocol.+ * @ingroup filter+ */+typedef struct TMR_GEN2_Select+{+  /** Whether to invert the selection (deselect tags that meet the comparison) */+  bool invert;+  /** The memory bank in which to compare the mask */+  TMR_GEN2_Bank bank;+  /** The location (in bits) at which to begin comparing the mask */+  uint32_t bitPointer;+  /** The length (in bits) of the mask */+  uint16_t maskBitLength;+  /** The mask value to compare with the specified region of tag memory, MSB first */ +  uint8_t *mask;+} TMR_GEN2_Select;++/** Gen2 session values */+typedef enum TMR_GEN2_Session+{+  TMR_GEN2_SESSION_MIN= 0x00,+  /** Session 0 */+  TMR_GEN2_SESSION_S0 = 0x00,+  /** Session 1 */+  TMR_GEN2_SESSION_S1 = 0x01,+  /** Session 2 */ +  TMR_GEN2_SESSION_S2 = 0x02,+  /** Session 3 */ +  TMR_GEN2_SESSION_S3 = 0x03,+  TMR_GEN2_SESSION_MAX     = TMR_GEN2_SESSION_S3,+  TMR_GEN2_SESSION_INVALID = TMR_GEN2_SESSION_MAX + 1+} TMR_GEN2_Session;++/** Gen2 divide ratio values */+typedef enum TMR_GEN2_DivideRatio+{+  /** DR of 8 */+  TMR_GEN2_DIVIDE_RATIO_8    = 0,+  /** DR of 64/3 */+  TMR_GEN2_DIVIDE_RATIO_64_3 = 1+} TMR_GEN2_DivideRatio;++/** Gen2 TrExt bit */+typedef enum TMR_GEN2_TrExt+{+  /** No pilot tone in tag response */+  TMR_GEN2_TR_EXT_NO_PILOT_TONE = 0,+  /** Pilot tone in tag response */+  TMR_GEN2_TR_EXT_PILOT_TONE    = 1+} TMR_GEN2_TrExt;++/** Gen2 target search algorithms */+typedef enum TMR_GEN2_Target+{+  TMR_GEN2_TARGET_MIN= 0,+  /** Search target A */+  TMR_GEN2_TARGET_A  = 0,+  /** Search target B */+  TMR_GEN2_TARGET_B  = 1,+  /** Search target A until exhausted, then search target B */+  TMR_GEN2_TARGET_AB = 2,+  /** Search target B until exhausted, then search target A */+  TMR_GEN2_TARGET_BA = 3,+  TMR_GEN2_TARGET_MAX     = TMR_GEN2_TARGET_BA,+  TMR_GEN2_TARGET_INVALID = TMR_GEN2_TARGET_MAX+1+}TMR_GEN2_Target;++/** Gen2 tag encoding modulation values */+typedef enum TMR_GEN2_TagEncoding+{+  /** FM0 **/+  TMR_GEN2_FM0 = 0,++  TMR_GEN2_MILLER_MIN = 1,+  /** M = 2 */+  TMR_GEN2_MILLER_M_2 = 1,+  /** M = 4 */+  TMR_GEN2_MILLER_M_4 = 2,+  /** M = 8 */+  TMR_GEN2_MILLER_M_8 = 3,+  TMR_GEN2_MILLER_MAX     = TMR_GEN2_MILLER_M_8,+  TMR_GEN2_MILLER_INVALID = TMR_GEN2_MILLER_MAX+1+}TMR_GEN2_TagEncoding;++/** Gen2 link frequencies */+typedef enum TMR_GEN2_LinkFrequency+{+  /** 250 kHz */+  TMR_GEN2_LINKFREQUENCY_250KHZ  = 250,+  /** 320 KHZ */+  TMR_GEN2_LINKFREQUENCY_320KHZ  = 320,+  /**640 kHz*/+  TMR_GEN2_LINKFREQUENCY_640KHZ   = 640,+  TMR_GEN2_LINKFREQUENCY_MAX     = 640,+  TMR_GEN2_LINKFREQUENCY_INVALID = TMR_GEN2_LINKFREQUENCY_MAX + 1,+} TMR_GEN2_LinkFrequency;++/** Gen2 Protcol Extension parameters */+typedef enum TMR_GEN2_ProtocolExtension+{+  TMR_GEN2_PROTOCOLEXTENSION_LICENSE_NONE			= 0,+  TMR_GEN2_PROTOCOLEXTENSION_LICENSE_IAV_DENATRAN	= 1+}TMR_GEN2_ProtocolExtension;++/** Gen2 bap parameters */+typedef struct TMR_GEN2_Bap+{+  /* Default to 3000 us */+  int32_t powerUpDelayUs;+  /* Default to 20000 us */+  int32_t freqHopOfftimeUs;+}TMR_GEN2_Bap;++/** Gen2v2 untraceably hides part of EPC memory or not */+typedef enum TMR_GEN2_UNTRACEABLE_Epc+{+	/* Tag exposes EPC memory */+	EPC_SHOW = 0,+	/*Tag untraceably hides EPC memory above that*/+	EPC_HIDE = 1+}TMR_GEN2_UNTRACEABLE_Epc;++/** Gen2v2 untraceably hides part of TID memory or not */+typedef enum TMR_GEN2_UNTRACEABLE_Tid+{+	/* Tag exposes TID memory. */+	HIDE_NONE = 0,+	/*Tag untraceably hides all of TID memory.*/+	HIDE_ALL = 1,+	/* Tag’s allocation class identifier is E0h then the +	Tag untraceably hides TID memory above 10h,inclusive;+	if the Tag’s allocation class identifier is E2h then the+	Tag untraceably hides TID memory above 20h, inclusive. */+	HIDE_SOME = 2,+	/* RFU */+	TID_RFU = 3+}TMR_GEN2_UNTRACEABLE_Tid;++/** Gen2v2 untraceably hides part of UserMemory memory or not */+typedef enum TMR_GEN2_UNTRACEABLE_UserMemory+{+	/* Tag exposes User memory */+	SHOW = 0,+	/*Tag untraceably hides User memory*/+	HIDE = 1+}TMR_GEN2_UNTRACEABLE_UserMemory;++/** specifies Gen2v2 Tag’s operating range */+typedef enum TMR_GEN2_UNTRACEABLE_Range+{+	/* Tag persistently enables normal operating range */+	NORMAL = 0,+	/*Tag persistently enables reduced operating range.*/+	REDUCED = 1,+	/* Tag temporarily toggles its operating range*/+	TOGGLE_TEMPORARLY = 2,+	/* RFU */+	RFU = 3+}TMR_GEN2_UNTRACEABLE_Range;++/** Authentication KeyId */+typedef enum TMR_NXP_KeyId+{+	/* key0*/+	KEY0 = 0,+	/*Key1*/+	KEY1 = 1+}TMR_NXP_KeyId;++/** Memory profile for the addition of custom data */+typedef enum TMR_NXP_Profile+{+	/* EPC memory bank */+	EPC = 0,+	/* TID memory bank */+	TID = 1,+	/* User memory bank */+	USER = 2+}TMR_NXP_Profile;++/** Gen2 Tari values */+typedef enum TMR_GEN2_Tari+{+  /** Tari of 25 microseconds */+  TMR_GEN2_TARI_25US    = 0,+  /** Tari of 12.5 microseconds */+  TMR_GEN2_TARI_12_5US  = 1,+  /** Tari of 6.25 microseconds */+  TMR_GEN2_TARI_6_25US  = 2,+  TMR_GEN2_TARI_MAX     = 2,+  TMR_GEN2_TARI_INVALID = TMR_GEN2_TARI_MAX + 1,+} TMR_GEN2_Tari;++/** Gen2 WriteMode */+typedef enum TMR_GEN2_WriteMode+{+  /** WORD ONLY */+  TMR_GEN2_WORD_ONLY    = 0,+  /** BLOCK ONLY */+  TMR_GEN2_BLOCK_ONLY    = 1,+  /** BLOCK FALLBACK */+  TMR_GEN2_BLOCK_FALLBACK    = 2,++} TMR_GEN2_WriteMode;++/**+ * Defines the values for different gen2 silicon types.+ */+typedef enum TMR_SR_GEN2_SiliconType+{+  TMR_SR_GEN2_SILICON_ANY             = 0x00,+  TMR_SR_GEN2_ALIEN_HIGGS_SILICON     = 0x01,+  TMR_SR_GEN2_NXP_G2X_SILICON         = 0x02,+  TMR_SR_GEN2_ALIEN_HIGGS3_SILICON    = 0x05,+  TMR_SR_GEN2_NXP_G2I_SILICON         = 0x07,+  TMR_SR_GEN2_IMPINJ_MONZA4_SILICON   = 0x08,+  TMR_SR_GEN2_IDS_SL900A_SILICON      = 0x0A,+  TMR_SR_GEN2_DENATRAN_IAV_SILICON    = 0x0B,+  TMR_SR_GEN2_NXP_AES_UCODE			  = 0x0C,+}TMR_SR_GEN2_SiliconType;++/**+ * The argument to a ChangeConfig command for NXP G2iL tags+ * User can set the configWord directly using the 16 bit 'data' field.+ * Otherwise, provides an option to individually set each flag.+ * Instance of TMR_NXP_ConfigWord must be initialized before using either+ * by declaring it as 'static' or by using the constructor routine+ * TMR_init_NXP_ConfigWord() method.+ */+typedef union TMR_NXP_ConfigWord+{+  uint16_t data;+  /*+   * Since the bit-fields are used, The bits in configWord are shown from+   * Least significant bit to Most significant bit.+   */+  struct+  {+    /** Least significant bit */+    /** PSF alarm flag (Permanently stored in tag memory)*/+    unsigned psfAlarm:1;+    /** Read protect TID bank (permanently stored in tag memory)*/+    unsigned readProtectTID:1;+    /** Read protect EPC bank (Permanently stored in tag memory)*/+    unsigned readProtectEPC:1;+     /** Read protect User memory bank (permanently stored in tag memory)*/+    unsigned readProtectUser:1;+    /** Read range reduction on/off (permanently stored in tag memory)*/+    unsigned privacyMode:1;+    /** Digital output (permanently stored in tag memory)*/+    unsigned digitalOutput:1;+    /** Maximum backscatter strength (permanently stored in tag memory)*/+    unsigned maxBackscatterStrength:1;+    /** Conditional Read Range Reduction open/short (permanently stored in tag memory)*/+    unsigned conditionalReadRangeReduction_openShort:1;+    /** Conditional Read Range Reduction on/off (permanently stored in tag memory)*/+    unsigned conditionalReadRangeReduction_onOff:1;+    /** Transparent mode data/raw (reset at power up)*/+    unsigned dataMode:1;+     /** Transparent mode on/off (reset at power up)*/+    unsigned transparentMode:1;+    /** Invert digital output (reset at power up)*/+    unsigned invertDigitalOutput:1;+    /** RFU 3*/+    unsigned RFU3:1;+    /** RFU 2*/+    unsigned RFU2:1;+    /** External supply flag digital input (read only)*/+    unsigned externalSupply:1;+    /** Tamper alarm flag (Read only)*/+    unsigned tamperAlarm:1;    +    /** Most significant bit */+  }bits;+}TMR_NXP_ConfigWord;++/**+ * TMR_Monza4_ControlByte is an argument to Monza4 QTReadWrite custom command+ * User can set the control byte directly using the 8 bit 'data' field.+ * Otherwise, provides an option to individually set each flag.+ * Instance of TMR_Monza4_ControlByte must be initialized before using either+ * by declaring it as 'static' (or initializing it to 0) or by using the constructor routine+ * TMR_init_Monza4_ControlByte() method.+ */+typedef union TMR_Monza4_ControlByte+{+  /* 8-bit control byte */+  uint8_t data;+  /*+   * Since bit-fields are used, The bits in control Byte are shown from+   * Least significant bit to Most significant bit.+   */+  struct +  {+    /**+     * The following bits are Reserved for Future Use. And will be ignored.+     * RFU_TM's are ThingMagic specific RFU bits, and RFU_Impinj bits are +     * as per the Monza4 specification.+     */+    unsigned RFU_TM0:1;+    unsigned RFU_TM1:1;+    unsigned RFU_TM2:1;+    unsigned RFU_TM3:1;+    unsigned RFU_Impinj4:1;+    unsigned RFU_Impinj5:1;+    /**+     * If Read/Write=1, the Persistence field indicates whether the QT control is+     * written to nonvolatile (NVM) or volatile memory.+     * Persistence=0 means write to volatile memory. +     * Persistence=1 means write to NVM memory+     */+    unsigned persistence:1;+    /**+     * The Read/Write bit indicates whether the tag reads or writes QT control data.+     * Read/Write=0 means read the QT control bits in cache.+     * Read/Write=1 means write the QT control bits+     */+    unsigned readWrite:1;    +  }bits;+}TMR_Monza4_ControlByte;++/**+ * TMR_Monza4_Payload is an argument to Monza4 QTReadWrite custom command+ * User can set the payload directly using the 16 bit 'data' field.+ * Otherwise, provides an option to individually set each flag.+ * Instance of TMR_Monza4_Payload must be initialized before using either+ * by declaring it as 'static' (or initializing it to 0) or by using the constructor routine+ * TMR_init_Monza4_Payload() method.+ * This field controls the QT functionality. These bits are ignored when the+ * Read/Write field equals 0 in control byte.+ */+typedef union TMR_Monza4_Payload+{+  /** 16-bit payload */+  uint16_t data;+  /*+   * Since bit-fields are used, The bits in payload are shown from+   * Least significant bit to Most significant bit.+   */+  struct+  {+    /**+     * The following bits are Reserved for Future Use. And will be ignored.+     * Tag will always return these bits as zero.+     * All these RFU bits are as per the monza4 spec.+     */+    unsigned RFU0:1;+    unsigned RFU1:1;+    unsigned RFU2:1;+    unsigned RFU3:1;+    unsigned RFU4:1;+    unsigned RFU5:1;+    unsigned RFU6:1;+    unsigned RFU7:1;+    unsigned RFU8:1;+    unsigned RFU9:1;+    unsigned RFU10:1;+    unsigned RFU11:1;+    unsigned RFU12:1;+    unsigned RFU13:1;+    /**+     *  Bit 14 +     *  1: Tag uses Public Memory Map +     *  0: Tag uses Private Memory Map+     */+    unsigned QT_MEM:1;+    /**+     *  Bit 15 (MSB) is first transmitted bit of the payload field.+     *  Bit # Name Description+     *  1: Tag reduces range if in or about to be in OPEN or SECURED state+     *  0: Tag does not reduce range+     */+    unsigned QT_SR:1;+  }bits;+}TMR_Monza4_Payload;++typedef struct TMR_GEN2_HibikiSystemInformation+{+  uint16_t infoFlags;     /* Indicates whether the banks are present and Custom Commands are implemented*/ +  uint8_t reservedMemory; /* Indicates the size of this memory bank in words*/+  uint8_t epcMemory;      /* Indicates the size of this memory bank in words*/+  uint8_t tidMemory;      /* Indicates the size of this memory bank in words*/+  uint8_t userMemory;     /* Indicates the size of this memory bank in words*/+  uint8_t setAttenuate;   /**/+  uint16_t bankLock;      /* Indicates Lock state for this type of lock*/+  uint16_t blockReadLock; /* Indicates Lock state for this type of lock*/+  uint16_t blockRwLock;   /* Indicates Lock state for this type of lock*/+  uint16_t blockWriteLock;/* Indicates Lock state for this type of lock*/+} TMR_GEN2_HibikiSystemInformation;++/** Size allocated for storing PC data in TMR_GEN2_TagData */+#define TMR_GEN2_MAX_PC_BYTE_COUNT (6)+/**+ * Gen2-specific per-tag data+ */+typedef struct TMR_GEN2_TagData+{ +  /** Length of the tag PC */+  uint8_t pcByteCount;+  /** Tag PC */+  uint8_t pc[TMR_GEN2_MAX_PC_BYTE_COUNT];+} TMR_GEN2_TagData;++++#ifdef __cplusplus+}+#endif++#endif /*_TMR_GEN2_H*/
+ cbits/api/tmr_gpio.h view
@@ -0,0 +1,55 @@+/* ex: set tabstop=2 shiftwidth=2 expandtab cindent: */+#ifndef _TMR_GPIO_H+#define _TMR_GPIO_H+/**+ *  @file tmr_gpio.h+ *  @brief Mercury API - GPIO Definitons+ *  @author Brian Fiegel+ *  @date 4/18/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.+ */++#ifdef  __cplusplus+extern "C" {+#endif++/**+ * The identity and state of a single GPIO pin.+ */+typedef struct TMR_GpioPin+{+  /** The ID number of the pin. */+  uint8_t id;+  /** Whether the pin is in the high state. */+  bool high;+  /** The direction of the pin */+  bool output;+}TMR_GpioPin;+++#ifdef  __cplusplus+}+#endif++#endif /* _TMR_GPIO_H_ */
+ cbits/api/tmr_ipx.h view
@@ -0,0 +1,41 @@+/* ex: set tabstop=2 shiftwidth=2 expandtab cindent: */+#ifndef _TMR_IPX_H+#define _TMR_IPX_H+/**+ *  @file tmr_ipx.h  + *  @brief Mercury API - iPx tag information and interfaces+ *  @author Nathan Williams+ *  @date 1/21/2010+ */++/*+ * Copyright (c) 2010 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.+ */++#ifdef  __cplusplus+extern "C" {+#endif++#ifdef __cplusplus+}+#endif++#endif /*_TMR_IPX_H*/
+ cbits/api/tmr_iso180006b.h view
@@ -0,0 +1,108 @@+/* ex: set tabstop=2 shiftwidth=2 expandtab cindent: */+#ifndef _TMR_ISO180006B_H+#define _TMR_ISO180006B_H+/**+ *  @file tmr_iso180006b.h  + *  @brief Mercury API - ISO180006B tag information and interfaces+ *  @author Brian Fiegel+ *  @date 5/7/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.+ */++#ifdef  __cplusplus+extern "C" {+#endif++/** ISO180006B Select operations */+typedef enum TMR_ISO180006B_SelectOp+{+  /** Select if tag data matches op data */+  TMR_ISO180006B_SELECT_OP_EQUALS       = 0,+  /** Select if tag data does not match op data */+  TMR_ISO180006B_SELECT_OP_NOT_EQUALS   = 1,+  /** Select if tag data is less than op data */+  TMR_ISO180006B_SELECT_OP_LESS_THAN    = 2,+  /** Select if tag data is greater than op data */+  TMR_ISO180006B_SELECT_OP_GREATER_THAN = 3+} TMR_ISO180006B_SelectOp;++/**+ * A single selection operation in the ISO18000-6B protocol.+ * @ingroup filter+ */ +typedef struct TMR_ISO180006B_Select+{+  /** Whether to invert the selection (deselect tags that meet the comparison). */+  bool invert;+  /** The operation to use to compare the tag data to the provided data. */+  TMR_ISO180006B_SelectOp op;+  /** The address of the tag memory to compare to the provided data. */+  uint8_t address;+  /** Bitmask of which of the eight provided data bytes to compare to the tag memory. */+  uint8_t mask;+  /** The data to compare. Exactly eight bytes. */+  uint8_t data[8];+} TMR_ISO180006B_Select;++/**+ * The arguments to a TMR_lockTag() method for ISO18000-6B tags. + * Represents the byte to be locked.+ */+typedef struct TMR_ISO180006B_LockAction+{+  /** The memory address of the byte to lock */+  uint8_t address;+} TMR_IS0180006B_LockAction;++/** ISO180006B link frequencies */+typedef enum TMR_ISO180006B_LinkFrequency+{+  /** 40 kHz */+  TMR_ISO180006B_LINKFREQUENCY_40KHZ  = 40,+  /** 160 kHz */+  TMR_ISO180006B_LINKFREQUENCY_160KHZ = 160,+} TMR_ISO180006B_LinkFrequency;++/** ISO180006B modulation depth */+typedef enum TMR_ISO180006B_ModulationDepth+{+  /** 99 percent modulation */+  TMR_ISO180006B_Modulation99percent = 0x00,+  /** 11 percent modulation */+  TMR_ISO180006B_Modulation11percent = 0x01+}TMR_ISO180006B_ModulationDepth;++/** ISO180006B Delimiter */+typedef enum TMR_ISO180006B_Delimiter+{+  /** delimiter 1*/+  TMR_ISO180006B_Delimiter1 = 0x01,+  /** delimiter 4 */+  TMR_ISO180006B_Delimiter4 = 0x04+}TMR_ISO180006B_Delimiter;+#ifdef __cplusplus+}+#endif++#endif /*_TMR_ISO180006B_H*/
+ cbits/api/tmr_llrp_reader.h view
@@ -0,0 +1,278 @@+#ifndef _TMR_LLRP_READER_H+#define _TMR_LLRP_READER_H+/**+ *  @file tmr_llrp_reader.h+ *  @brief Mercury API - LLRP Reader interface+ *  @author Somu+ *  @date 05/23/2011+ */++/*+ * Copyright (c) 2011 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 <pthread.h>+#include <semaphore.h>+#include "tmr_region.h"+#include "tmr_tag_protocol.h"+#include "tmr_serial_transport.h"+#include "tmr_params.h"+#include "ltkc.h"+#include "tm_ltkc.h"++#ifdef __cplusplus+extern "C" {+#endif+ +#define TM_MANUFACTURER_ID  26554+#define TMR_LLRP_SYNC_MAX_ROSPECS 256  +#define TMR_LLRP_MAX_RFMODE_ENTRIES 7+#define TMR_LLRP_READER_DEFAULT_PORT 5084++/**+ * This structure is returned from cmdGetRFControl+ **/+typedef struct TMR_LLRP_RFControl+{+  /* RFMode index */+  llrp_u16_t index;++  /* Tari */+  TMR_GEN2_Tari tari;++} TMR_LLRP_RFControl;++/**+ * Gen2 RF Mode Table structure.+ * Currently we use only BLF and Encoding from + * RF Mode table. + **/+typedef struct TMR_LLRP_C1G2RFModeTable+{+  /* Gen2 BLF */+  TMR_GEN2_LinkFrequency blf;++  /* Gen2 Tag encoding */+  TMR_GEN2_TagEncoding m;++  /* Min Tari Value*/+  TMR_GEN2_Tari minTari;++  /* Max Tari Value*/+  TMR_GEN2_Tari maxTari;++} TMR_LLRP_C1G2RFModeTable;++/**+ * This structure is returned from cmdGetReaderCapabilities.+ **/+typedef struct TMR_LLRP_ReaderCapabilities+{+  /** Country code */+  llrp_u16_t countryCode;++  /** Reader model */+  uint32_t model;++  /** Software version */+  char softwareVersion[128];++  /** Power level table */+  TMR_uint16List powerTable;+  uint16_t powerList[255];++  /** Frequency table */+  TMR_uint32List freqTable;+  uint32_t freqList[64];++  union+  {+    /** +     * Gen2 RF Mode tables+     * FIXME: Max RFModes available for now is 5.+     * and the index start from 1-5+     **/+    TMR_LLRP_C1G2RFModeTable gen2Modes[TMR_LLRP_MAX_RFMODE_ENTRIES];+    /**+     * Can have RF Mode table specific to +     * other protocols. +     **/+  } u;++} TMR_LLRP_ReaderCapabilities;++/** + * This struture used to+ * moniter the protocol+ * in read plan+ **/+typedef struct ROSpecProtocolTable+{+  /* rospecid */+  uint8_t rospecID;+  /*protocol */+  TMR_TagProtocol rospecProtocol;+}ROSpecProtocolTable;++/**+ * This is the structure used to+ * store the unhandled async response+ **/+typedef struct TMR_LLRP_UnhandledAsyncResponse+{+  /** Buffer to hold the LLRP message */+  LLRP_tSMessage *lMsg;+}TMR_LLRP_UnhandledAsyncResponse;++/**+ * LLRP reader structure+ */+typedef struct TMR_LLRP_LlrpReader+{+  /* @privatesection */+  LLRP_tSTypeRegistry *       pTypeRegistry;+  LLRP_tSConnection *         pConn;+  int                         portNum;+  llrp_u32_t                  msgId;+  llrp_u32_t                  roSpecId, accessSpecId;+  llrp_u16_t                  opSpecId;++  TMR_AntennaMapList *txRxMap;+  uint32_t transportTimeout;+  uint32_t commandTimeout;+  TMR_Region  regionId;+  TMR_GEN2_Password gen2AccessPassword;++  /* Static storage for the default map */+  TMR_AntennaMap staticTxRxMapData[TMR_SR_MAX_ANTENNA_PORTS];+  TMR_AntennaMapList staticTxRxMap;++  uint32_t portMask;+  /* Bit mask of supported protocol list */+  uint32_t supportedProtocols;++  TMR_TagProtocol currentProtocol;++  /* Buffer to store additional error message */+  /* TODO: Change TMR_SR_MAX_PACKET_SIZE to appropriate value */+  char errMsg[TMR_SR_MAX_PACKET_SIZE];++  /* Large bitmask that stores whether each parameter's presence+   * is known or not.+   */+  uint32_t paramConfirmed[TMR_PARAMWORDS];++  /* Large bitmask that, if the corresponding bit in paramConfirmed is set,+   * stores whether each parameter is present or not.+   */+  uint32_t paramPresent[TMR_PARAMWORDS];+  +  /* Number of tags reported by reader */+  int tagsRemaining;++  /* Array of LLRP_tSMessage pointers holding the tag read responses */+  LLRP_tSMessage **bufResponse;++  /* bufResponse read index */+  uint8_t bufPointer;+  uint8_t bufIndex;++  /* Pointer to buffer holding the tag read data */+  LLRP_tSTagReportData *pTagReportData;++  int searchTimeoutMs;++  /* Cache LLRP Reader Capabilities */+  TMR_LLRP_ReaderCapabilities capabilities;++  /**+   * LLRP Asynchronous receiver to handle+   * keep alive and events.+   **/+  pthread_t llrpReceiver;+  bool receiverSetup, receiverRunning, receiverEnabled;+  pthread_cond_t receiverCond;+  int numOfROSpecEvents;+  /** The above variables must be protected by this lock */+  pthread_mutex_t receiverLock;++  /**+   * For monitoring keepalives:+   * Used only in case of async reading+   **/+  uint64_t ka_start, ka_now;+  bool get_report, reportReceived;+  /**+   * For monitoring protcol type+   * in case of multiprotocol read+   **/+  ROSpecProtocolTable readPlanProtocol[TMR_SR_MAX_PACKET_SIZE];++  /**+   * For monitoring the unhandeled responses+   * during the async read+   **/+  TMR_LLRP_UnhandledAsyncResponse unhandledAsyncResponse;+  /** To check the status of async unhandled responses */+  bool isResponsePending;+  /** To cancel the receiver thread */+  bool threadCancel;+  /* To hold the No.of Keep alives missed count*/+  uint8_t keepAliveAckMissCnt;+}TMR_LLRP_LlrpReader;+++TMR_Status TMR_LLRP_connect(TMR_Reader *reader);+TMR_Status TMR_LLRP_destroy(TMR_Reader *reader);+TMR_Status TMR_LLRP_hasMoreTags(TMR_Reader *reader); +TMR_Status TMR_LLRP_getNextTag(TMR_Reader *reader, TMR_TagReadData *trd);+TMR_Status TMR_LLRP_executeTagOp(TMR_Reader *reader, TMR_TagOp *tagop, TMR_TagFilter *filter, TMR_uint8List *data);+TMR_Status TMR_LLRP_gpiGet(struct TMR_Reader *reader,uint8_t *count, TMR_GpioPin state[]);+TMR_Status TMR_LLRP_gpoSet(struct TMR_Reader *reader,uint8_t count, const TMR_GpioPin state[]);+TMR_Status TMR_LLRP_readTagMemBytes(struct TMR_Reader *reader, const TMR_TagFilter *filter,+                                    uint32_t bank, uint32_t addreass,+                                    uint16_t count,uint8_t data[]);+TMR_Status TMR_LLRP_readTagMemWords(struct TMR_Reader *reader, const TMR_TagFilter *filter,+                                    uint32_t bank, uint32_t address,+                                    uint16_t count, uint16_t *data);+TMR_Status TMR_LLRP_writeTagMemBytes(struct TMR_Reader *reader, const TMR_TagFilter *filter,+                                    uint32_t bank, uint32_t addreass,+                                    uint16_t count,const uint8_t data[]);+TMR_Status TMR_LLRP_writeTagMemWords(struct TMR_Reader *reader, const TMR_TagFilter *filter,+                                    uint32_t bank, uint32_t address,+                                    uint16_t count, const uint16_t *data);+TMR_Status TMR_LLRP_firmwareLoad( TMR_Reader *reader, void *cookie, TMR_FirmwareDataProvider provider);+TMR_Status TMR_LLRP_writeTag(TMR_Reader *reader, const TMR_TagFilter *filter, const TMR_TagData *data);+TMR_Status TMR_LLRP_killTag(struct TMR_Reader *reader, const TMR_TagFilter *filter,+                             const TMR_TagAuthentication *auth);+TMR_Status TMR_LLRP_lockTag(struct TMR_Reader *reader,const TMR_TagFilter *filter, TMR_TagLockAction *action);+TMR_Status TMR_LLRP_reboot(struct TMR_Reader *reader);+/**+ * Initialize LLRP reader.+ */+TMR_Status TMR_LLRP_LlrpReader_init(TMR_Reader *reader);++TMR_Status TMR_LLRP_read(struct TMR_Reader *reader, uint32_t timeoutMs, int32_t *tagCount);+#ifdef __cplusplus+}+#endif++#endif /* _TMR_LLRP_READER_H */
+ cbits/api/tmr_param.c view
@@ -0,0 +1,152 @@+/**+ *  @file tmr_param.c+ *  @brief Mercury API - parameter string implementation+ *  @author Nathan Williams+ *  @date 11/3/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 <string.h>++#include "tm_reader.h"+#include "tmr_utils.h"++#ifdef TMR_ENABLE_PARAM_STRINGS++static const char *paramNames[1 + TMR_PARAM_MAX] = {+  "",  /* TMR_PARAM_NONE */+  "/reader/baudRate",  /* TMR_PARAM_BAUDRATE */+  "/reader/probeBaudRates",/* TMR_PARAM_PROBEBAUDRATES */+  "/reader/commandTimeout",  /* TMR_PARAM_COMMANDTIMEOUT */+  "/reader/transportTimeout",  /* TMR_PARAM_TRANSPORTTIMEOUT */+  "/reader/powerMode",  /* TMR_PARAM_POWERMODE */+  "/reader/userMode",  /* TMR_PARAM_USERMODE */+  "/reader/antenna/checkPort",  /* TMR_PARAM_ANTENNA_CHECKPORT */+  "/reader/antenna/portList",  /* TMR_PARAM_ANTENNA_PORTLIST */+  "/reader/antenna/connectedPortList",  /* TMR_PARAM_ANTENNA_CONNECTEDPORTLIST */+  "/reader/antenna/portSwitchGpos",  /* TMR_PARAM_ANTENNA_PORTSWITCHGPOS */+  "/reader/antenna/settlingTimeList",  /* TMR_PARAM_ANTENNA_SETTLINGTIMELIST */+  "/reader/antenna/returnLoss", /* TMR_PARAM_ANTENNA_RETURNLOSS */+  "/reader/antenna/txRxMap",  /* TMR_PARAM_ANTENNA_TXRXMAP */+  "/reader/gpio/inputList",  /* TMR_PARAM_GPIO_INPUTLIST */+  "/reader/gpio/outputList",  /* TMR_PARAM_GPIO_OUTPUTLIST */+  "/reader/gen2/accessPassword",  /* TMR_PARAM_GEN2_ACCESSPASSWORD */+  "/reader/gen2/q",  /* TMR_PARAM_GEN2_Q */+  "/reader/gen2/tagEncoding",  /* TMR_PARAM_GEN2_TAGENCODING*/+  "/reader/gen2/session",  /* TMR_PARAM_GEN2_SESSION */+  "/reader/gen2/target",  /* TMR_PARAM_GEN2_TARGET */+  "/reader/gen2/BLF",  /* TMR_PARAM_GEN2_BLF */+  "/reader/gen2/tari",  /* TMR_PARAM_GEN2_TARI */+  "/reader/gen2/writeMode",/*TMR_PARAM_GEN2_WRITEMODE*/+  "/reader/gen2/bap",  /* TMR_PARAM_GEN2_BAP */+  "/reader/gen2/protocolExtension",  /* TMR_PARAM_GEN2_PROTOCOLEXTENSION */+  "/reader/iso180006b/BLF",  /* TMR_PARAM_ISO18000_6B_LINKFREQUENCY */+  "/reader/iso180006b/modulationDepth", /* TMR_PARAM_ISO18000_6B_MODULATION_DEPTH */+  "/reader/iso180006b/delimiter", /* TMR_PARAM_ISO18000_6B_DELIMITER */+  "/reader/read/asyncOffTime",  /* TMR_PARAM_READ_ASYNCOFFTIME */+  "/reader/read/asyncOnTime",  /* TMR_PARAM_READ_ASYNCONTIME */+  "/reader/read/plan",  /* TMR_PARAM_READ_PLAN */+  "/reader/radio/enablePowerSave", /* TMR_PARAM_RADIO_ENABLEPOWERSAVE */+  "/reader/radio/powerMax",  /* TMR_PARAM_RADIO_POWERMAX */+  "/reader/radio/powerMin",  /* TMR_PARAM_RADIO_POWERMIN */+  "/reader/radio/portReadPowerList",  /* TMR_PARAM_RADIO_PORTREADPOWERLIST */+  "/reader/radio/portWritePowerList",  /* TMR_PARAM_RADIO_PORTWRITEPOWERLIST */+  "/reader/radio/readPower",  /* TMR_PARAM_RADIO_READPOWER */+  "/reader/radio/writePower",  /* TMR_PARAM_RADIO_WRITEPOWER */+  "/reader/radio/temperature",  /* TMR_PARAM_RADIO_TEMPERATURE */+  "/reader/tagReadData/recordHighestRssi",  /* TMR_PARAM_TAGREADDATA_RECORDHIGHESTRSSI */+  "/reader/tagReadData/reportRssiInDbm",  /* TMR_PARAM_TAGREADDATA_REPORTRSSIINDBM */+  "/reader/tagReadData/uniqueByAntenna",  /* TMR_PARAM_TAGREADDATA_UNIQUEBYANTENNA */+  "/reader/tagReadData/uniqueByData",  /* TMR_PARAM_TAGREADDATA_UNIQUEBYDATA */+  "/reader/tagop/antenna",  /* TMR_PARAM_TAGOP_ANTENNA */+  "/reader/tagop/protocol",  /* TMR_PARAM_TAGOP_PROTOCOL */+  "/reader/version/hardware",  /* TMR_PARAM_VERSION_HARDWARE */+  "/reader/version/serial", /* TMR_PARAM_VERSION_SERIAL */+  "/reader/version/model",  /* TMR_PARAM_VERSION_MODEL */+  "/reader/version/software",  /* TMR_PARAM_VERSION_SOFTWARE */+  "/reader/version/supportedProtocols",  /* TMR_PARAM_VERSION_SUPPORTEDPROTOCOLS */+  "/reader/region/hopTable",  /* TMR_PARAM_REGION_HOPTABLE */+  "/reader/region/hopTime",  /* TMR_PARAM_REGION_HOPTIME */+  "/reader/region/id",  /* TMR_PARAM_REGION_ID */+  "/reader/region/supportedRegions",  /* TMR_PARAM_REGION_SUPPORTEDREGIONS */+  "/reader/region/lbt/enable",  /* TMR_PARAM_REGION_LBT_ENABLE */+  "/reader/licenseKey",  /* TMR_PARAM_LICENSE_KEY */+  "/reader/userConfig",  /* TMR_PARAM_USER_CONFIG */+  "/reader/radio/enableSJC", /* TMR_PARAM_RADIO_ENABLESJC */+  "/reader/extendedEpc", /* TMR_PARAM_EXTENDEDEPC */+  "/reader/statistics", /* TMR_PARAM_READER_STATISTICS */+  "/reader/stats", /* TMR_PARAM_READER_STATS */+  "/reader/uri", /* TMR_PARAM_URI */+  "/reader/version/productGroupID", /* TMR_PARAM_PRODUCT_GROUP_ID */+  "/reader/version/productGroup", /* TMR_PARAM_PRODUCT_GROUP */+  "/reader/version/productID", /* TMR_PARAM_PRODUCT_ID */+  "/reader/tagReadData/tagopSuccesses",  /* TMR_PARAM_TAGREADATA_TAGOPSUCCESSCOUNT */+  "/reader/tagReadData/tagopFailures", /* TMR_PARAM_TAGREADATA_TAGOPFAILURECOUNT */+  "/reader/status/antennaEnable", /* TMR_PARAM_STATUS_ENABLE_ANTENNAREPORT */+  "/reader/status/frequencyEnable", /* TMR_PARAM_STATUS_ENABLE_FREQUENCYREPORT */+  "/reader/status/temperatureEnable", /* TMR_PARAM_STATUS_ENABLE_TEMPERATUREREPORT */+  "/reader/tagReadData/enableReadFilter", /* TMR_PARAM_TAGREADDATA_ENABLEREADFILTER */+  "/reader/tagReadData/readFilterTimeout", /* TMR_PARAM_TAGREADDATA_READFILTERTIMEOUT */+  "/reader/tagReadData/uniqueByProtocol", /* TMR_PARAM_TAGREADDATA_UNIQUEBYPROTOCOL */+  "/reader/description", /* TMR_PARAM_READER_DESCRIPTION */+  "/reader/hostname", /* TMR_PARAM_READER_HOSTNAME */+  "/reader/currentTime", /* TMR_PARAM_CURRENTTIME */+	"/reader/gen2/writeReplyTimeout", /* TMR_PARAM_READER_WRITE_REPLY_TIMEOUT */+	"/reader/gen2/writeEarlyExit", /* /reader/gen2/writeEarlyExit */+  "/reader/stats/enable", /* /reader/stats/enable */+  "/reader/trigger/read/Gpi", /* TMR_PARAM_TRIGGER_READ_GPI */+  "/reader/metadataflags", /* TMR_PARAM_METADATAFLAG */+  "/reader/licensedFeatures",  /* TMR_PARAM_LICENSED_FEATURES */+  "/reader/selectedProtocols",  /* TMR_PARAM_SELECTED_PROTOCOLS */+};+++TMR_Param+TMR_paramID(const char *name)+{+  int i;++  for (i = 1 ; i <= TMR_PARAM_MAX ; i++)+  {+    if (0 == strcasecmp(name, paramNames[i]))+    {+      return (TMR_Param)i;+    }+  }++  return TMR_PARAM_NONE;+}++const char *+TMR_paramName(TMR_Param key)+{++  if (key <= TMR_PARAM_MAX)+  {+    return paramNames[key];+  }+  return NULL;+}++#endif /* TMR_ENABLE_PARAM_STRINGS */
+ cbits/api/tmr_params.h view
@@ -0,0 +1,224 @@+/* ex: set tabstop=2 shiftwidth=2 expandtab cindent: */+#ifndef _TMR_PARAMS_H+#define _TMR_PARAMS_H+/** + *  @file tmr_params.h+ *  @brief Mercury API - Reader parameter interface+ *  @author Nathan Williams+ *  @date 10/20/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.+ */++#ifdef  __cplusplus+extern "C" {+#endif++/**+ * Parameter keys for TMR_paramSet() and TMR_paramGet().  Each+ * parameter is listed with its associated string name and the+ * parameter type. A pointer to that type is passed to TMR_paramGet()+ * (for example, "TMR_String *" for /reader/version/model).+ */+typedef enum TMR_Param+{+  /** No such parameter - used as a return value from TMR_paramID().  */+  TMR_PARAM_NONE,+  TMR_PARAM_MIN,+  /** "/reader/baudRate", uint32_t */+  TMR_PARAM_BAUDRATE = TMR_PARAM_MIN,+  /** "/reader/probeBaudRates", TMR_uint32List */+  TMR_PARAM_PROBEBAUDRATES,+  /** "/reader/commandTimeout", uint32_t */+  TMR_PARAM_COMMANDTIMEOUT,+  /** "/reader/transportTimeout", uint32_t */+  TMR_PARAM_TRANSPORTTIMEOUT,+  /** "/reader/powerMode", TMR_SR_PowerMode */+  TMR_PARAM_POWERMODE,+  /** "/reader/userMode", TMR_SR_UserMode */+  TMR_PARAM_USERMODE,+  /** "/reader/antenna/checkPort", bool  */+  TMR_PARAM_ANTENNA_CHECKPORT,+  /** "/reader/antenna/portList", TMR_uint8List  */+  TMR_PARAM_ANTENNA_PORTLIST,+  /** "/reader/antenna/connectedPortList", TMR_uint8List  */+  TMR_PARAM_ANTENNA_CONNECTEDPORTLIST,+  /** "/reader/antenna/portSwitchGpos", TMR_uint8List  */+  TMR_PARAM_ANTENNA_PORTSWITCHGPOS,+  /** "/reader/antenna/settlingTimeList", TMR_PortValueList  */+  TMR_PARAM_ANTENNA_SETTLINGTIMELIST,+  /** "/reader/antenna/returnLoss", TMR_PortValueList */+  TMR_PARAM_ANTENNA_RETURNLOSS,+  /** "/reader/antenna/txRxMap", TMR_AntennaMapList  */+  TMR_PARAM_ANTENNA_TXRXMAP,+  /** "/reader/gpio/inputList", TMR_uint8List */+  TMR_PARAM_GPIO_INPUTLIST,+  /** "/reader/gpio/outputList", TMR_uint8List */+  TMR_PARAM_GPIO_OUTPUTLIST,+  /** "/reader/gen2/accessPassword", TMR_GEN2_Password */+  TMR_PARAM_GEN2_ACCESSPASSWORD,+  /** "/reader/gen2/q", TMR_GEN2_Q */+  TMR_PARAM_GEN2_Q,+  /** "/reader/gen2/tagEncoding", TMR_GEN2_TagEncoding */+  TMR_PARAM_GEN2_TAGENCODING,+  /** "/reader/gen2/session", TMR_GEN2_Session */+  TMR_PARAM_GEN2_SESSION,+  /** "/reader/gen2/target", TMR_GEN2_Target */+  TMR_PARAM_GEN2_TARGET,+  /** "/reader/gen2/BLF", TMR_GEN2_LinkFrequency */+  TMR_PARAM_GEN2_BLF,+  /** "/reader/gen2/tari", TMR_GEN2_Tari */+  TMR_PARAM_GEN2_TARI,+  /**"/reader/gen2/writeMode", TMR_GEN2_WriteMode */+  TMR_PARAM_GEN2_WRITEMODE,+  /** "/reader/gen2/bap", TMR_GEN2_Bap */+  TMR_PARAM_GEN2_BAP,+  /** "/reader/gen2/protocolExtension", TMR_GEN2_ProtocolExtension */+  TMR_PARAM_GEN2_PROTOCOLEXTENSION,+  /** "/reader/iso180006b/BLF", TMR_ISO180006B_LinkFrequency */+  TMR_PARAM_ISO180006B_BLF,+  /** "/reader/iso180006b/modulationDepth", TMR_ISO180006B_ModulationDepth */+  TMR_PARAM_ISO180006B_MODULATION_DEPTH,+  /** "/reader/iso180006b/delimiter", TMR_PARAM_ISO18000_6B_DELIMITER */+  TMR_PARAM_ISO180006B_DELIMITER,+  /** "/reader/read/asyncOffTime", uint32_t */+  TMR_PARAM_READ_ASYNCOFFTIME,+  /** "/reader/read/asyncOnTime", uint32_t */+  TMR_PARAM_READ_ASYNCONTIME,+  /** "/reader/read/plan", TMR_ReadPlan */+  TMR_PARAM_READ_PLAN,+  /** "/reader/radio/enablePowerSave", bool **/+  TMR_PARAM_RADIO_ENABLEPOWERSAVE,+  /** "/reader/radio/powerMax", int16_t */+  TMR_PARAM_RADIO_POWERMAX,+  /** "/reader/radio/powerMin", int16_t */+  TMR_PARAM_RADIO_POWERMIN,+  /** "/reader/radio/portReadPowerList", TMR_PortValueList */+  TMR_PARAM_RADIO_PORTREADPOWERLIST,+  /** "/reader/radio/portWritePowerList", TMR_PortValueList */+  TMR_PARAM_RADIO_PORTWRITEPOWERLIST,+  /** "/reader/radio/readPower", int32_t */+  TMR_PARAM_RADIO_READPOWER,+  /** "/reader/radio/writePower", int32_t */+  TMR_PARAM_RADIO_WRITEPOWER,+  /** "/reader/radio/temperature", int8_t */+  TMR_PARAM_RADIO_TEMPERATURE,+  /** "/reader/tagReadData/recordHighestRssi", bool */+  TMR_PARAM_TAGREADDATA_RECORDHIGHESTRSSI,+  /** "/reader/tagReadData/reportRssiInDbm", bool */+  TMR_PARAM_TAGREADDATA_REPORTRSSIINDBM,+  /** "/reader/tagReadData/uniqueByAntenna", bool */+  TMR_PARAM_TAGREADDATA_UNIQUEBYANTENNA,+  /** "/reader/tagReadData/uniqueByData", bool */+  TMR_PARAM_TAGREADDATA_UNIQUEBYDATA,+  /** "/reader/tagop/antenna", uint8_t */+  TMR_PARAM_TAGOP_ANTENNA,+  /** "/reader/tagop/protocol", TMR_TagProtocol */+  TMR_PARAM_TAGOP_PROTOCOL,+  /** "/reader/version/hardware", TMR_String */+  TMR_PARAM_VERSION_HARDWARE,+  /** "/reader/version/serial", TMR_String */+  TMR_PARAM_VERSION_SERIAL,+  /** "/reader/version/model", TMR_String */+  TMR_PARAM_VERSION_MODEL,+  /** "/reader/version/software", TMR_String */+  TMR_PARAM_VERSION_SOFTWARE,+  /** "/reader/version/supportedProtocols", TMR_TagProtocolList */+  TMR_PARAM_VERSION_SUPPORTEDPROTOCOLS,+  /** "/reader/region/hopTable", TMR_uint32List */+  TMR_PARAM_REGION_HOPTABLE,+  /** "/reader/region/hopTime", uint32_t */+  TMR_PARAM_REGION_HOPTIME,+  /** "/reader/region/id", TMR_Region */+  TMR_PARAM_REGION_ID,+  /** "/reader/region/supportedRegions", TMR_RegionList */+  TMR_PARAM_REGION_SUPPORTEDREGIONS,+  /** "/reader/region/lbt/enable", bool */+  TMR_PARAM_REGION_LBT_ENABLE,+  /** "/reader/licenseKey", TMR_uint8List */+  TMR_PARAM_LICENSE_KEY,+  /** "/reader/userConfig", TMR_UserConfigOption */+  TMR_PARAM_USER_CONFIG,+  /** "/reader/radio/enableSJC", bool */+  TMR_PARAM_RADIO_ENABLESJC,+  /** "/reader/extendedEpc", bool */+  TMR_PARAM_EXTENDEDEPC,+  /** "/reader/statistics", TMR_SR_ReaderStatistics */+  TMR_PARAM_READER_STATISTICS,+  /** "/reader/stats", TMR_Reader_StatsValues */+  TMR_PARAM_READER_STATS,+  /** "/reader/uri", TMR_String */+  TMR_PARAM_URI,+  /** "/reader/version/productGroupID", uint16_t */+  TMR_PARAM_PRODUCT_GROUP_ID,+  /** "/reader/version/productGroup", TMR_String */+  TMR_PARAM_PRODUCT_GROUP,+  /** "/reader/version/productID", uint16_t */+  TMR_PARAM_PRODUCT_ID,+  /** "/reader/tagReadData/tagopSuccesses", uint16_t */+  TMR_PARAM_TAGREADATA_TAGOPSUCCESSCOUNT,+  /** "/reader/tagReadData/tagopFailures",  uint16_t */+  TMR_PARAM_TAGREADATA_TAGOPFAILURECOUNT,+  /** "/reader/status/antennaEnable", bool */+  TMR_PARAM_STATUS_ENABLE_ANTENNAREPORT,+  /** "/reader/status/frequencyEnable", bool */+  TMR_PARAM_STATUS_ENABLE_FREQUENCYREPORT,+  /** "/reader/status/temperatureEnable", bool */+  TMR_PARAM_STATUS_ENABLE_TEMPERATUREREPORT,+  /** "/reader/tagReadData/enableReadFilter", bool */+  TMR_PARAM_TAGREADDATA_ENABLEREADFILTER,+  /** "/reader/tagReadData/readFilterTimeout", int32_t */+  TMR_PARAM_TAGREADDATA_READFILTERTIMEOUT,+  /** "/reader/tagReadData/uniqueByProtocol", bool */+  TMR_PARAM_TAGREADDATA_UNIQUEBYPROTOCOL,+  /** "/reader/description", TMR_String */+  TMR_PARAM_READER_DESCRIPTION,+  /** "/reader/hostname", TMR_String */+  TMR_PARAM_READER_HOSTNAME,+  /** "/reader/currentTime", struct tm */+  TMR_PARAM_CURRENTTIME,+	/** "/reader/gen2/writeReplyTimeout", uint16_t */+	TMR_PARAM_READER_WRITE_REPLY_TIMEOUT,+	/** "/reader/gen2/writeEarlyExit", bool */+	TMR_PARAM_READER_WRITE_EARLY_EXIT,+  /** "/reader/stats/enable", TMR_StatsEnable */+  TMR_PARAM_READER_STATS_ENABLE,+  /** "/reader/trigger/read/Gpi", TMR_uint8List */+  TMR_PARAM_TRIGGER_READ_GPI,+  /** "/reader/metadataflags", TMR_TRD_MetadataFlag*/+  TMR_PARAM_METADATAFLAG,+  /** "/reader/licensedFeatures", TMR_uint8List */+  TMR_PARAM_LICENSED_FEATURES,+  TMR_PARAM_SELECTED_PROTOCOLS,+  TMR_PARAM_END,+  TMR_PARAM_MAX = TMR_PARAM_END-1,++} TMR_Param;++#define TMR_PARAMWORDS ((1 + TMR_PARAM_MAX +31) / 32)++#ifdef __cplusplus+}+#endif++#endif /* _TMR_PARAMS_H */
+ cbits/api/tmr_read_plan.h view
@@ -0,0 +1,211 @@+/* ex: set tabstop=2 shiftwidth=2 expandtab cindent: */+#ifndef _TMR_READ_PLAN_H+#define _TMR_READ_PLAN_H+/** + *  @file tmr_read_plan.h+ *  @brief Mercury API - Read Plan Definitions+ *  @author Brian Fiegel+ *  @date 4/18/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 "tmr_tag_protocol.h"+#include "tmr_filter.h"+#include "tmr_tagop.h"++#ifdef  __cplusplus+extern "C" {+#endif+++/**+ * @defgroup readplan Read plans+ *+ * A read plan specifies the antennas, protocols, and filters to use+ * for a search (read). Each ReadPlan structure has a numeric weight+ * that controls what fraction of a search is used by that plan when+ * combined in a MultiReadPlan (see below). Read plans are specified+ * for the reader in the @c /reader/read/plan parameter.+ *+ * @{+ */++typedef struct TMR_ReadPlan TMR_ReadPlan;+typedef struct TMR_SimpleReadPlan TMR_SimpleReadPlan;+typedef struct TMR_MultiReadPlan TMR_MultiReadPlan;+typedef struct TMR_StopOnTagCount TMR_StopOnTagCount;+typedef struct TMR_TagObservationTrigger TMR_TagObservationTrigger;+typedef struct TMR_StopTrigger TMR_StopTrigger;+typedef struct TMR_GPITriggerRead TMR_GPITriggerRead;++/**+ * TODO: to be used later.+ **/ +/*struct TMR_TagObservationTrigger+{+};++struct TMR_StopTrigger+{+  TMR_TagObservationTrigger stopTrigger; +};*/++/**+ * A StopOnTagCount will be used in case of stop N trigger option.+ * It contains a flag to specify that user is requesting for stop+ * N trigger and a count to specify the number of tags user is + * requesting to read.+ **/+struct TMR_StopOnTagCount+{+  /* option for stop N trigger */+  bool stopNTriggerStatus;++  /* Number of tags to be read */+  uint32_t noOfTags;+};++/**+ * This will be used for GPI trigger read option.+ * It contains : + * enableTriggerRead a flag to specify that user is requesting for trigger read.+ * GPIList the list of GPI ports should be used to trigger the read.+ **/+struct TMR_GPITriggerRead+{+  /* option for trigger read */+  bool enable;+  /* RFU - The list of GPI ports */+  TMR_uint8List gpiList;+};++/**+ * A SimpleReadPlan contains a protocol, a list of antennas, and an+ * optional filter. The list of antennas may be an empty list, in+ * which case the reader will use all antennas in the antenna map (see+ * @c /reader/antenna/txRxMap) where the reader has detected an+ * antenna present. The filter describes any selection or filtering+ * operation to perform in the RFID protocol during the search. The+ * filter may be @c NULL, in which case no selection or filtering is+ * performed. Invalid combinations of protocols and filters (a Gen2+ * select on ISO180006B, for example) will produce an error at read+ * time.+ */+struct TMR_SimpleReadPlan+{+  /** The list of antennas to read on */+  TMR_uint8List antennas;+  /** The protocol to use for reading */+  TMR_TagProtocol protocol;+  /** The filter to apply to reading, or NULL */+  TMR_TagFilter *filter;+  /** The tag operation to apply to each read tag, or NULL */+  TMR_TagOp *tagop;+  /** Option to use the FastSearch */+  bool useFastSearch;+  /** The stop N trigger */+  TMR_StopOnTagCount stopOnCount;+  /** The GPI trigger read */+  TMR_GPITriggerRead triggerRead;+};++/**+ * A MultiReadPlan contains a list of other ReadPlan objects. The+ * relative weights of each of the included sub-plans are used+ * determine what fraction of the total read time to allot to that+ * sub-plan (for example, if the first plan has a weight of 20 and the+ * second has a weight of 10, the first 2/3 of any read will use the+ * first plan, and the remaining 1/3 will use the second+ * plan). MultiReadPlan is useful for specifying searches over+ * multiple protocols, for using different filters on different+ * antennas, and other combinations.+ */+struct TMR_MultiReadPlan+{+  /** Array of pointers to the subsidiary read plans */+  TMR_ReadPlan **plans;+  uint32_t totalWeight; /** Internal value - initialize to 0 */+  /** Number of elements in the array of read plans */+  uint8_t planCount;+};++/** The type of a read plan */+typedef enum TMR_ReadPlanType+{+  TMR_READ_PLAN_TYPE_INVALID,+  /** Simple read plan - one protocol, a set of antennas, an optional+   * tag filter, and an optional tag operation.+   */+  TMR_READ_PLAN_TYPE_SIMPLE,+  /** Multi-read plan - a list of read plans (simple or multi). */+  TMR_READ_PLAN_TYPE_MULTI+} TMR_ReadPlanType;++/**+ * A ReadPlan structure specifies the antennas, protocols, and filters+ * to use for a search (read).+ */+struct TMR_ReadPlan+{+  /** The type of the read plan and the type of the union that is populated */+  TMR_ReadPlanType type;+  /** The relative weight of this read plan */+  uint32_t weight;+  /** Option for Autonomous read */+  bool enableAutonomousRead;+  union+  {+    /** SimpleReadPlan contents */+    TMR_SimpleReadPlan simple;+    /** MultiReadPlan contents */+    TMR_MultiReadPlan multi;+  } u;+};++TMR_Status TMR_RP_init_simple(TMR_ReadPlan *plan, uint8_t antennaCount,+                              uint8_t *antennaList, TMR_TagProtocol protocol,+                              uint32_t weight);++TMR_Status TMR_RP_init_multi(TMR_ReadPlan *plan, TMR_ReadPlan **plans,+                             uint8_t planCount, uint32_t weight);++TMR_Status TMR_GPITR_init_enable(TMR_GPITriggerRead *triggerRead, bool enable);++TMR_Status TMR_RP_set_filter(TMR_ReadPlan *plan, TMR_TagFilter *filter);++TMR_Status TMR_RP_set_tagop(TMR_ReadPlan *plan, TMR_TagOp *tagop);+TMR_Status TMR_RP_set_enableTriggerRead(TMR_ReadPlan *plan, TMR_GPITriggerRead *triggerRead);++TMR_Status TMR_RP_set_useFastSearch(TMR_ReadPlan *plan, bool useFastSearch);+TMR_Status TMR_RP_set_stopTrigger(TMR_ReadPlan *plan, uint32_t count);+TMR_Status TMR_RP_set_enableAutonomousRead(TMR_ReadPlan *plan, bool autonomousRead);+/**+ * @}+ */++#ifdef  __cplusplus+}+#endif++#endif /* _TMR_READ_PLAN_H_ */
+ cbits/api/tmr_region.h view
@@ -0,0 +1,75 @@+/* ex: set tabstop=2 shiftwidth=2 expandtab cindent: */+#ifndef _TMR_REGION_H+#define _TMR_REGION_H+/**+ *  @file tmr_region.h+ *  @brief Mercury API - Region Definitions+ *  @author Brian Fiegel+ *  @date 4/18/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.+ */+#ifdef  __cplusplus+extern "C" {+#endif++/**+  * RFID regulatory regions+ */+typedef enum TMR_Region+{+  /** Unspecified region */         TMR_REGION_NONE = 0,+  /** North America */              TMR_REGION_NA   = 1,+  /** European Union */             TMR_REGION_EU   = 2,+  /** Korea */                      TMR_REGION_KR   = 3,+  /** India */                      TMR_REGION_IN   = 4,+  /** Japan */                      TMR_REGION_JP   = 5,+  /** People's Republic of China */ TMR_REGION_PRC  = 6,+  /** European Union 2 */           TMR_REGION_EU2  = 7,+  /** European Union 3 */           TMR_REGION_EU3  = 8,+  /** Korea 2*/                     TMR_REGION_KR2  = 9,+  /** People's Republic of China(840MHZ)*/TMR_REGION_PRC2 = 10,+  /** Australia */                  TMR_REGION_AU   = 11,+  /** New Zealand !!EXPERIMENTAL!! */ TMR_REGION_NZ   = 12,+  /** Reduced FCC region */         TMR_REGION_NA2 = 13,+  /** 5MHZ FCC band */              TMR_REGION_NA3 = 14,+  /** Israel  **/					TMR_REGION_IS= 15,+  /** Open */                       TMR_REGION_OPEN = 0xFF+} TMR_Region;++/** A list of TMR_Region values */+typedef struct TMR_RegionList+{+  /** Array of TMR_Region values */+  TMR_Region *list;+  /** Allocated size of the array */+  uint8_t max;+  /** Length of the list - may be larger than max, indicating truncated data */+  uint8_t len;+} TMR_RegionList;++#ifdef  __cplusplus+}+#endif++#endif /* _TMR_REGION_H_ */
+ cbits/api/tmr_serial_reader.h view
@@ -0,0 +1,473 @@+/* ex: set tabstop=2 shiftwidth=2 expandtab cindent: */+#ifndef _TMR_SERIAL_READER_H+#define _TMR_SERIAL_READER_H+/**+ *  @file tmr_serial_reader.h+ *  @brief Mercury API - Serial Reader interface+ *  @author Nathan Williams+ *  @date 10/20/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 "tmr_region.h"+#include "tmr_tag_protocol.h"+#include "tmr_serial_transport.h"++#define TMR_SR_MAX_PACKET_SIZE 256++#ifdef  __cplusplus+extern "C" {+#endif++/**+ * Defines the values for the parameter @c /reader/powerMode and the+ * return value and parameter to TMR_SR_cmdGetPowerMode and+ * TMR_SR_cmdSetPowerMode.+ */+typedef enum TMR_SR_PowerMode+{+  TMR_SR_POWER_MODE_MIN     = 0,+  TMR_SR_POWER_MODE_FULL    = 0,+  TMR_SR_POWER_MODE_MINSAVE = 1,+  TMR_SR_POWER_MODE_MEDSAVE = 2,+  TMR_SR_POWER_MODE_MAXSAVE = 3,+  TMR_SR_POWER_MODE_SLEEP   = 4,+  TMR_SR_POWER_MODE_MAX     = TMR_SR_POWER_MODE_SLEEP,+  TMR_SR_POWER_MODE_INVALID = TMR_SR_POWER_MODE_MAX + 1,+} TMR_SR_PowerMode;++/**+Operation Options for cmdSetProtocolLicenseKey+*/+typedef enum TMR_SR_SetProtocolLicenseOption+{+/**  Set Valid License Key */+TMR_SR_SET_LICENSE_KEY = 0x01,     +/**  Erase License Key */+TMR_SR_ERASE_LICENSE_KEY = 0x02, +}TMR_SR_SetProtocolLicenseOption;++/** +Operation Options for cmdSetUserProfile +*/+typedef enum TMR_SR_UserConfigOperation+{          +/**  Save operation */+TMR_USERCONFIG_SAVE = 0x01,     +/**  Restore operation */+TMR_USERCONFIG_RESTORE = 0x02, +/**  Verify operation */+TMR_USERCONFIG_VERIFY = 0x03,  +/** Clear operation  */+TMR_USERCONFIG_CLEAR = 0x04,+/** Save read plan configuration */+TMR_USERCONFIG_SAVE_WITH_READPLAN = 0x05,+}TMR_SR_UserConfigOperation; ++/**+Congfiguration category for cmdSetUserProfile+*/+typedef enum TMR_SR_UserConfigCategory+{+  /** All Configuration */+TMR_SR_ALL=0x01,   +}TMR_SR_UserConfigCategory;++/** +The configuration type for cmdSetUserProfile+*/+typedef enum TMR_SR_UserConfigType+{+/** Firmware default configurations */+TMR_SR_FIRMWARE_DEFAULT=0x00,+/** Custom configurations */+TMR_SR_CUSTOM_CONFIGURATION=0x01,      +}TMR_SR_UserConfigType;++/**+ * The user profile operation structure+ */+typedef struct TMR_SR_UserConfigOp+{+  /** @privatesection */++  /** User config category */+  TMR_SR_UserConfigCategory category;+  /** User config operation */+  TMR_SR_UserConfigOperation op;+}TMR_SR_UserConfigOp;++/**+ * Defines the values for the parameter /reader/userMode and the+ * return value and parameter to TMR_SR_cmdGetUserMode() and+ * TMR_SR_cmdSetUserMode.+ */+typedef enum TMR_SR_UserMode+{+  TMR_SR_USER_MODE_MIN      = 0,+  TMR_SR_USER_MODE_UNSPEC   = 0,+  TMR_SR_USER_MODE_PRINTER  = 1,+  TMR_SR_USER_MODE_CONVEYOR = 2,+  TMR_SR_USER_MODE_PORTAL   = 3,+  TMR_SR_USER_MODE_HANDHELD = 4,+  TMR_SR_USER_MODE_MAX      = TMR_SR_USER_MODE_HANDHELD,+  TMR_SR_USER_MODE_INVALID  = TMR_SR_USER_MODE_MAX + 1,+}TMR_SR_UserMode;++/**+ * This represents the types of Q algorithms avaliable on the reader.+ */+typedef enum TMR_SR_GEN2_QType+{+  TMR_SR_GEN2_Q_MIN     = 0,+  TMR_SR_GEN2_Q_DYNAMIC = 0,+  TMR_SR_GEN2_Q_STATIC  = 1,+  TMR_SR_GEN2_Q_MAX     = TMR_SR_GEN2_Q_STATIC,+  TMR_SR_GEN2_Q_INVALID = TMR_SR_GEN2_Q_MAX + 1,+} TMR_SR_GEN2_QType;++/** Configuration of the static-Q algorithm. */+typedef struct TMR_SR_GEN2_QStatic+{+  /** The initial Q value to use. */+  uint8_t initialQ;+} TMR_SR_GEN2_QStatic;++/**+ * This represents a Q algorithm on the reader.+ */+typedef struct TMR_SR_GEN2_Q+{+  /** The type of Q algorithm. */+  TMR_SR_GEN2_QType type;+  union+  {+    /** Configuration of the static-Q algorithm. */+    TMR_SR_GEN2_QStatic staticQ;+  }u;+} TMR_SR_GEN2_Q;+++/** An antenna port with an associated int32_t value. */+typedef struct TMR_PortValue+{+  /** The port number */+  uint8_t port;+  /** The value */+  int32_t value;+} TMR_PortValue;++/** List of TMR_PortValue values */+typedef struct TMR_PortValueList+{+  /** The array of values */+  TMR_PortValue *list;+  /** The number of entries there is space for in the array */+  uint8_t max;+  /** The number of entries in the list - may be larger than max, indicating truncated data. */+  uint8_t len;+} TMR_PortValueList;+++/**+ * Mapping between an arbitrary "antenna" number and a TX/RX port+ * pair. Not all TX/RX pairings are valid for a device.+ */+typedef struct TMR_AntennaMap+{+  /** The antenna number - an arbitrary value. */+  uint8_t antenna;+  /** The device antenna port to use for transmission. */+  uint8_t txPort;+  /** The device antenna port to use for reception. */+  uint8_t rxPort;+} TMR_AntennaMap;++/** List of antenna mappings */+typedef struct TMR_AntennaMapList+{+  /** The array of values */+  TMR_AntennaMap *list;+  /** The number of entries there is space for in the array */+  uint8_t max;+  /** The number of entries in the list - may be larger than max, indicating truncated data. */+  uint8_t len;+} TMR_AntennaMapList;++/**+ * The version structure returned from cmdVersion().+ */+typedef struct TMR_SR_VersionInfo+{+  /** Bootloader version, as four 8-bit numbers */+  uint8_t bootloader[4];+  /** Hardware version. Opaque format */+  uint8_t hardware[4];+  /** Date app firmware was built, as BCD YYYYMMDD */+  uint8_t fwDate[4];+  /** App firmware version, as four 8-bit numbers */+  uint8_t fwVersion[4];+  /** Bitmask of the protocols supported by the device (indexed by TMR_TagProtocol values minus one).  */+  uint32_t protocols;+} TMR_SR_VersionInfo;++/**+ * Current message TransportType+ **/+typedef enum TMR_TransportType+{+  /* Serial */+  TMR_SR_MSG_SOURCE_SERIAL = 0x0000,+  /* USB */+  TMR_SR_MSG_SOURCE_USB = 0x0003,+  /* Unknown */+  TMR_SR_MSG_SOURCE_UNKNOWN = 0x0004,+}TMR_TransportType;++/**+ * The serial reader structure.+ */+typedef struct TM_SR_SerialReader+{+  /** @privatesection */++  /* Serial transport information */+  TMR_SR_SerialTransport transport;+  union+  {+#ifdef TMR_ENABLE_SERIAL_TRANSPORT_NATIVE+    TMR_SR_SerialPortNativeContext nativeContext;+#endif+  } transportContext;++  /* User-configurable values */+  uint32_t baudRate;+  TMR_AntennaMapList *txRxMap;+  TMR_GEN2_Password gen2AccessPassword;+  uint32_t transportTimeout;+  uint32_t commandTimeout;+  TMR_Region regionId;++  /* Static storage for the default map */+  TMR_AntennaMap staticTxRxMapData[TMR_SR_MAX_ANTENNA_PORTS];+  TMR_AntennaMapList staticTxRxMap;++  /* Mostly-fixed information about the connected reader */+  TMR_SR_VersionInfo versionInfo;+  uint32_t portMask;++  /* Option to enable or disable the pre-amble */+  bool supportsPreamble;++  /* Cache extendedEPC setting */+  bool extendedEPC;++  /* Cached values */+  TMR_SR_PowerMode powerMode;+  TMR_TagProtocol currentProtocol;+  int8_t gpioDirections;++  /* Large bitmask that stores whether each parameter's presence+   * is known or not.+   */+  uint32_t paramConfirmed[TMR_PARAMWORDS];+  /* Large bitmask that, if the corresponding bit in paramConfirmed is set,+   * stores whether each parameter is present or not.+   */+  uint32_t paramPresent[TMR_PARAMWORDS];++  /* Temporary storage during a read and subsequent fetch of tags */+  uint32_t readTimeLow, readTimeHigh;+  uint32_t lastSentTagTimestampHigh, lastSentTagTimestampLow;+  uint32_t searchTimeoutMs;+  +  /* Number of tags reported by module read command.+   * In streaming mode, exact quantity is unknown, so use+   * 0 if stream has ended, non-zero if end-of-stream has+   * not yet been detected. */+  int tagsRemaining;+  /* Buffer tag records fetched from module but not yet passed to caller. */+  uint8_t bufResponse[TMR_SR_MAX_PACKET_SIZE];+  /* bufResponse read index */+  uint8_t bufPointer;+  /* Number of tag records in buffer but not yet passed to caller */+  uint8_t tagsRemainingInBuffer;+  /*TMR opCode*/+  uint8_t opCode;+  /*Gen2 Q Value from previous tagop */+  TMR_SR_GEN2_Q oldQ;+  /*Gen2 WriteMode*/+  TMR_GEN2_WriteMode writeMode;+  /* Buffer to store additional error message */+  char errMsg[TMR_SR_MAX_PACKET_SIZE];+  /* Product group id */+  uint16_t productId;+  /* Tag operation success count */+  uint16_t tagopSuccessCount;+  /* Tag operation failure count */+  uint16_t tagopFailureCount;+  /* Enable read filtering */+  bool enableReadFiltering;+  /* Read filter timeout */+  int32_t readFilterTimeout;+  /* Option to use the user specified transportTimeout */+  bool usrTimeoutEnable;+  /* Enable CRC calculation */+  bool crcEnabled;+  /* TransportType */+  TMR_TransportType transportType;+  /* Option for Gen2 all memory bank read */+  bool gen2AllMemoryBankEnabled;+  /* option for Gen2 Bap parameter */+  bool isBapEnabled;+  /* baud rates to be used for serial communication */+  TMR_uint32List probeBaudRates;+  /* storage for the probe baud rates */+  uint32_t baudRates[TMR_MAX_PROBE_BAUDRATE_LENGTH];+  /* Flag to be raised when Autonomous read is requested */+  bool enableAutonomousRead;+  /* The flag to be used in case of tag reading */+  bool isBasetimeUpdated;+} TMR_SR_SerialReader;++/**+ * This object is returned from TMR_SR_cmdGetReaderStatistics.+ */+typedef struct TMR_SR_ReaderStatistics+{+  /** The number of entries in the arrays. */+  uint8_t numPorts;+  /** per-port RF on time, in milliseconds. */+  uint32_t rfOnTime[TMR_SR_MAX_ANTENNA_PORTS];+  /** The per-port noise floor with transmitter off */+  uint32_t noiseFloor[TMR_SR_MAX_ANTENNA_PORTS];+  /** The per-port noise floor while transmitting. */+  uint32_t noiseFloorTxOn[TMR_SR_MAX_ANTENNA_PORTS];+}TMR_SR_ReaderStatistics;++/**+ *  Object of this contains antenna status report+ */+typedef struct TMR_SR_AntennaStatusReport+{+  /** Antenna */+  uint8_t ant;+}TMR_SR_AntennaStatusReport;++/**+ * Object of this contains frequency status report+ */+typedef struct TMR_SR_FrequencyStatusReport+{+  /** RF carrier frequency */+  uint32_t freq;+}TMR_SR_FrequencyStatusReport;++/**+ * Object of this contains temperature status report.+ */+typedef struct TMR_SR_TemperatureStatusReport+{+  /** Temperature */+  int8_t temp;+}TMR_SR_TemperatureStatusReport;++/**+ *  Status report content flags+ */+typedef enum TMR_SR_StatusType+{+  /* None */+  TMR_SR_STATUS_NONE = 0x0000,+  /* Frequency */+  TMR_SR_STATUS_FREQUENCY = 0x0002,+  /* Temperature */+  TMR_SR_STATUS_TEMPERATURE = 0x0004,+  /* Current Antenna Ports */+  TMR_SR_STATUS_ANTENNA = 0x0008,+  /* All */+  TMR_SR_STATUS_ALL = 0x000E,+  TMR_SR_STATUS_MAX = 4,+}TMR_SR_StatusType;++/**+ * This object contains the information related to status reports+ * sent by the module during continuous reading+ */+typedef struct TMR_SR_StatusReport+{+  TMR_SR_StatusType type;+  union+  {+    /** Antenna status report */+    TMR_SR_AntennaStatusReport asr;+    /** Frequency status report */+    TMR_SR_FrequencyStatusReport fsr;+    /** Temperature status report */+    TMR_SR_TemperatureStatusReport tsr;+  } u;+}TMR_SR_StatusReport;+++TMR_Status TMR_SR_connect(struct TMR_Reader *reader);+TMR_Status TMR_SR_destroy(struct TMR_Reader *reader);+TMR_Status TMR_SR_read(struct TMR_Reader *reader, uint32_t timeoutMs, int32_t *tagCount);+TMR_Status TMR_SR_hasMoreTags(struct TMR_Reader *reader);+TMR_Status TMR_SR_getNextTag(struct TMR_Reader *reader, TMR_TagReadData *read);+TMR_Status TMR_SR_executeTagOp(struct TMR_Reader *reader, TMR_TagOp *tagop, TMR_TagFilter *filter, TMR_uint8List *data);+TMR_Status TMR_SR_writeTag(struct TMR_Reader *reader, const TMR_TagFilter *filter, const TMR_TagData *data);+TMR_Status TMR_SR_killTag(struct TMR_Reader *reader, const TMR_TagFilter *filter, const TMR_TagAuthentication *auth);+TMR_Status TMR_SR_lockTag(struct TMR_Reader *reader, const TMR_TagFilter *filter, TMR_TagLockAction *action);+TMR_Status TMR_SR_readTagMemBytes(struct TMR_Reader *reader, const TMR_TagFilter *filter,+                              uint32_t bank, uint32_t address,+                              uint16_t count, uint8_t data[]);+TMR_Status TMR_SR_readTagMemWords(struct TMR_Reader *reader, const TMR_TagFilter *filter,+                              uint32_t bank, uint32_t address,+                              uint16_t count, uint16_t *data);+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 TMR_SR_writeTagMemWords(struct TMR_Reader *reader, const TMR_TagFilter *filter,+                               uint32_t bank, uint32_t address,+                               uint16_t count, const uint16_t data[]);+TMR_Status TMR_SR_gpoSet(struct TMR_Reader *reader, uint8_t count, const TMR_GpioPin state[]);+TMR_Status TMR_SR_gpiGet(struct TMR_Reader *reader, uint8_t *count, TMR_GpioPin state[]);+TMR_Status TMR_SR_firmwareLoad(TMR_Reader *reader, void *cookie,+                               TMR_FirmwareDataProvider provider);+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);+TMR_Status TMR_init_UserConfigOp(TMR_SR_UserConfigOp *config, TMR_SR_UserConfigOperation op);+TMR_Status TMR_SR_reboot(struct TMR_Reader *reader);++/**+ * Initialize a serial reader. The reader->u.serialReader.transport+ * structure must be initialized before calling this.+ */+TMR_Status TMR_SR_SerialReader_init(TMR_Reader *reader);++#ifdef __cplusplus+}+#endif++#endif /* _TMR_SERIAL_READER_H */
+ cbits/api/tmr_serial_transport.h view
@@ -0,0 +1,232 @@+#ifndef _TMR_SERIAL_TRANSPORT_H+#define _TMR_SERIAL_TRANSPORT_H+/**+ *  @file tmr_serial_transport.h+ *  @brief Mercury API - Serial Transport Interface+ *  @author Nathan Williams+ *  @date 10/20/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.+ */++#ifdef  __cplusplus+extern "C" {+#endif++#ifdef TMR_ENABLE_SERIAL_TRANSPORT_LLRP+#include <sys/types.h>+#include <sys/socket.h>+#endif++#if defined(WIN32) || defined(WINCE)+#if !defined(_WINSOCK2API_) && !defined(_WINSOCKAPI_)+#include <winsock2.h>+#endif+#endif++#ifdef OSDEP_SERIAL_INCLUDE+#include "osdep_serial_transport.h"+#endif++#ifndef PLATFORM_HANDLE+# ifdef WIN32+#  define PLATFORM_HANDLE HANDLE+# else+#if defined(ARDUINO) || defined(FREERTOS_USED)+#   define PLATFORM_HANDLE void*+# else+#  define PLATFORM_HANDLE int+# endif+# endif+#endif+typedef struct TMR_SR_SerialTransport TMR_SR_SerialTransport;+/**+ * The TMR_SR_SerialTransport structure is the mechanism that the+ * SerialReader layer uses to conduct low-level communications with+ * the device. Users may create their own SerialTransport objects for+ * systems with custom serial communication needs, and then use+ * TMR_SR_SerialReader_init() to complete the construction of the+ * reader object, as an alternative to using TMR_create().+ *+ * @see TMR_SR_SerialPortTransportInit and+ * TMR_SR_LlrpEapiTransportInit for pre-existing+ * TMR_SR_SerialTransport implementations.+ */+struct TMR_SR_SerialTransport+{+  /** Context value made avaliable to callback functions */+  void *cookie;++  /**+   * This callback causes the communication interface to be opened but+   * does not transmit any serial-layer data. This should perform+   * actions such as opening a serial port device or establishing a+   * network connection within a wrapper protocol.+   *+   * @param this The TMR_SR_SerialTransport structure.+   */+  TMR_Status (*open)(TMR_SR_SerialTransport *);++  /**+   * This callback transmits the provided bytes on the serial+   * transport. If the operation takes longer than timeoutMs to+   * complete, TMR_ERROR_TIMEOUT should be returned.+   *+   * @param this The TMR_SR_SerialTransport structure.+   * @param length The number of bytes to send.+   * @param message Pointer to the bytes to send.+   * @param timeoutMs The duration for the operation to complete.+   */+  TMR_Status (*sendBytes)(TMR_SR_SerialTransport *, uint32_t length, +                          uint8_t* message, const uint32_t timeoutMs);++  /**+   * This callback recieves bytes message on the serial transport. The+   * length parameter contains the size of the buffer pointed to by+   * message. If the operation takes longer than timeoutMs to receive+   * length bytes, TMR_ERROR_TIMEOUT should be returned.+   *+   * @param this The TMR_SR_SerialTransport structure.+   * @param length The number of bytes to receive.+   * @param[out] messageLength The number of bytes received.+   * @param[out] message Pointer to the location to store received bytes.+   * @param timeoutMs The duration for the operation to complete.+   */+  TMR_Status (*receiveBytes)(TMR_SR_SerialTransport *, uint32_t length,+                             uint32_t *messageLength, uint8_t* message, const uint32_t timeoutMs);+  /**+   * This callback causes the underlying serial transport connected to+   * the device to the provided baud rate.+   *+   * @param this The TMR_SR_SerialTransport structure.+   * @param rate The baud rate to set.+   */+  TMR_Status (*setBaudRate)(TMR_SR_SerialTransport *, uint32_t rate);++  /**+   * This callback releases any resources allocated by the transport+   * layer and informs the other end, if necessary, that the+   * connection is ending.+   *+   * @param this The TMR_SR_SerialTransport structure.+   */+  TMR_Status (*shutdown)(TMR_SR_SerialTransport *);++  /**+   * This callback takes any actions necessary (possibly none) to+   * remove unsent data from the output path.+   *+   * @param this The TMR_SR_SerialTransport structure.+   */+  TMR_Status (*flush)(TMR_SR_SerialTransport *);+};++#ifdef TMR_ENABLE_SERIAL_TRANSPORT_NATIVE+/**+ * The context structure used by the provided serial port transport interface.+ */+typedef struct TMR_SR_SerialPortNativeContext+{+  /** @privatesection */+  /** The file handle for the serial device */+  PLATFORM_HANDLE handle;+  /** The filesystem name of the serial device */+  char devicename[TMR_MAX_READER_NAME_LENGTH];+} TMR_SR_SerialPortNativeContext;+#endif++#ifdef TMR_ENABLE_SERIAL_TRANSPORT_LLRP+/**+ * The context structure used by the provided+ * serial-encapsulated-in-LLRP transport interface.+ */+typedef struct TMR_SR_LlrpEapiTransportContext+{+  /** @privatesection */+  /** The network address of the remote device */+  struct sockaddr_storage addr;+  /** The length of the contents of addr */+  socklen_t addrlen;+  /** Whether or not to power-cycle the reader upon opening a connection */+  bool powerCycleAtOpen;+  /** The file handle for the network socket */+  int socket;+  /** The current LLRP message ID */+  int sequenceId;+  /** Temporary buffer for receiving and processing a LLRP packet */+  uint8_t buf[270];+  /** Pointers into the buffer */+  uint16_t bufstart, buflen;+} TMR_SR_LlrpEapiTransportContext;+#endif++#ifdef TMR_ENABLE_SERIAL_TRANSPORT_NATIVE+/**+ * Initialize a TMR_SR_SerialTransport structure with a given serial device.+ *+ * @param transport The TMR_SR_SerialTransport structure to initialize.+ * @param context A TMR_SR_SerialPortNativeContext structure for the callbacks to use.+ * @param device The path or name of the serial device (@c /dev/ttyS0, @c COM1)+ */+#if defined(WIN32) || defined(WINCE)+__declspec(dllexport)+#endif+TMR_Status TMR_SR_SerialTransportNativeInit(TMR_SR_SerialTransport *transport,+                                            TMR_SR_SerialPortNativeContext *context,+                                            const char *device);+#if defined(WIN32) || defined(WINCE)+__declspec(dllexport)+#endif+TMR_Status TMR_SR_SerialTransportTcpNativeInit(TMR_SR_SerialTransport *transport,+                                            TMR_SR_SerialPortNativeContext *context,+                                            const char *device);+#endif /* TMR_ENABLE_SERIAL_TRANSPORT_NATIVE */++#ifdef TMR_ENABLE_SERIAL_TRANSPORT_LLRP+/**+ * Initialize a TMR_SR_SerialTransport structure with a LLRP+EAPI+ * connection to the given host and port.+ *+ * @param transport The TMR_SR_SerialTransport structure to initialize.+ * @param context A TMR_SR_LlrpEapiTransportContext structure for the callbacks to use.+ * @param host The name or address of the network device implementing LLRP+EAPI.+ * @param port The TCP port to use for the connection.+ * @param powerCycleAtOpen Whether or not to power-cycle the reader upon opening a connection.+ */+TMR_Status TMR_SR_LlrpEapiTransportInit(TMR_SR_SerialTransport *transport,+                                        TMR_SR_LlrpEapiTransportContext *context,+                                        const char *host, int port,+                                        bool powerCycleAtOpen);++/**+ * Power-cycle a device attached via LLRP transport+ * @param transport The TMR_SR_SerialTransport connected to the device+ */+TMR_Status TMR_LlrpEapiPowerCycle(TMR_SR_SerialTransport *this);+#endif++#ifdef __cplusplus+}+#endif++#endif /* _TMR_SERIAL_TRANSPORT_H */
+ cbits/api/tmr_status.h view
@@ -0,0 +1,238 @@+#ifndef _TMR_STATUS_H+#define _TMR_STATUS_H++/**+ *  @file tmr_status.h+ *  @brief Mercury API - status codes+ *  @author Nathan Williams+ *  @date 11/24/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 "tm_config.h"+#ifdef WINCE+#include <stdint_win32.h>+#else+#include <stdint.h>+#endif++#ifdef  __cplusplus+extern "C" {+#endif++typedef uint32_t TMR_Status;++#define TMR_STATUS_MAKE(type, value) (((type) << 24) | (value))+#define TMR_STATUS_GET_TYPE(x)       (((x) >> 24) & 0xff)+#define TMR_STATUS_GET_VALUE(x)      ((x) & 0xffffff)++#define TMR_SUCCESS_TYPE    0L+#define TMR_ERROR_TYPE_COMM 1L+#define TMR_ERROR_TYPE_CODE 2L+#define TMR_ERROR_TYPE_MISC 3L+#define TMR_ERROR_TYPE_LLRP 4L++#define TMR_SUCCESS TMR_STATUS_MAKE(TMR_SUCCESS_TYPE, 0)++#define TMR_ERROR_CODE(x)     TMR_STATUS_MAKE(TMR_ERROR_TYPE_CODE, (x))+#define TMR_ERROR_IS_CODE(x)  (TMR_ERROR_TYPE_CODE == TMR_STATUS_GET_TYPE(x))+#define TMR_ERROR_GET_CODE(x) TMR_STATUS_GET_VALUE(x)+/**Invalid number of arguments  */+#define TMR_ERROR_MSG_WRONG_NUMBER_OF_DATA                TMR_ERROR_CODE(0x100)+/**Command opcode not recognized.  */+#define TMR_ERROR_INVALID_OPCODE                          TMR_ERROR_CODE(0x101)+/**Command opcode recognized, but is not supported.  */+#define TMR_ERROR_UNIMPLEMENTED_OPCODE                    TMR_ERROR_CODE(0x102)+/**Requested power setting is above the allowed maximum.  */+#define TMR_ERROR_MSG_POWER_TOO_HIGH                      TMR_ERROR_CODE(0x103)+/**Requested frequency is outside the allowed range.  */+#define TMR_ERROR_MSG_INVALID_FREQ_RECEIVED               TMR_ERROR_CODE(0x104)+/**Parameter value is outside the allowed range.  */+#define TMR_ERROR_MSG_INVALID_PARAMETER_VALUE             TMR_ERROR_CODE(0x105)+/**Requested power setting is below the allowed minimum. */+#define TMR_ERROR_MSG_POWER_TOO_LOW                       TMR_ERROR_CODE(0x106)+/**Command not supported. */+#define TMR_ERROR_UNIMPLEMENTED_FEATURE                   TMR_ERROR_CODE(0x109)+/**Requested serial speed is not supported. */+#define TMR_ERROR_INVALID_BAUD_RATE                       TMR_ERROR_CODE(0x10a)+/**Region is not supported. */+#define TMR_ERROR_INVALID_REGION                          TMR_ERROR_CODE(0x10b)+/** License key code is invalid */+#define TMR_ERROR_INVALID_LICENSE_KEY                     TMR_ERROR_CODE(0x10c)+/**Firmware is corrupt: Checksum doesn't match content. */+#define TMR_ERROR_BL_INVALID_IMAGE_CRC                    TMR_ERROR_CODE(0x200)+/**Serial protocol status code for this exception. */+#define TMR_ERROR_BL_INVALID_APP_END_ADDR                 TMR_ERROR_CODE(0x201)+/**Internal reader error.  Contact support. */+#define TMR_ERROR_FLASH_BAD_ERASE_PASSWORD                TMR_ERROR_CODE(0x300)+/**Internal reader error.  Contact support. */+#define TMR_ERROR_FLASH_BAD_WRITE_PASSWORD                TMR_ERROR_CODE(0x301)+/**Internal reader error.  Contact support. */+#define TMR_ERROR_FLASH_UNDEFINED_SECTOR                  TMR_ERROR_CODE(0x302)+/**Internal reader error.  Contact support. */+#define TMR_ERROR_FLASH_ILLEGAL_SECTOR                    TMR_ERROR_CODE(0x303)+/**Internal reader error.  Contact support. */+#define TMR_ERROR_FLASH_WRITE_TO_NON_ERASED_AREA          TMR_ERROR_CODE(0x304)+/**Internal reader error.  Contact support. */+#define TMR_ERROR_FLASH_WRITE_TO_ILLEGAL_SECTOR           TMR_ERROR_CODE(0x305)+/**Internal reader error.  Contact support. */+#define TMR_ERROR_FLASH_VERIFY_FAILED                     TMR_ERROR_CODE(0x306)+/**Reader was asked to find tags, but none were detected. */+#define TMR_ERROR_NO_TAGS_FOUND                           TMR_ERROR_CODE(0x400)+/**RFID protocol has not been configured. */+#define TMR_ERROR_NO_PROTOCOL_DEFINED                     TMR_ERROR_CODE(0x401)+/**Requested RFID protocol is not recognized. */+#define TMR_ERROR_INVALID_PROTOCOL_SPECIFIED              TMR_ERROR_CODE(0x402)+/**For write-then-lock commands, tag was successfully written, but lock failed.*/+#define TMR_ERROR_WRITE_PASSED_LOCK_FAILED                TMR_ERROR_CODE(0x403)+/**Tag data was requested, but could not be read. */+#define TMR_ERROR_PROTOCOL_NO_DATA_READ                   TMR_ERROR_CODE(0x404)+/**Reader not fully initialized and hasn't yet turned on its radio.  Have you set region?*/+#define TMR_ERROR_AFE_NOT_ON                              TMR_ERROR_CODE(0x405)+/**Write to tag failed. */+#define TMR_ERROR_PROTOCOL_WRITE_FAILED                   TMR_ERROR_CODE(0x406)+/**Command is not supported in the current RFID protocol. */+#define TMR_ERROR_NOT_IMPLEMENTED_FOR_THIS_PROTOCOL       TMR_ERROR_CODE(0x407)+/**Data does not conform to protocol standards. */+#define TMR_ERROR_PROTOCOL_INVALID_WRITE_DATA             TMR_ERROR_CODE(0x408)+/**Requested data address is outside the valid range. */+#define TMR_ERROR_PROTOCOL_INVALID_ADDRESS                TMR_ERROR_CODE(0x409)+/**Unknown error during RFID operation. */+#define TMR_ERROR_GENERAL_TAG_ERROR                       TMR_ERROR_CODE(0x40a)+/**Read Tag Data was asked for more data than it supports. */+#define TMR_ERROR_DATA_TOO_LARGE                          TMR_ERROR_CODE(0x40b)+/**Incorrect password was provided to Kill Tag. */+#define TMR_ERROR_PROTOCOL_INVALID_KILL_PASSWORD          TMR_ERROR_CODE(0x40c)+/**Kill failed for unknown reason. */+#define TMR_ERROR_PROTOCOL_KILL_FAILED                    TMR_ERROR_CODE(0x40e)+/**Internal reader error.  Contact support. */+#define TMR_ERROR_PROTOCOL_BIT_DECODING_FAILED            TMR_ERROR_CODE(0x40f)+/**Internal reader error.  Contact support. */+#define TMR_ERROR_PROTOCOL_INVALID_EPC                    TMR_ERROR_CODE(0x410)+/**Internal reader error.  Contact support. */+#define TMR_ERROR_PROTOCOL_INVALID_NUM_DATA               TMR_ERROR_CODE(0x411)+/**Internal reader error.  Contact support. */+#define TMR_ERROR_GEN2_PROTOCOL_OTHER_ERROR               TMR_ERROR_CODE(0x420)+/**Internal reader error.  Contact support. */+#define TMR_ERROR_GEN2_PROTOCOL_MEMORY_OVERRUN_BAD_PC     TMR_ERROR_CODE(0x423)+/**Internal reader error.  Contact support. */+#define TMR_ERROR_GEN2_PROTOCOL_MEMORY_LOCKED             TMR_ERROR_CODE(0x424)+/**Authentication failed with specified key. */+#define TMR_ERROR_GEN2_PROTOCOL_V2_AUTHEN_FAILED				TMR_ERROR_CODE(0x425)+/** Untrace operation failed. */+#define TMR_ERROR_GEN2_PROTOCOL_V2_UNTRACE_FAILED				TMR_ERROR_CODE(0x426)+/**Internal reader error.  Contact support. */+#define TMR_ERROR_GEN2_PROTOCOL_INSUFFICIENT_POWER        TMR_ERROR_CODE(0x42b)+/**Internal reader error.  Contact support. */+#define TMR_ERROR_GEN2_PROTOCOL_NON_SPECIFIC_ERROR        TMR_ERROR_CODE(0x42f)+/**Internal reader error.  Contact support. */ +#define TMR_ERROR_GEN2_PROTOCOL_UNKNOWN_ERROR             TMR_ERROR_CODE(0x430)+/**A command was received to set a frequency outside the specified range. */+#define TMR_ERROR_AHAL_INVALID_FREQ                       TMR_ERROR_CODE(0x500)+/**With LBT enabled an attempt was made to set the frequency to an occupied channel. */+#define TMR_ERROR_AHAL_CHANNEL_OCCUPIED                   TMR_ERROR_CODE(0x501)+/**Checking antenna status while CW is on is not allowed. */+#define TMR_ERROR_AHAL_TRANSMITTER_ON                     TMR_ERROR_CODE(0x502)+/** Antenna not detected during pre-transmit safety test. */+#define TMR_ERROR_ANTENNA_NOT_CONNECTED                   TMR_ERROR_CODE(0x503)+/**Reader temperature outside safe range. */+#define TMR_ERROR_TEMPERATURE_EXCEED_LIMITS               TMR_ERROR_CODE(0x504)+/** Excess power detected at transmitter port, usually due to antenna tuning mismatch. */+#define TMR_ERROR_HIGH_RETURN_LOSS                        TMR_ERROR_CODE(0x505)+#define TMR_ERROR_INVALID_ANTENNA_CONFIG                  TMR_ERROR_CODE(0x507)+/**Asked for more tags than were available in the buffer. */+#define TMR_ERROR_TAG_ID_BUFFER_NOT_ENOUGH_TAGS_AVAILABLE TMR_ERROR_CODE(0x600)+/**Too many tags are in buffer.  Remove some with Get Tag ID Buffer or Clear Tag ID Buffer. */+#define TMR_ERROR_TAG_ID_BUFFER_FULL                      TMR_ERROR_CODE(0x601)+/**Internal error -- reader is trying to insert a duplicate tag record.  Contact support. */+#define TMR_ERROR_TAG_ID_BUFFER_REPEATED_TAG_ID           TMR_ERROR_CODE(0x602)+/**Asked for tags than a single transaction can handle. */+#define TMR_ERROR_TAG_ID_BUFFER_NUM_TAG_TOO_LARGE         TMR_ERROR_CODE(0x603)+/**Blocked response to get additional data from host. */+#define TMR_ERROR_TAG_ID_BUFFER_AUTH_REQUEST              TMR_ERROR_CODE(0x604)+/**Internal reader error.  Contact support. */+#define TMR_ERROR_SYSTEM_UNKNOWN_ERROR                    TMR_ERROR_CODE(0x7f00)+/**Internal reader error.  Contact support. */+#define TMR_ERROR_TM_ASSERT_FAILED                        TMR_ERROR_CODE(0x7f01)++#define TMR_ERROR_COMM(x)           TMR_STATUS_MAKE(TMR_ERROR_TYPE_COMM, (x))+#define TMR_ERROR_IS_COMM(x)        (TMR_ERROR_TYPE_COMM == TMR_STATUS_GET_TYPE(x))+#define TMR_ERROR_COMM_ERRNO(x)     TMR_ERROR_COMM(0x8000 | (x))+#define TMR_ERROR_COMM_IS_ERRNO(x)  (0x8000 == (TMR_STATUS_GET_VALUE(x) & 0x8000))+#define TMR_ERROR_COMM_GET_ERRNO(x) (TMR_STATUS_GET_VALUE(x) & 0x7fff)+#define TMR_ERROR_TIMEOUT           TMR_ERROR_COMM(1)+#define TMR_ERROR_NO_HOST           TMR_ERROR_COMM(2)+#define TMR_ERROR_LLRP              TMR_ERROR_COMM(3)+#define TMR_ERROR_PARSE             TMR_ERROR_COMM(4)+#define TMR_ERROR_DEVICE_RESET      TMR_ERROR_COMM(5)+#define TMR_ERROR_CRC_ERROR         TMR_ERROR_COMM(6)++#define TMR_ERROR_MISC(x)  TMR_STATUS_MAKE(TMR_ERROR_TYPE_MISC, (x))+#define TMR_ERROR_INVALID          TMR_ERROR_MISC(1)+#define TMR_ERROR_UNIMPLEMENTED    TMR_ERROR_MISC(2)+#define TMR_ERROR_UNSUPPORTED      TMR_ERROR_MISC(3)+#define TMR_ERROR_NO_ANTENNA       TMR_ERROR_MISC(4)+#define TMR_ERROR_READONLY         TMR_ERROR_MISC(5)+#define TMR_ERROR_TOO_BIG          TMR_ERROR_MISC(6)+#define TMR_ERROR_NO_THREADS       TMR_ERROR_MISC(7)+#define TMR_ERROR_NO_TAGS          TMR_ERROR_MISC(8)+#define TMR_ERROR_NOT_FOUND        TMR_ERROR_MISC(9)+#define TMR_ERROR_FIRMWARE_FORMAT  TMR_ERROR_MISC(10)+#define TMR_ERROR_TRYAGAIN         TMR_ERROR_MISC(11)+#define TMR_ERROR_OUT_OF_MEMORY    TMR_ERROR_MISC(12)+#define TMR_ERROR_INVALID_WRITE_MODE  TMR_ERROR_MISC(13)+#define TMR_ERROR_ILLEGAL_VALUE	   TMR_ERROR_MISC(14)+#define TMR_ERROR_END_OF_READING	 TMR_ERROR_MISC(15)+#define TMR_ERROR_UNSUPPORTED_READER_TYPE  TMR_ERROR_MISC(16)+#define TMR_ERROR_BUFFER_OVERFLOW  TMR_ERROR_MISC(17)+#define TMR_ERROR_LOADSAVE_CONFIG  TMR_ERROR_MISC(18)+#define TMR_ERROR_AUTOREAD_ENABLED TMR_ERROR_MISC(19)+#define TMR_ERROR_FIRMWARE_UPDATE_ON_AUTOREAD  TMR_ERROR_MISC(20)+#define TMR_ERROR_TIMESTAMP_NULL  TMR_ERROR_MISC(21)++/* LLRP related errors */+#define TMR_ERROR_LLRP_SPECIFIC(x)            TMR_STATUS_MAKE(TMR_ERROR_TYPE_LLRP, (x))+#define TMR_ERROR_IS_LLRP_SPECIFIC(x)         (TMR_ERROR_TYPE_LLRP == TMR_STATUS_GET_TYPE(x))+#define TMR_ERROR_LLRP_GETTYPEREGISTRY        TMR_ERROR_LLRP_SPECIFIC(1)+#define TMR_ERROR_LLRP_CONNECTIONFAILED       TMR_ERROR_LLRP_SPECIFIC(2)+#define TMR_ERROR_LLRP_SENDIO_ERROR           TMR_ERROR_LLRP_SPECIFIC(3)+#define TMR_ERROR_LLRP_RECEIVEIO_ERROR        TMR_ERROR_LLRP_SPECIFIC(4)+#define TMR_ERROR_LLRP_RECEIVE_TIMEOUT        TMR_ERROR_LLRP_SPECIFIC(5)+#define TMR_ERROR_LLRP_MSG_PARSE_ERROR        TMR_ERROR_LLRP_SPECIFIC(6)+#define TMR_ERROR_LLRP_ALREADY_CONNECTED      TMR_ERROR_LLRP_SPECIFIC(7)+#define TMR_ERROR_LLRP_INVALID_RFMODE         TMR_ERROR_LLRP_SPECIFIC(8)+#define TMR_ERROR_LLRP_UNDEFINED_VALUE        TMR_ERROR_LLRP_SPECIFIC(9)+#define TMR_ERROR_LLRP_READER_ERROR           TMR_ERROR_LLRP_SPECIFIC(10)+#define TMR_ERROR_LLRP_READER_CONNECTION_LOST TMR_ERROR_LLRP_SPECIFIC(11)+#define TMR_ERROR_LLRP_CLIENT_CONNECTION_EXISTS     TMR_ERROR_LLRP_SPECIFIC(12)++#ifdef TMR_ENABLE_ERROR_STRINGS+const char *TMR_strerror(TMR_Status status);+#endif++#ifdef __cplusplus+}+#endif++#endif /* _TMR_STATUS_H */
+ cbits/api/tmr_strerror.c view
@@ -0,0 +1,296 @@+/**+ *  @file tmr_strerror.c+ *  @brief Mercury API - status code to string conversion+ *  @author Nathan Williams+ *  @date 10/23/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 <stdio.h>+#include <string.h>++#include "tm_reader.h"++#if defined(TMR_ENABLE_ERROR_STRINGS)++const char *+TMR_strerror(TMR_Status status)+{+  return TMR_strerr(NULL, status);+}++const char *+TMR_strerr(TMR_Reader *reader, TMR_Status status)+{++  if (TMR_ERROR_IS_COMM(status) && TMR_ERROR_COMM_IS_ERRNO(status))+  {+#ifdef TMR_USE_STRERROR+    return strerror(TMR_ERROR_COMM_GET_ERRNO(status));+#else+    return "Error";+#endif    +  }++#ifdef TMR_ENABLE_LLRP_READER+  if (TMR_ERROR_IS_LLRP_SPECIFIC(status))+  {+    switch (status)+    {+      case TMR_ERROR_LLRP_MSG_PARSE_ERROR:+        return "Error parsing LLRP message";+      case TMR_ERROR_LLRP_ALREADY_CONNECTED:+        return "Already connected to reader";+      case TMR_ERROR_LLRP_INVALID_RFMODE:+        return "Specified RF Mode operation is not supported";+      case TMR_ERROR_LLRP_UNDEFINED_VALUE:+        return "Undefined Value";+      case TMR_ERROR_LLRP_READER_ERROR:+        return "LLRP reader unknown error";+      case TMR_ERROR_LLRP_READER_CONNECTION_LOST:+        return "LLRP reader connection lost";+      case TMR_ERROR_LLRP_GETTYPEREGISTRY:+        return "LLRP Reader GetTypeRegistry Failed";+      case TMR_ERROR_LLRP_CONNECTIONFAILED:+        return "LLRP Reader Connection attempt is failed";+      case TMR_ERROR_LLRP_CLIENT_CONNECTION_EXISTS:+        return "LLRP Reader Connection attempt is failed, A Client initiated connection already exists";+      case TMR_ERROR_LLRP_SENDIO_ERROR:+        return "LLRP Reader Send Messages failed";+      case TMR_ERROR_LLRP_RECEIVEIO_ERROR:+        return "LLRP Reader Receive Messages failed";+      case TMR_ERROR_LLRP_RECEIVE_TIMEOUT:+        return "LLRP Reader Receive Messages Timeout";+      default:+        {+          if (NULL == reader)+            return "Unknown error: Reader reference lost";+          else+        return reader->u.llrpReader.errMsg;+    }+  }+  }+#endif++  switch (status)+  {+  case TMR_ERROR_MSG_WRONG_NUMBER_OF_DATA:+    return "Message command length is incorrect";+  case TMR_ERROR_INVALID_OPCODE:+    return "Invalid command opcode";+  case TMR_ERROR_UNIMPLEMENTED_OPCODE:+    return "Unimplemented opcode";+  case TMR_ERROR_MSG_POWER_TOO_HIGH:+    return "Command attempted to set power above maximum";+  case TMR_ERROR_MSG_INVALID_FREQ_RECEIVED:+    return "Command attempted to set an unsupported frequency";+  case TMR_ERROR_MSG_INVALID_PARAMETER_VALUE:+    return "Parameter to command is invalid";+  case TMR_ERROR_MSG_POWER_TOO_LOW:+    return "Command attempted to set power below minimum";+  case TMR_ERROR_UNIMPLEMENTED_FEATURE:+    return "Unimplemented feature";+  case TMR_ERROR_INVALID_BAUD_RATE:+    return "Invalid baud rate";+  case TMR_ERROR_INVALID_REGION:+    return "Invalid region";+  case TMR_ERROR_INVALID_LICENSE_KEY:+    return "The license key code received is invalid";+  case TMR_ERROR_BL_INVALID_IMAGE_CRC:+    return "Application image failed CRC check";+  case TMR_ERROR_BL_INVALID_APP_END_ADDR:+    return "Application image failed data check";+  case TMR_ERROR_FLASH_BAD_ERASE_PASSWORD:+    return "Incorrect password to erase flash sector";+  case TMR_ERROR_FLASH_BAD_WRITE_PASSWORD:+    return "Incorrect password to write to flash sector";+  case TMR_ERROR_FLASH_UNDEFINED_SECTOR:+    return "Internal error in flash";+  case TMR_ERROR_FLASH_ILLEGAL_SECTOR:+    return "Incorrect password to erase or write to flash sector";+  case TMR_ERROR_FLASH_WRITE_TO_NON_ERASED_AREA:+    return "Area of flash to write to is not erased";+  case TMR_ERROR_FLASH_WRITE_TO_ILLEGAL_SECTOR:+    return "Flash write attempted to cross sector boundary";+  case TMR_ERROR_FLASH_VERIFY_FAILED:+    return "Flash verify failed";+  case TMR_ERROR_NO_TAGS_FOUND:+    return "No tags found";+  case TMR_ERROR_NO_PROTOCOL_DEFINED:+    return "Protocol not set";+  case TMR_ERROR_INVALID_PROTOCOL_SPECIFIED:+    return "Specified protocol not supported";+  case TMR_ERROR_WRITE_PASSED_LOCK_FAILED:+    return "Lock failed after write operation";+  case TMR_ERROR_PROTOCOL_NO_DATA_READ:+    return "No data could be read from a tag";+  case TMR_ERROR_AFE_NOT_ON:+    return "AFE not on - reader not sufficiently configured";+  case TMR_ERROR_PROTOCOL_WRITE_FAILED:+    return "Tag write operation failed";+  case TMR_ERROR_NOT_IMPLEMENTED_FOR_THIS_PROTOCOL:+    return "Operation not supported for this protocol";+  case TMR_ERROR_PROTOCOL_INVALID_WRITE_DATA:+    return "Tag ID supplied in write operation is incorrect";+  case TMR_ERROR_PROTOCOL_INVALID_ADDRESS:+    return "Invalid address in tag address space";+  case TMR_ERROR_GENERAL_TAG_ERROR:+    return "General tag error";+  case TMR_ERROR_DATA_TOO_LARGE:+    return "Size specified in read tag data command is too large";+  case TMR_ERROR_PROTOCOL_INVALID_KILL_PASSWORD:+    return "Kill password is not correct";+  case TMR_ERROR_PROTOCOL_KILL_FAILED:+    return "Kill failed";+  case TMR_ERROR_PROTOCOL_BIT_DECODING_FAILED:+    return "Bit decoding failed";+  case TMR_ERROR_PROTOCOL_INVALID_EPC:+    return "Invalid EPC provided";+  case TMR_ERROR_PROTOCOL_INVALID_NUM_DATA:+    return "Invalid amount of data provided";+  case TMR_ERROR_GEN2_PROTOCOL_OTHER_ERROR:+    return "Other Gen2 error";+  case TMR_ERROR_GEN2_PROTOCOL_MEMORY_OVERRUN_BAD_PC:+    return "Gen2 memory overrun - bad PC";+  case TMR_ERROR_GEN2_PROTOCOL_MEMORY_LOCKED:+    return "Gen2 memory locked";+  case TMR_ERROR_GEN2_PROTOCOL_INSUFFICIENT_POWER:+    return "Gen2 tag has insufficent power for operation";+  case TMR_ERROR_GEN2_PROTOCOL_NON_SPECIFIC_ERROR:+    return "Gen2 nonspecific error";+  case TMR_ERROR_GEN2_PROTOCOL_UNKNOWN_ERROR:+    return "Gen2 unknown error";+	case TMR_ERROR_GEN2_PROTOCOL_V2_AUTHEN_FAILED:+		return "Authentication failed with specified key.";+	case TMR_ERROR_GEN2_PROTOCOL_V2_UNTRACE_FAILED:+		return "Untrace operation failed.";+  case TMR_ERROR_AHAL_INVALID_FREQ:+    return "Invalid frequency";+  case TMR_ERROR_AHAL_CHANNEL_OCCUPIED:+    return "Channel occupied";+  case TMR_ERROR_AHAL_TRANSMITTER_ON:+    return "Transmitter already on";+  case TMR_ERROR_ANTENNA_NOT_CONNECTED:+    return "Antenna not connected";+  case TMR_ERROR_TEMPERATURE_EXCEED_LIMITS:+    return "Reader temperature too high";+  case TMR_ERROR_HIGH_RETURN_LOSS:+    return "High return loss detected, RF ended to avoid damage";+  case TMR_ERROR_INVALID_ANTENNA_CONFIG:+    return "Invalid antenna configuration";+  case TMR_ERROR_TAG_ID_BUFFER_NOT_ENOUGH_TAGS_AVAILABLE:+    return "Not enough tag IDs in buffer";+  case TMR_ERROR_TAG_ID_BUFFER_FULL:+    return "Tag ID buffer full";+  case TMR_ERROR_TAG_ID_BUFFER_REPEATED_TAG_ID:+    return "Tag ID buffer repeated tag ID";+  case TMR_ERROR_TAG_ID_BUFFER_NUM_TAG_TOO_LARGE:+    return "Number of tags too large";+  case TMR_ERROR_SYSTEM_UNKNOWN_ERROR:+    return "Unknown system error";+  case TMR_ERROR_TM_ASSERT_FAILED:+	{+	  if (NULL == reader)+	  {+    return "Assertion failed";+	  }+	  else+	  {+	    return reader->u.serialReader.errMsg;+	  }+	}+  case TMR_ERROR_BUFFER_OVERFLOW:+  return "Buffer overflow";+  case TMR_ERROR_TIMEOUT:+    return "Timeout";+  case TMR_ERROR_NO_HOST:+    return "No matching host found";+  case TMR_ERROR_LLRP:+    return "LLRP error";+  case TMR_ERROR_PARSE:+    return "Error parsing device response";+  case TMR_ERROR_DEVICE_RESET:+    return "Device was reset externally";+  case TMR_ERROR_CRC_ERROR:+    return "CRC Error";+  case TMR_ERROR_INVALID:+    return "Invalid argument";+  case TMR_ERROR_UNIMPLEMENTED:+    return "Unimplemented operation";+  case TMR_ERROR_NO_ANTENNA:+    return "No antenna or invalid antenna";+  case TMR_ERROR_READONLY:+    return "Value is read-only";+  case TMR_ERROR_TOO_BIG:+    return "Value too big";+  case TMR_ERROR_NO_THREADS:+    return "Thread initialization failed";+  case TMR_ERROR_NO_TAGS:+    return "No tags to be retrieved";+  case TMR_ERROR_NOT_FOUND:+    return "Key not found";+  case TMR_ERROR_FIRMWARE_FORMAT:+    return "Size or format of firmware image is incorrect";+  case TMR_ERROR_TRYAGAIN:+    return "Temporary error, try again";+  case TMR_ERROR_OUT_OF_MEMORY:+    return "Out of memory";+  case TMR_ERROR_UNSUPPORTED:+    return "Unsupported operation";+  case TMR_ERROR_INVALID_WRITE_MODE:+	return "Invalid write mode";+  case TMR_ERROR_ILLEGAL_VALUE:+    return "Illegal value";+  case TMR_ERROR_UNSUPPORTED_READER_TYPE:+    return "Unsupported reader type";+  case TMR_ERROR_AUTOREAD_ENABLED:+    return "Autonomous mode is enabled on reader. Please disable it";+  case TMR_ERROR_FIRMWARE_UPDATE_ON_AUTOREAD:+    return "Firmware update is successful. Autonomous mode is already enabled on reader";+  case TMR_ERROR_TIMESTAMP_NULL:+    return "Timestamp cannot be null";++  default:+    {+      if (NULL == reader)+        return "Unknown error: Reader reference lost";+      else+      {+#ifdef TMR_ENABLE_LLRP_READER+        if (TMR_READER_TYPE_LLRP == reader->readerType)+        {+          return reader->u.llrpReader.errMsg;+        }+        else+#endif+        {+          return reader->u.serialReader.errMsg;+        }+      }+    }+  }+}++#endif /* defined(TMR_ENABLE_ERROR_STRINGS) */
+ cbits/api/tmr_tag_auth.h view
@@ -0,0 +1,79 @@+/* ex: set tabstop=2 shiftwidth=2 expandtab cindent: */+#ifndef _TMR_TAG_AUTH_H+#define _TMR_TAG_AUTH_H+/**+ *  @file tmr_tag_auth.h+ *  @brief Mercury API - Tag Authentication Interface+ *  @author Brian Fiegel+ *  @date 4/18/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.+ */+#ifdef  __cplusplus+extern "C" {+#endif++#include "tmr_gen2.h"++/* + * RFID Authentication structures+ */+typedef enum TMR_AuthType+{+  TMR_AUTH_TYPE_GEN2_PASSWORD = 0,+  TMR_AUTH_TYPE_GEN2_DENATRAN_IAV_WRITE_CREDENTIALS = 1,+  TMR_AUTH_TYPE_GEN2_DENATRAN_IAV_WRITE_SEC_CREDENTIALS = 2,+} TMR_AuthType;++/**+ * Authentication data for RFID tag protocols.+ */+typedef struct TMR_TagAuthentication+{+  /**+   * The type of authentication data.+   * Indicates which member of the union is valid.+   */+  TMR_AuthType type;+  union+  {+    /** Gen2 authentication data */+    TMR_GEN2_Password gen2Password;+    /** Gen2 Denatran IAV write credential */+    TMR_GEN2_DENATRAN_IAV_WriteCredentials writeCreds;+    TMR_GEN2_DENATRAN_IAV_WriteSecCredentials writeSecCreds;+  } u;+} TMR_TagAuthentication;++TMR_Status TMR_TA_init_gen2(TMR_TagAuthentication *auth,+                            TMR_GEN2_Password password);++TMR_Status TMR_TA_init_gen2_Denatran_IAV_writeCredentials(TMR_TagAuthentication *auth, uint8_t idLength, uint8_t* tafId, uint8_t len,+                                                          uint8_t  *data);+TMR_Status TMR_TA_init_gen2_Denatran_IAV_writeSecCredentials(TMR_TagAuthentication *auth, uint8_t dataLength, uint8_t* data, uint8_t len,+                                                          uint8_t  *credentials);+#ifdef  __cplusplus+}+#endif++#endif /* _TMR_TAG_AUTH_H_ */
+ cbits/api/tmr_tag_data.h view
@@ -0,0 +1,186 @@+/* ex: set tabstop=2 shiftwidth=2 expandtab cindent: */+#ifndef _TMR_TAG_DATA_H+#define _TMR_TAG_DATA_H+/**+ *  @file tmr_tag_data.h  + *  @brief Mercury API - Tag and tag read data structures+ *  @author Brian Fiegel+ *  @date 5/7/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 "tmr_tag_protocol.h"+#include "tmr_gen2.h"++#ifdef  __cplusplus+extern "C" {+#endif++#define TMR_MAX_EPC_BYTE_COUNT (62)++/**+ * A structure to represent RFID tags.+ * @ingroup filter+ */+typedef struct TMR_TagData+{+  /** Tag EPC */+  uint8_t epc[TMR_MAX_EPC_BYTE_COUNT];+  /** Protocol of the tag */+  TMR_TagProtocol protocol;+  /** Length of the tag's EPC in bytes */+  uint8_t epcByteCount;+  /** Tag CRC */+  uint16_t crc;+  /** Protocol-specific tag information */+  union+  {+    /** Gen2-specific tag information */+    TMR_GEN2_TagData gen2;+  }u;+} TMR_TagData;+  +/**+ * Convert a hexadecimal string into an array of bytes. The string may+ * optionally include a "0x" prefix, which will be ignored. + *+ * @param hex The hexadecimal string to convert.+ * @param[out] bytes The array to store the converted bytes.+ * @param size The length of the byte array to store into.+ * @param[out] convertLen The number of bytes written to the array, or @c NULL.+ * + * @test If hex string is empty, *bytes should not be altered.+ * @test *convertLen is set to the correct value.+ * @test Function works when convertLen is @c NULL.+ * @test Specific values: @c "00", @c "0000", @c "ffff", @c "0xffff", @c "00112233445566778899aabbccddeeff00112233445566778899aabbccddeeff00112233445566778899aabbccddeeff00112233445566778899aabbccddeeff00112233445566778899aabbccddeeff00112233445566778899aabbccddeeff00112233445566778899aabbccddeeff00112233445566778899aabb".+ */+TMR_Status TMR_hexToBytes(const char *hex, uint8_t *bytes, uint32_t size, +                          uint32_t *convertLen);++/**+ * Convert an array of bytes, such as a tag EPC, into a hexadecimal string.+ *+ * @param bytes The byte array to convert.+ * @param size The length of the byte array to convert.+ * @param[out] hex The converted hexadecimal string, null-terminated.+ *+ * @test If size is 0, *hex should point to an empty string.+ */+void TMR_bytesToHex(const uint8_t *bytes, uint32_t size, char *hex);++/**+ * Defines the constants that may be combined to form the metadata+ * bitmask argument to the TMR_SR_cmdReadTagSingle,+ * TMR_SR_cmdReadTagData, and TMR_SR_cmdGetTagBuffer methods.+ */+typedef enum TMR_TRD_MetadataFlag+{+  TMR_TRD_METADATA_FLAG_NONE      = 0x0000,+  TMR_TRD_METADATA_FLAG_READCOUNT = 0x0001,+  TMR_TRD_METADATA_FLAG_RSSI      = 0x0002,+  TMR_TRD_METADATA_FLAG_ANTENNAID = 0x0004,+  TMR_TRD_METADATA_FLAG_FREQUENCY = 0x0008,+  TMR_TRD_METADATA_FLAG_TIMESTAMP = 0x0010,+  TMR_TRD_METADATA_FLAG_PHASE     = 0x0020,+  TMR_TRD_METADATA_FLAG_PROTOCOL  = 0x0040,+  TMR_TRD_METADATA_FLAG_DATA      = 0x0080,+  TMR_TRD_METADATA_FLAG_GPIO_STATUS = 0x0100,+  TMR_TRD_METADATA_FLAG_ALL       =                         +                                       (TMR_TRD_METADATA_FLAG_READCOUNT |+                                        TMR_TRD_METADATA_FLAG_RSSI      |+                                        TMR_TRD_METADATA_FLAG_ANTENNAID |+                                        TMR_TRD_METADATA_FLAG_FREQUENCY |+                                        TMR_TRD_METADATA_FLAG_TIMESTAMP |+                                        TMR_TRD_METADATA_FLAG_PHASE |+                                        TMR_TRD_METADATA_FLAG_PROTOCOL  |+                                        TMR_TRD_METADATA_FLAG_DATA |+                                        TMR_TRD_METADATA_FLAG_GPIO_STATUS)+} TMR_TRD_MetadataFlag;++/**+ * A class to represent a read of an RFID tag. Provides access to the+ TMR_TRD_METADATA_FLAG_FREQUENCY tag structure and the metadata of the read event, such as the time+ * of the read, the antenna that read the tag, and the number of times+ * the tag was seen by the air protocol.+ */+typedef struct TMR_TagReadData+{+  /** The tag that was read */+  TMR_TagData tag;+  /** The set of metadata items below that are valid */+  uint16_t metadataFlags;+  /** Tag response phase */+  uint16_t phase;+  /** Antenna where the tag was read */+  uint8_t antenna;+  /** State of GPIO pins at the moment of the tag read */ +  TMR_GpioPin gpio[16];+   /** the actual number of available gpio pins on module*/+  uint8_t gpioCount;+  /** Number of times the tag was read */+  uint32_t readCount;+  /** Strength of the signal received from the tag */+  int32_t rssi;+  /** RF carrier frequency the tag was read with */+  uint32_t frequency;+  /** Absolute time of the read (32 least-significant bits), in milliseconds since 1/1/1970 UTC */+  uint32_t timestampLow;+  /** Absolute time of the read (32 most-significant bits), in milliseconds since 1/1/1970 UTC */+  uint32_t timestampHigh;+  /** Data read from the tag */+  TMR_uint8List data;+  /** Read EPC bank data bytes */+  TMR_uint8List epcMemData;+  /** Read TID bank data bytes */+  TMR_uint8List tidMemData;+  /** Read USER bank data bytes */+  TMR_uint8List userMemData;+  /** Read RESERVED bank data bytes */+  TMR_uint8List reservedMemData;+  /** [PRIVATE] Relative time of the read within the read interval, in microseconds (for internal use only,+   * this value is used to calculate timestampLow and timestampHigh)+   **/+  bool isAsyncRead;+  uint32_t dspMicros;+#if TMR_MAX_EMBEDDED_DATA_LENGTH+  /** Preallocated storage for data */+  uint8_t _dataList[TMR_MAX_EMBEDDED_DATA_LENGTH];+  uint8_t _epcMemDataList[TMR_MAX_EMBEDDED_DATA_LENGTH];+  uint8_t _tidMemDataList[TMR_MAX_EMBEDDED_DATA_LENGTH];+  uint8_t _userMemDataList[TMR_MAX_EMBEDDED_DATA_LENGTH];+  uint8_t _reservedMemDataList[TMR_MAX_EMBEDDED_DATA_LENGTH];+#endif +  /** Reader instance, to keep track of tag reads */+  TMR_Reader *reader;+} TMR_TagReadData;++TMR_Status TMR_TRD_init(TMR_TagReadData *trd);+TMR_Status TMR_TRD_init_data(TMR_TagReadData *trd, uint16_t size, uint8_t *buf);+TMR_Status TMR_TRD_MEMBANK_init_data(TMR_uint8List *data, uint16_t size, uint8_t *buf);++#ifdef  __cplusplus+}+#endif++#endif /* __TAG_DATA_H */
+ cbits/api/tmr_tag_lock_action.h view
@@ -0,0 +1,77 @@+/* ex: set tabstop=2 shiftwidth=2 expandtab cindent: */+#ifndef _TMR_TAG_LOCK_ACTION_H+#define _TMR_TAG_LOCK_ACTION_H+/**+ *  @file tmr_tag_lock_action.h+ *  @brief Mercury API - Tag Lock Action Interface+ *  @author Brian Fiegel+ *  @date 4/18/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.+ */+#ifdef  __cplusplus+extern "C" {+#endif++#include "tmr_gen2.h"+#include "tmr_iso180006b.h"++/**+ * Types of RFID Tag Locking Structures+ */+typedef enum TMR_TagLockActionType+{+  TMR_LOCK_ACTION_TYPE_GEN2_LOCK_ACTION       = 0,+  TMR_LOCK_ACTION_TYPE_ISO180006B_LOCK_ACTION = 1+} TMR_TagLockActionType;++/**+ * Tag locking structure+ */+typedef struct TMR_TagLockAction+{+  /** +   * Type of the included locking structure. +   * Indicates which member of the union is valid.+   */+  TMR_TagLockActionType type;+  union+  {+    /** Gen2 locking data */+    TMR_GEN2_LockAction gen2LockAction;+    /** ISO180006B locking data */+    TMR_IS0180006B_LockAction iso180006bLockAction;+  } u;+}TMR_TagLockAction;++TMR_Status TMR_TLA_init_gen2(TMR_TagLockAction *lockAction, uint16_t mask,+                             uint16_t action);++TMR_Status TMR_TLA_init_ISO180006B(TMR_TagLockAction *lockAction,+                                   uint8_t address);++#ifdef  __cplusplus+}+#endif++#endif /* _TMR_TAG_LOCK_ACTION_H_ */
+ cbits/api/tmr_tag_protocol.h view
@@ -0,0 +1,70 @@+/* ex: set tabstop=2 shiftwidth=2 expandtab cindent: */+#ifndef _TMR_TAG_PROTOCOL_H+#define _TMR_TAG_PROTOCOL_H+/**+ *  @file tmr_tag_protocol.h+ *  @brief Mercury API - Tag Protocols+ *  @author Brian Fiegel+ *  @date 4/18/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.+ */+#ifdef  __cplusplus+extern "C" {+#endif++#include "tmr_gen2.h"+#include "tmr_iso180006b.h"+#include "tmr_ipx.h"++/**+ * RFID Tag Protocols+ */+typedef enum TMR_TagProtocol +{+  TMR_TAG_PROTOCOL_NONE              = 0x00,+  TMR_TAG_PROTOCOL_ISO180006B        = 0x03,+  TMR_TAG_PROTOCOL_GEN2              = 0x05,+  TMR_TAG_PROTOCOL_ISO180006B_UCODE  = 0x06, +  TMR_TAG_PROTOCOL_IPX64             = 0x07,+  TMR_TAG_PROTOCOL_IPX256            = 0x08,+	TMR_TAG_PROTOCOL_ATA               = 0x1D,+} TMR_TagProtocol;++/** A list of TMR_Protocol values */+typedef struct TMR_TagProtocolList+{+  /** The array of values */+  TMR_TagProtocol *list;+  /** The number of entries there is space for in the array */+  uint8_t max;+  /** The number of entries in the list - may be larger than max, indicating truncated data. */+  uint8_t len;+} TMR_TagProtocolList;++#ifdef  __cplusplus+}+#endif+++#endif /* _TMR_TAG_PROTOCOL_H_ */
+ cbits/api/tmr_tagop.h view
@@ -0,0 +1,1734 @@+#ifndef _TMR_TAGOP_H+#define _TMR_TAGOP_H+/** + *  @file tmr_tagop.h+ *  @brief Mercury API - Tag Operations Interface+ *  @author Nathan Williams+ *  @date 1/8/2010+ */++/*+ * 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 "tmr_tag_auth.h"+#include "osdep.h"++#ifdef  __cplusplus+extern "C" {+#endif++/** The type of a tag operation structure */+typedef enum TMR_TagOpType+{+  /** Gen2 EPC write */+  TMR_TAGOP_GEN2_WRITETAG,+  /** Gen2 memory read */+  TMR_TAGOP_GEN2_READDATA,+  /** Gen2 memory write */+  TMR_TAGOP_GEN2_WRITEDATA,+  /** Gen2 memory lock/unlock */+  TMR_TAGOP_GEN2_LOCK,+  /** Gen2 tag kill */+  TMR_TAGOP_GEN2_KILL,+  /** Gen2 tag block write */+  TMR_TAGOP_GEN2_BLOCKWRITE,+  /** Gen2 tag block permalock */+  TMR_TAGOP_GEN2_BLOCKPERMALOCK,+  /** Gen2 tag block erase */+  TMR_TAGOP_GEN2_BLOCKERASE,+  /** Higgs2 Partial Load Image */+  TMR_TAGOP_GEN2_ALIEN_HIGGS2_PARTIALLOADIMAGE,+  /** Higgs2 Full Load Image */+  TMR_TAGOP_GEN2_ALIEN_HIGGS2_FULLLOADIMAGE,+  /** Higgs3 Fast Load Image */+  TMR_TAGOP_GEN2_ALIEN_HIGGS3_FASTLOADIMAGE,+  /** Higgs3 Load Image */+  TMR_TAGOP_GEN2_ALIEN_HIGGS3_LOADIMAGE,+  /** Higgs3 Block Read Lock */+  TMR_TAGOP_GEN2_ALIEN_HIGGS3_BLOCKREADLOCK,++  /** NXP set read protect */+  TMR_TAGOP_GEN2_NXP_SETREADPROTECT,+  /** NXP reset read protect */+  TMR_TAGOP_GEN2_NXP_RESETREADPROTECT,+  /** NXP Change EAS */+  TMR_TAGOP_GEN2_NXP_CHANGEEAS,+  /** NXP EAS Alarm */+  TMR_TAGOP_GEN2_NXP_EASALARM,+  /** NXP Calibrate */+  TMR_TAGOP_GEN2_NXP_CALIBRATE,+  /** NXP ChangeConfig */+  TMR_TAGOP_GEN2_NXP_CHANGECONFIG,++/** NXP AES Gen2v2 untraceable operations */+  TMR_TAGOP_GEN2_NXP_UNTRACEABLE,+  /** NXP AES Gen2v2 Authenticate operations */+  TMR_TAGOP_GEN2_NXP_AUTHENTICATE,+  /** NXP AES Gen2v2 ReadBuffer operations */+  TMR_TAGOP_GEN2_NXP_READBUFFER,+++  /** Monza4 QT Read/Write*/+  TMR_TAGOP_GEN2_IMPINJ_MONZA4_QTREADWRITE,++  /** ISO180006B memory read */+  TMR_TAGOP_ISO180006B_READDATA,+  /** ISO180006B memory write */+  TMR_TAGOP_ISO180006B_WRITEDATA,+  /** ISO180006B memory lock/unlock */+  TMR_TAGOP_ISO180006B_LOCK,+  /** ISO180006B tag kill */+  /** Gen2 Secure read */+  TMR_TAGOP_GEN2_SECURE_READDATA,++  /** Gen2 IAVDenatran ActivateSecureMode - PA Protocol */+  TMR_TAGOP_GEN2_DENATRAN_IAV_ACTIVATESECUREMODE,+  /** Gen2 IAVDenatran Authenticate OBU - PA Protocol */+  TMR_TAGOP_GEN2_DENATRAN_IAV_AUTHENTICATEOBU,+  /** Gen2 IAVDenatran GEN2_ACTIVATE_SINIAV_MODE - G0 Protocol */+  TMR_TAGOP_GEN2_ACTIVATE_SINIAV_MODE,+  /** Gen2 IAVDenatran GEN2_OBU_AUTH_ID - G0 Protocol */+  TMR_TAGOP_GEN2_OBU_AUTH_ID,+  /** Gen2 IAVDenatran GEN2_AUTHENTICATE_OBU_FULL_PASS1 - G0 Protocol */+  TMR_TAGOP_GEN2_AUTHENTICATE_OBU_FULL_PASS1,+  /** Gen2 IAVDenatran GEN2_AUTHENTICATE_OBU_FULL_PASS2 - G0 Protocol */+  TMR_TAGOP_GEN2_AUTHENTICATE_OBU_FULL_PASS2,+  /** Gen2 IAVDenatran GEN2_OBU_READ_FROM_MEM_MAP - G0 Protocol */+  TMR_TAGOP_GEN2_OBU_READ_FROM_MEM_MAP,+  /** Gen2 IAVDenatran GEN2_OBU_WRITE_TO_MEM_MAP - G0 Protocol */+  TMR_TAGOP_GEN2_OBU_WRITE_TO_MEM_MAP,+  /** Gen2 IAVDenatran GET_TOKEN_ID - G0 Protocol */+  TMR_TAGOP_GEN2_DENATRAN_IAV_GET_TOKEN_ID,+  /** Gen2 IAVDenatran AUTHENTICATE_OBU_FULL_PASS */+  TMR_TAGOP_GEN2_DENATRAN_IAV_AUTHENTICATE_OBU_FULL_PASS,+  /** Gen2 IAVDenatran Read Sec - IP63 protocol */+  TMR_TAGOP_GEN2_DENATRAN_IAV_READ_SEC,+  /** Gen2 IAVDenatran Write Sec - IP63 protocol */+  TMR_TAGOP_GEN2_DENATRAN_IAV_WRITE_SEC,+  /** Gen2 IAVDenatran GEN2_G0_PA_OBU_AUTHENTICATE_ID - ( PA + G0 ) Protocol */+  TMR_TAGOP_GEN2_DENATRAN_IAV_G0_PA_OBU_AUTHENTICATE_ID,+  +  /** Gen2 Ids get sensor type */+  TMR_TAGOP_GEN2_IDS_SL900A_GETSENSOR,+  /** Gen2 Ids get log state */+  TMR_TAGOP_GEN2_IDS_SL900A_GETLOGSTATE,+  /** Gen2 Ids set log mode */+  TMR_TAGOP_GEN2_IDS_SL900A_SETLOGMODE,+  /** Gen2 Ids end log */+  TMR_TAGOP_GEN2_IDS_SL900A_ENDLOG,+  /** Gen2 Ids Initialize */+  TMR_TAGOP_GEN2_IDS_SL900A_INITIALIZE,+  /** Gen2 Ids Fifo Status */+  TMR_TAGOP_GEN2_IDS_SL900A_ACCESSFIFOSTATUS,+  /** Gen2 Ids Fifo Read */+  TMR_TAGOP_GEN2_IDS_SL900A_ACCESSFIFOREAD,+  /** Gen2 Ids Fifo write */+  TMR_TAGOP_GEN2_IDS_SL900A_ACCESSFIFOWRITE,+  /** Gen2 Ids Starrt Log */+  TMR_TAGOP_GEN2_IDS_SL900A_STARTLOG,+  /** Gen2 Ids GetCalibrationData */+  TMR_TAGOP_GEN2_IDS_SL900A_GETCALIBRATIONDATA,+  /** Gen2 Ids SetCalibration */+  TMR_TAGOP_GEN2_IDS_SL900A_SETCALIBRATIONDATA,+  /** Gen2 Ids SetSfeParameters */+  TMR_TAGOP_GEN2_IDS_SL900A_SETSFEPARAMETERS,+  /** Gen2 Ids GetMeasurmentSetup */+  TMR_TAGOP_GEN2_IDS_SL900A_GETMEASUREMENTSETUP,+  /** Gen2 Ids GetBattery Level */+  TMR_TAGOP_GEN2_IDS_SL900A_GETBATTERYLEVEL,+  /** Gen2 Ids SetLogLimits */+  TMR_TAGOP_GEN2_IDS_SL900A_SETLOGLIMITS,+  /** Gen2 Ids SetShelfLife */+  TMR_TAGOP_GEN2_IDS_SL900A_SETSHELFLIFE,+  /** Set IDS Password */+  TMR_TAGOP_GEN2_IDS_SL900A_SETPASSWORD,+++  /** List of tag operations */+  TMR_TAGOP_LIST+} TMR_TagOpType;++/** The type of Gen2 Secure operation  */+typedef enum SecureTagType+{+  GEN2_EMBEDDED_SECURE_DEFAULT = 0x00,+  /* Alien Higgs 3 secure access */+  GEN2_EMBEDDED_SECURE_HIGGS3_ACCESS   = (1 << 1),+  /* Monza 4 secure access */+  GEN2_EMBEDDED_SECURE_MONZA4_ACCESS   = (1 << 2)+}SecureTagType;+ +/* The type of Gen2 IAVDenatranCmdEnum */+typedef enum IAVDenatranSecureTagOpType+{+  /* Activate Secure Mode - PA Protocol */+  GEN2_ACTIVATE_SECURE_MODE  = 0x00,+  /* Authenticate OBU - PA Protocol */+  GEN2_AUTHENTICATE_OBU  = 0x01,+  /* Activate Siniav Mode OBU - G0 Protocol */+  GEN2_ACTIVATE_SINIAV_MODE = 0x02,+  /* Authenticate OBU ID - G0 Protocol */+  GEN2_OBU_AUTH_ID = 0x03,+  /* Authenticate OBU FullPass1 - G0 Protocol */+  GEN2_AUTHENTICATE_OBU_FULL_PASS1 = 0x04,+  /* Authenticate OBU FullPass2 - G0 Protocol */+  GEN2_AUTHENTICATE_OBU_FULL_PASS2 = 0x05,+  /* Read From Mem - G0 Protocol */+  GEN2_OBU_READ_FROM_MEM_MAP = 0x06,+  /* Write to Mem - G0 Protocol */+  GEN2_OBU_WRITE_TO_MEM_MAP = 0x07,+  /* Authenticate OBU FullPass2 - G0 Protocol */+  GEN2_AUTHENTICATE_OBU_FULL_PASS = 0x08,+  /* Get token ID - Go Protocol */+  GEN2_GET_TOKEN_ID = 0x09,+  /* Read Sec - IP63 Protocol */+  GEN2_READ_SEC = 0x0A,+  /* Write Sec - IP63 Protocol */+  GEN2_WRITE_SEC = 0x0B,+  /* Pa G0 - (PA + G0) Protocol */+  GEN2_PA_G0_AUTHENTICATE = 0x0C,+}IAVDenatranSecureTagOpType;++/* The type of Gen2 secure password  */+typedef enum SecurePasswordType+{+  /* Gen2 password type */+  TMR_SECURE_GEN2_PASSWORD = 0x01,+  /* Look up table password */+  TMR_SECURE_GEN2_LOOKUP_TABLE_PASSWORD = 0x02+}SecurePasswordType;++/* The fild type of calibration data that user can modify */+typedef enum CalibrationParameter+{+  /* AD1 lower voltage reference - coarse */+  TMR_GEN2_IDS_SL900A_CALIBRATION_COARSE1,+  /* AD2 lower voltage reference - coarse */+  TMR_GEN2_IDS_SL900A_CALIBRATION_COARSE2,+  /* Switches the lower AD voltage reference to ground */+  TMR_GEN2_IDS_SL900A_CALIBRATION_GNDSWITCH,+  /* POR voltage level for 1.5V system */+  TMR_GEN2_IDS_SL900A_CALIBRATION_SELP12,+  /* RTC oscillator calibration */+  TMR_GEN2_IDS_SL900A_CALIBRATION_DF,+  /* Controlled battery supply for external sensor - the battery voltage is connected to the EXC pin */+  TMR_GEN2_IDS_SL900A_CALIBRATION_SWEXTEN,+  /* POR voltage level for 3V system */+  TMR_GEN2_IDS_SL900A_CALIBRATION_SELP22,+  /* Voltage level interrupt level for external sensor -- ratiometric */+  TMR_GEN2_IDS_SL900A_CALIBRATION_IRLEV,+  /* Excitate for resistive sensors without DC */+  TMR_GEN2_IDS_SL900A_CALIBRATION_EXCRES,+}CalibrationParameter;++/* The field type of sfe parameters that user can modify */+typedef enum SfeParameter+{+  /* External sensor 2 range */+  TMR_GEN2_IDS_SL900A_SFE_RANG,+  /* External sensor 1 range */+  TMR_GEN2_IDS_SL900A_SFE_SETI,+  /* External sensor 1 type */+  TMR_GEN2_IDS_SL900A_SFE_EXT1,+  /* External sensor 2 type */+  TMR_GEN2_IDS_SL900A_SFE_EXT2,+  /* Use preset range */+  TMR_GEN2_IDS_SL900A_SFE_AUTORANGEDISABLE,+  /* Sensor used in limit check */+  TMR_GEN2_IDS_SL900A_SFE_VERIFYSENSORID,+}SfeParameter;++typedef struct TMR_TagOp_GEN2_NXP_Tam1Authentication+{+	uint8_t Authentication;+	uint8_t CSI;+	uint8_t keyID;+	uint8_t KeyLength;+	uint8_t IchallengeLength;+	TMR_uint8List  Key;+	TMR_uint8List Ichallenge;+} TMR_TagOp_GEN2_NXP_Tam1Authentication;++typedef struct TMR_TagOp_GEN2_NXP_Tam2Authentication+{+	TMR_TagOp_GEN2_NXP_Tam1Authentication tam1Auth;+	uint16_t Offset;+	uint8_t ProtMode;+	uint8_t BlockCount;+	TMR_NXP_Profile profile;+} TMR_TagOp_GEN2_NXP_Tam2Authentication;++typedef enum TMR_GEN2_UNTRACEABLE_AuthType+{+	/* Tag exposes EPC memory */+	UNTRACEABLE_WITH_AUTHENTICATION = 0,+	/*Tag untraceably hides EPC memory above that*/+	UNTRACEABLE_WITH_ACCESS = 1++}TMR_GEN2_UNTRACEABLE_AuthType;+typedef struct TMR_TagOp_GEN2_NXP_UNTRACEABLE_Authentication+{   +	TMR_GEN2_UNTRACEABLE_AuthType authType;+	TMR_TagOp_GEN2_NXP_Tam1Authentication tam1Auth;+	TMR_GEN2_Password accessPassword;++}TMR_TagOp_GEN2_NXP_UNTRACEABLE_Authentication;++typedef struct TMR_TagOp_GEN2_NXP_Untraceable+{+	TMR_TagOp_GEN2_NXP_UNTRACEABLE_Authentication auth; +	TMR_GEN2_UNTRACEABLE_Epc epc;+	int32_t epcLength;+	TMR_GEN2_UNTRACEABLE_Tid tid;+	TMR_GEN2_UNTRACEABLE_UserMemory userMemory;+	TMR_GEN2_UNTRACEABLE_Range range;+	uint8_t subCommand;++} TMR_TagOp_GEN2_NXP_Untraceable;++typedef enum TMR_GEN2_AUTHENTICATE_Type+{+	TAM1_AUTHENTICATION,+	TAM2_AUTHENTICATION+}TMR_GEN2_AUTHENTICATE_Type;++typedef struct TMR_TagOp_GEN2_NXP_Authenticate+{+	TMR_GEN2_AUTHENTICATE_Type type;+	TMR_TagOp_GEN2_NXP_Tam1Authentication tam1Auth;+	TMR_TagOp_GEN2_NXP_Tam2Authentication tam2Auth;+	uint8_t subCommand;+}TMR_TagOp_GEN2_NXP_Authenticate;++typedef struct TMR_TagOp_GEN2_NXP_Readbuffer+{+	uint16_t wordPointer;+	uint16_t bitCount;+	TMR_TagOp_GEN2_NXP_Authenticate authenticate;++}TMR_TagOp_GEN2_NXP_Readbuffer;++/** Parameters of a Gen2 EPC write operation */+typedef struct TMR_TagOp_GEN2_WriteTag+{+  /** Tag EPC */+  TMR_TagData* epcptr;+} TMR_TagOp_GEN2_WriteTag;++/** Parameters of a Gen2 memory read operation */+typedef struct TMR_TagOp_GEN2_ReadData+{+  /** Gen2 memory bank to read from */+  TMR_GEN2_Bank bank;+  /** Word address to start reading at */+  uint32_t wordAddress;+  /** Number of words to read */+  uint8_t len;+} TMR_TagOp_GEN2_ReadData;++/** Parameters of Gen2 Secure operation */++/* Parameters of SecurePassWordLookup Table */+typedef struct SecurePasswordLookup+{+  /* used in case Gen2 passWord */+  TMR_TagAuthentication gen2PassWord;++  /* used in case of password look table */+  /* Number of bits used to address the AP list (MSB byte - byte 4) */+  uint8_t secureAddressLength;+  /* EPC word offset (Next MSB byte - byte 3) */+  uint8_t secureAddressOffset;+  /*  User flash offset, starting from 0x0000 (LSB 2 bytes) */+   uint16_t secureFlashOffset;+} SecurePasswordLookup;++typedef struct TMR_TagOp_GEN2_SecureReadData+{+  /** Gen2 read operation */+  TMR_TagOp_GEN2_ReadData readData;++  /** type of Gen2 Secure operation*/+  /* Options to select Alien Higgs 3 secure access and Monza 4 secure access */+  SecureTagType type;+  /* option to select Gen2 password or look up table password */+  SecurePasswordType passwordType;+  /* Options to specify the password */+  SecurePasswordLookup password;+ } TMR_TagOp_GEN2_SecureReadData;++/** Parameters of a Gen2 memory write operation */+typedef struct TMR_TagOp_GEN2_WriteData+{+  /** Gen2 memory bank to write to */+  TMR_GEN2_Bank bank;+  /** Word address to start writing at */+  uint32_t wordAddress;+  /** Data to write */+  TMR_uint16List data;+} TMR_TagOp_GEN2_WriteData;++/** Parameters of a Gen2 memory lock/unlock operation */+typedef struct TMR_TagOp_GEN2_Lock+{ +  /** Bitmask indicating which lock bits to change */+  uint16_t mask;+  /** New values of each bit specified in the mask */+  uint16_t action;+  /** Access Password to use to lock the tag*/+  TMR_GEN2_Password accessPassword;+} TMR_TagOp_GEN2_Lock;++/** Parameters of a Gen2 tag kill operation */+typedef struct TMR_TagOp_GEN2_Kill+{+  /** Kill password to use to kill the tag */+  TMR_GEN2_Password password;+} TMR_TagOp_GEN2_Kill;++/** Parameters of a Gen2 tag Block Write operation */+typedef struct TMR_TagOp_GEN2_BlockWrite+{+  /** Gen2 memory bank to write to */+  TMR_GEN2_Bank bank; +  /** The word address to start writing to */+  uint32_t wordPtr; +  /** The data to write */+  TMR_uint16List data; +}TMR_TagOp_GEN2_BlockWrite;++/** Parameters of a Gen2 tag Block PermaLock operation */+typedef struct TMR_TagOp_GEN2_BlockPermaLock+{+  /** Read lock status or write it? */+  uint8_t readLock; +  /** Gen2 memory bank to lock */+  TMR_GEN2_Bank bank; +  /** The starting word address to lock */+  uint32_t blockPtr;+  /** Mask: Which blocks to lock? */+  TMR_uint16List mask;+}TMR_TagOp_GEN2_BlockPermaLock;++/** Parameters of a Gen2 tag Block Erase operation */+typedef struct TMR_TagOp_GEN2_BlockErase+{+  /** Gen2 memory bank to erase */+  TMR_GEN2_Bank bank;+  /** The starting word address for block erase */+  uint32_t wordPtr;+  /** Number of words to erase */+  uint8_t wordCount;+} TMR_TagOp_GEN2_BlockErase;++/** Parameters of a Gen2 memory lock/unlock operation */+typedef struct TMR_TagOp_ISO180006B_Lock+{ +  /** The memory address of the byte to lock */+  uint8_t address;+} TMR_TagOp_ISO180006B_Lock;++/** Parameters of an ISO180006B memory read operation */+typedef struct TMR_TagOp_ISO180006B_ReadData+{+  /** Byte address to start reading at */+  uint8_t byteAddress;+  /** Number of bytes to read */+  uint8_t len;+} TMR_TagOp_ISO180006B_ReadData;++/** Parameters of an ISO180006B memory write operation */+typedef struct TMR_TagOp_ISO180006B_WriteData+{+  /** Byte address to start writing at */+  uint8_t byteAddress;+  /** Data to write */+  TMR_uint8List data;+} TMR_TagOp_ISO180006B_WriteData;++/**+ *  Tagops for Gen2 custom commands+ **/++/** Parameters for Alien Higgs2, Partial Load Image command*/+typedef struct TMR_TagOp_GEN2_Alien_Higgs2_PartialLoadImage+{+  /** Kill password to write to the tag */+  TMR_GEN2_Password killPassword;+  /** Access password to write to the tag */+  TMR_GEN2_Password accessPassword;+  /** Tag EPC to write to the tag*/+  TMR_TagData* epcptr;+} TMR_TagOp_GEN2_Alien_Higgs2_PartialLoadImage;++/** Parameters for Alien Higgs2, Full Load Image command*/+typedef struct TMR_TagOp_GEN2_Alien_Higgs2_FullLoadImage+{+  /** Kill password to write to the tag */+  TMR_GEN2_Password killPassword;+  /** Access password to write to the tag */+  TMR_GEN2_Password accessPassword;+  /** Lock Bits */+  uint16_t lockBits;+  /** PC word */+  uint16_t pcWord;+  /** Tag EPC to write to the tag*/+  TMR_TagData* epcptr;+} TMR_TagOp_GEN2_Alien_Higgs2_FullLoadImage;++/** Parameters for Alien Higgs3, Fast Load Image command*/+typedef struct TMR_TagOp_GEN2_Alien_Higgs3_FastLoadImage+{+  /** Access password used to write to the tag */+  TMR_GEN2_Password currentAccessPassword;+  /** Kill password to write to the tag */+  TMR_GEN2_Password killPassword;+  /** Access password to write to the tag */+  TMR_GEN2_Password accessPassword;+  /** PC word */+  uint16_t pcWord;+  /** Tag EPC to write to the tag*/+  TMR_TagData* epcptr;+} TMR_TagOp_GEN2_Alien_Higgs3_FastLoadImage;+++/** Parameters for Alien Higgs3, Load Image command*/+typedef struct TMR_TagOp_GEN2_Alien_Higgs3_LoadImage+{+  /** Access password used to write to the tag */+  TMR_GEN2_Password currentAccessPassword;+  /** Kill password to write to the tag */+  TMR_GEN2_Password killPassword;+  /** Access password to write to the tag */+  TMR_GEN2_Password accessPassword;+  /** PC word */+  uint16_t pcWord;+  /** Tag EPC and user data to write to the tag (76 bytes)*/+  TMR_uint8List *epcAndUserData;+} TMR_TagOp_GEN2_Alien_Higgs3_LoadImage;++/** Parameters for Alien Higgs3, Block Read Lock command*/+typedef struct TMR_TagOp_GEN2_Alien_Higgs3_BlockReadLock+{+  /** Access password to use to write to the tag, in case if the tag is already locked */+  TMR_GEN2_Password accessPassword;+  /** A bitmask of bits to lock */+  uint8_t lockBits;+} TMR_TagOp_GEN2_Alien_Higgs3_BlockReadLock;++/** Parameters for NXP, Set Read Protect command */+typedef struct TMR_TagOp_GEN2_NXP_SetReadProtect+{+  /** Access password to use to write to the tag */+  TMR_GEN2_Password accessPassword;+}TMR_TagOp_GEN2_NXP_SetReadProtect;++/** Parameters for NXP, Reset Read Protect Command*/+typedef struct TMR_TagOp_GEN2_NXP_ResetReadProtect+{+  /** Access password to use to write to the tag */+  TMR_GEN2_Password accessPassword;+} TMR_TagOp_GEN2_NXP_ResetReadProtect;++/** Parameters for NXP, Change EAS Command*/+typedef struct TMR_TagOp_GEN2_NXP_ChangeEAS+{+  /** Access password to use to write to the tag */+  TMR_GEN2_Password accessPassword;+  /** Reset or set EAS bit */+  bool reset;+} TMR_TagOp_GEN2_NXP_ChangeEAS;++/** Parameters for NXP, EAS alarm command */+typedef struct TMR_TagOp_GEN2_NXP_EASAlarm+{+  /** Gen2 divide ratio to use */+  TMR_GEN2_DivideRatio dr;+  /** Gen2 M parameter to use */+  TMR_GEN2_TagEncoding m;+  /** Gen2 TrExt value to use */+  TMR_GEN2_TrExt trExt;  +} TMR_TagOp_GEN2_NXP_EASAlarm;++/** Parameters for NXP, Calibration command */+typedef struct TMR_TagOp_GEN2_NXP_Calibrate+{+  /** Access password to use to write to the tag */+  TMR_GEN2_Password accessPassword;+} TMR_TagOp_GEN2_NXP_Calibrate;++/** Parameters for NXP, Change Config command */+typedef struct TMR_TagOp_GEN2_NXP_ChangeConfig+{+  /** Access password to use to write to the tag */+  TMR_GEN2_Password accessPassword;+  /** ConfigWord to write to the tag*/+  TMR_NXP_ConfigWord configWord;+}TMR_TagOp_GEN2_NXP_ChangeConfig;++/** Parameters for NXP, Change Config command */+typedef struct TMR_TagOp_GEN2_Impinj_Monza4_QTReadWrite+{+  /** Access password to use to write to the tag */+  TMR_GEN2_Password accessPassword;+  /** Control Byte to write to the tag*/+  TMR_Monza4_ControlByte controlByte;+  /** Payload */+  TMR_Monza4_Payload payload;    +}TMR_TagOp_GEN2_Impinj_Monza4_QTReadWrite;+ +/** Parameters for IAV, ActivateSecureMode command */+typedef struct TMR_TagOp_GEN2_Denatran_IAV_Activate_Secure_Mode+{+  /* Enum for IAV tagoperation */+  IAVDenatranSecureTagOpType mode;+  /* RFU field */+  uint8_t payload;+}TMR_TagOp_GEN2_Denatran_IAV_Activate_Secure_Mode;++/** Parameters for IAV, AuthenticateOBU command */+typedef struct TMR_TagOp_GEN2_Denatran_IAV_Authenticate_OBU+{+  /* Enum for IAV tagoperation */+  IAVDenatranSecureTagOpType mode;+  /* RFU field */+  uint8_t payload;+}TMR_TagOp_GEN2_Denatran_IAV_Authenticate_OBU;++/** Parameters for IAV, Activate_Siniav_Mode command - G0 Protocol */+typedef struct TMR_TagOp_GEN2_Denatran_IAV_Activate_Siniav_Mode+{+  /* Enum for IAV tagoperation */+  IAVDenatranSecureTagOpType mode;+  /* RFU field */+  uint8_t payload;+  /* token desc */+  bool isTokenDesc;+  /* 64 bits of token data */+  uint8_t token[8];+}TMR_TagOp_GEN2_Denatran_IAV_Activate_Siniav_Mode;++/** Parameters for IAV, OBU_Auth_ID command - G0 Protocol */+typedef struct TMR_TagOp_GEN2_Denatran_IAV_OBU_Auth_ID+{+  /* Enum for IAV tagoperation */+  IAVDenatranSecureTagOpType mode;+  /* RFU field */+  uint8_t payload;+}TMR_TagOp_GEN2_Denatran_IAV_OBU_Auth_ID;++/** Parameters for IAV, OBU_Auth_Full_Pass1 command - G0 Protocol */+typedef struct TMR_TagOp_GEN2_Denatran_IAV_OBU_Auth_Full_Pass1+{+  /* Enum for IAV tagoperation */+  IAVDenatranSecureTagOpType mode;+  /* RFU field */+  uint8_t payload;+}TMR_TagOp_GEN2_Denatran_IAV_OBU_Auth_Full_Pass1;++/** Parameters for IAV,  OBU_Auth_Full_Pass2 command - G0 Protocol */+typedef struct TMR_TagOp_GEN2_Denatran_IAV_OBU_Auth_Full_Pass2+{+  /* Enum for IAV tagoperation */+  IAVDenatranSecureTagOpType mode;+  /* RFU field */+  uint8_t payload;+}TMR_TagOp_GEN2_Denatran_IAV_OBU_Auth_Full_Pass2;++/** Parameters for IAV,  OBU_ReadFromMemMap command - G0 Protocol */+typedef struct TMR_TagOp_GEN2_Denatran_IAV_OBU_ReadFromMemMap+{+  /* Enum for IAV tagoperation */+  IAVDenatranSecureTagOpType mode;+  /* RFU field */+  uint8_t payload;+  /* address to be read from USER bank */+  uint16_t readPtr;+}TMR_TagOp_GEN2_Denatran_IAV_OBU_ReadFromMemMap;++/** Parameters for IAV, read sec  command - IP63 Protocol */+typedef struct TMR_TagOp_GEN2_Denatran_IAV_Read_Sec+{+  /* Enum for IAV tagoperation */+  IAVDenatranSecureTagOpType mode;+  /* RFU field */+  uint8_t payload;+  /* address to be read from USER bank */+  uint16_t readPtr;+}TMR_TagOp_GEN2_Denatran_IAV_Read_Sec;++/** Parameters for IAV,  OBU_WriteToMemMap command - G0 Protocol */+typedef struct TMR_TagOp_GEN2_Denatran_IAV_OBU_WriteToMemMap+{+  /* Enum for IAV tagoperation */+  IAVDenatranSecureTagOpType mode;+  /* RFU field */+  uint8_t payload;+  /* Pointer to the USER data */+  uint16_t writePtr;+  /* data to be written */+  uint16_t wordData;+  /* Tag ID */+  uint8_t* tagIdentification;+  /* Credentials written word */+  uint8_t* dataBuf;  +}TMR_TagOp_GEN2_Denatran_IAV_OBU_WriteToMemMap;++/** Parameters for IAV,  write sec command - IP63 Protocol */+typedef struct TMR_TagOp_GEN2_Denatran_IAV_Write_Sec+{+  /* Enum for IAV tagoperation */+  IAVDenatranSecureTagOpType mode;+  /* RFU field */+  uint8_t payload;+  /* data words */+  uint8_t* dataWords;+  /* Credentials written word */+  uint8_t* dataBuf;+}TMR_TagOp_GEN2_Denatran_IAV_Write_Sec;++/** Parameters for IAV, Get Token ID command */+typedef struct TMR_TagOp_GEN2_Denatran_IAV_Get_Token_Id+{+  /* Enum for IAV tagoperation */+  IAVDenatranSecureTagOpType mode;+}TMR_TagOp_GEN2_Denatran_IAV_Get_Token_Id;++/** Parameters for IAV, Authenticate OBU Full Pass */+typedef struct TMR_TagOp_GEN2_Denatran_IAV_OBU_Auth_Full_Pass+{+  /* Enum for IAV tagoperation */+  IAVDenatranSecureTagOpType mode;+  /* RFU field */+  uint8_t payload;+}TMR_TagOp_GEN2_Denatran_IAV_OBU_Auth_Full_Pass;++/** Parameters for IAV, G0_PA_OBU_Auth_ID */+typedef struct TMR_TagOp_GEN2_Denatran_IAV_G0_PA_OBU_Auth_ID+{+  /* Enum for IAV tagoperation */+  IAVDenatranSecureTagOpType mode;+  /* RFU field */+  uint8_t payload;+}TMR_TagOp_GEN2_Denatran_IAV_G0_PA_OBU_Auth_ID;++/* Forward declaration for the benefit of TMR_TagOp_List */+typedef struct TMR_TagOp TMR_TagOp;++/** List of tag operations */+typedef struct TMR_TagOp_List+{+  /** Array of pointers to tag operations*/+  TMR_TagOp **list;+  /** Number of tag operations in list */+  uint16_t len;+} TMR_TagOp_List;++/** Sub-class for Gen2 Alien Higgs2 custom tag extensions */+typedef struct TMR_TagOp_GEN2_Alien_Higgs2+{+  union+  {+    TMR_TagOp_GEN2_Alien_Higgs2_PartialLoadImage partialLoadImage;+    TMR_TagOp_GEN2_Alien_Higgs2_FullLoadImage fullLoadImage;+  } u;+}TMR_TagOp_GEN2_Alien_Higgs2;++/** Sub-class for Gen2 Alien Higgs3 custom tag extensions */+typedef struct TMR_TagOp_GEN2_Alien_Higgs3+{+  union+  {+    TMR_TagOp_GEN2_Alien_Higgs3_FastLoadImage fastLoadImage;+    TMR_TagOp_GEN2_Alien_Higgs3_LoadImage loadImage;+    TMR_TagOp_GEN2_Alien_Higgs3_BlockReadLock blockReadLock;+  } u;+}TMR_TagOp_GEN2_Alien_Higgs3;++/** Sub-class for Gen2 Alien custom tag extensions */+typedef struct TMR_TagOp_GEN2_Alien+{+  union+  {+    TMR_TagOp_GEN2_Alien_Higgs2 higgs2;+    TMR_TagOp_GEN2_Alien_Higgs3 higgs3;+  } u;+}TMR_TagOp_GEN2_Alien;++/** Sub-class for Gen2 NXP custom tag extensions */+typedef struct TMR_TagOp_GEN2_NXP+{+  union+  {+    TMR_TagOp_GEN2_NXP_SetReadProtect setReadProtect;+    TMR_TagOp_GEN2_NXP_ResetReadProtect resetReadProtect;+    TMR_TagOp_GEN2_NXP_ChangeEAS changeEAS;+    TMR_TagOp_GEN2_NXP_EASAlarm EASAlarm;+    TMR_TagOp_GEN2_NXP_Calibrate calibrate;+    TMR_TagOp_GEN2_NXP_ChangeConfig changeConfig;+	TMR_TagOp_GEN2_NXP_Untraceable untraceable;+	TMR_TagOp_GEN2_NXP_Authenticate authenticate;+	TMR_TagOp_GEN2_NXP_Readbuffer readBuffer;+  }u;+}TMR_TagOp_GEN2_NXP;++/** Sub-class for Gen2 Impinj Monza4 custom tag extensions */+typedef struct TMR_TagOp_GEN2_Impinj_Monza4+{+  union+  {+    TMR_TagOp_GEN2_Impinj_Monza4_QTReadWrite qtReadWrite;+  } u;+}TMR_TagOp_GEN2_Impinj_Monza4;++/** Sub-class for Gen2 Impinj custom tag extensions */+typedef struct TMR_TagOp_GEN2_Impinj+{+  union+  {+    TMR_TagOp_GEN2_Impinj_Monza4 monza4;+  } u;+}TMR_TagOp_GEN2_Impinj;++/** Sub-class for Gen2 IavDenatran custom tag extensions */+typedef struct TMR_TagOp_GEN2_Denatran+{+  union+  {+    TMR_TagOp_GEN2_Denatran_IAV_Activate_Secure_Mode secureMode;+    TMR_TagOp_GEN2_Denatran_IAV_Authenticate_OBU authenticateOBU;+    TMR_TagOp_GEN2_Denatran_IAV_Activate_Siniav_Mode activateSiniavMode;+    TMR_TagOp_GEN2_Denatran_IAV_OBU_Auth_ID obuAuthId;+    TMR_TagOp_GEN2_Denatran_IAV_OBU_Auth_Full_Pass1 obuAuthFullPass1;+    TMR_TagOp_GEN2_Denatran_IAV_OBU_Auth_Full_Pass2 obuAuthFullPass2;+    TMR_TagOp_GEN2_Denatran_IAV_OBU_ReadFromMemMap obuReadFromMemMap;+    TMR_TagOp_GEN2_Denatran_IAV_OBU_WriteToMemMap obuWriteToMemMap;+    TMR_TagOp_GEN2_Denatran_IAV_Get_Token_Id getTokenId;+    TMR_TagOp_GEN2_Denatran_IAV_Read_Sec readSec;+    TMR_TagOp_GEN2_Denatran_IAV_Write_Sec writeSec;+    TMR_TagOp_GEN2_Denatran_IAV_OBU_Auth_Full_Pass obuAuthFullPass;+    TMR_TagOp_GEN2_Denatran_IAV_G0_PA_OBU_Auth_ID g0paobuauthid;+  } u;+}TMR_TagOp_GEN2_Denatran;++/** Sensor type for IDS Sl900A chip */+typedef enum Sensor+{+  /* SL900A sensor type values */+  TMR_GEN2_IDS_SL900A_SENSOR_TEMP  = 0x00,+  TMR_GEN2_IDS_SL900A_SENSOR_EXT1  = 0x01,+  TMR_GEN2_IDS_SL900A_SENSOR_EXT2  = 0x02,+  TMR_GEN2_IDS_SL900A_SENSOR_BATTV = 0x03,+}Sensor;++/** SL900A password access level values */+typedef enum PasswordLevel+{+  /* No access to any protected area */+  TMR_GEN2_IDS_SL900A_PASSWORD_NOT_ALLOWED = 0x00,+  /* System area access */+  TMR_GEN2_IDS_SL900A_PASSWORD_SYSTEM = 0x01,+  /* Application area access */+  TMR_GEN2_IDS_SL900A_PASSWORD_APPLICATION = 0x02,+  /* Measurement area access */+  TMR_GEN2_IDS_SL900A_PASSWORD_MEASUREMENT = 0x03,+}PasswordLevel;++/** SL900A Data log format selection */+typedef enum LoggingForm+{+  /* Dense Logging */+  TMR_GEN2_IDS_SL900A_LOGGINGFORM_DENSE = 0x00,+  /* Log values outside specified limits */+  TMR_GEN2_IDS_SL900A_LOGGINGFORM_OUTOFLIMITS = 0x01,+  /* Log values at limit crossing points */+  TMR_GEN2_IDS_SL900A_LOGGINGFORM_LIMITSCROSSING = 0x03,+  /* Trigger log on EXT1 input */+  TMR_GEN2_IDS_SL900A_LOGGINGFORM_IRQ1 = 0x05,+  /* Trigger log on EXT2 input */+  TMR_GEN2_IDS_SL900A_LOGGINGFORM_IRQ2 = 0x06,+  /* Trigger log on EXT1 and EXT2 input */+  TMR_GEN2_IDS_SL900A_LOGGINGFORM_IRQ1IRQ2 = 0x07,+}LoggingForm;++/** SL900A Data log memory-full behavior */+typedef enum DelayMode+{+  /* Start logging after delay time */+  TMR_GEN2_IDS_SL900A_DELAYMODE_TIMER = 0x00,+  /* Start logging on external input */+  TMR_GEN2_IDS_SL900A_DELAYMODE_EXTSWITCH = 0x01,+}DelayMode;++/** SL900A Logging memory-full behavior */+typedef enum StorageRule+{+  /* Stop logging when memory fills */+  TMR_GEN2_IDS_SL900A_STORAGERULE_NORMAL = 0x00,+  /*  Roll around (circular buffer) when memory fills */+  TMR_GEN2_IDS_SL900A_STORAGERULE_ROLLING = 0x01,+}StorageRule;++/** Sub-Class for BatterType, re-check or default */+typedef enum BatteryType+{+  /* Default */+  TMR_GEN2_IDS_SL900A_BATTERYTYPE_CHECK = 0x00,+  /* Application requested for the re-check of battery type */+  TMR_GEN2_IDS_SL900A_BATTERYTYPE_RECHECK = 0x01,+}BatteryType;++/** Sub-Class for Raw 9 or 21-bit Get Log State reply */+typedef struct LimitCounter+{+  /* Number of times selected sensor has gone beyond extreme lower limit */+  uint8_t extremeLower;+  /* Number of times selected sensor has gone beyond lower limit */+  uint8_t lower;+  /* Number of times selected sensor has gone beyond upper limit */+  uint8_t upper;+  /* Number of times selected sensor has gone beyond extreme upper limit */+  uint8_t extremeUpper;+}LimitCounter;++/** Sub-Class for  specifying 40 bit LogLimits Value */+typedef struct LogLimits+{+  /* Specifying the extreme lower limit */+  uint16_t extremeLower;+  /* Specifying the lower limit */+  uint16_t lower;+  /* Specifying the upper limit */+  uint16_t upper;+  /* Specifying the extreme upper limit */+  uint16_t extremeUpper;+}LogLimits;++/** Sub-class for SystemStatus reply object */+typedef struct SystemStatus+{+  /* Measurement Address Pointer */+  uint16_t MeasurementAddressPointer;+  /* Number of memory replacements */+  uint8_t NumMemReplacements;+  /* Number of measurements */+  uint16_t NumMeasurements;+  /* Active */+  bool Active;+}SystemStatus;++/** Sub-Class for Log Status Flags */+typedef struct StatusFlags+{+  /* Logging active */+  bool Active;+  /* Measurement area full */+  bool Full;+  /* Measurement overwritten */+  bool Overwritten;+  /* A/D error occurred */+  bool ADError;+  /* Low battery */+  bool LowBattery;+  /* Shelf life low error */+  bool ShelfLifeLow;+  /* Shelf life high error */+  bool ShelfLifeHigh;+  /* ShelfLifeExpired */+  bool ShelfLifeExpired;+}StatusFlags;+/** Sub-class for get log state value reply */+typedef struct TMR_TagOp_GEN2_IDS_SL900A_LogState+{+  /* Number of excursions beyond set limits */+  LimitCounter limitCount;+  /* Logging system status */+  SystemStatus statStatus;+  /* Logging status flags */+  StatusFlags  statFlag;+}TMR_TagOp_GEN2_IDS_SL900A_LogState;++/** Sub-Class for Get Sensor Value reply */+typedef struct TMR_TagOp_GEN2_IDS_SL900A_SensorReading+{+  /* Raw 16-bit response from GetSensorValue command */+  uint16_t reply;+  /* Raw sensor reply */+  uint16_t Raw;+  /* Did A/D conversion error occur? */+  bool ADError;+  /* 5-bit Range/Limit value */+  uint8_t RangeLimit;+  /* 10-bit Sensor value */+  uint16_t Value;+}TMR_TagOp_GEN2_IDS_SL900A_SensorReading;++/** Sub-Class for Get Battery Level Reply */+typedef struct TMR_TagOp_GEN2_IDS_SL900A_BatteryLevelReading+{+  /* Raw 16-bit response from GetBatteryLevel command */+  uint16_t reply;+  /* Did A/D conversion error occur? */+  bool ADError;+  /* 1-bit Battery Type */+  uint8_t BatteryType;+  /* 10-bit Battery Level value */+  uint16_t Value;+}TMR_TagOp_GEN2_IDS_SL900A_BatteryLevelReading;++/** Sub-class for  SL900A  Log Mode Data */+typedef struct LogModeData+{+  /* Raw 8-bit response from Measurement Setup Data command */+  uint8_t Raw;+  /* Logging Format */+  LoggingForm Form;+  /* Log Memory-Full Behavior */+  StorageRule Storage;+  /* Enable log for EXT1 external sensor */+  bool Ext1Enable;+  /* Enable log for EXT2 external sensor */+  bool Ext2Enable;+  /* Enable log for temperature sensor */+  bool TempEnable;+  /* Enable log for battery sensor */+  bool BattEnable;+}LogModeData;++/** Sub-class for Calibration Data */+typedef struct TMR_TagOp_GEN2_IDS_SL900A_CalibrationData+{+  /* Raw 56-bit Calibration data value */+  uint64_t raw;+  /* AD1 lower voltage reference - fine - DO NOT MODIFY */+  uint8_t Ad1;+  /* AD1 lower voltage reference - coarse */+  uint8_t Coarse1;+  /* AD2 lower voltage reference - fine - DO NOT MODIFY */+  uint8_t Ad2;+  /* AD2 lower voltage reference - coarse */+  uint8_t Coarse2;+  /* Switches the lower AD voltage reference to ground */+  bool GndSwitch;+  /* POR voltage level for 1.5V system */+  uint8_t Selp12;+  /* Main reference voltage calibration -- DO NOT MODIFY */+  uint8_t Adf;+  /* RTC oscillator calibration */+  uint8_t Df;+  /* Controlled battery supply for external sensor - the battery voltage is connected to the EXC pin */+  bool SwExtEn;+  /* POR voltage level for 3V system */+  uint8_t Selp22;+  /* Voltage level interrupt level for external sensor -- ratiometric */+  uint8_t Irlev;+  /* Main system clock oscillator calibration -- DO NOT MODIFY */+  uint8_t RingCal;+  /* Temperature conversion offset calibration -- DO NOT MODIFY */+  uint8_t  OffInt;+  /* Bandgap voltage temperature coefficient calibration -- DO NOT MODIFY */+  uint8_t Reftc;+  /* Excitate for resistive sensors without DC */+  bool ExcRes;+  /*  Reserved for Future Use */+  uint8_t RFU;+  /* Specifyes the field user can modify */+  CalibrationParameter type;+}TMR_TagOp_GEN2_IDS_SL900A_CalibrationData;++/** Sub-class to specify Sensor Front End Parameters */+typedef struct TMR_TagOp_GEN2_IDS_SL900A_SfeParameters+{+  /*  Raw 16-bit SFE parameters value */+  uint16_t raw;+  /* External sensor 2 range */+  uint8_t Rang;+  /* External sensor 1 range */+  uint8_t Seti;+  /** +   * External sensor 1 type+   * 00 -- linear resistive sensor+   * 01 -- high impedance input (voltage follower), bridge+   * 10 -- capacitive sensor with DC+   * 11 -- capacitive or resistive sensor without DC+   */+  uint8_t Ext1;+  /**+   * External sensor 2 type+   * 00 -- linear conductive sensor+   * 01 -- high impedance input (voltage follower), bridge+   */+  uint8_t Ext2;+  /* Use preset range */+  bool AutorangeDisable;+  /**+   * Sensor used in limit check+   * 00 - first selected sensor+   * 01 -- second selected sensor+   * 10 -- third selected sensor+   * 11 -- fourth selected sensor+   */+  uint8_t VerifySensorID;+  /* specifies the type of field user want to modufy */+  SfeParameter type;+}TMR_TagOp_GEN2_IDS_SL900A_SfeParameters;++/** Sub-Class to Combination Calibration Data / SFE Parameters object */+typedef struct TMR_TagOp_GEN2_IDS_SL900A_CalSfe+{+  /* Calibration Data */+  TMR_TagOp_GEN2_IDS_SL900A_CalibrationData Cal;+  /* Sensor Front End Parameters */+  TMR_TagOp_GEN2_IDS_SL900A_SfeParameters Sfe;+}TMR_TagOp_GEN2_IDS_SL900A_CalSfe;++/**Sub-Class to spcify fifo source */+typedef enum FifoSource+{+  /* Data from SPI */+  TMR_GEN2_IDS_SL900A_FIFOSOURCE_SPI = 0x00,+  /* Data from RFID */+  TMR_GEN2_IDS_SL900A_FIFOSOURCE_RFID = 0x01,+}FifoSource;+/** Sub-Class for Get status fifo reply */+typedef struct TMR_TagOp_GEN2_IDS_SL900A_FifoStatus+{+  /* Raw 8-bit response from AccessFifo Status command */+  uint8_t raw;+  /* FIFO Busy bit */+  bool fifoBusy;+  /* Data Ready bit */+  bool dataReady;+  /* No Data bit */+  bool noData;+  /* Data Source bit (SPI, RFID) */+  FifoSource source;+  /* Number of valid bytes in FIFO register */+  uint8_t numValidBytes;+}TMR_TagOp_GEN2_IDS_SL900A_FifoStatus;++/** Sub-Class for specifying SL900A application data */+typedef struct ApplicationData+{+  /* Raw 16-bit protocol value */+  uint16_t raw;+  /* Number of user bank memory words to reserve for non-logging purposes */+  uint16_t NumberOfWords;+  /* Broken word pointer */+  uint8_t BrokenWordPointer;+}ApplicationData;++/** Sub-Class for Gen2 Ids Sl900A coustom tag extension */+typedef struct TMR_TagOP_GEN2_IDS_SL900A+{+  /* SL900A sensor type values */+  Sensor sensortype;+  /* SL900A password access level values */+  PasswordLevel level;+  /* Data log format selection */+  LoggingForm dataLog;+  /* Data log memory-full behavior */+  DelayMode mode;+  /* Logging memory-full behavior */+  StorageRule rule;+}TMR_TagOP_GEN2_IDS_SL900A;++/** Sub- class for Ids Sl900A sensor */+typedef struct TMR_TagOp_GEN2_IDS_SL900A_GetSensorValue+{+  TMR_TagOP_GEN2_IDS_SL900A sl900A;+  /* Custom Command Code */+  uint8_t CommandCode;+  /* Gen2 access password */+  uint32_t AccessPassword;+  /* IDS SL900A Password */+  uint32_t Password;+}TMR_TagOp_GEN2_IDS_SL900A_GetSensorValue;++/** Sub-class for IDs SL900A get log state */+typedef struct TMR_TagOp_GEN2_IDS_SL900A_GetLogState+{+  TMR_TagOP_GEN2_IDS_SL900A sl900A;+  /* Custom Command Code */+  uint8_t CommandCode;+  /* Gen2 access password */+  uint32_t AccessPassword;+  /* IDS SL900A Password */+  uint32_t Password;+}TMR_TagOp_GEN2_IDS_SL900A_GetLogState;++/** Sub-Class for IDS SL900A set log mode */+typedef struct TMR_TagOp_GEN2_IDS_SL900A_SetLogMode+{+  TMR_TagOP_GEN2_IDS_SL900A sl900A;+  /* Custom Command Code */+  uint8_t CommandCode;+  /* Gen2 access password */+  uint32_t AccessPassword;+  /* IDS SL900A Password */+  uint32_t Password;+  /*Enable log for EXT1 external sensor */+  bool Ext1Enable;+  /* Enable log for EXT2 external sensor */+  bool Ext2Enable;+  /* Enable log for temperature sensor */+  bool TempEnable;+  /* Enable log for battery sensor */+  bool BattEnable;+  /* Time (seconds) between log readings */+  uint16_t LogInterval;+}TMR_TagOp_GEN2_IDS_SL900A_SetLogMode;++/** Sub-Class for Gen2 end log command*/+typedef struct TMR_TagOp_GEN2_IDS_SL900A_EndLog+{+  TMR_TagOP_GEN2_IDS_SL900A sl900A;+  /* Custom Command Code */+  uint8_t CommandCode;+  /* Gen2 access password */+  uint32_t AccessPassword;+  /* IDS SL900A Password */+  uint32_t Password;+}TMR_TagOp_GEN2_IDS_SL900A_EndLog;++/** Sub-Class for DelayTime */+typedef struct Delay+{+  /* Raw 16-bit protocol value */+  uint16_t raw;+  /* Logging start mode */+  DelayMode Mode;+  /* Logging timer delay value (units of 512 seconds) */+  uint16_t Time;+  /* Trigger log on both timer and external interrupts */+  bool IrqTimerEnable;+}Delay;++/** Sub-Classs for ShelfLife Block 0 */+typedef struct TMR_TagOp_GEN2_IDS_SL900A_ShelfLifeBlock0+{+  /* raw value of block0 */+  uint32_t raw;+  /* Tmax */+  uint8_t Tmax;+  /* Tmin */+  uint8_t Tmin;+  /* Tstd */+  uint8_t Tstd;+  /* Ea */+  uint8_t Ea;+}TMR_TagOp_GEN2_IDS_SL900A_ShelfLifeBlock0;++/** Sub-Class for ShelfLife Block 1 */+typedef struct TMR_TagOp_GEN2_IDS_SL900A_ShelfLifeBlock1+{+  /* raw value for block 1 */+  uint32_t raw;+  /* SLinit */+  uint16_t SLinit;+  /* Tint */+  uint16_t Tint;+  /* SensorID */+  uint8_t sensorID;+  /* Enable negative shelf life */+  bool enableNegative;+  /* Shelf life algorithem enable */+  bool algorithmEnable;+  /* RFU bytes */+  uint8_t rfu;+}TMR_TagOp_GEN2_IDS_SL900A_ShelfLifeBlock1;++/** Sub-class for GetMeasurmentSetUp command */+typedef struct TMR_TagOp_GEN2_IDS_SL900A_MeasurementSetupData+{+  /* Raw 16 byte response from Measurement Setup Data command */+  uint8_t Raw[16];+  /* LogLimits Data */+  LogLimits loglimit;+  /* Log Mode Data */+  LogModeData logModeData;+  /* Delay Data */+  Delay delyTime;+  /* Application Data */+  ApplicationData addData;+  /* Time (seconds) between log readings */+  uint16_t logInterval;+  /* Start Time */+  TMR_TimeStructure startTime;+}TMR_TagOp_GEN2_IDS_SL900A_MeasurementSetupData;++/** Sub-Class for GEN2 initialize command */+typedef struct TMR_TagOp_GEN2_IDS_SL900A_Initialize+{+  TMR_TagOP_GEN2_IDS_SL900A sl900A;+  /* Logging memory configuration */+  ApplicationData applicationData;+  /* Custom Command Code */+  uint8_t CommandCode;+  /* Gen2 access password */+  uint32_t AccessPassword;+  /* IDS SL900A Password */+  uint32_t Password;+  /* Delay time */+  Delay delayTime;+}TMR_TagOp_GEN2_IDS_SL900A_Initialize;++/** Sub-Class for specifying AccessFifo operation */+typedef enum AccessFifoOperation+{+  /* Read from FIFO */+  TMR_GEN2_IDS_SL900A_ACCESSFIFO_READ = 0x80,+  /* Write to FIFO */+  TMR_GEN2_IDS_SL900A_ACCESSFIFO_WRITE = 0xA0,+  /* Get FIFO status */+  TMR_GEN2_IDS_SL900A_ACCESSFIFO_STATUS = 0xC0,+}AccessFifoOperation;++/** Sub-Class for Gen2 Ids AccessFifo command */+typedef struct TMR_TagOp_GEN2_IDS_SL900A_AccessFifo+{+  TMR_TagOP_GEN2_IDS_SL900A sl900A;+  /* Custom Command Code */+  uint8_t CommandCode;+  /* Gen2 access password */+  uint32_t AccessPassword;+  /* IDS SL900A Password */+  uint32_t Password;+  /* specify the operation do be done on fifo */+  AccessFifoOperation operation;+}TMR_TagOp_GEN2_IDS_SL900A_AccessFifo;++/** Sub-Class for Gen2 Ids accessFifo write command */+typedef struct TMR_TagOp_GEN2_IDS_SL900A_AccessFifoWrite+{+  TMR_TagOp_GEN2_IDS_SL900A_AccessFifo write;+  /* Bytes to write to FIFO */+  TMR_uint8List *payLoad;+}TMR_TagOp_GEN2_IDS_SL900A_AccessFifoWrite;++/** Sub-Class for Gen2 Ids accessFifo read command */+typedef struct TMR_TagOp_GEN2_IDS_SL900A_AccessFifoRead+{+  TMR_TagOp_GEN2_IDS_SL900A_AccessFifo read;+  /* Number of bytes to read from FIFO */+  uint8_t length;+}TMR_TagOp_GEN2_IDS_SL900A_AccessFifoRead;++/** Sub-Class for Gen2 Ids accessFifo status command */+typedef struct TMR_TagOp_GEN2_IDS_SL900A_AccessFifoStatus+{+  TMR_TagOp_GEN2_IDS_SL900A_AccessFifo status;+}TMR_TagOp_GEN2_IDS_SL900A_AccessFifoStatus;++/** Sub-Class for Gen2 StartLog command */+typedef struct TMR_TagOp_GEN2_IDS_SL900A_StartLog+{+  TMR_TagOP_GEN2_IDS_SL900A sl900A;+  /* Custom Command Code */+  uint8_t CommandCode;+  /* Gen2 access password */+  uint32_t AccessPassword;+  /* IDS SL900A Password */+  uint32_t Password;+  /* Time to initialize log timestamp counter with */+  uint32_t startTime;  +}TMR_TagOp_GEN2_IDS_SL900A_StartLog;++/** Sub-Class for Gen2 IDS GetCalibrationData command */+typedef struct  TMR_TagOp_GEN2_IDS_SL900A_GetCalibrationData+{+  TMR_TagOP_GEN2_IDS_SL900A sl900A;+  /* Custom Command Code */+  uint8_t CommandCode;+  /* Gen2 access password */+  uint32_t AccessPassword;+  /* IDS SL900A Password */+  uint32_t Password;+}TMR_TagOp_GEN2_IDS_SL900A_GetCalibrationData;++/** Sub-Class for Gen2 IDS SetCalibrationData command */+typedef struct TMR_TagOp_GEN2_IDS_SL900A_SetCalibrationData+{+  TMR_TagOP_GEN2_IDS_SL900A sl900A;+  /* Custom Command Code */+  uint8_t CommandCode;+  /* Gen2 access password */+  uint32_t AccessPassword;+  /* IDS SL900A Password */+  uint32_t Password;+  /* Calibration parameters */+  TMR_TagOp_GEN2_IDS_SL900A_CalibrationData cal; +}TMR_TagOp_GEN2_IDS_SL900A_SetCalibrationData;++/** Sub-class for Gen2 Ids SetSfeParameters command */+typedef struct TMR_TagOp_GEN2_IDS_SL900A_SetSfeParameters+{+  TMR_TagOP_GEN2_IDS_SL900A sl900A;+  /* Custom Command Code */+  uint8_t CommandCode;+  /* Gen2 access password */+  uint32_t AccessPassword;+  /* IDS SL900A Password */+  uint32_t Password;+  /* Sfe Parameters */+  TMR_TagOp_GEN2_IDS_SL900A_SfeParameters *sfe;+}TMR_TagOp_GEN2_IDS_SL900A_SetSfeParameters;++/** Sub-class for Gen2 Ids GetMeasurementSetup command */+typedef struct TMR_TagOp_GEN2_IDS_SL900A_GetMeasurementSetup+{+  TMR_TagOP_GEN2_IDS_SL900A sl900A;+  /* Custom Command Code */+  uint8_t CommandCode;+  /* Gen2 access password */+  uint32_t AccessPassword;+  /* IDS SL900A Password */+  uint32_t Password;+}TMR_TagOp_GEN2_IDS_SL900A_GetMeasurementSetup;++/** Sub-class for Gen2 Ids GetBatteryLevel command */+typedef struct TMR_TagOp_GEN2_IDS_SL900A_GetBatteryLevel+{+  TMR_TagOP_GEN2_IDS_SL900A sl900A;+  /* Custom Command Code */+  uint8_t CommandCode;+  /* Gen2 access password */+  uint32_t AccessPassword;+  /* IDS SL900A Password */+  uint32_t Password;+  /* enum BatterType, re-check or default */+  BatteryType batteryType;+}TMR_TagOp_GEN2_IDS_SL900A_GetBatteryLevel;++/** Sub-Class for Gen2 Ids SetLogLimits Command */+typedef struct TMR_TagOp_GEN2_IDS_SL900A_SetLogLimits+{+  TMR_TagOP_GEN2_IDS_SL900A sl900A;+  /* Custom Command Code */+  uint8_t CommandCode;+  /* Gen2 access password */+  uint32_t AccessPassword;+  /* IDS SL900A Password */+  uint32_t Password;+  /* Specify the Log Limits */+  LogLimits limit;+}TMR_TagOp_GEN2_IDS_SL900A_SetLogLimits;++/** Sub-Class for Gen2 Ids SetShelfLife Command */+typedef struct TMR_TagOp_GEN2_IDS_SL900A_SetShelfLife+{+  TMR_TagOP_GEN2_IDS_SL900A sl900A;+  /* Custom Command Code */+  uint8_t CommandCode;+  /* Gen2 access password */+  uint32_t AccessPassword;+  /* IDS SL900A Password */+  uint32_t Password;+  /* Specify the ShelfLifeBlock0 */+  TMR_TagOp_GEN2_IDS_SL900A_ShelfLifeBlock0 *shelfLifeBlock0;+  /* Specify the ShelfLifeBlock1 */+  TMR_TagOp_GEN2_IDS_SL900A_ShelfLifeBlock1 *shelfLifeBlock1;+}TMR_TagOp_GEN2_IDS_SL900A_SetShelfLife;++/** Sub-Class for Gen2 Ids SetPassword Command */+typedef struct TMR_TagOp_GEN2_IDS_SL900A_SetPassword+{+  TMR_TagOP_GEN2_IDS_SL900A sl900A;+  /* Custom Command Code */+  uint8_t CommandCode;+  /* Gen2 access password */+  uint32_t AccessPassword;+  /* IDS SL900A Password */+  uint32_t Password;+  /* New Passwordlevel */+  PasswordLevel NewPasswordLevel;+  /* New password */+  uint32_t NewPassword;+}TMR_TagOp_GEN2_IDS_SL900A_SetPassword;++/** Sub-class for Gen2 Ids parameters */+typedef struct TMR_TagOP_GEN2_IDS+{+  union+  {+    TMR_TagOp_GEN2_IDS_SL900A_GetSensorValue sensor;+    TMR_TagOp_GEN2_IDS_SL900A_GetLogState  getLog;+    TMR_TagOp_GEN2_IDS_SL900A_SetLogMode   setLogMode;+    TMR_TagOp_GEN2_IDS_SL900A_EndLog endLog;+    TMR_TagOp_GEN2_IDS_SL900A_Initialize initialize;+    TMR_TagOp_GEN2_IDS_SL900A_AccessFifoRead accessFifoRead;+    TMR_TagOp_GEN2_IDS_SL900A_AccessFifoWrite accessFifoWrite;+    TMR_TagOp_GEN2_IDS_SL900A_AccessFifoStatus accessFifoStatus;+    TMR_TagOp_GEN2_IDS_SL900A_StartLog startLog;+    TMR_TagOp_GEN2_IDS_SL900A_GetCalibrationData calibrationData;+    TMR_TagOp_GEN2_IDS_SL900A_SetCalibrationData setCalibration;+    TMR_TagOp_GEN2_IDS_SL900A_SetSfeParameters setSfeParameters;+    TMR_TagOp_GEN2_IDS_SL900A_GetMeasurementSetup measurementSetup;+    TMR_TagOp_GEN2_IDS_SL900A_GetBatteryLevel batteryLevel;+    TMR_TagOp_GEN2_IDS_SL900A_SetLogLimits setLogLimit;+    TMR_TagOp_GEN2_IDS_SL900A_SetShelfLife setShelfLife;+    TMR_TagOp_GEN2_IDS_SL900A_SetPassword setPassword;+    +  }u;+}TMR_TagOP_GEN2_IDS;+/** Sub-class for Gen2 custom tagops */+typedef struct TMR_TagOp_GEN2_Custom+{+  TMR_SR_GEN2_SiliconType chipType;+  union+  {+    TMR_TagOp_GEN2_Alien alien;+    TMR_TagOp_GEN2_NXP nxp;+    TMR_TagOp_GEN2_Impinj impinj;+    TMR_TagOP_GEN2_IDS ids;+    TMR_TagOp_GEN2_Denatran IavDenatran;+  } u;+}TMR_TagOp_GEN2_Custom;++/** Sub-class for ISO180006B tagops */+typedef struct TMR_TagOp_ISO180006B+{+  union+  {+    TMR_TagOp_ISO180006B_Lock lock;+    TMR_TagOp_ISO180006B_WriteData writeData;+    TMR_TagOp_ISO180006B_ReadData readData;+  } u;+}TMR_TagOp_ISO180006B;++/** Sub-class for Gen2 standard tagops */+typedef struct TMR_TagOp_GEN2+{+  union+  {+    TMR_TagOp_GEN2_WriteTag writeTag;+    TMR_TagOp_GEN2_WriteData writeData;+    TMR_TagOp_GEN2_ReadData readData;+    TMR_TagOp_GEN2_SecureReadData secureReadData;+    TMR_TagOp_GEN2_Lock lock;+    TMR_TagOp_GEN2_Kill kill;+    TMR_TagOp_GEN2_BlockWrite blockWrite;+    TMR_TagOp_GEN2_BlockPermaLock blockPermaLock;+    TMR_TagOp_GEN2_BlockErase blockErase;+    TMR_TagOp_GEN2_Custom custom;+  } u;+}TMR_TagOp_GEN2;++/** Tag operation data structure */+struct TMR_TagOp+{+  TMR_TagOpType type;+  union+  {+    TMR_TagOp_GEN2 gen2;+    TMR_TagOp_ISO180006B iso180006b;+    TMR_TagOp_List list;+  } u;+};++TMR_Status TMR_TagOp_init_GEN2_WriteTag(TMR_TagOp *tagop, TMR_TagData* epc);+TMR_Status TMR_TagOp_init_GEN2_ReadData(TMR_TagOp *tagop, TMR_GEN2_Bank bank,+                                        uint32_t wordAddress, uint8_t len);+TMR_Status TMR_TagOp_init_GEN2_SecureReadData(TMR_TagOp *tagop, TMR_GEN2_Bank bank, uint32_t wordAddress,+                                               uint8_t len, uint8_t type, uint8_t passwordType);+TMR_Status TMR_TagOp_init_GEN2_SecurePassWord(TMR_TagOp *tagop, uint8_t passwordType, uint32_t gen2PassWord,+                                              uint8_t addressLength, uint8_t addressOffset, uint16_t flashOffset);+TMR_Status TMR_TagOp_init_GEN2_WriteData(TMR_TagOp *tagop, TMR_GEN2_Bank bank,+                                         uint32_t wordAddress,+                                         TMR_uint16List *data);+TMR_Status TMR_TagOp_init_GEN2_Lock(TMR_TagOp *tagop, uint16_t mask,+                                    uint16_t action,  TMR_GEN2_Password accessPassword);+TMR_Status TMR_TagOp_init_GEN2_Kill(TMR_TagOp *tagop,+                                    TMR_GEN2_Password killPassword);+TMR_Status TMR_TagOp_init_GEN2_BlockWrite(TMR_TagOp *tagop, TMR_GEN2_Bank bank, uint32_t wordPtr, TMR_uint16List *data);+TMR_Status TMR_TagOp_init_GEN2_BlockPermaLock(TMR_TagOp *tagop, uint8_t readLock, TMR_GEN2_Bank bank, uint32_t blockPtr, TMR_uint16List* mask);+TMR_Status TMR_TagOp_init_GEN2_BlockErase(TMR_TagOp *tagop, TMR_GEN2_Bank bank, uint32_t wordPtr, uint8_t wordCount);++TMR_Status TMR_TagOp_init_ISO180006B_ReadData(TMR_TagOp *tagop, uint8_t byteAddress, uint8_t len);+TMR_Status TMR_TagOp_init_ISO180006B_WriteData(TMR_TagOp *tagop, uint8_t byteAddress, TMR_uint8List *data);+TMR_Status TMR_TagOp_init_ISO180006B_Lock(TMR_TagOp *tagop, uint8_t address);+TMR_Status TMR_TagOp_init_GEN2_Alien_Higgs2_PartialLoadImage(TMR_TagOp *tagop, TMR_GEN2_Password killPassword,+                                                  TMR_GEN2_Password accessPassword, TMR_TagData *epc);+TMR_Status TMR_TagOp_init_GEN2_Alien_Higgs2_FullLoadImage(TMR_TagOp *tagop, TMR_GEN2_Password killPassword,+                                    TMR_GEN2_Password accessPassword, uint16_t lockBits, +                                    uint16_t pcWord, TMR_TagData *epc);+TMR_Status TMR_TagOp_init_GEN2_Alien_Higgs3_FastLoadImage(TMR_TagOp *tagop, TMR_GEN2_Password currentAccessPassword,+                                    TMR_GEN2_Password accessPassword, TMR_GEN2_Password killPassword, +                                    uint16_t pcWord, TMR_TagData *epc);+TMR_Status TMR_TagOp_init_GEN2_Alien_Higgs3_LoadImage(TMR_TagOp *tagop, TMR_GEN2_Password currentAccessPassword,+                                    TMR_GEN2_Password accessPassword, TMR_GEN2_Password killPassword, +                                    uint16_t pcWord, TMR_uint8List *epcAndUserData);+TMR_Status TMR_TagOp_init_GEN2_Alien_Higgs3_BlockReadLock(TMR_TagOp *tagop, TMR_GEN2_Password accessPassword, uint8_t lockBits);++TMR_Status TMR_TagOp_init_GEN2_NXP_G2I_SetReadProtect(TMR_TagOp *tagop, TMR_GEN2_Password accessPassword);+TMR_Status TMR_TagOp_init_GEN2_NXP_G2X_SetReadProtect(TMR_TagOp *tagop, TMR_GEN2_Password accessPassword);++TMR_Status TMR_TagOp_init_GEN2_NXP_G2I_ResetReadProtect(TMR_TagOp *tagop, TMR_GEN2_Password accessPassword);+TMR_Status TMR_TagOp_init_GEN2_NXP_G2X_ResetReadProtect(TMR_TagOp *tagop, TMR_GEN2_Password accessPassword);++TMR_Status TMR_TagOp_init_GEN2_NXP_G2I_ChangeEAS(TMR_TagOp *tagop, TMR_GEN2_Password accessPassword, bool resetEAS);+TMR_Status TMR_TagOp_init_GEN2_NXP_G2X_ChangeEAS(TMR_TagOp *tagop, TMR_GEN2_Password accessPassword, bool resetEAS);++TMR_Status TMR_TagOp_init_GEN2_NXP_G2I_EASAlarm(TMR_TagOp *tagop, TMR_GEN2_DivideRatio dr, TMR_GEN2_TagEncoding m, TMR_GEN2_TrExt trExt);+TMR_Status TMR_TagOp_init_GEN2_NXP_G2X_EASAlarm(TMR_TagOp *tagop, TMR_GEN2_DivideRatio dr, TMR_GEN2_TagEncoding m, TMR_GEN2_TrExt trExt);++TMR_Status TMR_TagOp_init_GEN2_NXP_G2I_Calibrate(TMR_TagOp *tagop, TMR_GEN2_Password accessPassword);+TMR_Status TMR_TagOp_init_GEN2_NXP_G2X_Calibrate(TMR_TagOp *tagop, TMR_GEN2_Password accessPassword);++TMR_Status TMR_TagOp_init_GEN2_NXP_G2I_ChangeConfig(TMR_TagOp *tagop, TMR_GEN2_Password accessPassword, TMR_NXP_ConfigWord configWord);+TMR_Status TMR_TagOp_init_GEN2_NXP_G2X_ChangeConfig(TMR_TagOp *tagop, TMR_GEN2_Password accessPassword, TMR_NXP_ConfigWord configWord);+TMR_Status TMR_TagOp_init_GEN2_NXP_AES_Untraceable(TMR_TagOp *tagop,TMR_GEN2_UNTRACEABLE_Epc epc, int epclen , TMR_GEN2_UNTRACEABLE_Tid tid,+				    TMR_GEN2_UNTRACEABLE_UserMemory user, TMR_GEN2_UNTRACEABLE_Range range, TMR_TagOp_GEN2_NXP_Untraceable *auth);+TMR_Status TMR_TagOp_init_GEN2_NXP_AES_Authenticate(TMR_TagOp *tagop, TMR_TagOp_GEN2_NXP_Authenticate *authenticate);+TMR_Status TMR_TagOp_init_GEN2_NXP_AES_ReadBuffer(TMR_TagOp *tagop, uint16_t wordPointer, uint16_t bitCount, TMR_TagOp_GEN2_NXP_Readbuffer *readbuffer);+TMR_Status TMR_TagOp_init_GEN2_NXP_AES_Tam1authentication(TMR_TagOp_GEN2_NXP_Tam1Authentication *auth, TMR_NXP_KeyId keyid, TMR_uint8List *key, +					TMR_uint8List *ichallenge ,bool sendRawData );+TMR_Status TMR_TagOp_init_GEN2_NXP_AES_Tam2authentication(TMR_TagOp_GEN2_NXP_Tam2Authentication *auth, TMR_NXP_KeyId keyid, TMR_uint8List *key, +					TMR_uint8List *ichallenge, TMR_NXP_Profile profile, uint16_t Offset,uint8_t blockCount,bool sendRawData);++TMR_Status TMR_TagOp_init_GEN2_Impinj_Monza4_QTReadWrite(TMR_TagOp *tagop, TMR_GEN2_Password accessPassword,+                                             TMR_Monza4_ControlByte controlByte, TMR_Monza4_Payload payload);++TMR_Status TMR_TagOp_init_GEN2_Denatran_IAV_Activate_Secure_Mode(TMR_TagOp *tagop, uint8_t rfuByte);+TMR_Status TMR_TagOp_init_GEN2_Denatran_IAV_Authenticate_OBU(TMR_TagOp *tagop, uint8_t rfuByte);+TMR_Status TMR_TagOp_init_GEN2_Denatran_IAV_Activate_Siniav_Mode(TMR_TagOp *tagop, uint8_t rfuByte, TMR_uint8List *data);+TMR_Status TMR_TagOp_init_GEN2_Denatran_IAV_OBU_Auth_ID(TMR_TagOp *tagop, uint8_t rfuByte);+TMR_Status TMR_TagOp_init_GEN2_Denatran_IAV_OBU_Auth_Full_Pass1(TMR_TagOp *tagop, uint8_t rfuByte);+TMR_Status TMR_TagOp_init_GEN2_Denatran_IAV_OBU_Auth_Full_Pass2(TMR_TagOp *tagop, uint8_t rfuByte);+TMR_Status TMR_TagOp_init_GEN2_Denatran_IAV_OBU_ReadFromMemMap(TMR_TagOp *tagop, uint8_t rfuByte, uint16_t wordAddress);+TMR_Status TMR_TagOp_init_GEN2_Denatran_IAV_OBU_WriteToMemMap(TMR_TagOp *tagop, uint8_t rfuByte, uint16_t wordAddress, uint16_t word, uint8_t* tagID, uint8_t* data);+TMR_Status TMR_TagOp_init_GEN2_Denatran_IAV_GetTokenId(TMR_TagOp *tagop);+TMR_Status TMR_TagOp_init_GEN2_Denatran_IAV_OBU_Auth_Full_Pass(TMR_TagOp *tagop, uint8_t payload);+TMR_Status TMR_TagOp_init_GEN2_Denatran_IAV_ReadSec(TMR_TagOp *tagop, uint8_t payload, uint16_t wordAddress);+TMR_Status TMR_TagOp_init_GEN2_Denatran_IAV_WriteSec(TMR_TagOp *tagop, uint8_t payload, uint8_t* data, uint8_t* credentials);+TMR_Status TMR_TagOp_init_GEN2_Denatran_IAV_G0_PA_OBU_Auth(TMR_TagOp *tagop, uint8_t rfuByte);++TMR_Status +TMR_init_GEN2_NXP_G2I_ConfigWord(TMR_NXP_ConfigWord *configWord);++TMR_Status+TMR_init_GEN2_Impinj_Monza4_ControlByte(TMR_Monza4_ControlByte *controlByte);++TMR_Status+TMR_init_GEN2_Impinj_Monza4_Payload(TMR_Monza4_Payload *payload);++TMR_Status+TMR_TagOp_init_GEN2_IDS_SL900A_GetSensorValue(TMR_TagOp *tagop, TMR_GEN2_Password accessPassword,+                                              PasswordLevel level, uint32_t password, Sensor type);+TMR_Status+TMR_TagOp_init_GEN2_IDS_SL900A_GetCalibrationData(TMR_TagOp *tagop, TMR_GEN2_Password accessPassword,+                                                  PasswordLevel leveli, uint32_t password);+TMR_Status+TMR_TagOp_init_GEN2_IDS_SL900A_SetLogLimit(TMR_TagOp *tagop, TMR_GEN2_Password accessPassword, +                                           PasswordLevel level, uint32_t password, LogLimits *logLimits);+TMR_Status+TMR_TagOp_init_GEN2_IDS_SL900A_SetCalibrationData(TMR_TagOp *tagop, TMR_GEN2_Password accessPassword, PasswordLevel level, +                                                  uint32_t password, TMR_TagOp_GEN2_IDS_SL900A_CalibrationData *data);+TMR_Status+TMR_TagOp_init_GEN2_IDS_SL900A_SetSfeParameters(TMR_TagOp *tagop, TMR_GEN2_Password accessPassword, PasswordLevel level, +                                                uint32_t password, TMR_TagOp_GEN2_IDS_SL900A_SfeParameters *data);+TMR_Status+TMR_init_GEN2_IDS_SL900A_SensorReading(TMR_uint8List *reply, TMR_TagOp_GEN2_IDS_SL900A_SensorReading *sensor);++TMR_Status+TMR_init_GEN2_IDS_SL900A_BatteryLevelReading(TMR_uint8List *reply, TMR_TagOp_GEN2_IDS_SL900A_BatteryLevelReading *battery);++TMR_Status+TMR_init_GEN2_IDS_SL900A_MeasurementSetupData(TMR_uint8List *reply, TMR_TagOp_GEN2_IDS_SL900A_MeasurementSetupData *measurment);++TMR_Status+TMR_init_GEN2_IDS_SL900A_CalSfe(TMR_uint8List *reply, TMR_TagOp_GEN2_IDS_SL900A_CalSfe *calSfe);++TMR_Status+TMR_init_GEN2_IDS_SL900A_CalibrationData(uint8_t byte[7], TMR_TagOp_GEN2_IDS_SL900A_CalibrationData *cal);++TMR_Status+TMR_update_GEN2_IDS_SL900A_CalibrationData(TMR_TagOp_GEN2_IDS_SL900A_CalibrationData *cal);++TMR_Status+TMR_update_GEN2_IDS_SL900A_SfeParameters(TMR_TagOp_GEN2_IDS_SL900A_SfeParameters *sfe);++TMR_Status+TMR_init_GEN2_IDS_SL900A_SfeParameters(uint8_t byte[2], TMR_TagOp_GEN2_IDS_SL900A_SfeParameters *sfe);++TMR_Status+TMR_TagOp_init_GEN2_IDS_SL900A_GetLogState(TMR_TagOp *tagop, TMR_GEN2_Password accessPassword,+                                           PasswordLevel level, uint32_t password);++TMR_Status+TMR_TagOp_init_GEN2_IDS_SL900A_SetLogMode(TMR_TagOp *tagop, TMR_GEN2_Password accessPassword, PasswordLevel level,+                                          uint32_t password, LoggingForm form, StorageRule rule, bool Ext1Enable,+                                          bool Ext2Enable, bool TempEnable, bool BattEnable, uint16_t LogInterval);++TMR_Status+TMR_init_GEN2_IDS_SL900A_LogState(TMR_uint8List *reply, TMR_TagOp_GEN2_IDS_SL900A_LogState *log);++TMR_Status+TMR_TagOp_init_GEN2_IDS_SL900A_Initialize(TMR_TagOp *tagop, TMR_GEN2_Password accessPassword, PasswordLevel level,+                                          uint32_t password, uint8_t delayMode, uint16_t delayTime, bool timeEnable,+                                          uint16_t numberOfWords, uint8_t BrokenWordPointer);++TMR_Status+TMR_TagOp_init_GEN2_IDS_SL900A_EndLog(TMR_TagOp *tagop, TMR_GEN2_Password accessPassword,+                                      PasswordLevel level, uint32_t password);+TMR_Status+TMR_TagOp_init_GEN2_IDS_SL900A_AccessFifoStatus(TMR_TagOp *tagop, TMR_GEN2_Password accessPassword,+                                                PasswordLevel level ,uint32_t password);+TMR_Status+TMR_TagOp_init_GEN2_IDS_SL900A_AccessFifoRead(TMR_TagOp *tagop, TMR_GEN2_Password accessPassword, PasswordLevel level,+                                              uint32_t password,  uint8_t readLength);+TMR_Status+TMR_TagOp_init_GEN2_IDS_SL900A_AccessFifoWrite(TMR_TagOp *tagop, TMR_GEN2_Password accessPassword,+                                               PasswordLevel level, uint32_t password, TMR_uint8List *payLoad);+TMR_Status+TMR_init_GEN2_IDS_SL900A_FifoStatus(TMR_uint8List *reply, TMR_TagOp_GEN2_IDS_SL900A_FifoStatus *status);++TMR_Status+TMR_TagOp_init_GEN2_IDS_SL900A_StartLog(TMR_TagOp *tagop, TMR_GEN2_Password accessPassword,+                                        PasswordLevel level, uint32_t password, TMR_TimeStructure *timestamp);+TMR_Status+TMR_TagOp_init_GEN2_IDS_SL900A_GetMeasurementSetup(TMR_TagOp *tagop, TMR_GEN2_Password accessPassword,+                                                   PasswordLevel level, uint32_t password);++TMR_Status+TMR_TagOp_init_GEN2_IDS_SL900A_SetPassword(TMR_TagOp *tagop, TMR_GEN2_Password accessPassword, PasswordLevel level,+                                           uint32_t password, PasswordLevel newPasswordLevel, uint32_t newPassword);+TMR_Status+TMR_TagOp_init_GEN2_IDS_SL900A_GetBatteryLevel(TMR_TagOp *tagop, TMR_GEN2_Password accessPassword,+                                               PasswordLevel level, uint32_t password, BatteryType type);+TMR_Status+TMR_TagOp_init_GEN2_IDS_SL900A_ShelfLifeBlock0(TMR_TagOp_GEN2_IDS_SL900A_ShelfLifeBlock0 *block0,+                                               uint8_t tmax, uint8_t Tmin, uint8_t tstd, uint8_t Ea);+TMR_Status+TMR_TagOp_init_GEN2_IDS_SL900A_ShelfLifeBlock1(TMR_TagOp_GEN2_IDS_SL900A_ShelfLifeBlock1 *block1,+                                               uint16_t slinit, uint16_t tint, uint8_t sensorid,+                                               bool negative, bool algorithm);+TMR_Status+TMR_TagOp_init_GEN2_IDS_SL900A_SetShelfLife(TMR_TagOp *tagop, TMR_GEN2_Password accessPassword, PasswordLevel level,+                                            uint32_t password, TMR_TagOp_GEN2_IDS_SL900A_ShelfLifeBlock0 *block0,+                                            TMR_TagOp_GEN2_IDS_SL900A_ShelfLifeBlock1 *block1);+TMR_Status+TMR_GEN2_init_BapParams(TMR_GEN2_Bap *bapVal, int32_t powerUpDelayUs, int32_t freqHopOfftimeUs);+#ifdef __cplusplus+}+#endif++#endif /* _TMR_TAGOP_H */
+ cbits/api/tmr_types.h view
@@ -0,0 +1,121 @@+/* ex: set tabstop=2 shiftwidth=2 expandtab cindent: */+#ifndef _TMR_TYPES_H+#define _TMR_TYPES_H+/**+ *  @file tmr_types.h+ *  @brief Mercury API - General data type definitions+ *  @author Nathan Williams+ *  @date 10/20/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.+ */++#ifdef WINCE+#include <stdint_win32.h>+#else+#include <stdint.h>+#endif+#include <stdbool.h>++#ifdef  __cplusplus+extern "C" {+#endif++/** Internal string representation with known storage size */+typedef struct TMR_String+{+  /** The null-terminated string value */+  char *value;+  /** The allocated number of bytes pointed to */+  uint16_t max;+} TMR_String;++/** List of uint8_t values */+typedef struct TMR_uint8List+{+  /** The array of values */+  uint8_t *list;+  /** The number of entries there is space for in the array */+  uint16_t max;+  /** The number of entries in the list - may be larger than max, indicating truncated data. */+  uint16_t len;+} TMR_uint8List;++/** List of uint16_t values */+typedef struct TMR_uint16List+{+  /** The array of values */+  uint16_t *list;+  /** The number of entries there is space for in the array */+  uint16_t max;+  /** The number of entries in the list - may be larger than max, indicating truncated data. */+  uint16_t len;+} TMR_uint16List;++/** List of uint32_t values */+typedef struct TMR_uint32List+{+  /** The array of values */+  uint32_t *list;+  /** The number of entries there is space for in the array */+  uint16_t max;+  /** The number of entries in the list - may be larger than max, indicating truncated data. */+  uint16_t len;+} TMR_uint32List;++/** List of int8_t values */+typedef struct TMR_int8List+{+  /** The array of values */+  int8_t *list;+  /** The number of entries there is space for the array */+  int8_t max;+  /** The number of entries in the list - may be larger than max, indicating truncated data. */+  int8_t len;+}TMR_int8List;++/**+ * Function callback used to obtain firmware data during a firmware+ * load operation.  TMR_firmwareLoad will call this repeatedly to+ * obtain data to send to the reader. A buffer of a specified size+ * will be passed in; the callback is free to place less than that+ * amount of data in the buffer, provided that size is modified+ * accordingly. When the end of the firmware image has been reached,+ * the callback should return false.  ++ * @see TMR_memoryProvider and TMR_fileProvider for pre-existing+ * callbacks to load firmware from system memory or from a file.+ * + * @param cookie Arbitrary data passed to the callback.+ * @param[in] size Pointer to amount of space in the buffer.+ * @param[out] Points to number of bytes stored in the buffer.+ * @param[out] data Buffer of bytes of firmware image.+ * @return true if there is more data to load+ */+typedef bool (*TMR_FirmwareDataProvider)(void *cookie, uint16_t *size, uint8_t *data);++#ifdef __cplusplus+}+#endif++#endif /* _TMR_TYPES_H */
+ cbits/api/tmr_utils.c view
@@ -0,0 +1,233 @@+/**+ *  @file tmr_utils.c+ *  @brief Mercury API - utility functions+ *  @author Nathan Williams+ *  @date 12/10/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 <stddef.h>+#include <string.h>++#include "osdep.h"+#include "tmr_types.h"+#include "tmr_utils.h"++#ifndef TMR_USE_HOST_C_LIBRARY++void *+tm_memcpy(void *dest, const void *src, size_t n)+{+  const uint8_t *u8src;+  uint8_t *u8dest;++  u8dest = dest;+  u8src = src;++  while (0 != n)+  {+    *u8dest = *u8src;+    u8dest++;+    u8src++;+    n--;+  }++  return dest;+}++char *+tm_strcpy(char *dest, const char *src)+{+  char *ptr, val;++  ptr = dest;++  do+  {+    val = *src;+    *ptr = val;+    ptr++;+    src++;+  } +  while ('\0' != val);++  return dest;+}++char *+tm_strchr(const char *s, int c)+{+  const char *ptr;++  for (ptr = s; *ptr != '\0'; ptr++)+  {+    if (*ptr == c)+    {+      return (char *)ptr;+    }+  }++  return NULL;+}++#endif /* TMR_USE_HOST_C_LIBRARY */++int+tm_strcasecmp(const char *s1, const char *s2)+{+  char v1, v2;+  int diff;++  do+  {+    v1 = *s1;+    if (v1 >= 'a' && v1 <= 'z')+      v1 -= 'a' - 'A';+    v2 = *s2;+    if (v2 >= 'a' && v2 <= 'z')+      v2 -= 'a' - 'A';+    s1++;+    s2++;+  }+  while (v1 == v2 && '\0' != v1 && '\0' != v2);++  diff = v1 - v2;+  if (diff < 0)+    return -1;+  else if (diff > 0)+    return 1;+  else+    return 0;+}++/* Get a high/low timestamp pair, being careful not to get one value+ * before a wraparound and the other one after, which would lead to+ * 50-day time jumps forward or backwards.  (high<<32)|low is in milliseconds.+ */+void+tm_gettime_consistent(uint32_t *high, uint32_t *low)+{+  uint32_t tmpHigh;++  *high   = tmr_gettime_high();+  *low    = tmr_gettime_low();+  tmpHigh = tmr_gettime_high();++  if (tmpHigh != *high)+  {+    *high = tmpHigh;+    *low = tmr_gettime_low();+  }+}++/* Find the time difference from start to end, allowing for end having+ * wrapped around UINT32_MAX and back to zero.+ */+uint32_t+tm_time_subtract(uint32_t end, uint32_t start)+{+  if (end >= start)+    return end - start;+  else+    return (UINT32_MAX - start) + end;+}++/** Minimum number of bytes required to hold a given number of bits.+ *+ * @param bitCount  number of bits to hold+ * @return  Minimum length of bytes that can contain that many bits+ */+int tm_u8s_per_bits(int bitCount) +{+	return ((0<bitCount) ?((((bitCount)-1)>>3)+1) :0);+}++void+TMR_stringCopy(TMR_String *dest, const char *src, int len)+{+  if (dest->max - 1 < len)+  {+    len = dest->max - 1;+  }+  if (dest->max > 0)+  {+    memcpy(dest->value, src, len);+    dest->value[len] = '\0';+  }+}++uint64_t+TMR_makeBitMask(int offset, int length)+{+  uint64_t mask;++  mask = 0;+  mask = ~mask;+  mask <<= length;+  mask = ~mask;++  mask <<= offset;++  return mask;+}++uint32_t+TMR_byteArrayToInt(uint8_t data[], int offset)+{+  uint32_t value = 0;+  int count;++  for( count = 0; count < 4; count++)+  {+    value <<= 8;+    value ^= (data[count + offset] & 0x000000FF);+  }+  return value;+}++uint16_t+TMR_byteArrayToShort(uint8_t data[], int offset)+{+  uint16_t value = 0;+  int hi, lo;+  hi = (uint16_t) (data[offset++]) << 8;+  lo = (uint16_t) (data[offset++]);+  value = (uint16_t)(hi | lo);++  return value;+}++uint64_t+TMR_byteArrayToLong(uint8_t data[], int offset)+{+  uint64_t value = 0;+  int i;+  for (i = 0; i < 8; i++)+  {+    value <<= 8;+    value ^= (uint64_t) (data[i + offset] & 0xff);+  }+  return value;+}+
+ cbits/api/tmr_utils.h view
@@ -0,0 +1,156 @@+#ifndef _TMR_UTILS_H+#define _TMR_UTILS_H++/**+ *  @file tmr_utils.h+ *  @brief Mercury API - generic utilities+ *  @author Nathan Williams+ *  @date 12/1/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.+ */++#ifdef WINCE+#include <stdint_win32.h>+#else+#include <stdint.h>+#endif+#include <stddef.h>++#ifdef  __cplusplus+extern "C" {+#endif++/* Macros for working with values embedded in uint8_t arrays (msg) */+/* Absolute-value get */+#define GETU8AT(msg, i) ( \+  ((msg)[(i)])          )++#define GETU16AT(msg, i) ( \+  ((uint16_t)((msg)[(i)  ]) <<  8)   | \+  ((msg)[(i)+1] <<  0)   )++#define GETS16AT(msg, i) ( \+    ((int16_t)((msg)[(i)  ]) <<  8)   | \+    ((int16_t)((msg)[(i)+1]) <<  0)   )++#define GETU24AT(msg, i) ( \+  ((uint32_t)((msg)[(i)  ]) <<  16)  | \+  ((uint32_t)((msg)[(i)+1]) <<   8)  | \+  ((msg)[(i)+2] <<   0)  )++#define GETU32AT(msg, i) ( \+  ((uint32_t)((msg)[(i)  ]) <<  24)  | \+  ((uint32_t)((msg)[(i)+1]) <<  16)  | \+  ((uint32_t)((msg)[(i)+2]) <<   8)  | \+  ((msg)[(i)+3] <<   0)  )++/* Get and update index to next position */+#define GETU8(msg, i)   ((msg)[(i)++])+#define GETU16(msg, i)  (i+=2, GETU16AT((msg), i-2))+#define GETU24(msg, i)  (i+=3, GETU24AT((msg), i-3))+#define GETU32(msg, i)  (i+=4, GETU32AT((msg), i-4))++/* Set and update index to next position */+#define SETU8(msg, i, u8val) do {      \+  (msg)[(i)++] = (u8val)      & 0xff;  \+} while (0)++#define SETU16(msg, i, u16val) do {    \+  uint16_t _tmp = (u16val);            \+  (msg)[(i)++] =(uint8_t) (_tmp >>  8) & 0xff;  \+  (msg)[(i)++] =(uint8_t)(_tmp >>  0) & 0xff;  \+} while (0)++#define SETS16(msg, i, s16val) do {    \+  int16_t _tmp = (s16val);            \+  (msg)[(i)++] =(int8_t) (_tmp >>  8) & 0xff;  \+  (msg)[(i)++] =(int8_t)(_tmp >>  0) & 0xff;  \+} while (0)++#define SETU32(msg, i, u32val) do {    \+  uint32_t _tmp = (u32val);            \+  (msg)[(i)++] = (uint8_t)(_tmp >> 24) & 0xff;  \+  (msg)[(i)++] = (uint8_t)(_tmp >> 16) & 0xff;  \+  (msg)[(i)++] = (uint8_t)(_tmp >>  8) & 0xff;  \+  (msg)[(i)++] = (uint8_t)(_tmp >>  0) & 0xff;  \+} while (0)++#define SETS32(msg, i, s32val) do {    \+  int32_t _tmp = (s32val);            \+  (msg)[(i)++] = (int8_t)(_tmp >> 24) & 0xff;  \+  (msg)[(i)++] = (int8_t)(_tmp >> 16) & 0xff;  \+  (msg)[(i)++] = (int8_t)(_tmp >>  8) & 0xff;  \+  (msg)[(i)++] = (int8_t)(_tmp >>  0) & 0xff;  \+} while (0)++/* Append a value to our list structures, which have both+ * a allocated-space value (max) and a length-of-underlying-list+ * value (len). Len can exceed max, which indicates to the caller+ * that there was not enough space in the passed-in list structure+ * to store the entire list.+ */+#define LISTAPPEND(l, value) do {         \+  (l)->len++;                             \+  if ((l)->len <= (l)->max)               \+    (l)->list[(l)->len - 1] = (value);    \+} while (0)+++/* Macros for working with large bitmasks made up of arrays of uint32_t */+#define BITGET(array, number) (((array)[(number)/32] >> ((number)&31)) & 1)+#define BITSET(array, number) ((array)[(number)/32] |= ((uint32_t)1 << ((number)&31)))+#define BITCLR(array, number) ((array)[(number)/32] &= ~((uint32_t)1 << ((number)&31)))++#define numberof(x) (sizeof((x))/sizeof((x)[0]))++#ifndef TMR_USE_HOST_C_LIBRARY+void *tm_memcpy(void *dest, const void *src, size_t n);+char *tm_strcpy(char *dest, const char *src);+char *tm_strchr(const char *s, int c);++#undef memcpy+#undef strcpy+#undef strchr++#define memcpy tm_memcpy+#define strcpy tm_strcpy+#define strchr tm_strchr+#endif++int tm_strcasecmp(const char *s1, const char *s2);+#define strcasecmp tm_strcasecmp++void tm_gettime_consistent(uint32_t *high, uint32_t *low);+uint32_t tm_time_subtract(uint32_t end, uint32_t start);+int tm_u8s_per_bits(int bitCount);+void TMR_stringCopy(TMR_String *dest, const char *src, int len);+uint64_t TMR_makeBitMask(int offset, int lenght);+uint32_t TMR_byteArrayToInt(uint8_t data[], int offset);+uint16_t TMR_byteArrayToShort(uint8_t data[], int offset);+uint64_t TMR_byteArrayToLong(uint8_t data[], int offset);+#ifdef __cplusplus+}+#endif++#endif /* _TMR_UTILS_H */
+ cbits/glue/glue.c view
@@ -0,0 +1,340 @@+#define _GNU_SOURCE++#include <locale.h>+#include <stdbool.h>+#include <stdlib.h>+#include <string.h>+#include <time.h>+#ifndef _WIN32+#include <xlocale.h>+#endif+#include <HsFFI.h>++#include "glue.h"+#include "serial_reader_imp.h"++static TMR_Status free_transport_listener (TMR_Reader *reader,+                                           TransportListenerEtc *listener,+                                           TransportListenerEtc **prev)+{+    TMR_Status stat;++    stat = TMR_removeTransportListener (reader, &listener->block);+    free (listener->key);+    hs_free_fun_ptr (listener->funPtr);+    *prev = listener->next;+    free (listener);++    return stat;+}++static void free_all_transport_listeners (ReaderEtc *reader)+{+    while (reader->transportListeners) {+        free_transport_listener (&reader->reader,+                                 reader->transportListeners,+                                 &reader->transportListeners);+    }+}++/* These wrapper functions have at least two purposes:+ * 1) Check whether the reader has been destroyed+ * 2) Many of the reader methods are actually macros, so wrapping+ *    them in a real function makes it possible to call them+ *    from Haskell.+ *+ * Some of the wrapper functions also perform additional actions to+ * make calling from Haskell easier.+ */++TMR_Status c_TMR_create (ReaderEtc *reader, const char *deviceUri)+{+    reader->transportListeners = NULL;+    reader->readPlan = NULL;+    reader->destroyed = false;+    strcpy (reader->uri, deviceUri);+    return TMR_create (&reader->reader, deviceUri);+}++TMR_Status c_TMR_connect (ReaderEtc *reader)+{+    if (reader->destroyed)+        return ERROR_ALREADY_DESTROYED;+    else+        return TMR_connect (&reader->reader);+}++TMR_Status c_TMR_destroy (ReaderEtc *reader)+{+    if (reader->destroyed) {+        return ERROR_ALREADY_DESTROYED;+    } else {+        TMR_Status status;++        free_all_transport_listeners (reader);+        status = TMR_destroy (&reader->reader);+        free (reader->readPlan);+        reader->destroyed = true;+        return status;+    }+}++TMR_Status c_TMR_read (ReaderEtc *reader, uint32_t timeoutMs, int32_t *tagCount)+{+    if (reader->destroyed)+        return ERROR_ALREADY_DESTROYED;+    else+        return TMR_read (&reader->reader, timeoutMs, tagCount);+}++TMR_Status c_TMR_hasMoreTags (ReaderEtc *reader)+{+    if (reader->destroyed)+        return ERROR_ALREADY_DESTROYED;+    else+        return TMR_hasMoreTags (&reader->reader);+}++TMR_Status c_TMR_getNextTag (ReaderEtc *reader, TMR_TagReadData *tagData)+{+    if (reader->destroyed)+        return ERROR_ALREADY_DESTROYED;+    else+        return TMR_getNextTag (&reader->reader, tagData);+}++TMR_Status c_TMR_executeTagOp (ReaderEtc *reader,+                               TMR_TagOp *tagop,+                               TMR_TagFilter *filter,+                               TMR_uint8List *data)+{+    if (reader->destroyed)+        return ERROR_ALREADY_DESTROYED;+    else+        return TMR_executeTagOp (&reader->reader, tagop, filter, data);+}++TMR_Status c_TMR_gpoSet (ReaderEtc *reader,+                         uint8_t count,+                         const TMR_GpioPin state[])+{+    if (reader->destroyed)+        return ERROR_ALREADY_DESTROYED;+    else+        return TMR_gpoSet (&reader->reader, count, state);+}++TMR_Status c_TMR_gpiGet (ReaderEtc *reader,+                         uint8_t *count,+                         TMR_GpioPin state[])+{+    if (reader->destroyed)+        return ERROR_ALREADY_DESTROYED;+    else+        return TMR_gpiGet (&reader->reader, count, state);+}++TMR_Status c_TMR_firmwareLoad (ReaderEtc *reader,+                               uint8_t *firmwareStart,+                               uint32_t firmwareSize)+{+    if (reader->destroyed)+        return ERROR_ALREADY_DESTROYED;+    else {+        TMR_memoryCookie cookie;+        cookie.firmwareStart = firmwareStart;+        cookie.firmwareSize = firmwareSize;+        return TMR_firmwareLoad (&reader->reader, &cookie, TMR_memoryProvider);+    }+}++TMR_Status c_TMR_paramSet(ReaderEtc *reader,+                          TMR_Param key,+                          const void *value)+{+    if (reader->destroyed)+        return ERROR_ALREADY_DESTROYED;+    else {+        TMR_Status status;++        status = TMR_paramSet (&reader->reader, key, value);+        if (key == TMR_PARAM_READ_PLAN) {+            if (status == TMR_SUCCESS) {+                /* TMR_paramSet appears to only do a shallow copy of the+                 * read plan, meaning that the internal pointers need to+                 * stay pointing at valid memory.  We handle this by+                 * keeping ownership of the ReadPlanEtc, which includes+                 * space for the lists to point at.+                 *+                 * When the read plan is set, we need to free the old+                 * ReadPlanEtc, and keep a pointer to the new one.+                 */+                free (reader->readPlan);+                reader->readPlan = (ReadPlanEtc *) value;+            }+        }++        return status;+    }+}++TMR_Status c_TMR_paramGet(ReaderEtc *reader, TMR_Param key, void *value)+{+    if (reader->destroyed)+        return ERROR_ALREADY_DESTROYED;+    else {+        /* TMR_PARAM_READ_PLAN appears to be write-only, so fulfill the+         * read from our cached copy. */+        if (key == TMR_PARAM_READ_PLAN) {+            TMR_ReadPlan *rp;++            rp = (TMR_ReadPlan *) value;+            if (reader->readPlan) {+                /* Shallow copy the ReadPlan, although the pointers will+                 * still point at parts of the cached ReadPlanEtc. */+                *rp = reader->readPlan->plan;+            } else {+                /* No cached read plan, which means it's initialized to+                 * the default. */+                c_default_read_plan (rp);+            }++            return TMR_SUCCESS;+        } else {+            return TMR_paramGet (&reader->reader, key, value);+        }+    }+}++TMR_Status c_TMR_reboot (ReaderEtc *reader)+{+    if (reader->destroyed)+        return ERROR_ALREADY_DESTROYED;+    else+        return TMR_reboot (&reader->reader);+}++void c_default_read_plan (TMR_ReadPlan *rp)+{+    /* This should match the call to TMR_RP_init_simple() in+     * TMR_reader_init_internal() in tm_reader.c. */+    TMR_RP_init_simple (rp, 0, NULL, TMR_TAG_PROTOCOL_GEN2, 1);+}++TMR_Status c_TMR_paramList (ReaderEtc *reader, TMR_Param *keys, uint32_t *len)+{+    if (reader->destroyed)+        return ERROR_ALREADY_DESTROYED;+    else+        return TMR_paramList (&reader->reader, keys, len);+}++/* takes ownership of func and unique */+TMR_Status c_TMR_addTransportListener (ReaderEtc *reader,+                                       TMR_TransportListener func,+                                       char *unique)+{+    TransportListenerEtc *listener;++    if (reader->destroyed)+        return ERROR_ALREADY_DESTROYED;++    listener = (TransportListenerEtc *) malloc (sizeof (TransportListenerEtc));+    if (! listener)+        return TMR_ERROR_OUT_OF_MEMORY;++    listener->block.listener = func;+    listener->block.cookie = NULL;+    listener->key = unique;+    listener->funPtr = (HsFunPtr) func;+    listener->next = reader->transportListeners;+    reader->transportListeners = listener;++    return TMR_addTransportListener (&reader->reader, &listener->block);+}++TMR_Status c_TMR_removeTransportListener (ReaderEtc *reader,+                                          const char *unique)+{+    TransportListenerEtc *listener, **prev;++    if (reader->destroyed)+        return ERROR_ALREADY_DESTROYED;++    prev = &reader->transportListeners;+    for (listener = reader->transportListeners;+         listener != NULL;+         prev = &listener->next, listener = listener->next) {+        if (0 == strcmp (unique, listener->key))+            return free_transport_listener (&reader->reader, listener, prev);+    }++    return TMR_ERROR_INVALID;+}++const char *c_TMR_strerr (ReaderEtc *reader, TMR_Status status)+{+    TMR_Reader *tmr;++    if (reader && !reader->destroyed)+        tmr = &reader->reader;+    else+        tmr = NULL;++    switch (status) {+    case ERROR_ALREADY_DESTROYED:+        return "Attempt to use reader after it was destroyed";+    default:+        return TMR_strerr (tmr, status);+    }+}++void *c_new_c_locale (void)+{+    /* We need to call tzset once before calling localtime_r, and this seems+     * like a good place to do it. */+    tzset();+#ifdef _WIN32+    /* Unused on Windows, so value doesn't matter, but can't be NULL. */+    return (void*) 1;+#else+    /* Allocate a new locale.  We only do this once, so it's okay+     * that it leaks. */+    return (void *) newlocale(LC_ALL_MASK, "C", (locale_t) 0);+#endif+}++int c_format_time (char *buf,+                   size_t len,+                   const char *fmt,+                   time_t seconds,+                   bool local,+                   void *locale)+{+    time_t t;+    struct tm stm, *stmp;++    t = seconds;+#ifdef _WIN32+    if (local)+        stmp = localtime (&t);+    else+        stmp = gmtime (&t);+#else+    if (local)+        stmp = localtime_r (&t, &stm);+    else+        stmp = gmtime_r (&t, &stm);+#endif++    if (! stmp)+        return -1;+#ifdef _WIN32+    if (0 == strftime (buf, len, fmt, stmp))+        return -1;+#else+    if (0 == strftime_l (buf, len, fmt, stmp, (locale_t) locale))+        return -1;+#endif+    return 0;+}
+ cbits/glue/glue.h view
@@ -0,0 +1,141 @@+#ifndef GLUE_H+#define GLUE_H++#include <stdbool.h>+#include <time.h>+#include <HsFFI.h>++#include "tm_reader.h"++/** An error which originates from the Haskell binding, not the underlying C library. */+#define ERROR_TYPE_BINDING 127L++#define ERROR_BINDING(x)                TMR_STATUS_MAKE(ERROR_TYPE_BINDING, (x))++/** Attempt to use reader after it was destroyed. */+#define ERROR_ALREADY_DESTROYED         ERROR_BINDING(1)++typedef struct TransportListenerEtc TransportListenerEtc;+typedef struct ReaderEtc ReaderEtc;+typedef struct List16 List16;+typedef struct List8 List8;+typedef struct ReadPlanEtc ReadPlanEtc;+typedef struct TagOpEtc TagOpEtc;+typedef struct TagFilterEtc TagFilterEtc;++struct ReaderEtc {+    TMR_Reader reader;+    TransportListenerEtc *transportListeners;+    ReadPlanEtc *readPlan;+    bool destroyed;+    char uri[1]; // must be last+};++struct TransportListenerEtc {+    TMR_TransportListenerBlock block;+    char *key;+    HsFunPtr funPtr;+    struct TransportListenerEtc *next;+};++/* Has the same storage layout as the various TMR_*List structs+ * which use a 16-bit length, such as:+ * TMR_uint8List+ * TMR_uint16List+ * TMR_uint32List+ * TMR_StatsPerAntennaValuesList+ * Can also be used for TMR_String, if you ignore len.+ */+struct List16 {+    /** The array of values */+    void *list;+    /** The number of entries there is space for in the array */+    uint16_t max;+    /** The number of entries in the list - may be larger than max, indicating truncated data. */+    uint16_t len;+};++/* Has the same storage layout as the various TMR_*List structs+ * which use an 8-bit length, such as:+ * TMR_int8List+ * TMR_RegionList+ * TMR_TagProtocolList+ */+struct List8 {+    /** The array of values */+    void *list;+    /** The number of entries there is space for in the array */+    uint8_t max;+    /** The number of entries in the list - may be larger than max, indicating truncated data. */+    uint8_t len;+};++#define GLUE_MAX_MASK TMR_MAX_EMBEDDED_DATA_LENGTH++struct TagFilterEtc {+    TMR_TagFilter filter;+    uint8_t mask[GLUE_MAX_MASK];+};++#define GLUE_MAX_DATA16 TMR_MAX_EMBEDDED_DATA_LENGTH++struct TagOpEtc {+    TMR_TagOp tagop;+    union {+        TMR_TagData epc;+        uint16_t data16[GLUE_MAX_DATA16];+    } u;+};++#define GLUE_MAX_ANTENNAS TMR_SR_MAX_ANTENNA_PORTS+#define GLUE_MAX_GPIPORTS 16++struct ReadPlanEtc {+    TMR_ReadPlan plan;+    uint8_t antennas[GLUE_MAX_ANTENNAS];+    uint8_t gpiPorts[GLUE_MAX_GPIPORTS];+    TagFilterEtc filter;+    TagOpEtc tagop;+};++TMR_Status c_TMR_create (ReaderEtc *reader, const char *deviceUri);+TMR_Status c_TMR_connect (ReaderEtc *reader);+TMR_Status c_TMR_destroy (ReaderEtc *reader);+TMR_Status c_TMR_read (ReaderEtc *reader, uint32_t timeoutMs, int32_t *tagCount);+TMR_Status c_TMR_hasMoreTags (ReaderEtc *reader);+TMR_Status c_TMR_getNextTag (ReaderEtc *reader, TMR_TagReadData *tagData);+TMR_Status c_TMR_executeTagOp (ReaderEtc *reader,+                               TMR_TagOp *tagop,+                               TMR_TagFilter *filter,+                               TMR_uint8List *data);+TMR_Status c_TMR_gpoSet (ReaderEtc *reader,+                         uint8_t count,+                         const TMR_GpioPin state[]);+TMR_Status c_TMR_gpiGet (ReaderEtc *reader,+                         uint8_t *count,+                         TMR_GpioPin state[]);+TMR_Status c_TMR_firmwareLoad (ReaderEtc *reader,+                               uint8_t *firmwareStart,+                               uint32_t firmwareSize);+TMR_Status c_TMR_paramSet (ReaderEtc *reader,+                           TMR_Param key,+                           const void *value);+TMR_Status c_TMR_paramGet (ReaderEtc *reader, TMR_Param key, void *value);+TMR_Status c_TMR_reboot (ReaderEtc *reader);+void c_default_read_plan (TMR_ReadPlan *rp);+TMR_Status c_TMR_paramList (ReaderEtc *reader, TMR_Param *keys, uint32_t *len);+TMR_Status c_TMR_addTransportListener (ReaderEtc *reader,+                                       TMR_TransportListener func,+                                       char *unique);+TMR_Status c_TMR_removeTransportListener (ReaderEtc *reader,+                                          const char *unique);+const char *c_TMR_strerr (ReaderEtc *reader, TMR_Status status);+void *c_new_c_locale (void);+int c_format_time (char *buf,+                   size_t len,+                   const char *fmt,+                   time_t seconds,+                   bool local,+                   void *locale);++#endif  /* GLUE_H */
+ examples/ExampleUtil.hs view
@@ -0,0 +1,122 @@+{-# LANGUAGE OverloadedStrings #-}++module ExampleUtil+  ( createAndConnect+  , createConnectAndParams+  , optUri+  , optRegion+  , optPower+  , optListen+  ) where++import Control.Exception ( throw, try )+import Control.Monad ( when, void, forM_ )+import Data.Int ( Int32 )+import Data.Monoid ( (<>) )+import qualified Data.Text as T ( replicate, pack, length )+import qualified Data.Text.IO as T ( putStrLn )+import Options.Applicative+    ( Parser,+      value,+      switch,+      strOption,+      short,+      option,+      metavar,+      long,+      help,+      auto )+import qualified System.Hardware.MercuryApi as TMR+import qualified System.Hardware.MercuryApi.Params as TMR+import System.Exit ( exitFailure )+import System.Info ( os )+import System.IO ( stdout )++printRegionsAndFail :: TMR.Reader -> IO a+printRegionsAndFail rdr = do+  rgns <- TMR.paramGetRegionSupportedRegions rdr+  T.putStrLn "Region must be one of:"+  forM_ rgns $ \rgn -> do+    let dr = TMR.displayRegion rgn+        nSpaces = 6 - T.length dr+        spaces = T.replicate nSpaces " "+    T.putStrLn $ "  " <> dr <> spaces <> TMR.displayRegionDescription rgn+  exitFailure++parseRegionOrFail :: TMR.Reader -> String -> IO TMR.Region+parseRegionOrFail rdr s =+  case TMR.parseRegion (T.pack s) of+    Nothing -> printRegionsAndFail rdr+    Just rgn -> return rgn++printPowerAndFail :: TMR.Reader -> IO a+printPowerAndFail rdr = do+  lo <- TMR.paramGetRadioPowerMin rdr+  hi <- TMR.paramGetRadioPowerMax rdr+  putStrLn $ "Power must be between " ++ show lo ++ " and " ++ show hi+  exitFailure++handleParamError :: TMR.Reader -> Either TMR.MercuryException () -> IO ()+handleParamError _ (Right _) = return ()+handleParamError rdr (Left err) = hpe (TMR.meStatus err)+  where hpe TMR.ERROR_INVALID_REGION = printRegionsAndFail rdr+        hpe TMR.ERROR_MSG_POWER_TOO_HIGH = printPowerAndFail rdr+        hpe TMR.ERROR_MSG_POWER_TOO_LOW = printPowerAndFail rdr+        hpe _ = throw err++createAndConnect :: String -> Bool -> IO TMR.Reader+createAndConnect uri listen = do+  rdr <- TMR.create $ T.pack uri+  when (listen) $ do+    listener <- TMR.opcodeListener stdout+    void $ TMR.addTransportListener rdr listener+  TMR.paramSetTransportTimeout rdr 10000+  TMR.connect rdr+  return rdr++createConnectAndParams :: String -> Bool -> String -> Int32 -> IO TMR.Reader+createConnectAndParams uri listen region power = do+  rdr <- createAndConnect uri listen+  rgn <- parseRegionOrFail rdr region+  eth <- try $ TMR.paramSetBasics rdr rgn power TMR.sparkFunAntennas+  handleParamError rdr eth+  TMR.paramSetTagReadDataRecordHighestRssi rdr True+  return rdr++defUri :: String+defUri = case os of+           "darwin" -> "tmr:///dev/cu.SLAB_USBtoUART"+           "mingw32" -> "tmr:///COM4"+           _ -> "tmr:///dev/ttyUSB0"++defRegion :: String+defRegion = "na2"++defPower :: Int32+defPower = 2300++optUri :: Parser String+optUri = strOption (long "uri" <>+                    short 'u' <>+                    metavar "URI" <>+                    help ("Reader to connect to (default " ++ defUri ++ ")") <>+                    value defUri)++optRegion :: Parser String+optRegion = strOption (long "region" <>+                       short 'r' <>+                       metavar "REGION" <>+                       help ("Regulatory region (default " ++ defRegion ++ ")") <>+                       value defRegion)++optPower :: Parser Int32+optPower = option auto (long "power" <>+                        short 'p' <>+                        metavar "CENTI-DBM" <>+                        help ("Power level (0-2700, default " ++ show defPower ++ ")") <>+                        value defPower)++optListen :: Parser Bool+optListen = switch (long "transport-listener" <>+                    short 't' <>+                    help "Print bytes sent on serial port")
+ examples/LICENSE-FOR-EXAMPLES view
@@ -0,0 +1,121 @@+Creative Commons Legal Code++CC0 1.0 Universal++    CREATIVE COMMONS CORPORATION IS NOT A LAW FIRM AND DOES NOT PROVIDE+    LEGAL SERVICES. DISTRIBUTION OF THIS DOCUMENT DOES NOT CREATE AN+    ATTORNEY-CLIENT RELATIONSHIP. CREATIVE COMMONS PROVIDES THIS+    INFORMATION ON AN "AS-IS" BASIS. CREATIVE COMMONS MAKES NO WARRANTIES+    REGARDING THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS+    PROVIDED HEREUNDER, AND DISCLAIMS LIABILITY FOR DAMAGES RESULTING FROM+    THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS PROVIDED+    HEREUNDER.++Statement of Purpose++The laws of most jurisdictions throughout the world automatically confer+exclusive Copyright and Related Rights (defined below) upon the creator+and subsequent owner(s) (each and all, an "owner") of an original work of+authorship and/or a database (each, a "Work").++Certain owners wish to permanently relinquish those rights to a Work for+the purpose of contributing to a commons of creative, cultural and+scientific works ("Commons") that the public can reliably and without fear+of later claims of infringement build upon, modify, incorporate in other+works, reuse and redistribute as freely as possible in any form whatsoever+and for any purposes, including without limitation commercial purposes.+These owners may contribute to the Commons to promote the ideal of a free+culture and the further production of creative, cultural and scientific+works, or to gain reputation or greater distribution for their Work in+part through the use and efforts of others.++For these and/or other purposes and motivations, and without any+expectation of additional consideration or compensation, the person+associating CC0 with a Work (the "Affirmer"), to the extent that he or she+is an owner of Copyright and Related Rights in the Work, voluntarily+elects to apply CC0 to the Work and publicly distribute the Work under its+terms, with knowledge of his or her Copyright and Related Rights in the+Work and the meaning and intended legal effect of CC0 on those rights.++1. Copyright and Related Rights. A Work made available under CC0 may be+protected by copyright and related or neighboring rights ("Copyright and+Related Rights"). Copyright and Related Rights include, but are not+limited to, the following:++  i. the right to reproduce, adapt, distribute, perform, display,+     communicate, and translate a Work;+ ii. moral rights retained by the original author(s) and/or performer(s);+iii. publicity and privacy rights pertaining to a person's image or+     likeness depicted in a Work;+ iv. rights protecting against unfair competition in regards to a Work,+     subject to the limitations in paragraph 4(a), below;+  v. rights protecting the extraction, dissemination, use and reuse of data+     in a Work;+ vi. database rights (such as those arising under Directive 96/9/EC of the+     European Parliament and of the Council of 11 March 1996 on the legal+     protection of databases, and under any national implementation+     thereof, including any amended or successor version of such+     directive); and+vii. other similar, equivalent or corresponding rights throughout the+     world based on applicable law or treaty, and any national+     implementations thereof.++2. Waiver. To the greatest extent permitted by, but not in contravention+of, applicable law, Affirmer hereby overtly, fully, permanently,+irrevocably and unconditionally waives, abandons, and surrenders all of+Affirmer's Copyright and Related Rights and associated claims and causes+of action, whether now known or unknown (including existing as well as+future claims and causes of action), in the Work (i) in all territories+worldwide, (ii) for the maximum duration provided by applicable law or+treaty (including future time extensions), (iii) in any current or future+medium and for any number of copies, and (iv) for any purpose whatsoever,+including without limitation commercial, advertising or promotional+purposes (the "Waiver"). Affirmer makes the Waiver for the benefit of each+member of the public at large and to the detriment of Affirmer's heirs and+successors, fully intending that such Waiver shall not be subject to+revocation, rescission, cancellation, termination, or any other legal or+equitable action to disrupt the quiet enjoyment of the Work by the public+as contemplated by Affirmer's express Statement of Purpose.++3. Public License Fallback. Should any part of the Waiver for any reason+be judged legally invalid or ineffective under applicable law, then the+Waiver shall be preserved to the maximum extent permitted taking into+account Affirmer's express Statement of Purpose. In addition, to the+extent the Waiver is so judged Affirmer hereby grants to each affected+person a royalty-free, non transferable, non sublicensable, non exclusive,+irrevocable and unconditional license to exercise Affirmer's Copyright and+Related Rights in the Work (i) in all territories worldwide, (ii) for the+maximum duration provided by applicable law or treaty (including future+time extensions), (iii) in any current or future medium and for any number+of copies, and (iv) for any purpose whatsoever, including without+limitation commercial, advertising or promotional purposes (the+"License"). The License shall be deemed effective as of the date CC0 was+applied by Affirmer to the Work. Should any part of the License for any+reason be judged legally invalid or ineffective under applicable law, such+partial invalidity or ineffectiveness shall not invalidate the remainder+of the License, and in such case Affirmer hereby affirms that he or she+will not (i) exercise any of his or her remaining Copyright and Related+Rights in the Work or (ii) assert any associated claims and causes of+action with respect to the Work, in either case contrary to Affirmer's+express Statement of Purpose.++4. Limitations and Disclaimers.++ a. No trademark or patent rights held by Affirmer are waived, abandoned,+    surrendered, licensed or otherwise affected by this document.+ b. Affirmer offers the Work as-is and makes no representations or+    warranties of any kind concerning the Work, express, implied,+    statutory or otherwise, including without limitation warranties of+    title, merchantability, fitness for a particular purpose, non+    infringement, or the absence of latent or other defects, accuracy, or+    the present or absence of errors, whether or not discoverable, all to+    the greatest extent permissible under applicable law.+ c. Affirmer disclaims responsibility for clearing rights of other persons+    that may apply to the Work or any use thereof, including without+    limitation any person's Copyright and Related Rights in the Work.+    Further, Affirmer disclaims responsibility for obtaining any necessary+    consents, permissions or other rights required for any use of the+    Work.+ d. Affirmer understands and acknowledges that Creative Commons is not a+    party to this document and has no duty or obligation with respect to+    this CC0 or use of the Work.
+ examples/tmr-firmware.hs view
@@ -0,0 +1,65 @@+{-# LANGUAGE OverloadedStrings #-}++import Control.Monad ( when )+import Data.Monoid ( (<>) )+import qualified Data.Text.IO as T ( putStrLn )+import Options.Applicative+    ( Applicative((<*>)),+      Parser,+      helper,+      execParser,+      str,+      progDesc,+      metavar,+      info,+      header,+      fullDesc,+      argument,+      (<$>),+      optional )+import qualified System.Hardware.MercuryApi as TMR+import System.Exit ( exitSuccess )++import ExampleUtil++data Opts = Opts+  { oUri :: String+  , oListen :: Bool+  , oFilename :: Maybe String+  }++opts :: Parser Opts+opts = Opts+  <$> optUri+  <*> optListen+  <*> optional (argument str (metavar "FILENAME"))++opts' = info (helper <*> opts)+  ( fullDesc <>+    progDesc ("If run without firmware file, just print current " +++              "firmware version.  " +++              "Firmware file can be downloaded from: " +++              "http://www.thingmagic.com/index.php/download-nano-firmware") <>+    header "tmr-firmware - write a new firmware image to reader" )++printFwVers :: TMR.Reader -> IO ()+printFwVers rdr =+  TMR.paramGet rdr TMR.PARAM_VERSION_SOFTWARE >>= T.putStrLn++main = do+  o <- execParser opts'+  rdr <- createAndConnect (oUri o) (oListen o)++  putStr "Current firmware version: "+  printFwVers rdr++  when (oFilename o == Nothing) exitSuccess+  let (Just fwFile) = oFilename o++  putStrLn $ "Loading firmware image from " ++ fwFile+  TMR.firmwareLoadFile rdr fwFile++  putStr "New firmware version: "+  printFwVers rdr++  TMR.destroy rdr
+ examples/tmr-gpio.hs view
@@ -0,0 +1,81 @@+{-# LANGUAGE OverloadedStrings #-}++import Control.Concurrent ( threadDelay )+import Control.Exception ( finally )+import Control.Monad ( when )+import Data.Monoid ( (<>) )+import qualified Data.Text.IO as T ( putStrLn )+import Options.Applicative+    ( Alternative(many),+      Applicative((<*>)),+      Parser,+      helper,+      execParser,+      metavar,+      info,+      header,+      fullDesc,+      auto,+      argument,+      (<$>) )+import qualified System.Hardware.MercuryApi as TMR+import qualified System.Hardware.MercuryApi.Params as TMR++import ExampleUtil++data Opts = Opts+  { oUri :: String+  , oListen :: Bool+  , oGpos :: [TMR.PinNumber]+  }++opts :: Parser Opts+opts = Opts+  <$> optUri+  <*> optListen+  <*> many (argument auto (metavar "OUTPUTS..."))++opts' = info (helper <*> opts)+  ( fullDesc <>+    header "tmr-gpio - print GPIs and control GPOs" )++delayMillis :: Int+delayMillis = 100++mkPin :: TMR.PinNumber -> TMR.PinNumber -> TMR.GpioPin+mkPin highPin pin =+  TMR.GpioPin+  { TMR.gpId = pin+  , TMR.gpHigh = highPin == pin+  , TMR.gpOutput = True+  }++gpioLoop :: TMR.Reader -> [TMR.PinNumber] -> Integer -> [TMR.GpioPin] -> IO ()+gpioLoop rdr outPins millis oldPins = do+  pins <- TMR.gpiGet rdr+  when (pins /= oldPins) $ mapM_ T.putStrLn $ TMR.displayGpio pins+  when (not $ null outPins) $ do+    let oLen = length outPins+        pinNo = outPins !! fromIntegral ((millis `div` 1000) `mod` fromIntegral oLen)+        gpoPins = map (mkPin pinNo) outPins+    TMR.gpoSet rdr gpoPins+  threadDelay $ delayMillis * 1000+  gpioLoop rdr outPins (millis + fromIntegral delayMillis) pins++main = do+  o <- execParser opts'+  rdr <- createAndConnect (oUri o) (oListen o)++  -- set all the pins to input+  TMR.paramSetGpioInputList rdr [1..4]++  -- then set some to output+  let outPins = oGpos o+  TMR.paramSetGpioOutputList rdr outPins+  putStrLn $ "cycling among output pins " ++ show outPins++  -- now see which inputs are left+  inPins <- TMR.paramGetGpioInputList rdr+  putStrLn $ "listening on input pins " ++ show inPins++  gpioLoop rdr outPins 0 [] `finally` TMR.destroy rdr
+ examples/tmr-lock.hs view
@@ -0,0 +1,96 @@+{-# LANGUAGE OverloadedStrings #-}++import Control.Exception ( throw, try )+import Control.Monad ( when, void )+import Data.Int ( Int32 )+import Data.List ( maximumBy )+import Data.Monoid ( (<>) )+import Data.Ord ( comparing )+import qualified Data.Text.IO as T ( putStrLn )+import Options.Applicative+    ( Applicative((<*>)),+      Parser,+      helper,+      execParser,+      info,+      header,+      fullDesc,+      (<$>) )+import qualified System.Hardware.MercuryApi as TMR++import ExampleUtil++data Opts = Opts+  { oUri :: String+  , oRegion :: String+  , oPower :: Int32+  , oListen :: Bool+  }++opts :: Parser Opts+opts = Opts+  <$> optUri+  <*> optRegion+  <*> optPower+  <*> optListen++opts' = info (helper <*> opts)+  ( fullDesc <>+    header "tmr-lock - test that locking works" )++password :: TMR.GEN2_Password+password = 12345++main = do+  o <- execParser opts'++  rdr <- createConnectAndParams (oUri o) (oListen o) (oRegion o) (oPower o)++  tags <- TMR.read rdr 1000+  putStrLn $ "read " ++ show (length tags) ++ " tags"+  when (not $ null tags) $ do+    let trd = maximumBy (comparing TMR.trRssi) tags+        td = TMR.trTag trd+        epc = TMR.tdEpc td+        hex = TMR.bytesToHex epc++    T.putStrLn $ "writing password to <" <> hex <> ">"+    let epcFilt = TMR.TagFilterEPC td+        opWrite = TMR.TagOp_GEN2_WriteData+                  { TMR.opBank = TMR.GEN2_BANK_RESERVED+                  , TMR.opWordAddress = TMR.accessPasswordAddress+                  , TMR.opData = TMR.passwordToWords password+                  }+    TMR.executeTagOp rdr opWrite (Just epcFilt)++    T.putStrLn $ "locking <" <> hex <> ">"+    let opLock = TMR.TagOp_GEN2_Lock+                 { TMR.opMask   = [TMR.GEN2_LOCK_BITS_USER]+                 , TMR.opAction = [TMR.GEN2_LOCK_BITS_USER]+                 , TMR.opAccessPassword = password+                 }+    TMR.executeTagOp rdr opLock (Just epcFilt)++    T.putStrLn $ "attempting to write user data to <" <> hex <> ">"+    let opWrite2 = TMR.TagOp_GEN2_WriteData+                  { TMR.opBank = TMR.GEN2_BANK_USER+                  , TMR.opWordAddress = 0+                  , TMR.opData = TMR.packBytesIntoWords "This should fail"+                  }+    eth <- try $ TMR.executeTagOp rdr opWrite2 (Just epcFilt)+    case eth of+      Right _ ->+        T.putStrLn "Write succeeded, but it shouldn't have."+      Left err ->+        when (TMR.meStatus err /= TMR.ERROR_PROTOCOL_WRITE_FAILED &&+              TMR.meStatus err /= TMR.ERROR_PROTOCOL_BIT_DECODING_FAILED) $ throw err++    T.putStrLn $ "unlocking <" <> hex <> ">"+    let opUnlock = TMR.TagOp_GEN2_Lock+                   { TMR.opMask   = [TMR.GEN2_LOCK_BITS_USER]+                   , TMR.opAction = []+                   , TMR.opAccessPassword = password+                   }+    void $ TMR.executeTagOp rdr opUnlock (Just epcFilt)++  TMR.destroy rdr
+ examples/tmr-params.hs view
@@ -0,0 +1,79 @@+{-# LANGUAGE OverloadedStrings #-}++import Control.Exception ( try )+import Control.Monad ( forM_ )+import Data.List ( sortBy )+import Data.Monoid ( (<>) )+import qualified Data.Text as T ( dropWhileEnd )+import qualified Data.Text.IO as T ( putStrLn, putStr )+import Options.Applicative+    ( Applicative((<*>)),+      Parser,+      helper,+      execParser,+      info,+      header,+      fullDesc,+      (<$>) )+import System.Console.ANSI+    ( SGR(Reset, SetColor),+      Color(Blue, Green, Red),+      ColorIntensity(Dull, Vivid),+      ConsoleLayer(Foreground),+      setSGR )+import qualified System.Hardware.MercuryApi as TMR+import qualified System.Hardware.MercuryApi.Params as TMR++import ExampleUtil++data Opts = Opts+  { oUri :: String+  , oListen :: Bool+  }++opts :: Parser Opts+opts = Opts+  <$> optUri+  <*> optListen++opts' = info (helper <*> opts)+  ( fullDesc <>+    header "tmr-params - print parameters" )++compareParams :: TMR.Param -> TMR.Param -> Ordering+compareParams p1 p2 =+  let n1 = TMR.paramName p1+      n2 = TMR.paramName p2+      b1 = T.dropWhileEnd (/= '/') n1+      b2 = T.dropWhileEnd (/= '/') n2+  in case b1 `compare` b2 of+       EQ -> n1 `compare` n2+       x -> x++main = do+  o <- execParser opts'+  T.putStrLn $ "API version: " <> TMR.apiVersion+  rdr <- createAndConnect (oUri o) (oListen o)++  params <- TMR.paramList rdr+  forM_ (sortBy compareParams params) $ \param -> do+    setSGR [SetColor Foreground Vivid Blue]+    putStr $ show param+    setSGR [Reset]+    T.putStrLn $ " - " <> TMR.paramName param+    let typ = TMR.displayParamType $ TMR.paramType param+    eth <- try $ TMR.paramGetString rdr param+    case eth of+      Left err -> do+        setSGR [SetColor Foreground Vivid Red]+        putStrLn $ "  " ++ show (TMR.meStatus err)+        setSGR [Reset]+      Right txt -> do+        setSGR [SetColor Foreground Dull Green]+        T.putStr $ "  " <> txt+        setSGR [Reset]+        T.putStr $ " :: " <> typ+        case TMR.paramUnits param of+          Nothing -> T.putStrLn ""+          Just units -> T.putStrLn $ " (" <> units <> ")"+  TMR.destroy rdr
+ examples/tmr-read.hs view
@@ -0,0 +1,99 @@+{-# LANGUAGE OverloadedStrings #-}++import Control.Monad ( when, forM_ )+import qualified Data.ByteString as B ( takeWhile, null )+import Data.Int ( Int32 )+import Data.List ( sortBy )+import Data.Monoid ( (<>) )+import Data.Ord ( comparing )+import qualified Data.Text as T ( Text, takeWhile, pack, null )+import qualified Data.Text.IO as T ( putStrLn )+import Options.Applicative+    ( Applicative((<*>)),+      Parser,+      helper,+      execParser,+      switch,+      short,+      long,+      info,+      help,+      header,+      fullDesc,+      (<$>) )+import System.Console.ANSI+    ( SGR(Reset, SetColor, SetConsoleIntensity),+      Color(Blue),+      ColorIntensity(Vivid),+      ConsoleIntensity(BoldIntensity),+      ConsoleLayer(Foreground),+      setSGR )+import qualified System.Hardware.MercuryApi as TMR+import Text.Printf ( printf )++import ExampleUtil++data Opts = Opts+  { oUri :: String+  , oRegion :: String+  , oPower :: Int32+  , oListen :: Bool+  , oLong :: Bool+  }++opts :: Parser Opts+opts = Opts+  <$> optUri+  <*> optRegion+  <*> optPower+  <*> optListen+  <*> switch (long "long" <>+              short 'l' <>+              help "Print lots of information per tag")++opts' = info (helper <*> opts)+  ( fullDesc <>+    header "tmr-read - read tags" )++readUser =+  TMR.TagOp_GEN2_ReadData+  { TMR.opBank = TMR.GEN2_BANK_USER+  , TMR.opExtraBanks = []+  , TMR.opWordAddress = 0+  , TMR.opLen = 32+  }++putWithBold :: T.Text -> IO ()+putWithBold txt = do+  let bold = T.null $ T.takeWhile (== ' ') txt+  when bold $ setSGR [SetConsoleIntensity BoldIntensity]+  T.putStrLn txt+  when bold $ setSGR [Reset]++displayTag :: TMR.TagReadData -> T.Text+displayTag trd = strength <> " <" <> epc <> ">" <> user+  where+    strength = T.pack $ printf "%3d" (TMR.trRssi trd)+    epc = TMR.bytesToHex $ TMR.tdEpc $ TMR.trTag trd+    dat = TMR.trData trd+    user =+      if B.null dat+      then "" -- this means it failed to read the user data+      else T.pack $ ' ' : show (B.takeWhile (/= 0) dat)++main = do+  o <- execParser opts'++  rdr <- createConnectAndParams (oUri o) (oListen o) (oRegion o) (oPower o)+  TMR.paramSetReadPlanTagop rdr (Just readUser)++  tags <- TMR.read rdr 1000+  let tags' = reverse $ sortBy (comparing TMR.trRssi) tags+  setSGR [SetColor Foreground Vivid Blue]+  putStrLn $ "read " ++ show (length tags') ++ " tags"+  setSGR [Reset]+  if oLong o+    then mapM_ putWithBold (concatMap TMR.displayTagReadData tags')+    else forM_ tags' (T.putStrLn . displayTag)++  TMR.destroy rdr
+ examples/tmr-write.hs view
@@ -0,0 +1,100 @@+{-# LANGUAGE OverloadedStrings #-}++import Control.Monad ( when )+import qualified Data.ByteString as B ( snoc, pack )+import Data.Int ( Int32 )+import Data.List ( maximumBy )+import Data.Monoid ( (<>) )+import Data.Ord ( comparing )+import qualified Data.Text as T ( Text, pack )+import qualified Data.Text.Encoding as T ( encodeUtf8 )+import qualified Data.Text.IO as T ( putStrLn )+import Options.Applicative+    ( Applicative((<*>)),+      Parser,+      helper,+      execParser,+      switch,+      str,+      short,+      metavar,+      long,+      info,+      help,+      header,+      fullDesc,+      argument,+      (<$>) )+import System.Console.ANSI+    ( SGR(Reset, SetColor),+      Color(Green, Red),+      ColorIntensity(Vivid),+      ConsoleLayer(Foreground),+      setSGR )+import qualified System.Hardware.MercuryApi as TMR++import ExampleUtil++data Opts = Opts+  { oUri :: String+  , oRegion :: String+  , oPower :: Int32+  , oListen :: Bool+  , oRewrite :: Bool+  , oString :: String+  }++opts :: Parser Opts+opts = Opts+  <$> optUri+  <*> optRegion+  <*> optPower+  <*> optListen+  <*> switch (long "rewrite" <>+              short 'R' <>+              help "Write to a tag even if written before")+  <*> argument str (metavar "STRING")++opts' = info (helper <*> opts)+  ( fullDesc <>+    header "tmr-write - write a string to user data of tag" )++emptyUserDataFilter :: TMR.TagFilter+emptyUserDataFilter = TMR.mkFilterGen2 TMR.GEN2_BANK_USER 0 $ B.pack [0, 0]++printColor :: Color -> T.Text -> IO ()+printColor c txt = do+  setSGR [SetColor Foreground Vivid c]+  T.putStrLn txt+  setSGR [Reset]++main = do+  o <- execParser opts'++  rdr <- createConnectAndParams (oUri o) (oListen o) (oRegion o) (oPower o)+  when (not $ oRewrite o) $+    TMR.paramSetReadPlanFilter rdr (Just emptyUserDataFilter)++  tags <- TMR.read rdr 1000+  putStrLn $ "read " ++ show (length tags) ++ " tags"+  if null tags+    then do+    printColor Red "No tag found"+    else do+    let trd = maximumBy (comparing TMR.trRssi) tags+        td = TMR.trTag trd+        epc = TMR.tdEpc td+        hex = TMR.bytesToHex epc+    T.putStrLn $ "writing <" <> hex <> ">"+    let epcFilt = TMR.TagFilterEPC td+        txt = T.pack (oString o)+        words = TMR.packBytesIntoWords $ T.encodeUtf8 txt `B.snoc` 0+        opWrite = TMR.TagOp_GEN2_WriteData+                  { TMR.opBank = TMR.GEN2_BANK_USER+                  , TMR.opWordAddress = 0+                  , TMR.opData = words+                  }+    TMR.executeTagOp rdr opWrite (Just epcFilt)+    printColor Green "Success!"++  TMR.destroy rdr
+ mercury-api.cabal view
@@ -0,0 +1,270 @@+-- Initial mercury-api.cabal generated by cabal init.  For further+-- documentation, see http://haskell.org/cabal/users-guide/++-- The name of the package.+name:                mercury-api++-- The package version.  See the Haskell package versioning policy (PVP)+-- for standards guiding when and how versions should be incremented.+-- https://wiki.haskell.org/Package_versioning_policy+-- PVP summary:      +-+------- breaking API changes+--                   | | +----- non-breaking API additions+--                   | | | +--- code changes with no API change+version:             0.1.0.0++-- A short (one-line) description of the package.+synopsis:            Haskell binding to Mercury API for ThingMagic RFID readers++-- A longer description of the package.+description:+    This package is a Haskell binding to the \"Mercury API\" C API for+    ThingMagic RFID readers.  It is especially geared toward the+    <https://www.sparkfun.com/products/14066 SparkFun Simultaneous RFID Reader>,+    which uses ThingMagic's M6e Nano module, but it should work with other+    ThingMagic readers.  (Though currently, only support for serial readers+    is compiled in.)  Most of the function and type names are the same as+    their counterparts in the C API, with the @TMR_@ prefix dropped.  For more+    in-depth, language-independent documentation of Mercury API, see+    <http://www.thingmagic.com/images/Downloads/Docs/MercuryAPI_ProgrammerGuide_for_v1.27.3.pdf Mercury API Programmers Guide>.++-- The license under which the package is released.+license:             MIT++-- The file containing the license text.+license-file:        LICENSE++-- The package author(s).+author:              Patrick Pelletier++-- An email address to which users can send suggestions, bug reports, and+-- patches.+maintainer:          code@funwithsoftware.org++homepage:            https://github.com/ppelleti/hs-mercury-api++bug-reports:         https://github.com/ppelleti/hs-mercury-api/issues++-- A copyright notice.+copyright:           © Patrick Pelletier, 2017++category:            Hardware++build-type:          Simple++-- Extra files to be distributed with the package, such as examples or a+-- README.+extra-source-files:  ChangeLog.md+                   , README.md+                   , UPGRADING.md+                   , examples/LICENSE-FOR-EXAMPLES+                   , tests/*.result+                   , tests/*.transport+                   , cbits/api/*.h+                   , cbits/api/patches/README.md+                   , cbits/api/patches/*.patch+                   , cbits/glue/glue.h++-- Constraint on the version of Cabal needed to build this package.+cabal-version:       >=1.10++tested-with:+  GHC==7.6.3,+  GHC==7.8.4,+  GHC==7.10.3,+  GHC==8.0.2++source-repository head+  Type:     git+  Location: https://github.com/ppelleti/hs-mercury-api.git+++library+  -- Modules exported by the library.+  exposed-modules:     System.Hardware.MercuryApi+                     , System.Hardware.MercuryApi.Params+                     , System.Hardware.MercuryApi.Testing++  -- Modules included in this library but not exported.+  other-modules:       System.Hardware.MercuryApi.Enums+                     , System.Hardware.MercuryApi.Records+                     , System.Hardware.MercuryApi.ParamValue++  -- LANGUAGE extensions used by modules in this package.+  -- other-extensions:++  -- Apparently these are supposed to be listed in dependency order,+  -- although the Cabal documentation doesn't breathe a word about it:+  -- https://ghc.haskell.org/trac/ghc/ticket/13786#comment:3+  --+  -- Furthermore, it appears that Cabal always puts conditional sources+  -- after unconditional sources, so in order to get the sources in the+  -- right order, they need to all be conditional, i. e. we have to list+  -- the sources twice, once for Windows and once for POSIX.+  if os(windows)+    c-sources:         cbits/api/serial_transport_win32.c+                     , cbits/api/osdep_win32.c+                     , cbits/api/tmr_strerror.c+                     , cbits/api/tmr_utils.c+                     , cbits/api/tmr_param.c+                     , cbits/api/hex_bytes.c+                     , cbits/api/serial_reader_l3.c+                     , cbits/api/serial_reader.c+                     , cbits/api/tm_reader_async.c+                     , cbits/api/tm_reader.c+                     , cbits/glue/glue.c+  else+    c-sources:         cbits/api/serial_transport_posix.c+                     , cbits/api/osdep_posix.c+                     , cbits/api/tmr_strerror.c+                     , cbits/api/tmr_utils.c+                     , cbits/api/tmr_param.c+                     , cbits/api/hex_bytes.c+                     , cbits/api/serial_reader_l3.c+                     , cbits/api/serial_reader.c+                     , cbits/api/tm_reader_async.c+                     , cbits/api/tm_reader.c+                     , cbits/glue/glue.c++  include-dirs:        cbits/api+                     , cbits/glue++  cc-options:          -DTMR_ENABLE_SERIAL_READER_ONLY=1+                       -DTMR_USE_HOST_C_LIBRARY=1++  -- Other library packages from which modules are imported.+  build-depends:       base >= 4.6 && < 5+                     , ansi-terminal >= 0.6.2.3 && < 0.7+                     , bytestring >= 0.10.4 && < 0.11+                     , clock >= 0.7.2 && < 0.8+                     , hashable >= 1.2.4 && < 1.3+                     , text >= 1.2 && < 1.3+                     , unordered-containers >= 0.2.7.1 && < 0.3++  -- Directories containing source files.+  hs-source-dirs:      src++  -- Extra tools (e.g. alex, hsc2hs, ...) needed to build the source.+  build-tools:         hsc2hs++  -- Base language which the package is written in.+  default-language:    Haskell2010+++executable tmr-params+  main-is:             tmr-params.hs+  other-modules:       ExampleUtil+  build-depends:       base >= 4.6 && < 5+                     , ansi-terminal >= 0.6.2.3 && < 0.7+                     , bytestring >= 0.10.4 && < 0.11+                     , mercury-api+                     , optparse-applicative >= 0.13 && < 0.14+                     , text >= 1.2 && < 1.3+  hs-source-dirs:      examples+  default-language:    Haskell2010+  ghc-options:         -threaded+++executable tmr-firmware+  main-is:             tmr-firmware.hs+  other-modules:       ExampleUtil+  build-depends:       base >= 4.6 && < 5+                     , bytestring >= 0.10.4 && < 0.11+                     , mercury-api+                     , optparse-applicative >= 0.13 && < 0.14+                     , text >= 1.2 && < 1.3+  hs-source-dirs:      examples+  default-language:    Haskell2010+  ghc-options:         -threaded+++executable tmr-read+  main-is:             tmr-read.hs+  other-modules:       ExampleUtil+  build-depends:       base >= 4.6 && < 5+                     , ansi-terminal >= 0.6.2.3 && < 0.7+                     , bytestring >= 0.10.4 && < 0.11+                     , mercury-api+                     , optparse-applicative >= 0.13 && < 0.14+                     , text >= 1.2 && < 1.3+  hs-source-dirs:      examples+  default-language:    Haskell2010+  ghc-options:         -threaded+++executable tmr-write+  main-is:             tmr-write.hs+  other-modules:       ExampleUtil+  build-depends:       base >= 4.6 && < 5+                     , ansi-terminal >= 0.6.2.3 && < 0.7+                     , bytestring >= 0.10.4 && < 0.11+                     , mercury-api+                     , optparse-applicative >= 0.13 && < 0.14+                     , text >= 1.2 && < 1.3+  hs-source-dirs:      examples+  default-language:    Haskell2010+  ghc-options:         -threaded+++executable tmr-lock+  main-is:             tmr-lock.hs+  other-modules:       ExampleUtil+  build-depends:       base >= 4.6 && < 5+                     , bytestring >= 0.10.4 && < 0.11+                     , mercury-api+                     , optparse-applicative >= 0.13 && < 0.14+                     , text >= 1.2 && < 1.3+  hs-source-dirs:      examples+  default-language:    Haskell2010+  ghc-options:         -threaded+++executable tmr-gpio+  main-is:             tmr-gpio.hs+  other-modules:       ExampleUtil+  build-depends:       base >= 4.6 && < 5+                     , bytestring >= 0.10.4 && < 0.11+                     , mercury-api+                     , optparse-applicative >= 0.13 && < 0.14+                     , text >= 1.2 && < 1.3+  hs-source-dirs:      examples+  default-language:    Haskell2010+  ghc-options:         -threaded+++test-suite replay+  type:                exitcode-stdio-1.0+  main-is:             replay.hs+  build-depends:       base >= 4.6 && < 5+                     , bytestring >= 0.10.4 && < 0.11+                     , directory >= 1.2.2 && < 1.4+                     , mercury-api+                     , optparse-applicative >= 0.13 && < 0.14+                     , text >= 1.2 && < 1.3+  hs-source-dirs:      tests+  default-language:    Haskell2010+  ghc-options:         -threaded+++test-suite unit+  type:                exitcode-stdio-1.0+  main-is:             unit.hs+  build-depends:       base >= 4.6 && < 5+                     , bytestring >= 0.10.4 && < 0.11+                     , HUnit >= 1.5 && < 1.7+                     , mercury-api+                     , text >= 1.2 && < 1.3+  hs-source-dirs:      tests+  default-language:    Haskell2010+  ghc-options:         -threaded+++test-suite param-test+  type:                exitcode-stdio-1.0+  main-is:             param-test.hs+  build-depends:       base >= 4.6 && < 5+                     , HUnit >= 1.5 && < 1.7+                     , mercury-api+                     , text >= 1.2 && < 1.3+  hs-source-dirs:      tests+  default-language:    Haskell2010+  ghc-options:         -threaded
+ src/System/Hardware/MercuryApi.hs view
@@ -0,0 +1,1048 @@+{-# LANGUAGE ForeignFunctionInterface, DeriveDataTypeable, OverloadedStrings, BangPatterns #-}+{-|+Module      : System.Hardware.MercuryApi+Description : Control ThingMagic RFID readers+Copyright   : © Patrick Pelletier, 2017+License     : MIT+Maintainer  : code@funwithsoftware.org+Portability : POSIX, Windows++This module is a Haskell binding to the \"Mercury API\" C API for+ThingMagic RFID readers.  It is especially geared toward the+<https://www.sparkfun.com/products/14066 SparkFun Simultaneous RFID Reader>,+which uses ThingMagic's M6e Nano module, but it should work with other+ThingMagic readers.  (Though currently, only support for serial readers+is compiled in.)  Most of the function and type names are the same as+their counterparts in the C API, with the @TMR_@ prefix dropped.  For more+in-depth, language-independent documentation of Mercury API, see+<http://www.thingmagic.com/images/Downloads/Docs/MercuryAPI_ProgrammerGuide_for_v1.27.3.pdf Mercury API Programmers Guide>.++This module is intended to be imported @qualified@, e. g.++> import qualified System.Hardware.MercuryApi as TMR+-}++module System.Hardware.MercuryApi+  ( -- * Reader+    create+  , connect+  , read+  , executeTagOp+  , reboot+  , destroy+  , withReader+    -- ** Parameters+    -- | Although 'paramGet' and 'paramSet' are very flexible, they only+    -- check that the parameter type is correct at runtime.  You may+    -- prefer to use the functions in "System.Hardware.MercuryApi.Params",+    -- which ensure the correct type at compile time.+  , paramList+  , paramGet+  , paramSet+  , paramSetBasics+  , paramSetReadPlanFilter+  , paramSetReadPlanTagop+    -- ** Listeners+    -- | Transport listeners can be used to monitor the raw serial data+    -- going to and from the reader, for debugging purposes.  A listener+    -- that prints the data to a 'Handle' is available from 'hexListener'+    -- or 'opcodeListener'.+  , addTransportListener+  , removeTransportListener+    -- ** GPIO+    -- | The M6e Nano has 4 GPIO pins that can be controlled by software,+    -- numbered 1-4.  On the+    -- <https://www.sparkfun.com/products/14066 SparkFun Simultaneous RFID Reader>,+    -- GPIO 1 is available on the GPIO1 pin, and GPIOs 2, 3, and 4 are available+    -- on the LV2, LV3, and LV4 pins.  The GPIO1 pin is 5V, but+    -- <https://learn.sparkfun.com/tutorials/simultaneous-rfid-tag-reader-hookup-guide/hardware-overview the LV pins are 3.3V only>.+    -- To configure GPIOs as inputs or outputs, use 'PARAM_GPIO_INPUTLIST'+    -- and 'PARAM_GPIO_OUTPUTLIST'.+  , gpiGet+  , gpoSet+    -- ** Firmware+    -- | Firmware for the M6e Nano can be obtained+    -- <http://www.thingmagic.com/index.php/download-nano-firmware here>.+  , firmwareLoad+  , firmwareLoadFile+    -- * Utility functions+    -- ** Listeners+  , hexListener+  , opcodeListener+    -- ** Data helpers+  , packBytesIntoWords+  , passwordToWords+  , mkFilterGen2+    -- ** Parameters+  , paramName+  , paramID+  , paramType+  , paramUnits+    -- ** Hex conversion+  , bytesToHex+  , bytesToHexWithSpaces+  , hexToBytes+    -- ** Display+    -- | Some functions to format data in a more human-friendly+    -- format than 'show'.+  , displayTimestamp+  , displayLocalTimestamp+  , displayData+  , displayGpio+  , displayTagData+  , displayTagReadData+  , displayParamType+  , displayRegion+  , displayRegionDescription+  , parseRegion+    -- * Constants+  , apiVersion+  , sparkFunAntennas+  , defaultReadPlan+  , killPasswordAddress+  , accessPasswordAddress+    -- * Types+    -- ** Opaque types+  , Reader+  , ParamValue+  , TransportListenerId+    -- ** Typedefs+  , TransportListener+  , PinNumber+  , AntennaPort+  , GEN2_Password+  , MillisecondsSinceEpoch+    -- ** Records+  , MercuryException (..)+  , ReadPlan (..)+  , TagOp (..)+  , TagFilter (..)+  , FilterOn (..)+  , TagReadData (..)+  , GpioPin (..)+  , TagData (..)+  , GEN2_TagData (..)+  , ReadWrite (..)+    -- ** Enums+  , StatusType (..)+  , Status (..)+  , Param (..)+  , ParamType (..)+  , Region (..)+  , TagProtocol (..)+  , MetadataFlag (..)+  , GEN2_Bank (..)+  , GEN2_LockBits (..)+  , GEN2_WriteMode (..)+  , PowerMode (..)+  , TransportDirection (..)+  ) where++import Prelude hiding (read)++import Control.Applicative ( (<$>) )+-- IOException is needed here so that Haddock can link to it+import Control.Exception ( Exception, IOException, throwIO, try, bracket )+import Control.Monad ( when )+import qualified Data.ByteString as B+import qualified Data.HashMap.Strict as H+import Data.IORef ( IORef, newIORef, atomicModifyIORef' )+import Data.List ( intercalate )+import Data.Monoid ( (<>) )+import qualified Data.Text as T+import qualified Data.Text.IO as T ( hPutStrLn )+import Data.Typeable ( Typeable )+import Data.Word ( Word8, Word16, Word32 )+import Foreign+    ( Int32,+      Ptr,+      FunPtr,+      ForeignPtr,+      nullPtr,+      withForeignPtr,+      Storable(peek, poke),+      Bits((.&.), (.|.), bit, shiftL, shiftR, testBit),+      castPtr,+      mallocForeignPtrBytes,+      addForeignPtrFinalizer,+      with,+      toBool,+      withArrayLen,+      peekArray,+      allocaArray,+      allocaBytes,+      alloca )+import Foreign.C+    ( CStringLen,+      CString,+      CInt(..),+      CTime(..),+      CSize(..),+      Errno(..),+      withCAString,+      newCAString,+      throwErrnoIfNull,+      errnoToIOError )+import Text.Printf ( printf )+import System.Clock+    ( TimeSpec(nsec, sec), Clock(Monotonic), getTime )+import System.Console.ANSI+    ( SGR(Reset, SetColor),+      ConsoleLayer(Foreground),+      ColorIntensity(Vivid),+      Color(Cyan, Magenta),+      hSupportsANSI,+      hSetSGR )+import System.IO ( Handle, hFlush )+import qualified System.IO.Unsafe as U ( unsafePerformIO )+import Text.Read (readMaybe)++import System.Hardware.MercuryApi.Enums+import System.Hardware.MercuryApi.Records+import System.Hardware.MercuryApi.ParamValue++-- | An opaque type which represents a connection to an RFID reader.+-- Note that @Reader@ is not threadsafe, so if you want to use a+-- @Reader@ from more than one thread, you will need to implement+-- your own locking.+newtype Reader = Reader (ForeignPtr ReaderEtc)++type RawStatus = Word32+type RawType = Word32++type RawTransportListener =+  CBool -> Word32 -> Ptr Word8 -> Word32 -> Ptr () -> IO ()++-- | The direction of data travel.  Passed to 'TransportListener'.+data TransportDirection = Rx -- ^ Receive+                        | Tx -- ^ Transmit+                        deriving (Eq, Ord, Show, Read, Bounded, Enum)++-- | A function which can be installed via 'addTransportListener'+-- to be called every time Mercury API sends or receives data on+-- the serial port.+type TransportListener = TransportDirection -- ^ Direction of data transmission+                       -> B.ByteString  -- ^ Binary data sent or received+                       -> Word32        -- ^ Timeout+                       -> IO ()++-- | An opaque type which can be passed to 'removeTransportListener'+-- to remove a transport listener.+newtype TransportListenerId = TransportListenerId Integer deriving (Eq)++newtype Locale = Locale ()++-- Many of these need to be safe because they could call back+-- into Haskell via the transport listener.  (Or via the custom+-- transport we use for testing.)++foreign import ccall safe "glue.h c_TMR_create"+    c_TMR_create :: Ptr ReaderEtc+                 -> CString+                 -> IO RawStatus++foreign import ccall safe "glue.h c_TMR_connect"+    c_TMR_connect :: Ptr ReaderEtc+                  -> IO RawStatus++foreign import ccall safe "glue.h c_TMR_destroy"+    c_TMR_destroy :: Ptr ReaderEtc+                  -> IO RawStatus++foreign import ccall unsafe "glue.h &c_TMR_destroy"+    p_TMR_destroy :: FunPtr (Ptr ReaderEtc -> IO ())++foreign import ccall safe "glue.h c_TMR_read"+    c_TMR_read :: Ptr ReaderEtc+               -> Word32+               -> Ptr Word32+               -> IO RawStatus++foreign import ccall safe "glue.h c_TMR_hasMoreTags"+    c_TMR_hasMoreTags :: Ptr ReaderEtc+                      -> IO RawStatus++foreign import ccall safe "glue.h c_TMR_getNextTag"+    c_TMR_getNextTag :: Ptr ReaderEtc+                     -> Ptr TagReadData+                     -> IO RawStatus++foreign import ccall unsafe "tmr_tag_data.h TMR_TRD_init"+    c_TMR_TRD_init :: Ptr TagReadData+                   -> IO RawStatus++foreign import ccall safe "glue.h c_TMR_executeTagOp"+    c_TMR_executeTagOp :: Ptr ReaderEtc+                       -> Ptr TagOp+                       -> Ptr TagFilter+                       -> Ptr List16+                       -> IO RawStatus++foreign import ccall safe "glue.h c_TMR_gpoSet"+    c_TMR_gpoSet :: Ptr ReaderEtc+                 -> Word8+                 -> Ptr GpioPin+                 -> IO RawStatus++foreign import ccall safe "glue.h c_TMR_gpiGet"+    c_TMR_gpiGet :: Ptr ReaderEtc+                 -> Ptr Word8+                 -> Ptr GpioPin+                 -> IO RawStatus++foreign import ccall safe "glue.h c_TMR_firmwareLoad"+    c_TMR_firmwareLoad :: Ptr ReaderEtc+                       -> Ptr Word8+                       -> Word32+                       -> IO RawStatus++foreign import ccall safe "glue.h c_TMR_paramSet"+    c_TMR_paramSet :: Ptr ReaderEtc+                   -> RawParam+                   -> Ptr ()+                   -> IO RawStatus++foreign import ccall safe "glue.h c_TMR_paramGet"+    c_TMR_paramGet :: Ptr ReaderEtc+                   -> RawParam+                   -> Ptr ()+                   -> IO RawStatus++foreign import ccall safe "glue.h c_TMR_reboot"+    c_TMR_reboot :: Ptr ReaderEtc+                 -> IO RawStatus++foreign import ccall unsafe "glue.h c_default_read_plan"+    c_default_read_plan :: Ptr ReadPlan+                        -> IO ()++foreign import ccall safe "glue.h c_TMR_paramList"+    c_TMR_paramList :: Ptr ReaderEtc+                    -> Ptr RawParam+                    -> Ptr Word32+                    -> IO RawStatus++foreign import ccall "wrapper"+    wrapTransportListener :: RawTransportListener+                          -> IO (FunPtr RawTransportListener)++-- takes ownership of the FunPtr and the CString+foreign import ccall unsafe "glue.h c_TMR_addTransportListener"+    c_TMR_addTransportListener :: Ptr ReaderEtc+                               -> FunPtr RawTransportListener+                               -> CString+                               -> IO RawStatus++foreign import ccall unsafe "glue.h c_TMR_removeTransportListener"+    c_TMR_removeTransportListener :: Ptr ReaderEtc+                                  -> CString+                                  -> IO RawStatus++foreign import ccall unsafe "glue.h c_TMR_strerr"+    c_TMR_strerr :: Ptr ReaderEtc+                 -> RawStatus+                 -> IO CString++-- This is a pure function, because it returns a string literal+foreign import ccall unsafe "tm_reader.h TMR_paramName"+    c_TMR_paramName :: RawParam+                    -> CString++foreign import ccall unsafe "tmr_tag_data.h TMR_hexToBytes"+    c_TMR_hexToBytes :: CString+                     -> Ptr Word8+                     -> Word32+                     -> Ptr Word32+                     -> IO RawStatus++foreign import ccall unsafe "tmr_tag_data.h TMR_bytesToHex"+    c_TMR_bytesToHex :: Ptr Word8+                     -> Word32+                     -> CString+                     -> IO ()++foreign import ccall unsafe "glue.h c_new_c_locale"+    c_new_c_locale :: IO (Ptr Locale)++foreign import ccall unsafe "glue.h c_format_time"+    c_format_time :: CString+                  -> CSize+                  -> CString+                  -> CTime+                  -> CBool+                  -> Ptr Locale+                  -> IO CInt++-- | Represents any error that can occur in a MercuryApi call,+-- except for those which can be represented by 'IOException'.+data MercuryException =+  MercuryException+  { meStatusType :: StatusType -- ^ general category of error+  , meStatus     :: Status     -- ^ the specific error+  , meMessage    :: T.Text     -- ^ the error message+  , meLocation   :: T.Text     -- ^ function where the error occurred+  , meParam      :: T.Text     -- ^ more information, such as the parameter+                               -- in 'paramGet' or 'paramSet'+  , meUri        :: T.Text     -- ^ URI of the reader+  }+  deriving (Eq, Ord, Show, Read, Typeable)++instance Exception MercuryException++statusGetType :: RawStatus -> RawType+statusGetType stat = stat `shiftR` 24++errnoBit :: Int+errnoBit = 15++statusIsErrno :: StatusType -> RawStatus -> Bool+statusIsErrno ERROR_TYPE_COMM rstat = rstat `testBit` errnoBit+statusIsErrno _ _ = False++statusGetErrno :: RawStatus -> Errno+statusGetErrno rstat = Errno $ fromIntegral $ rstat .&. (bit errnoBit - 1)++checkStatus' :: Ptr ReaderEtc+             -> RawStatus+             -> T.Text+             -> T.Text+             -> IO T.Text+             -> IO ()+checkStatus' rdr rstat loc param getUri = do+  let t = toStatusType $ statusGetType rstat+      stat = toStatus rstat+  case t of+    SUCCESS_TYPE -> return ()+    _ -> do+      uri <- getUri+      if statusIsErrno t rstat+        then do+        let errno = statusGetErrno rstat+            ioe = errnoToIOError (T.unpack loc) errno Nothing+                  (Just $ T.unpack uri)+        throwIO ioe+        else do+        cstr <- c_TMR_strerr rdr rstat+        msg <- textFromCString cstr+        let exc = MercuryException+                  { meStatusType = t+                  , meStatus = stat+                  , meMessage = msg+                  , meLocation = loc+                  , meParam = param+                  , meUri = uri+                  }+        throwIO exc++checkStatus :: Ptr ReaderEtc -> RawStatus -> T.Text -> T.Text -> IO ()+checkStatus rdr rstat loc param =+  checkStatus' rdr rstat loc param (textFromCString $ uriPtr rdr)++uniqueCounter :: IORef Integer+{-# NOINLINE uniqueCounter #-}+uniqueCounter = U.unsafePerformIO $ newIORef 0++newUnique :: IO Integer+newUnique = atomicModifyIORef' uniqueCounter f+  where f x = (x + 1, x)++castToCStringLen :: Integral a => a -> Ptr Word8 -> CStringLen+castToCStringLen len ptr = (castPtr ptr, fromIntegral len)++paramPairs :: [(Param, T.Text)]+paramPairs = map f [minBound..maxBound]+  where+    f p = (p, U.unsafePerformIO $ textFromCString $ c_TMR_paramName $ fromParam p)++paramMap :: H.HashMap Param T.Text+paramMap = H.fromList paramPairs++paramMapReverse :: H.HashMap T.Text Param+paramMapReverse = H.fromList $ map swap paramPairs+  where swap (x, y) = (y, x)++-- | Return the string name (e. g. \"\/reader\/read\/plan\")+-- corresponding to a 'Param'.+paramName :: Param -> T.Text+paramName p = paramMap H.! p -- all possible keys are in the map, so can't fail++-- | Return the 'Param' corresponding to a string name+-- (e. g. \"\/reader\/read\/plan\").  Returns 'PARAM_NONE' if no such+-- parameter exists.+paramID :: T.Text -> Param+paramID name = H.lookupDefault PARAM_NONE name paramMapReverse++-- | Create a new 'Reader' with the specified URI.  The reader is+-- not contacted at this point.  On Mac OS X, be sure to use the+-- serial device that starts with @cu.@, not the one that starts with+-- @tty.@.+create :: T.Text -- ^ a reader URI, such as @tmr:\/\/\/dev\/ttyUSB0@ on Linux,+                 -- @tmr:\/\/\/dev\/cu.SLAB_USBtoUART@ on Mac OS X, or+                 -- @tmr:\/\/\/COM4@ on Windows.+       -> IO Reader+create deviceUri = do+  B.useAsCStringLen (textToBS deviceUri) $ \(cs, len) -> do+    fp <- mallocForeignPtrBytes (sizeofReaderEtc + len)+    withForeignPtr fp $ \p -> do+      status <- c_TMR_create p cs+      checkStatus' p status "create" "" (return deviceUri)+    addForeignPtrFinalizer p_TMR_destroy fp+    return $ Reader fp++withReaderEtc :: Reader+              -> T.Text+              -> T.Text+              -> (Ptr ReaderEtc -> IO RawStatus)+              -> IO ()+withReaderEtc (Reader fp) location param func = do+  withForeignPtr fp $ \p -> do+    status <- func p+    checkStatus p status location param++-- | Establishes the connection to the reader at the URI specified in+-- the 'create' call.  The existence of a reader at the address is+-- verified and the reader is brought into a state appropriate for+-- performing RF operations.+connect :: Reader -> IO ()+connect rdr = withReaderEtc rdr "connect" "" c_TMR_connect++-- | Closes the connection to the reader and releases any resources+-- that have been consumed by the reader structure.  Any further+-- operations performed on the reader will fail with+-- 'ERROR_ALREADY_DESTROYED'.  On finalization of the 'Reader',+-- 'destroy' will be called automatically if it has not already been called.+destroy :: Reader -> IO ()+destroy rdr = withReaderEtc rdr "destroy" "" c_TMR_destroy++-- | Create a new 'Reader' with the specified URI, pass it to the given+-- computation, and destroy it when the computation exits.+withReader :: T.Text -- ^ a reader URI, such as @tmr:\/\/\/dev\/ttyUSB0@ on+                     -- Linux, @tmr:\/\/\/dev\/cu.SLAB_USBtoUART@ on Mac OS X,+                     -- or @tmr:\/\/\/COM4@ on Windows.+           -> (Reader -> IO a) -- ^ computation to run with Reader+           -> IO a+withReader uri = bracket (create uri) destroy++hasMoreTags :: Ptr CBool -> Ptr ReaderEtc -> IO RawStatus+hasMoreTags boolPtr rdrPtr = do+  status <- c_TMR_hasMoreTags rdrPtr+  let (moreTags, status') = case toStatus status of+                              ERROR_NO_TAGS -> (cFalse, 0)+                              _ -> (cTrue, status)+  poke boolPtr moreTags+  return status'++tShow :: Show a => a -> T.Text+tShow = T.pack . show++readLoop :: Reader+         -> Word32+         -> Ptr TagReadData+         -> Ptr CBool+         -> Int+         -> [TagReadData]+         -> IO [TagReadData]+readLoop rdr tagCount trdPtr boolPtr !tagNum !trds = do+  let tagNum' = tagNum + 1+      progress = "(" <> tShow tagNum' <> " of " <> tShow tagCount <> ")"+  withReaderEtc rdr "read"+    ("hasMoreTags " <> progress)+    (hasMoreTags boolPtr)+  moreTags <- toBool' <$> peek boolPtr+  if moreTags+    then do+    c_TMR_TRD_init trdPtr -- ignore return value because it is always success+    withReaderEtc rdr "read" ("getNextTag " <> progress)+      $ \p -> c_TMR_getNextTag p trdPtr+    trd <- peek trdPtr+    readLoop rdr tagCount trdPtr boolPtr tagNum' (trd : trds)+    else do+    return $ reverse trds++-- | Search for tags for a fixed duration.  Follows the 'ReadPlan'+-- stored in 'PARAM_READ_PLAN'.+read :: Reader -- ^ The reader being operated on+     -> Word32 -- ^ The number of milliseconds to search for tags+     -> IO [TagReadData]+read rdr timeoutMs = do+  alloca $ \tagCountPtr -> do+    withReaderEtc rdr "read" "" $ \p -> c_TMR_read p timeoutMs tagCountPtr+    tagCount <- peek tagCountPtr+    alloca $ \trdPtr -> alloca $+                        \boolPtr -> readLoop rdr tagCount trdPtr boolPtr 0 []++-- | Directly executes a 'TagOp' command.+-- Operates on the first tag found, with applicable tag filtering.+-- The call returns immediately after finding one tag+-- and operating on it, unless the command timeout expires first.+-- The operation is performed on the antenna specified in the+-- 'PARAM_TAGOP_ANTENNA' parameter.+-- 'PARAM_TAGOP_PROTOCOL' specifies the protocol to be used.+-- Some TagOps return data, while others will just return an+-- empty 'B.ByteString'.+executeTagOp :: Reader -> TagOp -> Maybe TagFilter -> IO B.ByteString+executeTagOp rdr tagOp tagFilter = alloca $ \pOp -> alloca $ \pFilt -> do+  eth1 <- try $ poke pOp tagOp+  case eth1 of+    Left err -> throwPE rdr err "executeTagOp" "tagop"+    Right _ -> return ()+  pFilt' <- case tagFilter of+              Nothing -> return nullPtr+              Just tf -> do+                eth2 <- try $ poke pFilt tf+                case eth2 of+                  Left err -> throwPE rdr err "executeTagOp" "filter"+                  Right _ -> return pFilt+  results <- getList16 $ \pList -> do+    withReaderEtc rdr "executeTagOp" (tagOpName tagOp) $ \pRdr -> do+      c_TMR_executeTagOp pRdr pOp pFilt' (castPtr pList)+  return $ B.pack results++-- | Set the state of some GPO pins.+gpoSet :: Reader -> [GpioPin] -> IO ()+gpoSet rdr gpios = do+  withArrayLen gpios $ \len gpioPtr -> do+    eth <- try $ castLen "[GpioPin]" len+    case eth of+      Left err -> throwPE rdr err "gpoSet" ""+      Right len' -> do+        withReaderEtc rdr "gpoSet" "" $ \pRdr -> do+          c_TMR_gpoSet pRdr len' gpioPtr++-- | Get the state of all GPI pins.+gpiGet :: Reader -> IO [GpioPin]+gpiGet rdr = do+  let maxLen = maxBound+  with maxLen $ \lenPtr -> do+    allocaArray (fromIntegral maxLen) $ \gpioPtr -> do+      withReaderEtc rdr "gpiGet" "" $ \pRdr -> do+        c_TMR_gpiGet pRdr lenPtr gpioPtr+      len <- peek lenPtr+      peekArray (fromIntegral len) gpioPtr++-- | Attempts to install firmware on the reader, then restart and reinitialize.+firmwareLoad :: Reader       -- ^ The reader being operated on+             -> B.ByteString -- ^ The binary firmware image to install+             -> IO ()+firmwareLoad = firmwareLoad' ""++firmwareLoad' :: T.Text -> Reader -> B.ByteString -> IO ()+firmwareLoad' filename rdr firmware = do+  B.useAsCStringLen firmware $ \(fwPtr, fwLen) -> do+    withReaderEtc rdr "firmwareLoad" filename $+      \p -> c_TMR_firmwareLoad p (castPtr fwPtr) (fromIntegral fwLen)++-- | Like 'firmwareLoad', but loads firmware from a file.+-- (e. g. @NanoFW-1.7.1.2.sim@)+firmwareLoadFile :: Reader   -- ^ The reader being operated on+                 -> FilePath -- ^ Name of file containing firmware image+                 -> IO ()+firmwareLoadFile rdr filename = do+  firmware <- B.readFile filename+  firmwareLoad' (T.pack filename) rdr firmware++throwPE :: Reader -> ParamException -> T.Text -> T.Text -> IO a+throwPE (Reader fp) (ParamException statusType status msg) loc param = do+  uri <- withForeignPtr fp (textFromCString . uriPtr)+  throwIO $ MercuryException+    { meStatusType = statusType+    , meStatus = status+    , meMessage = msg+    , meLocation = loc+    , meParam = param+    , meUri = uri+    }++unimplementedParam :: ParamException+unimplementedParam =+  ParamException ERROR_TYPE_BINDING ERROR_UNIMPLEMENTED_PARAM+  "The given parameter is not yet implemented in the Haskell binding."++invalidParam :: ParamType -> ParamType -> ParamException+invalidParam expected actual =+  ParamException ERROR_TYPE_BINDING ERROR_INVALID_PARAM_TYPE+  ( "Expected " <> displayParamType expected <>+    " but got " <> displayParamType actual )++-- | Sets the value of a reader parameter.  Throws 'MercuryException'+-- with a 'meStatus' of 'ERROR_INVALID_PARAM_TYPE' if the parameter value+-- is not of the correct type (sadly, this is only checked at runtime) or+-- 'ERROR_UNIMPLEMENTED_PARAM' if the parameter has not yet been implemented+-- in the Haskell binding.  Can also propagate errors from the C API, such+-- as 'ERROR_UNSUPPORTED' or 'ERROR_READONLY'.+paramSet :: ParamValue a => Reader -> Param -> a -> IO ()+paramSet rdr param value = do+  let pt = paramType param+      pt' = pType value+      rp = fromParam param+      pName = T.pack $ show param+  when (pt == ParamTypeUnimplemented) $+    throwPE rdr unimplementedParam "paramSet" pName+  when (pt /= pt') $+    throwPE rdr (invalidParam pt pt') "paramSet" pName+  eth <- try $ pSet value $ \pp -> withReaderEtc rdr "paramSet" pName $+                                   \p -> c_TMR_paramSet p rp pp+  case eth of+    Left err -> throwPE rdr err "paramSet" pName+    Right _ -> return ()++withReturnType :: (a -> IO a) -> IO a+withReturnType f = f undefined++-- | Gets the value of a reader parameter.  Throws 'MercuryException'+-- with a 'meStatus' of 'ERROR_INVALID_PARAM_TYPE' if the parameter value+-- is not of the correct type (sadly, this is only checked at runtime) or+-- 'ERROR_UNIMPLEMENTED_PARAM' if the parameter has not yet been implemented+-- in the Haskell binding.  Can also propagate errors from the C API, such+-- as 'ERROR_UNSUPPORTED'.+paramGet :: ParamValue a => Reader -> Param -> IO a+paramGet rdr param = withReturnType $ \returnType -> do+  let pt = paramType param+      pt' = pType returnType+      rp = fromParam param+      pName = T.pack $ show param+  when (pt == ParamTypeUnimplemented) $+    throwPE rdr unimplementedParam "paramGet" pName+  when (pt /= pt') $+    throwPE rdr (invalidParam pt pt') "paramGet" pName+  pGet $ \pp -> withReaderEtc rdr "paramGet" pName $+                \p -> c_TMR_paramGet p rp pp++-- | Convenience function to set some of the most essential parameters.+-- The specified 'Region' is written into 'PARAM_REGION_ID'.+-- The specified power level is written into 'PARAM_RADIO_READPOWER'+-- and 'PARAM_RADIO_WRITEPOWER'.  The specified antenna list is+-- written into the 'rpAntennas' field of 'PARAM_READ_PLAN', and the first+-- antenna in the list is written into 'PARAM_TAGOP_ANTENNA'.  For the+-- <https://www.sparkfun.com/products/14066 SparkFun Simultaneous RFID Reader>,+-- the antenna list should be 'sparkFunAntennas', and if powering the reader+-- off USB, the power level should be 500+-- (<https://learn.sparkfun.com/tutorials/simultaneous-rfid-tag-reader-hookup-guide/power-supply-considerations 5 dBm>).+-- (Higher power levels can be used with a separate power supply.)+paramSetBasics :: Reader   -- ^ The reader being operated on+               -> Region   -- ^ The region+               -> Int32    -- ^ Power in centi-dBm+               -> [AntennaPort] -- ^ Antenna list+               -> IO ()+paramSetBasics rdr rgn pwr ant = do+  paramSet rdr PARAM_REGION_ID rgn+  paramSet rdr PARAM_RADIO_READPOWER pwr+  paramSet rdr PARAM_RADIO_WRITEPOWER pwr+  plan <- paramGet rdr PARAM_READ_PLAN+  paramSet rdr PARAM_READ_PLAN plan { rpAntennas = ant }+  when (not $ null ant) $ paramSet rdr PARAM_TAGOP_ANTENNA (head ant)++-- | Sets the 'rpFilter' field of the 'PARAM_READ_PLAN' parameter,+-- while leaving the rest of the read plan unchanged.+paramSetReadPlanFilter :: Reader -> Maybe TagFilter -> IO ()+paramSetReadPlanFilter rdr filt = do+  plan <- paramGet rdr PARAM_READ_PLAN+  paramSet rdr PARAM_READ_PLAN plan { rpFilter = filt }++-- | Sets the 'rpTagop' field of the 'PARAM_READ_PLAN' parameter,+-- while leaving the rest of the read plan unchanged.+paramSetReadPlanTagop :: Reader -> Maybe TagOp -> IO ()+paramSetReadPlanTagop rdr op = do+  plan <- paramGet rdr PARAM_READ_PLAN+  paramSet rdr PARAM_READ_PLAN plan { rpTagop = op }++-- | The read plan that the reader starts out with by default.+-- This has reasonable settings for most things, except for the+-- antennas, which need to be set.  (e. g. set 'rpAntennas' to+-- 'sparkFunAntennas')+defaultReadPlan :: ReadPlan+defaultReadPlan = U.unsafePerformIO $ do+  alloca $ \p -> do+    c_default_read_plan p+    peek p++-- | The constant @[1]@, which is the correct value for 'rpAntennas'+-- when using the+-- <http://sparkfun.com/products/14066 SparkFun Simultaneous RFID Reader>.+sparkFunAntennas :: [AntennaPort]+sparkFunAntennas = [1]++-- | Reboot the reader+reboot :: Reader -> IO ()+reboot rdr = withReaderEtc rdr "reboot" "" c_TMR_reboot++-- | Get a list of parameters supported by the reader.+paramList :: Reader -> IO [Param]+paramList rdr = do+  let maxParams = paramMax + 1+  alloca $ \nParams -> do+    poke nParams (fromIntegral maxParams)+    allocaArray (fromIntegral maxParams) $ \params -> do+      withReaderEtc rdr "paramList" "" $ \p -> c_TMR_paramList p params nParams+      actual <- peek nParams+      result <- peekArray (min (fromIntegral actual) (fromIntegral maxParams)) params+      return $ map toParam result++txToDirection :: Bool -> TransportDirection+txToDirection True = Tx+txToDirection False = Rx++callTransportListener :: TransportListener -> RawTransportListener+callTransportListener listener tx dataLen dataPtr timeout _ = do+  bs <- B.packCStringLen (castToCStringLen dataLen dataPtr)+  listener (txToDirection $ toBool tx) bs timeout++-- | Add a listener to the list of functions that will be called for+-- each message sent to or recieved from the reader.+addTransportListener :: Reader                 -- ^ The reader to operate on.+                     -> TransportListener      -- ^ The listener to call.+                     -> IO TransportListenerId -- ^ A unique identifier which+                                               -- can be used to remove the+                                               -- listener later.+addTransportListener rdr listener = do+  unique <- newUnique+  funPtr <- wrapTransportListener (callTransportListener listener)+  cs <- newCAString (show unique)+  withReaderEtc rdr "addTransportListener" "" $+    \p -> c_TMR_addTransportListener p funPtr cs+  return (TransportListenerId unique)++-- | Remove a listener from the list of functions that will be called+-- for each message sent to or recieved from the reader.+removeTransportListener :: Reader              -- ^ The reader to operate on.+                        -> TransportListenerId -- ^ The return value of a call+                                               -- to 'addTransportListener'.+                        -> IO ()+removeTransportListener rdr (TransportListenerId unique) = do+  withCAString (show unique) $ \cs -> do+    withReaderEtc rdr "removeTransportListener" "" $+      \p -> c_TMR_removeTransportListener p cs++-- | Given a 'Handle', returns a 'TransportListener' which prints+-- transport data to that handle in hex.  If the handle is a terminal,+-- prints transmitted data in magenta and received data in cyan.+hexListener :: Handle -> IO TransportListener+hexListener h = do+  useColor <- hSupportsANSI h+  return (listenerImpl h useColor False)++-- | Identical to 'hexListener', but also prints the opcode of each packet,+-- and a timestamp.  (The timestamp is relative to an arbitrary point in+-- time, so is only useful for computing differences between timestamps.)+opcodeListener :: Handle -> IO TransportListener+opcodeListener h = do+  useColor <- hSupportsANSI h+  return (listenerImpl h useColor True)++listenerImpl :: Handle -> Bool -> Bool -> TransportListener+listenerImpl h useColor printOpcode dir dat _ = do+  setColors useColor [SetColor Foreground Vivid (color dir)]+  opc <- if printOpcode+         then opcodeAndTime dat+         else return []+  mapM_ (T.hPutStrLn h) $ lstn opc (prefix dir)+  setColors useColor [Reset]+  flushColor useColor+  where+    setColors False _ = return ()+    setColors True sgr = hSetSGR h sgr+    flushColor False = return ()+    flushColor True = hFlush h+    prefix Tx = "Sending: "+    prefix Rx = "Received:"+    color Tx = Magenta+    color Rx = Cyan+    lstn opc pfx =+      zipWith T.append (pfx : repeat "         ") (opc ++ displayData dat)++extractOpcode :: B.ByteString -> T.Text+extractOpcode bs+  | B.length bs < 3 = "too short"+  | otherwise = opcodeName (bs `B.index` 2)++opcodeAndTime :: B.ByteString -> IO [T.Text]+opcodeAndTime bs = do+  now <- getTime Monotonic+  let opcode = extractOpcode bs+      tm = printf "%d.%09d" (sec now) (nsec now)+  return [pad 30 opcode <> T.pack tm]++-- | Convert a hexadecimal string (without spaces) into a+-- 'B.ByteString'.  The hex string may optionally include a "0x"+-- prefix, which will be ignored.  If the input cannot be parsed as a+-- hex string, returns 'Nothing'.+hexToBytes :: T.Text -> Maybe B.ByteString+hexToBytes hex = U.unsafePerformIO $ do+  let hexBs = textToBS hex+      hexLen = B.length hexBs+      bufLen = 1 + (hexLen `div` 2)+  alloca $ \pLen -> allocaBytes bufLen $ \buf -> B.useAsCString hexBs $ \cs -> do+    status <- c_TMR_hexToBytes cs buf (fromIntegral bufLen) pLen+    outLen <- peek pLen+    if (status == 0)+      then Just <$> B.packCStringLen (castPtr buf, fromIntegral outLen)+      else return Nothing++-- | Convert a 'B.ByteString', such as a tag EPC, into a hexadecimal string.+bytesToHex :: B.ByteString -> T.Text+bytesToHex bytes = U.unsafePerformIO $ do+  let bytesLen = B.length bytes+      bufLen = 1 + bytesLen * 2+  allocaBytes bufLen $ \buf -> B.useAsCString bytes $ \cs -> do+    c_TMR_bytesToHex (castPtr cs) (fromIntegral bytesLen) buf+    textFromBS <$> B.packCString buf++-- | Like 'bytesToHex', but with a space between each byte.+bytesToHexWithSpaces :: B.ByteString -> T.Text+bytesToHexWithSpaces = T.pack . intercalate " " . map (printf "%02x") . B.unpack++pad :: Int -> T.Text -> T.Text+pad x t = t <> T.replicate (x - T.length t) " "++-- | Format a 'B.ByteString' as 16 bytes per line, with both hex and ascii+-- on the line.+displayData :: B.ByteString -> [T.Text]+displayData bytes+  | B.null bytes = []+  | otherwise =+    let (bs1, bs2) = B.splitAt 16 bytes+        (bs1a, bs1b) = B.splitAt 8 bs1+        dotify x = if x < 0x20 || x >= 0x7f then 0x2e else x+        hex = map (pad 25 . bytesToHexWithSpaces) [bs1a, bs1b]+        ascii = B.map dotify bs1+        txt = T.concat $ hex ++ ["|", textFromBS ascii, "|"]+    in txt : displayData bs2++displayByteString :: B.ByteString -> T.Text+displayByteString bs =+  "<" <> bytesToHex bs <> "> (" <> T.pack (show $ B.length bs) <> " bytes)"++-- | Convert a 'TagData' to a human-readable list of lines.+displayTagData :: TagData -> [T.Text]+displayTagData td =+  concat+  [ [ "TagData"+    , "  epc         = " <> displayByteString (tdEpc td)+    , "  protocol    = " <> tShow (tdProtocol td)+    , "  crc         = " <> T.pack (printf "0x%04x" $ tdCrc td)+    ]+  , case tdGen2 td of+      Nothing -> []+      Just gen2 -> ["  gen2.pc     = " <> displayByteString (g2Pc gen2)]+  ]++indent :: [T.Text] -> [T.Text]+indent = map ("  " <>)++cLocale :: Ptr Locale+{-# NOINLINE cLocale #-}+cLocale = U.unsafePerformIO $ throwErrnoIfNull "newlocale" c_new_c_locale++formatTimestamp :: MillisecondsSinceEpoch -> CBool -> String -> IO T.Text+formatTimestamp t local z = do+  let (seconds, millis) = t `divMod` 1000+      fmt = "%Y-%m-%dT%H:%M:%S" ++ printf ".%03d" millis ++ z+      bufSize = 80+  withCAString fmt $ \cFmt -> allocaBytes bufSize $ \buf -> do+    ret <- c_format_time buf (fromIntegral bufSize) cFmt+           (CTime $ fromIntegral seconds) local cLocale+    if ret < 0+      then return $ T.pack $ printf "%d.%03d" seconds millis+      else textFromCString buf++-- | Convert a timestamp into+-- <https://en.wikipedia.org/wiki/ISO_8601 ISO 8601> format in UTC.+displayTimestamp :: MillisecondsSinceEpoch -- ^ milliseconds since 1\/1\/1970 UTC+                 -> T.Text+displayTimestamp t = U.unsafePerformIO $ formatTimestamp t cFalse "Z"++-- | Convert a timestamp into <https://en.wikipedia.org/wiki/ISO_8601 ISO 8601>+-- format in the local timezone.+displayLocalTimestamp :: MillisecondsSinceEpoch -- ^ milliseconds since 1\/1\/1970 UTC+                      -> IO T.Text+displayLocalTimestamp t = formatTimestamp t cTrue "%z"++-- | Convert a list of 'GpioPin' to a human-readable list of lines.+displayGpio :: [GpioPin] -> [T.Text]+displayGpio gpios = "Gpio" : map dispGpio gpios+  where+    dispGpio gpio = "  pin " <> tShow (gpId gpio) <>+                    (if (gpHigh gpio) then " high" else " low ") <>+                    (if (gpOutput gpio) then " output" else "  input")++-- | Convert a 'TagReadData' to a human-readable list of lines.+displayTagReadData :: TagReadData -> [T.Text]+displayTagReadData trd =+  concat+  [ [ "TagReadData" ]+  , indent (displayTagData $ trTag trd)+  , [ "  metadataFlags = " <> T.intercalate "|" (map fl $ trMetadataFlags trd)+    , "  phase         = " <> tShow (trPhase trd)+    , "  antenna       = " <> tShow (trAntenna trd)+    ]+  , indent (displayGpio $ trGpio trd)+  , [ "  readCount     = " <> tShow (trReadCount trd)+    , "  rssi          = " <> tShow (trRssi trd)+    , "  frequency     = " <> tShow (trFrequency trd)+    , "  timestamp     = " <> displayTimestamp (trTimestamp trd)+    ]+  , dat "data" (trData trd)+  , dat "epcMemData" (trEpcMemData trd)+  , dat "tidMemData" (trTidMemData trd)+  , dat "userMemData" (trUserMemData trd)+  , dat "reservedMemData" (trReservedMemData trd)+  ]+  where+    nDrop = T.length "METADATA_FLAG_"+    fl = T.drop nDrop . tShow+    dat name bs =+      if B.null bs+      then []+      else indent ((name <> ": " <> T.pack (show $ B.length bs) <> " bytes")+                   : indent (displayData bs))++regionPrefix :: T.Text+regionPrefix = "REGION_"++-- | Like 'show' for 'Region', but in lower case and without the+-- @REGION_@ prefix.+displayRegion :: Region -> T.Text+displayRegion = T.toLower . T.pack . drop (T.length regionPrefix) . show++-- | Like 'readMaybe' for 'Region', but case-insenstive and without the+-- @REGION_@ prefix.+parseRegion :: T.Text -> Maybe Region+parseRegion = readMaybe . T.unpack . T.toUpper . T.append regionPrefix++-- | Convert a 'B.ByteString' into a list of 'Word16', in big-endian+-- order.  Padded with 0 if the number of bytes is odd.+packBytesIntoWords :: B.ByteString -> [Word16]+packBytesIntoWords bs = pbw (B.unpack bs)+  where pbw [] = []+        pbw [x] = [pk x 0]+        pbw (x1:x2:xs) = pk x1 x2 : pbw xs+        pk x1 x2 = (fromIntegral x1 `shiftL` 8) .|. fromIntegral x2++-- | Split a password into two 16-bit words, suitable for writing+-- into reserved memory.+passwordToWords :: GEN2_Password -> [Word16]+passwordToWords pwd = map fromIntegral [pwd `shiftR` 16, pwd .&. 0xffff]++-- | Create a 'TagFilterGen2' with the most common settings+mkFilterGen2 :: GEN2_Bank    -- ^ The bank to filter on+             -> Word32       -- ^ The location (in bits) at which to begin+                             -- comparing the mask+             -> B.ByteString -- ^ The mask value to compare with the specified+                             -- region of tag memory+             -> TagFilter+mkFilterGen2 bank bitPointer mask =+  TagFilterGen2+  { tfInvert = False+  , tfFilterOn = FilterOnBank bank+  , tfBitPointer = bitPointer+  , tfMaskBitLength = fromIntegral $ 8 * B.length mask+  , tfMask = mask+  }++-- | Word address of kill password in reserved memory.+killPasswordAddress :: Word32+killPasswordAddress = 0++-- | Word address of access password in reserved memory.+accessPasswordAddress :: Word32+accessPasswordAddress = 2
+ src/System/Hardware/MercuryApi/Enums.hsc view
@@ -0,0 +1,967 @@+-- Automatically generated by util/generate-tmr-hsc.pl+{-# LANGUAGE OverloadedStrings, FlexibleInstances, DeriveDataTypeable #-}+module System.Hardware.MercuryApi.Enums where++import Data.Hashable ( Hashable(..) )+import Data.Int ( Int8, Int16, Int32 )+import Data.Monoid ( (<>) )+import Data.Text (Text)+import qualified Data.Text as T ( pack )+import Data.Word ( Word8, Word16, Word32 )+import Text.Printf ( printf )++#include <tm_reader.h>+#include <serial_reader_imp.h>+#include <glue.h>++-- | Indicates a general category of error.+data StatusType =+    SUCCESS_TYPE+  | ERROR_TYPE_COMM+  | ERROR_TYPE_CODE+  | ERROR_TYPE_MISC+  | ERROR_TYPE_LLRP+  | ERROR_TYPE_BINDING -- ^ An error which originates from the Haskell binding, not the underlying C library.+  | ERROR_TYPE_UNKNOWN -- ^ Not a recognized status type+  deriving (Eq, Ord, Show, Read, Bounded, Enum)++toStatusType :: Word32 -> StatusType+toStatusType #{const TMR_SUCCESS_TYPE} = SUCCESS_TYPE+toStatusType #{const TMR_ERROR_TYPE_COMM} = ERROR_TYPE_COMM+toStatusType #{const TMR_ERROR_TYPE_CODE} = ERROR_TYPE_CODE+toStatusType #{const TMR_ERROR_TYPE_MISC} = ERROR_TYPE_MISC+toStatusType #{const TMR_ERROR_TYPE_LLRP} = ERROR_TYPE_LLRP+toStatusType #{const ERROR_TYPE_BINDING} = ERROR_TYPE_BINDING+toStatusType _ = ERROR_TYPE_UNKNOWN++-- | A specific error encountered by the C API or the Haskell binding.+data Status =+    SUCCESS -- ^ Success!  (Never thrown in an exception)+  | ERROR_MSG_WRONG_NUMBER_OF_DATA -- ^ Invalid number of arguments+  | ERROR_INVALID_OPCODE -- ^ Command opcode not recognized.+  | ERROR_UNIMPLEMENTED_OPCODE -- ^ Command opcode recognized, but is not supported.+  | ERROR_MSG_POWER_TOO_HIGH -- ^ Requested power setting is above the allowed maximum.+  | ERROR_MSG_INVALID_FREQ_RECEIVED -- ^ Requested frequency is outside the allowed range.+  | ERROR_MSG_INVALID_PARAMETER_VALUE -- ^ Parameter value is outside the allowed range.+  | ERROR_MSG_POWER_TOO_LOW -- ^ Requested power setting is below the allowed minimum.+  | ERROR_UNIMPLEMENTED_FEATURE -- ^ Command not supported.+  | ERROR_INVALID_BAUD_RATE -- ^ Requested serial speed is not supported.+  | ERROR_INVALID_REGION -- ^ Region is not supported.+  | ERROR_INVALID_LICENSE_KEY -- ^  License key code is invalid+  | ERROR_BL_INVALID_IMAGE_CRC -- ^ Firmware is corrupt: Checksum doesn\'t match content.+  | ERROR_BL_INVALID_APP_END_ADDR -- ^ Serial protocol status code for this exception.+  | ERROR_FLASH_BAD_ERASE_PASSWORD -- ^ Internal reader error.  Contact support.+  | ERROR_FLASH_BAD_WRITE_PASSWORD -- ^ Internal reader error.  Contact support.+  | ERROR_FLASH_UNDEFINED_SECTOR -- ^ Internal reader error.  Contact support.+  | ERROR_FLASH_ILLEGAL_SECTOR -- ^ Internal reader error.  Contact support.+  | ERROR_FLASH_WRITE_TO_NON_ERASED_AREA -- ^ Internal reader error.  Contact support.+  | ERROR_FLASH_WRITE_TO_ILLEGAL_SECTOR -- ^ Internal reader error.  Contact support.+  | ERROR_FLASH_VERIFY_FAILED -- ^ Internal reader error.  Contact support.+  | ERROR_NO_TAGS_FOUND -- ^ Reader was asked to find tags, but none were detected.+  | ERROR_NO_PROTOCOL_DEFINED -- ^ RFID protocol has not been configured.+  | ERROR_INVALID_PROTOCOL_SPECIFIED -- ^ Requested RFID protocol is not recognized.+  | ERROR_WRITE_PASSED_LOCK_FAILED -- ^ Lock failed after write operation+  | ERROR_PROTOCOL_NO_DATA_READ -- ^ Tag data was requested, but could not be read.+  | ERROR_AFE_NOT_ON -- ^ AFE not on - reader not sufficiently configured+  | ERROR_PROTOCOL_WRITE_FAILED -- ^ Write to tag failed.+  | ERROR_NOT_IMPLEMENTED_FOR_THIS_PROTOCOL -- ^ Command is not supported in the current RFID protocol.+  | ERROR_PROTOCOL_INVALID_WRITE_DATA -- ^ Data does not conform to protocol standards.+  | ERROR_PROTOCOL_INVALID_ADDRESS -- ^ Requested data address is outside the valid range.+  | ERROR_GENERAL_TAG_ERROR -- ^ Unknown error during RFID operation.+  | ERROR_DATA_TOO_LARGE -- ^ Read Tag Data was asked for more data than it supports.+  | ERROR_PROTOCOL_INVALID_KILL_PASSWORD -- ^ Incorrect password was provided to Kill Tag.+  | ERROR_PROTOCOL_KILL_FAILED -- ^ Kill failed for unknown reason.+  | ERROR_PROTOCOL_BIT_DECODING_FAILED -- ^ Internal reader error.  Contact support.+  | ERROR_PROTOCOL_INVALID_EPC -- ^ Internal reader error.  Contact support.+  | ERROR_PROTOCOL_INVALID_NUM_DATA -- ^ Internal reader error.  Contact support.+  | ERROR_GEN2_PROTOCOL_OTHER_ERROR -- ^ Internal reader error.  Contact support.+  | ERROR_GEN2_PROTOCOL_MEMORY_OVERRUN_BAD_PC -- ^ Internal reader error.  Contact support.+  | ERROR_GEN2_PROTOCOL_MEMORY_LOCKED -- ^ Internal reader error.  Contact support.+  | ERROR_GEN2_PROTOCOL_V2_AUTHEN_FAILED -- ^ Authentication failed with specified key.+  | ERROR_GEN2_PROTOCOL_V2_UNTRACE_FAILED -- ^  Untrace operation failed.+  | ERROR_GEN2_PROTOCOL_INSUFFICIENT_POWER -- ^ Internal reader error.  Contact support.+  | ERROR_GEN2_PROTOCOL_NON_SPECIFIC_ERROR -- ^ Internal reader error.  Contact support.+  | ERROR_GEN2_PROTOCOL_UNKNOWN_ERROR -- ^ Internal reader error.  Contact support.+  | ERROR_AHAL_INVALID_FREQ -- ^ A command was received to set a frequency outside the specified range.+  | ERROR_AHAL_CHANNEL_OCCUPIED -- ^ With LBT enabled an attempt was made to set the frequency to an occupied channel.+  | ERROR_AHAL_TRANSMITTER_ON -- ^ Checking antenna status while CW is on is not allowed.+  | ERROR_ANTENNA_NOT_CONNECTED -- ^  Antenna not detected during pre-transmit safety test.+  | ERROR_TEMPERATURE_EXCEED_LIMITS -- ^ Reader temperature outside safe range.+  | ERROR_HIGH_RETURN_LOSS -- ^  Excess power detected at transmitter port, usually due to antenna tuning mismatch.+  | ERROR_INVALID_ANTENNA_CONFIG -- ^ Invalid antenna configuration+  | ERROR_TAG_ID_BUFFER_NOT_ENOUGH_TAGS_AVAILABLE -- ^ Asked for more tags than were available in the buffer.+  | ERROR_TAG_ID_BUFFER_FULL -- ^ Too many tags are in buffer.  Remove some with Get Tag ID Buffer or Clear Tag ID Buffer.+  | ERROR_TAG_ID_BUFFER_REPEATED_TAG_ID -- ^ Internal error -- reader is trying to insert a duplicate tag record.  Contact support.+  | ERROR_TAG_ID_BUFFER_NUM_TAG_TOO_LARGE -- ^ Asked for tags than a single transaction can handle.+  | ERROR_TAG_ID_BUFFER_AUTH_REQUEST -- ^ Blocked response to get additional data from host.+  | ERROR_SYSTEM_UNKNOWN_ERROR -- ^ Internal reader error.  Contact support.+  | ERROR_TM_ASSERT_FAILED -- ^ Internal reader error.  Contact support.+  | ERROR_TIMEOUT -- ^ Timeout+  | ERROR_NO_HOST -- ^ No matching host found+  | ERROR_LLRP -- ^ LLRP error+  | ERROR_PARSE -- ^ Error parsing device response+  | ERROR_DEVICE_RESET -- ^ Device was reset externally+  | ERROR_CRC_ERROR -- ^ CRC Error+  | ERROR_INVALID -- ^ Invalid argument+  | ERROR_UNIMPLEMENTED -- ^ Unimplemented operation+  | ERROR_UNSUPPORTED -- ^ Unsupported operation+  | ERROR_NO_ANTENNA -- ^ No antenna or invalid antenna+  | ERROR_READONLY -- ^ Value is read-only+  | ERROR_TOO_BIG -- ^ Value too big+  | ERROR_NO_THREADS -- ^ Thread initialization failed+  | ERROR_NO_TAGS -- ^ No tags to be retrieved+  | ERROR_NOT_FOUND -- ^ Key not found+  | ERROR_FIRMWARE_FORMAT -- ^ Size or format of firmware image is incorrect+  | ERROR_TRYAGAIN -- ^ Temporary error, try again+  | ERROR_OUT_OF_MEMORY -- ^ Out of memory+  | ERROR_INVALID_WRITE_MODE -- ^ Invalid write mode+  | ERROR_ILLEGAL_VALUE -- ^ Illegal value+  | ERROR_END_OF_READING+  | ERROR_UNSUPPORTED_READER_TYPE -- ^ Unsupported reader type+  | ERROR_BUFFER_OVERFLOW -- ^ Buffer overflow+  | ERROR_LOADSAVE_CONFIG+  | ERROR_AUTOREAD_ENABLED -- ^ Autonomous mode is enabled on reader. Please disable it+  | ERROR_FIRMWARE_UPDATE_ON_AUTOREAD -- ^ Firmware update is successful. Autonomous mode is already enabled on reader+  | ERROR_TIMESTAMP_NULL -- ^ Timestamp cannot be null+  | ERROR_LLRP_GETTYPEREGISTRY -- ^ LLRP Reader GetTypeRegistry Failed+  | ERROR_LLRP_CONNECTIONFAILED -- ^ LLRP Reader Connection attempt is failed+  | ERROR_LLRP_SENDIO_ERROR -- ^ LLRP Reader Send Messages failed+  | ERROR_LLRP_RECEIVEIO_ERROR -- ^ LLRP Reader Receive Messages failed+  | ERROR_LLRP_RECEIVE_TIMEOUT -- ^ LLRP Reader Receive Messages Timeout+  | ERROR_LLRP_MSG_PARSE_ERROR -- ^ Error parsing LLRP message+  | ERROR_LLRP_ALREADY_CONNECTED -- ^ Already connected to reader+  | ERROR_LLRP_INVALID_RFMODE -- ^ Specified RF Mode operation is not supported+  | ERROR_LLRP_UNDEFINED_VALUE -- ^ Undefined Value+  | ERROR_LLRP_READER_ERROR -- ^ LLRP reader unknown error+  | ERROR_LLRP_READER_CONNECTION_LOST -- ^ LLRP reader connection lost+  | ERROR_LLRP_CLIENT_CONNECTION_EXISTS -- ^ LLRP Reader Connection attempt is failed, A Client initiated connection already exists+  | ERROR_ALREADY_DESTROYED -- ^ Attempt to use reader after it was destroyed.+  | ERROR_INVALID_PARAM_TYPE -- ^ The parameter value was not of the type expected.+  | ERROR_UNIMPLEMENTED_PARAM -- ^ The given parameter is not yet implemented in the Haskell binding.+  | ERROR_UNKNOWN Word32 -- ^ C API returned an unrecognized status code+  deriving (Eq, Ord, Show, Read)++toStatus :: Word32 -> Status+toStatus #{const TMR_SUCCESS} = SUCCESS+toStatus #{const TMR_ERROR_MSG_WRONG_NUMBER_OF_DATA} = ERROR_MSG_WRONG_NUMBER_OF_DATA+toStatus #{const TMR_ERROR_INVALID_OPCODE} = ERROR_INVALID_OPCODE+toStatus #{const TMR_ERROR_UNIMPLEMENTED_OPCODE} = ERROR_UNIMPLEMENTED_OPCODE+toStatus #{const TMR_ERROR_MSG_POWER_TOO_HIGH} = ERROR_MSG_POWER_TOO_HIGH+toStatus #{const TMR_ERROR_MSG_INVALID_FREQ_RECEIVED} = ERROR_MSG_INVALID_FREQ_RECEIVED+toStatus #{const TMR_ERROR_MSG_INVALID_PARAMETER_VALUE} = ERROR_MSG_INVALID_PARAMETER_VALUE+toStatus #{const TMR_ERROR_MSG_POWER_TOO_LOW} = ERROR_MSG_POWER_TOO_LOW+toStatus #{const TMR_ERROR_UNIMPLEMENTED_FEATURE} = ERROR_UNIMPLEMENTED_FEATURE+toStatus #{const TMR_ERROR_INVALID_BAUD_RATE} = ERROR_INVALID_BAUD_RATE+toStatus #{const TMR_ERROR_INVALID_REGION} = ERROR_INVALID_REGION+toStatus #{const TMR_ERROR_INVALID_LICENSE_KEY} = ERROR_INVALID_LICENSE_KEY+toStatus #{const TMR_ERROR_BL_INVALID_IMAGE_CRC} = ERROR_BL_INVALID_IMAGE_CRC+toStatus #{const TMR_ERROR_BL_INVALID_APP_END_ADDR} = ERROR_BL_INVALID_APP_END_ADDR+toStatus #{const TMR_ERROR_FLASH_BAD_ERASE_PASSWORD} = ERROR_FLASH_BAD_ERASE_PASSWORD+toStatus #{const TMR_ERROR_FLASH_BAD_WRITE_PASSWORD} = ERROR_FLASH_BAD_WRITE_PASSWORD+toStatus #{const TMR_ERROR_FLASH_UNDEFINED_SECTOR} = ERROR_FLASH_UNDEFINED_SECTOR+toStatus #{const TMR_ERROR_FLASH_ILLEGAL_SECTOR} = ERROR_FLASH_ILLEGAL_SECTOR+toStatus #{const TMR_ERROR_FLASH_WRITE_TO_NON_ERASED_AREA} = ERROR_FLASH_WRITE_TO_NON_ERASED_AREA+toStatus #{const TMR_ERROR_FLASH_WRITE_TO_ILLEGAL_SECTOR} = ERROR_FLASH_WRITE_TO_ILLEGAL_SECTOR+toStatus #{const TMR_ERROR_FLASH_VERIFY_FAILED} = ERROR_FLASH_VERIFY_FAILED+toStatus #{const TMR_ERROR_NO_TAGS_FOUND} = ERROR_NO_TAGS_FOUND+toStatus #{const TMR_ERROR_NO_PROTOCOL_DEFINED} = ERROR_NO_PROTOCOL_DEFINED+toStatus #{const TMR_ERROR_INVALID_PROTOCOL_SPECIFIED} = ERROR_INVALID_PROTOCOL_SPECIFIED+toStatus #{const TMR_ERROR_WRITE_PASSED_LOCK_FAILED} = ERROR_WRITE_PASSED_LOCK_FAILED+toStatus #{const TMR_ERROR_PROTOCOL_NO_DATA_READ} = ERROR_PROTOCOL_NO_DATA_READ+toStatus #{const TMR_ERROR_AFE_NOT_ON} = ERROR_AFE_NOT_ON+toStatus #{const TMR_ERROR_PROTOCOL_WRITE_FAILED} = ERROR_PROTOCOL_WRITE_FAILED+toStatus #{const TMR_ERROR_NOT_IMPLEMENTED_FOR_THIS_PROTOCOL} = ERROR_NOT_IMPLEMENTED_FOR_THIS_PROTOCOL+toStatus #{const TMR_ERROR_PROTOCOL_INVALID_WRITE_DATA} = ERROR_PROTOCOL_INVALID_WRITE_DATA+toStatus #{const TMR_ERROR_PROTOCOL_INVALID_ADDRESS} = ERROR_PROTOCOL_INVALID_ADDRESS+toStatus #{const TMR_ERROR_GENERAL_TAG_ERROR} = ERROR_GENERAL_TAG_ERROR+toStatus #{const TMR_ERROR_DATA_TOO_LARGE} = ERROR_DATA_TOO_LARGE+toStatus #{const TMR_ERROR_PROTOCOL_INVALID_KILL_PASSWORD} = ERROR_PROTOCOL_INVALID_KILL_PASSWORD+toStatus #{const TMR_ERROR_PROTOCOL_KILL_FAILED} = ERROR_PROTOCOL_KILL_FAILED+toStatus #{const TMR_ERROR_PROTOCOL_BIT_DECODING_FAILED} = ERROR_PROTOCOL_BIT_DECODING_FAILED+toStatus #{const TMR_ERROR_PROTOCOL_INVALID_EPC} = ERROR_PROTOCOL_INVALID_EPC+toStatus #{const TMR_ERROR_PROTOCOL_INVALID_NUM_DATA} = ERROR_PROTOCOL_INVALID_NUM_DATA+toStatus #{const TMR_ERROR_GEN2_PROTOCOL_OTHER_ERROR} = ERROR_GEN2_PROTOCOL_OTHER_ERROR+toStatus #{const TMR_ERROR_GEN2_PROTOCOL_MEMORY_OVERRUN_BAD_PC} = ERROR_GEN2_PROTOCOL_MEMORY_OVERRUN_BAD_PC+toStatus #{const TMR_ERROR_GEN2_PROTOCOL_MEMORY_LOCKED} = ERROR_GEN2_PROTOCOL_MEMORY_LOCKED+toStatus #{const TMR_ERROR_GEN2_PROTOCOL_V2_AUTHEN_FAILED} = ERROR_GEN2_PROTOCOL_V2_AUTHEN_FAILED+toStatus #{const TMR_ERROR_GEN2_PROTOCOL_V2_UNTRACE_FAILED} = ERROR_GEN2_PROTOCOL_V2_UNTRACE_FAILED+toStatus #{const TMR_ERROR_GEN2_PROTOCOL_INSUFFICIENT_POWER} = ERROR_GEN2_PROTOCOL_INSUFFICIENT_POWER+toStatus #{const TMR_ERROR_GEN2_PROTOCOL_NON_SPECIFIC_ERROR} = ERROR_GEN2_PROTOCOL_NON_SPECIFIC_ERROR+toStatus #{const TMR_ERROR_GEN2_PROTOCOL_UNKNOWN_ERROR} = ERROR_GEN2_PROTOCOL_UNKNOWN_ERROR+toStatus #{const TMR_ERROR_AHAL_INVALID_FREQ} = ERROR_AHAL_INVALID_FREQ+toStatus #{const TMR_ERROR_AHAL_CHANNEL_OCCUPIED} = ERROR_AHAL_CHANNEL_OCCUPIED+toStatus #{const TMR_ERROR_AHAL_TRANSMITTER_ON} = ERROR_AHAL_TRANSMITTER_ON+toStatus #{const TMR_ERROR_ANTENNA_NOT_CONNECTED} = ERROR_ANTENNA_NOT_CONNECTED+toStatus #{const TMR_ERROR_TEMPERATURE_EXCEED_LIMITS} = ERROR_TEMPERATURE_EXCEED_LIMITS+toStatus #{const TMR_ERROR_HIGH_RETURN_LOSS} = ERROR_HIGH_RETURN_LOSS+toStatus #{const TMR_ERROR_INVALID_ANTENNA_CONFIG} = ERROR_INVALID_ANTENNA_CONFIG+toStatus #{const TMR_ERROR_TAG_ID_BUFFER_NOT_ENOUGH_TAGS_AVAILABLE} = ERROR_TAG_ID_BUFFER_NOT_ENOUGH_TAGS_AVAILABLE+toStatus #{const TMR_ERROR_TAG_ID_BUFFER_FULL} = ERROR_TAG_ID_BUFFER_FULL+toStatus #{const TMR_ERROR_TAG_ID_BUFFER_REPEATED_TAG_ID} = ERROR_TAG_ID_BUFFER_REPEATED_TAG_ID+toStatus #{const TMR_ERROR_TAG_ID_BUFFER_NUM_TAG_TOO_LARGE} = ERROR_TAG_ID_BUFFER_NUM_TAG_TOO_LARGE+toStatus #{const TMR_ERROR_TAG_ID_BUFFER_AUTH_REQUEST} = ERROR_TAG_ID_BUFFER_AUTH_REQUEST+toStatus #{const TMR_ERROR_SYSTEM_UNKNOWN_ERROR} = ERROR_SYSTEM_UNKNOWN_ERROR+toStatus #{const TMR_ERROR_TM_ASSERT_FAILED} = ERROR_TM_ASSERT_FAILED+toStatus #{const TMR_ERROR_TIMEOUT} = ERROR_TIMEOUT+toStatus #{const TMR_ERROR_NO_HOST} = ERROR_NO_HOST+toStatus #{const TMR_ERROR_LLRP} = ERROR_LLRP+toStatus #{const TMR_ERROR_PARSE} = ERROR_PARSE+toStatus #{const TMR_ERROR_DEVICE_RESET} = ERROR_DEVICE_RESET+toStatus #{const TMR_ERROR_CRC_ERROR} = ERROR_CRC_ERROR+toStatus #{const TMR_ERROR_INVALID} = ERROR_INVALID+toStatus #{const TMR_ERROR_UNIMPLEMENTED} = ERROR_UNIMPLEMENTED+toStatus #{const TMR_ERROR_UNSUPPORTED} = ERROR_UNSUPPORTED+toStatus #{const TMR_ERROR_NO_ANTENNA} = ERROR_NO_ANTENNA+toStatus #{const TMR_ERROR_READONLY} = ERROR_READONLY+toStatus #{const TMR_ERROR_TOO_BIG} = ERROR_TOO_BIG+toStatus #{const TMR_ERROR_NO_THREADS} = ERROR_NO_THREADS+toStatus #{const TMR_ERROR_NO_TAGS} = ERROR_NO_TAGS+toStatus #{const TMR_ERROR_NOT_FOUND} = ERROR_NOT_FOUND+toStatus #{const TMR_ERROR_FIRMWARE_FORMAT} = ERROR_FIRMWARE_FORMAT+toStatus #{const TMR_ERROR_TRYAGAIN} = ERROR_TRYAGAIN+toStatus #{const TMR_ERROR_OUT_OF_MEMORY} = ERROR_OUT_OF_MEMORY+toStatus #{const TMR_ERROR_INVALID_WRITE_MODE} = ERROR_INVALID_WRITE_MODE+toStatus #{const TMR_ERROR_ILLEGAL_VALUE} = ERROR_ILLEGAL_VALUE+toStatus #{const TMR_ERROR_END_OF_READING} = ERROR_END_OF_READING+toStatus #{const TMR_ERROR_UNSUPPORTED_READER_TYPE} = ERROR_UNSUPPORTED_READER_TYPE+toStatus #{const TMR_ERROR_BUFFER_OVERFLOW} = ERROR_BUFFER_OVERFLOW+toStatus #{const TMR_ERROR_LOADSAVE_CONFIG} = ERROR_LOADSAVE_CONFIG+toStatus #{const TMR_ERROR_AUTOREAD_ENABLED} = ERROR_AUTOREAD_ENABLED+toStatus #{const TMR_ERROR_FIRMWARE_UPDATE_ON_AUTOREAD} = ERROR_FIRMWARE_UPDATE_ON_AUTOREAD+toStatus #{const TMR_ERROR_TIMESTAMP_NULL} = ERROR_TIMESTAMP_NULL+toStatus #{const TMR_ERROR_LLRP_GETTYPEREGISTRY} = ERROR_LLRP_GETTYPEREGISTRY+toStatus #{const TMR_ERROR_LLRP_CONNECTIONFAILED} = ERROR_LLRP_CONNECTIONFAILED+toStatus #{const TMR_ERROR_LLRP_SENDIO_ERROR} = ERROR_LLRP_SENDIO_ERROR+toStatus #{const TMR_ERROR_LLRP_RECEIVEIO_ERROR} = ERROR_LLRP_RECEIVEIO_ERROR+toStatus #{const TMR_ERROR_LLRP_RECEIVE_TIMEOUT} = ERROR_LLRP_RECEIVE_TIMEOUT+toStatus #{const TMR_ERROR_LLRP_MSG_PARSE_ERROR} = ERROR_LLRP_MSG_PARSE_ERROR+toStatus #{const TMR_ERROR_LLRP_ALREADY_CONNECTED} = ERROR_LLRP_ALREADY_CONNECTED+toStatus #{const TMR_ERROR_LLRP_INVALID_RFMODE} = ERROR_LLRP_INVALID_RFMODE+toStatus #{const TMR_ERROR_LLRP_UNDEFINED_VALUE} = ERROR_LLRP_UNDEFINED_VALUE+toStatus #{const TMR_ERROR_LLRP_READER_ERROR} = ERROR_LLRP_READER_ERROR+toStatus #{const TMR_ERROR_LLRP_READER_CONNECTION_LOST} = ERROR_LLRP_READER_CONNECTION_LOST+toStatus #{const TMR_ERROR_LLRP_CLIENT_CONNECTION_EXISTS} = ERROR_LLRP_CLIENT_CONNECTION_EXISTS+toStatus #{const ERROR_ALREADY_DESTROYED} = ERROR_ALREADY_DESTROYED+toStatus x = ERROR_UNKNOWN x++type RawRegion = #{type TMR_Region}++-- | RFID regulatory regions+data Region =+    REGION_NONE -- ^ Unspecified region+  | REGION_NA -- ^ North America+  | REGION_EU -- ^ European Union+  | REGION_KR -- ^ Korea+  | REGION_IN -- ^ India+  | REGION_JP -- ^ Japan+  | REGION_PRC -- ^ People\'s Republic of China+  | REGION_EU2 -- ^ European Union 2+  | REGION_EU3 -- ^ European Union 3+  | REGION_KR2 -- ^ Korea 2+  | REGION_PRC2 -- ^ People\'s Republic of China(840MHZ)+  | REGION_AU -- ^ Australia+  | REGION_NZ -- ^ New Zealand !!EXPERIMENTAL!!+  | REGION_NA2 -- ^ Reduced FCC region+  | REGION_NA3 -- ^ 5MHZ FCC band+  | REGION_IS -- ^ Israel+  | REGION_OPEN -- ^ Open+  deriving (Eq, Ord, Show, Read, Bounded, Enum)++toRegion :: RawRegion -> Region+toRegion #{const TMR_REGION_NONE} = REGION_NONE+toRegion #{const TMR_REGION_NA} = REGION_NA+toRegion #{const TMR_REGION_EU} = REGION_EU+toRegion #{const TMR_REGION_KR} = REGION_KR+toRegion #{const TMR_REGION_IN} = REGION_IN+toRegion #{const TMR_REGION_JP} = REGION_JP+toRegion #{const TMR_REGION_PRC} = REGION_PRC+toRegion #{const TMR_REGION_EU2} = REGION_EU2+toRegion #{const TMR_REGION_EU3} = REGION_EU3+toRegion #{const TMR_REGION_KR2} = REGION_KR2+toRegion #{const TMR_REGION_PRC2} = REGION_PRC2+toRegion #{const TMR_REGION_AU} = REGION_AU+toRegion #{const TMR_REGION_NZ} = REGION_NZ+toRegion #{const TMR_REGION_NA2} = REGION_NA2+toRegion #{const TMR_REGION_NA3} = REGION_NA3+toRegion #{const TMR_REGION_IS} = REGION_IS+toRegion #{const TMR_REGION_OPEN} = REGION_OPEN+toRegion _ = REGION_NONE++fromRegion :: Region -> RawRegion+fromRegion REGION_NONE = #{const TMR_REGION_NONE}+fromRegion REGION_NA = #{const TMR_REGION_NA}+fromRegion REGION_EU = #{const TMR_REGION_EU}+fromRegion REGION_KR = #{const TMR_REGION_KR}+fromRegion REGION_IN = #{const TMR_REGION_IN}+fromRegion REGION_JP = #{const TMR_REGION_JP}+fromRegion REGION_PRC = #{const TMR_REGION_PRC}+fromRegion REGION_EU2 = #{const TMR_REGION_EU2}+fromRegion REGION_EU3 = #{const TMR_REGION_EU3}+fromRegion REGION_KR2 = #{const TMR_REGION_KR2}+fromRegion REGION_PRC2 = #{const TMR_REGION_PRC2}+fromRegion REGION_AU = #{const TMR_REGION_AU}+fromRegion REGION_NZ = #{const TMR_REGION_NZ}+fromRegion REGION_NA2 = #{const TMR_REGION_NA2}+fromRegion REGION_NA3 = #{const TMR_REGION_NA3}+fromRegion REGION_IS = #{const TMR_REGION_IS}+fromRegion REGION_OPEN = #{const TMR_REGION_OPEN}++-- | A description of the given region, useful for a user interface.+displayRegionDescription :: Region -> Text+displayRegionDescription REGION_NONE = "Unspecified region"+displayRegionDescription REGION_NA = "North America"+displayRegionDescription REGION_EU = "European Union"+displayRegionDescription REGION_KR = "Korea"+displayRegionDescription REGION_IN = "India"+displayRegionDescription REGION_JP = "Japan"+displayRegionDescription REGION_PRC = "People's Republic of China"+displayRegionDescription REGION_EU2 = "European Union 2"+displayRegionDescription REGION_EU3 = "European Union 3"+displayRegionDescription REGION_KR2 = "Korea 2"+displayRegionDescription REGION_PRC2 = "People's Republic of China(840MHZ)"+displayRegionDescription REGION_AU = "Australia"+displayRegionDescription REGION_NZ = "New Zealand !!EXPERIMENTAL!!"+displayRegionDescription REGION_NA2 = "Reduced FCC region"+displayRegionDescription REGION_NA3 = "5MHZ FCC band"+displayRegionDescription REGION_IS = "Israel"+displayRegionDescription REGION_OPEN = "Open"++type RawTagProtocol = #{type TMR_TagProtocol}++-- | The protocol used by an RFID tag.  Only 'TAG_PROTOCOL_GEN2'+-- is supported by the M6e Nano, and therefore the Haskell+-- binding currently only supports that protocol.+data TagProtocol =+    TAG_PROTOCOL_NONE+  | TAG_PROTOCOL_ISO180006B+  | TAG_PROTOCOL_GEN2+  | TAG_PROTOCOL_ISO180006B_UCODE+  | TAG_PROTOCOL_IPX64+  | TAG_PROTOCOL_IPX256+  | TAG_PROTOCOL_ATA+  deriving (Eq, Ord, Show, Read, Bounded, Enum)++toTagProtocol :: RawTagProtocol -> TagProtocol+toTagProtocol #{const TMR_TAG_PROTOCOL_NONE} = TAG_PROTOCOL_NONE+toTagProtocol #{const TMR_TAG_PROTOCOL_ISO180006B} = TAG_PROTOCOL_ISO180006B+toTagProtocol #{const TMR_TAG_PROTOCOL_GEN2} = TAG_PROTOCOL_GEN2+toTagProtocol #{const TMR_TAG_PROTOCOL_ISO180006B_UCODE} = TAG_PROTOCOL_ISO180006B_UCODE+toTagProtocol #{const TMR_TAG_PROTOCOL_IPX64} = TAG_PROTOCOL_IPX64+toTagProtocol #{const TMR_TAG_PROTOCOL_IPX256} = TAG_PROTOCOL_IPX256+toTagProtocol #{const TMR_TAG_PROTOCOL_ATA} = TAG_PROTOCOL_ATA+toTagProtocol _ = TAG_PROTOCOL_NONE++fromTagProtocol :: TagProtocol -> RawTagProtocol+fromTagProtocol TAG_PROTOCOL_NONE = #{const TMR_TAG_PROTOCOL_NONE}+fromTagProtocol TAG_PROTOCOL_ISO180006B = #{const TMR_TAG_PROTOCOL_ISO180006B}+fromTagProtocol TAG_PROTOCOL_GEN2 = #{const TMR_TAG_PROTOCOL_GEN2}+fromTagProtocol TAG_PROTOCOL_ISO180006B_UCODE = #{const TMR_TAG_PROTOCOL_ISO180006B_UCODE}+fromTagProtocol TAG_PROTOCOL_IPX64 = #{const TMR_TAG_PROTOCOL_IPX64}+fromTagProtocol TAG_PROTOCOL_IPX256 = #{const TMR_TAG_PROTOCOL_IPX256}+fromTagProtocol TAG_PROTOCOL_ATA = #{const TMR_TAG_PROTOCOL_ATA}++type RawMetadataFlag = #{type TMR_TRD_MetadataFlag}++-- | Various metadata parameters which can be requested+-- in 'PARAM_METADATAFLAG'.+data MetadataFlag =+    METADATA_FLAG_READCOUNT+  | METADATA_FLAG_RSSI+  | METADATA_FLAG_ANTENNAID+  | METADATA_FLAG_FREQUENCY+  | METADATA_FLAG_TIMESTAMP+  | METADATA_FLAG_PHASE+  | METADATA_FLAG_PROTOCOL+  | METADATA_FLAG_DATA+  | METADATA_FLAG_GPIO_STATUS+  deriving (Eq, Ord, Show, Read, Bounded, Enum)++fromMetadataFlag :: MetadataFlag -> RawMetadataFlag+fromMetadataFlag METADATA_FLAG_READCOUNT = #{const TMR_TRD_METADATA_FLAG_READCOUNT}+fromMetadataFlag METADATA_FLAG_RSSI = #{const TMR_TRD_METADATA_FLAG_RSSI}+fromMetadataFlag METADATA_FLAG_ANTENNAID = #{const TMR_TRD_METADATA_FLAG_ANTENNAID}+fromMetadataFlag METADATA_FLAG_FREQUENCY = #{const TMR_TRD_METADATA_FLAG_FREQUENCY}+fromMetadataFlag METADATA_FLAG_TIMESTAMP = #{const TMR_TRD_METADATA_FLAG_TIMESTAMP}+fromMetadataFlag METADATA_FLAG_PHASE = #{const TMR_TRD_METADATA_FLAG_PHASE}+fromMetadataFlag METADATA_FLAG_PROTOCOL = #{const TMR_TRD_METADATA_FLAG_PROTOCOL}+fromMetadataFlag METADATA_FLAG_DATA = #{const TMR_TRD_METADATA_FLAG_DATA}+fromMetadataFlag METADATA_FLAG_GPIO_STATUS = #{const TMR_TRD_METADATA_FLAG_GPIO_STATUS}++type RawBank = #{type TMR_GEN2_Bank}++-- | Gen2 memory banks+data GEN2_Bank =+    GEN2_BANK_RESERVED -- ^ Reserved bank (kill and access passwords)+  | GEN2_BANK_EPC -- ^ EPC memory bank+  | GEN2_BANK_TID -- ^ TID memory bank+  | GEN2_BANK_USER -- ^ User memory bank+  deriving (Eq, Ord, Show, Read, Bounded, Enum)++fromBank :: GEN2_Bank -> RawBank+fromBank GEN2_BANK_RESERVED = #{const TMR_GEN2_BANK_RESERVED}+fromBank GEN2_BANK_EPC = #{const TMR_GEN2_BANK_EPC}+fromBank GEN2_BANK_TID = #{const TMR_GEN2_BANK_TID}+fromBank GEN2_BANK_USER = #{const TMR_GEN2_BANK_USER}++toBank :: RawBank -> GEN2_Bank+toBank #{const TMR_GEN2_BANK_RESERVED} = GEN2_BANK_RESERVED+toBank #{const TMR_GEN2_BANK_EPC} = GEN2_BANK_EPC+toBank #{const TMR_GEN2_BANK_TID} = GEN2_BANK_TID+toBank #{const TMR_GEN2_BANK_USER} = GEN2_BANK_USER+toBank x = error $ "didn't expect bank to be " ++ show x++fromExtraBank :: GEN2_Bank -> RawBank+fromExtraBank GEN2_BANK_RESERVED = #{const TMR_GEN2_BANK_RESERVED_ENABLED}+fromExtraBank GEN2_BANK_EPC = #{const TMR_GEN2_BANK_EPC_ENABLED}+fromExtraBank GEN2_BANK_TID = #{const TMR_GEN2_BANK_TID_ENABLED}+fromExtraBank GEN2_BANK_USER = #{const TMR_GEN2_BANK_USER_ENABLED}++type RawLockBits = #{type TMR_GEN2_LockBits}++-- | Memory lock bits+data GEN2_LockBits =+    GEN2_LOCK_BITS_USER_PERM -- ^ User memory bank lock permalock bit+  | GEN2_LOCK_BITS_USER -- ^ User memory bank lock bit+  | GEN2_LOCK_BITS_TID_PERM -- ^ TID memory bank lock permalock bit+  | GEN2_LOCK_BITS_TID -- ^ TID memory bank lock bit+  | GEN2_LOCK_BITS_EPC_PERM -- ^ EPC memory bank lock permalock bit+  | GEN2_LOCK_BITS_EPC -- ^ EPC memory bank lock bit+  | GEN2_LOCK_BITS_ACCESS_PERM -- ^ Access password lock permalock bit+  | GEN2_LOCK_BITS_ACCESS -- ^ Access password lock bit+  | GEN2_LOCK_BITS_KILL_PERM -- ^ Kill password lock permalock bit+  | GEN2_LOCK_BITS_KILL -- ^ Kill password lock bit+  deriving (Eq, Ord, Show, Read, Bounded, Enum)++fromLockBits :: GEN2_LockBits -> RawLockBits+fromLockBits GEN2_LOCK_BITS_USER_PERM = #{const TMR_GEN2_LOCK_BITS_USER_PERM}+fromLockBits GEN2_LOCK_BITS_USER = #{const TMR_GEN2_LOCK_BITS_USER}+fromLockBits GEN2_LOCK_BITS_TID_PERM = #{const TMR_GEN2_LOCK_BITS_TID_PERM}+fromLockBits GEN2_LOCK_BITS_TID = #{const TMR_GEN2_LOCK_BITS_TID}+fromLockBits GEN2_LOCK_BITS_EPC_PERM = #{const TMR_GEN2_LOCK_BITS_EPC_PERM}+fromLockBits GEN2_LOCK_BITS_EPC = #{const TMR_GEN2_LOCK_BITS_EPC}+fromLockBits GEN2_LOCK_BITS_ACCESS_PERM = #{const TMR_GEN2_LOCK_BITS_ACCESS_PERM}+fromLockBits GEN2_LOCK_BITS_ACCESS = #{const TMR_GEN2_LOCK_BITS_ACCESS}+fromLockBits GEN2_LOCK_BITS_KILL_PERM = #{const TMR_GEN2_LOCK_BITS_KILL_PERM}+fromLockBits GEN2_LOCK_BITS_KILL = #{const TMR_GEN2_LOCK_BITS_KILL}++opcodeName :: Word8 -> Text+opcodeName #{const TMR_SR_OPCODE_WRITE_FLASH} = "WRITE_FLASH"+opcodeName #{const TMR_SR_OPCODE_READ_FLASH} = "READ_FLASH"+opcodeName #{const TMR_SR_OPCODE_VERSION} = "VERSION"+opcodeName #{const TMR_SR_OPCODE_BOOT_FIRMWARE} = "BOOT_FIRMWARE"+opcodeName #{const TMR_SR_OPCODE_SET_BAUD_RATE} = "SET_BAUD_RATE"+opcodeName #{const TMR_SR_OPCODE_ERASE_FLASH} = "ERASE_FLASH"+opcodeName #{const TMR_SR_OPCODE_VERIFY_IMAGE_CRC} = "VERIFY_IMAGE_CRC"+opcodeName #{const TMR_SR_OPCODE_BOOT_BOOTLOADER} = "BOOT_BOOTLOADER"+opcodeName #{const TMR_SR_OPCODE_HW_VERSION} = "HW_VERSION"+opcodeName #{const TMR_SR_OPCODE_MODIFY_FLASH} = "MODIFY_FLASH"+opcodeName #{const TMR_SR_OPCODE_GET_DSP_SILICON_ID} = "GET_DSP_SILICON_ID"+opcodeName #{const TMR_SR_OPCODE_GET_CURRENT_PROGRAM} = "GET_CURRENT_PROGRAM"+opcodeName #{const TMR_SR_OPCODE_WRITE_FLASH_SECTOR} = "WRITE_FLASH_SECTOR"+opcodeName #{const TMR_SR_OPCODE_GET_SECTOR_SIZE} = "GET_SECTOR_SIZE"+opcodeName #{const TMR_SR_OPCODE_MODIFY_FLASH_SECTOR} = "MODIFY_FLASH_SECTOR"+opcodeName #{const TMR_SR_OPCODE_READ_TAG_ID_SINGLE} = "READ_TAG_ID_SINGLE"+opcodeName #{const TMR_SR_OPCODE_READ_TAG_ID_MULTIPLE} = "READ_TAG_ID_MULTIPLE"+opcodeName #{const TMR_SR_OPCODE_WRITE_TAG_ID} = "WRITE_TAG_ID"+opcodeName #{const TMR_SR_OPCODE_WRITE_TAG_DATA} = "WRITE_TAG_DATA"+opcodeName #{const TMR_SR_OPCODE_LOCK_TAG} = "LOCK_TAG"+opcodeName #{const TMR_SR_OPCODE_KILL_TAG} = "KILL_TAG"+opcodeName #{const TMR_SR_OPCODE_READ_TAG_DATA} = "READ_TAG_DATA"+opcodeName #{const TMR_SR_OPCODE_GET_TAG_ID_BUFFER} = "GET_TAG_ID_BUFFER"+opcodeName #{const TMR_SR_OPCODE_CLEAR_TAG_ID_BUFFER} = "CLEAR_TAG_ID_BUFFER"+opcodeName #{const TMR_SR_OPCODE_WRITE_TAG_SPECIFIC} = "WRITE_TAG_SPECIFIC"+opcodeName #{const TMR_SR_OPCODE_ERASE_BLOCK_TAG_SPECIFIC} = "ERASE_BLOCK_TAG_SPECIFIC"+opcodeName #{const TMR_SR_OPCODE_MULTI_PROTOCOL_TAG_OP} = "MULTI_PROTOCOL_TAG_OP"+opcodeName #{const TMR_SR_OPCODE_GET_ANTENNA_PORT} = "GET_ANTENNA_PORT"+opcodeName #{const TMR_SR_OPCODE_GET_READ_TX_POWER} = "GET_READ_TX_POWER"+opcodeName #{const TMR_SR_OPCODE_GET_TAG_PROTOCOL} = "GET_TAG_PROTOCOL"+opcodeName #{const TMR_SR_OPCODE_GET_WRITE_TX_POWER} = "GET_WRITE_TX_POWER"+opcodeName #{const TMR_SR_OPCODE_GET_FREQ_HOP_TABLE} = "GET_FREQ_HOP_TABLE"+opcodeName #{const TMR_SR_OPCODE_GET_USER_GPIO_INPUTS} = "GET_USER_GPIO_INPUTS"+opcodeName #{const TMR_SR_OPCODE_GET_REGION} = "GET_REGION"+opcodeName #{const TMR_SR_OPCODE_GET_POWER_MODE} = "GET_POWER_MODE"+opcodeName #{const TMR_SR_OPCODE_GET_USER_MODE} = "GET_USER_MODE"+opcodeName #{const TMR_SR_OPCODE_GET_READER_OPTIONAL_PARAMS} = "GET_READER_OPTIONAL_PARAMS"+opcodeName #{const TMR_SR_OPCODE_GET_PROTOCOL_PARAM} = "GET_PROTOCOL_PARAM"+opcodeName #{const TMR_SR_OPCODE_GET_READER_STATS} = "GET_READER_STATS"+opcodeName #{const TMR_SR_OPCODE_GET_USER_PROFILE} = "GET_USER_PROFILE"+opcodeName #{const TMR_SR_OPCODE_GET_AVAILABLE_PROTOCOLS} = "GET_AVAILABLE_PROTOCOLS"+opcodeName #{const TMR_SR_OPCODE_GET_AVAILABLE_REGIONS} = "GET_AVAILABLE_REGIONS"+opcodeName #{const TMR_SR_OPCODE_GET_TEMPERATURE} = "GET_TEMPERATURE"+opcodeName #{const TMR_SR_OPCODE_SET_ANTENNA_PORT} = "SET_ANTENNA_PORT"+opcodeName #{const TMR_SR_OPCODE_SET_READ_TX_POWER} = "SET_READ_TX_POWER"+opcodeName #{const TMR_SR_OPCODE_SET_TAG_PROTOCOL} = "SET_TAG_PROTOCOL"+opcodeName #{const TMR_SR_OPCODE_SET_WRITE_TX_POWER} = "SET_WRITE_TX_POWER"+opcodeName #{const TMR_SR_OPCODE_SET_FREQ_HOP_TABLE} = "SET_FREQ_HOP_TABLE"+opcodeName #{const TMR_SR_OPCODE_SET_USER_GPIO_OUTPUTS} = "SET_USER_GPIO_OUTPUTS"+opcodeName #{const TMR_SR_OPCODE_SET_REGION} = "SET_REGION"+opcodeName #{const TMR_SR_OPCODE_SET_POWER_MODE} = "SET_POWER_MODE"+opcodeName #{const TMR_SR_OPCODE_SET_USER_MODE} = "SET_USER_MODE"+opcodeName #{const TMR_SR_OPCODE_SET_READER_OPTIONAL_PARAMS} = "SET_READER_OPTIONAL_PARAMS"+opcodeName #{const TMR_SR_OPCODE_SET_PROTOCOL_PARAM} = "SET_PROTOCOL_PARAM"+opcodeName #{const TMR_SR_OPCODE_SET_USER_PROFILE} = "SET_USER_PROFILE"+opcodeName #{const TMR_SR_OPCODE_SET_PROTOCOL_LICENSEKEY} = "SET_PROTOCOL_LICENSEKEY"+opcodeName #{const TMR_SR_OPCODE_SET_OPERATING_FREQ} = "SET_OPERATING_FREQ"+opcodeName #{const TMR_SR_OPCODE_TX_CW_SIGNAL} = "TX_CW_SIGNAL"+opcodeName x = "Unknown opcode " <> T.pack (printf "0x%02X" x)++type RawWriteMode = #{type TMR_GEN2_WriteMode}++-- | Whether to use word write or block write for+-- 'System.Hardware.MercuryApi.TagOp_GEN2_WriteData'.+data GEN2_WriteMode =+    GEN2_WORD_ONLY+  | GEN2_BLOCK_ONLY+  | GEN2_BLOCK_FALLBACK+  deriving (Eq, Ord, Show, Read, Bounded, Enum)++fromWriteMode :: GEN2_WriteMode -> RawWriteMode+fromWriteMode GEN2_WORD_ONLY = #{const TMR_GEN2_WORD_ONLY}+fromWriteMode GEN2_BLOCK_ONLY = #{const TMR_GEN2_BLOCK_ONLY}+fromWriteMode GEN2_BLOCK_FALLBACK = #{const TMR_GEN2_BLOCK_FALLBACK}++toWriteMode :: RawWriteMode -> GEN2_WriteMode+toWriteMode #{const TMR_GEN2_WORD_ONLY} = GEN2_WORD_ONLY+toWriteMode #{const TMR_GEN2_BLOCK_ONLY} = GEN2_BLOCK_ONLY+toWriteMode #{const TMR_GEN2_BLOCK_FALLBACK} = GEN2_BLOCK_FALLBACK+toWriteMode x = error $ "didn't expect WriteMode to be " ++ show x++type RawPowerMode = #{type TMR_SR_PowerMode}++-- | Value for parameter 'PARAM_POWERMODE'.  On the M6e Nano,+-- 'POWER_MODE_MINSAVE', 'POWER_MODE_MEDSAVE', and+-- 'POWER_MODE_MAXSAVE' are all the same.+data PowerMode =+    POWER_MODE_FULL+  | POWER_MODE_MINSAVE+  | POWER_MODE_MEDSAVE+  | POWER_MODE_MAXSAVE+  | POWER_MODE_SLEEP+  deriving (Eq, Ord, Show, Read, Bounded, Enum)++fromPowerMode :: PowerMode -> RawPowerMode+fromPowerMode POWER_MODE_FULL = #{const TMR_SR_POWER_MODE_FULL}+fromPowerMode POWER_MODE_MINSAVE = #{const TMR_SR_POWER_MODE_MINSAVE}+fromPowerMode POWER_MODE_MEDSAVE = #{const TMR_SR_POWER_MODE_MEDSAVE}+fromPowerMode POWER_MODE_MAXSAVE = #{const TMR_SR_POWER_MODE_MAXSAVE}+fromPowerMode POWER_MODE_SLEEP = #{const TMR_SR_POWER_MODE_SLEEP}++toPowerMode :: RawPowerMode -> PowerMode+toPowerMode #{const TMR_SR_POWER_MODE_FULL} = POWER_MODE_FULL+toPowerMode #{const TMR_SR_POWER_MODE_MINSAVE} = POWER_MODE_MINSAVE+toPowerMode #{const TMR_SR_POWER_MODE_MEDSAVE} = POWER_MODE_MEDSAVE+toPowerMode #{const TMR_SR_POWER_MODE_MAXSAVE} = POWER_MODE_MAXSAVE+toPowerMode #{const TMR_SR_POWER_MODE_SLEEP} = POWER_MODE_SLEEP+toPowerMode x = error $ "didn't expect PowerMode to be " ++ show x++type RawParam = #{type TMR_Param}++-- | Reader parameters which you can get and set.  The names+-- are the same as the names of the enum in the C API.+-- (Unfortunately, these do not correspond to the+-- \"path\"-style names in any systematic way.)+-- Each parameter is listed with its \"path\", and the+-- Haskell type which is used to store it.  Some parameters+-- are also listed with the physical units the parameter+-- is in.  Not all parameters are implemented in the Haskell+-- binding.  Please file a Github issue if there is a parameter+-- you need which is not implemented.+data Param =+    PARAM_NONE -- ^ No such parameter - used as a return value from 'System.Hardware.MercuryApi.paramID'.+  | PARAM_BAUDRATE -- ^ @\/reader\/baudRate@ 'Word32'+  | PARAM_COMMANDTIMEOUT -- ^ @\/reader\/commandTimeout@ 'Word32' (milliseconds)+  | PARAM_CURRENTTIME -- ^ @\/reader\/currentTime@ (Not yet implemented)+  | PARAM_READER_DESCRIPTION -- ^ @\/reader\/description@ 'Text'+  | PARAM_EXTENDEDEPC -- ^ @\/reader\/extendedEpc@ 'Bool'+  | PARAM_READER_HOSTNAME -- ^ @\/reader\/hostname@ 'Text'+  | PARAM_LICENSE_KEY -- ^ @\/reader\/licenseKey@ ['Word8']+  | PARAM_LICENSED_FEATURES -- ^ @\/reader\/licensedFeatures@ ['Word8']+  | PARAM_METADATAFLAG -- ^ @\/reader\/metadataflags@ ['MetadataFlag']+  | PARAM_POWERMODE -- ^ @\/reader\/powerMode@ 'PowerMode'+  | PARAM_PROBEBAUDRATES -- ^ @\/reader\/probeBaudRates@ ['Word32']+  | PARAM_READER_STATISTICS -- ^ @\/reader\/statistics@ (Not yet implemented)+  | PARAM_READER_STATS -- ^ @\/reader\/stats@ (Not yet implemented)+  | PARAM_TRANSPORTTIMEOUT -- ^ @\/reader\/transportTimeout@ 'Word32' (milliseconds)+  | PARAM_URI -- ^ @\/reader\/uri@ 'Text' (read-only)+  | PARAM_USER_CONFIG -- ^ @\/reader\/userConfig@ (Not yet implemented)+  | PARAM_USERMODE -- ^ @\/reader\/userMode@ (Not yet implemented)+  | PARAM_ANTENNA_CHECKPORT -- ^ @\/reader\/antenna\/checkPort@ 'Bool'+  | PARAM_ANTENNA_CONNECTEDPORTLIST -- ^ @\/reader\/antenna\/connectedPortList@ ['Word8'], or typedef ['System.Hardware.MercuryApi.AntennaPort'] (read-only)+  | PARAM_ANTENNA_PORTLIST -- ^ @\/reader\/antenna\/portList@ ['Word8'], or typedef ['System.Hardware.MercuryApi.AntennaPort'] (read-only)+  | PARAM_ANTENNA_PORTSWITCHGPOS -- ^ @\/reader\/antenna\/portSwitchGpos@ ['Word8'], or typedef ['System.Hardware.MercuryApi.PinNumber']+  | PARAM_ANTENNA_RETURNLOSS -- ^ @\/reader\/antenna\/returnLoss@ (Not yet implemented)+  | PARAM_ANTENNA_SETTLINGTIMELIST -- ^ @\/reader\/antenna\/settlingTimeList@ (Not yet implemented)+  | PARAM_ANTENNA_TXRXMAP -- ^ @\/reader\/antenna\/txRxMap@ (Not yet implemented)+  | PARAM_GEN2_BLF -- ^ @\/reader\/gen2\/BLF@ (Not yet implemented)+  | PARAM_GEN2_ACCESSPASSWORD -- ^ @\/reader\/gen2\/accessPassword@ 'Word32', or typedef 'System.Hardware.MercuryApi.GEN2_Password'+  | PARAM_GEN2_BAP -- ^ @\/reader\/gen2\/bap@ (Not yet implemented)+  | PARAM_GEN2_PROTOCOLEXTENSION -- ^ @\/reader\/gen2\/protocolExtension@ (Not yet implemented)+  | PARAM_GEN2_Q -- ^ @\/reader\/gen2\/q@ (Not yet implemented)+  | PARAM_GEN2_SESSION -- ^ @\/reader\/gen2\/session@ (Not yet implemented)+  | PARAM_GEN2_TAGENCODING -- ^ @\/reader\/gen2\/tagEncoding@ (Not yet implemented)+  | PARAM_GEN2_TARGET -- ^ @\/reader\/gen2\/target@ (Not yet implemented)+  | PARAM_GEN2_TARI -- ^ @\/reader\/gen2\/tari@ (Not yet implemented)+  | PARAM_READER_WRITE_EARLY_EXIT -- ^ @\/reader\/gen2\/writeEarlyExit@ 'Bool'+  | PARAM_GEN2_WRITEMODE -- ^ @\/reader\/gen2\/writeMode@ 'GEN2_WriteMode'+  | PARAM_READER_WRITE_REPLY_TIMEOUT -- ^ @\/reader\/gen2\/writeReplyTimeout@ 'Word16' (microseconds)+  | PARAM_GPIO_INPUTLIST -- ^ @\/reader\/gpio\/inputList@ ['Word8'], or typedef ['System.Hardware.MercuryApi.PinNumber']+  | PARAM_GPIO_OUTPUTLIST -- ^ @\/reader\/gpio\/outputList@ ['Word8'], or typedef ['System.Hardware.MercuryApi.PinNumber']+  | PARAM_ISO180006B_BLF -- ^ @\/reader\/iso180006b\/BLF@ (Not yet implemented)+  | PARAM_ISO180006B_DELIMITER -- ^ @\/reader\/iso180006b\/delimiter@ (Not yet implemented)+  | PARAM_ISO180006B_MODULATION_DEPTH -- ^ @\/reader\/iso180006b\/modulationDepth@ (Not yet implemented)+  | PARAM_RADIO_ENABLEPOWERSAVE -- ^ @\/reader\/radio\/enablePowerSave@ 'Bool'+  | PARAM_RADIO_ENABLESJC -- ^ @\/reader\/radio\/enableSJC@ 'Bool'+  | PARAM_RADIO_PORTREADPOWERLIST -- ^ @\/reader\/radio\/portReadPowerList@ (Not yet implemented)+  | PARAM_RADIO_PORTWRITEPOWERLIST -- ^ @\/reader\/radio\/portWritePowerList@ (Not yet implemented)+  | PARAM_RADIO_POWERMAX -- ^ @\/reader\/radio\/powerMax@ 'Int16' (centi-dBm, read-only)+  | PARAM_RADIO_POWERMIN -- ^ @\/reader\/radio\/powerMin@ 'Int16' (centi-dBm, read-only)+  | PARAM_RADIO_READPOWER -- ^ @\/reader\/radio\/readPower@ 'Int32' (centi-dBm)+  | PARAM_RADIO_TEMPERATURE -- ^ @\/reader\/radio\/temperature@ 'Int8' (degrees C, read-only)+  | PARAM_RADIO_WRITEPOWER -- ^ @\/reader\/radio\/writePower@ 'Int32' (centi-dBm)+  | PARAM_READ_ASYNCOFFTIME -- ^ @\/reader\/read\/asyncOffTime@ 'Word32' (milliseconds)+  | PARAM_READ_ASYNCONTIME -- ^ @\/reader\/read\/asyncOnTime@ 'Word32' (milliseconds)+  | PARAM_READ_PLAN -- ^ @\/reader\/read\/plan@ 'System.Hardware.MercuryApi.ReadPlan'+  | PARAM_REGION_HOPTABLE -- ^ @\/reader\/region\/hopTable@ ['Word32'] (kHz)+  | PARAM_REGION_HOPTIME -- ^ @\/reader\/region\/hopTime@ 'Word32' (milliseconds)+  | PARAM_REGION_ID -- ^ @\/reader\/region\/id@ 'Region'+  | PARAM_REGION_SUPPORTEDREGIONS -- ^ @\/reader\/region\/supportedRegions@ ['Region'] (read-only)+  | PARAM_REGION_LBT_ENABLE -- ^ @\/reader\/region\/lbt\/enable@ 'Bool'+  | PARAM_READER_STATS_ENABLE -- ^ @\/reader\/stats\/enable@ (Not yet implemented)+  | PARAM_STATUS_ENABLE_ANTENNAREPORT -- ^ @\/reader\/status\/antennaEnable@ 'Bool'+  | PARAM_STATUS_ENABLE_FREQUENCYREPORT -- ^ @\/reader\/status\/frequencyEnable@ 'Bool'+  | PARAM_STATUS_ENABLE_TEMPERATUREREPORT -- ^ @\/reader\/status\/temperatureEnable@ 'Bool'+  | PARAM_TAGREADDATA_ENABLEREADFILTER -- ^ @\/reader\/tagReadData\/enableReadFilter@ 'Bool'+  | PARAM_TAGREADDATA_READFILTERTIMEOUT -- ^ @\/reader\/tagReadData\/readFilterTimeout@ 'Int32'+  | PARAM_TAGREADDATA_RECORDHIGHESTRSSI -- ^ @\/reader\/tagReadData\/recordHighestRssi@ 'Bool'+  | PARAM_TAGREADDATA_REPORTRSSIINDBM -- ^ @\/reader\/tagReadData\/reportRssiInDbm@ 'Bool'+  | PARAM_TAGREADATA_TAGOPFAILURECOUNT -- ^ @\/reader\/tagReadData\/tagopFailures@ 'Word16' (read-only)+  | PARAM_TAGREADATA_TAGOPSUCCESSCOUNT -- ^ @\/reader\/tagReadData\/tagopSuccesses@ 'Word16' (read-only)+  | PARAM_TAGREADDATA_UNIQUEBYANTENNA -- ^ @\/reader\/tagReadData\/uniqueByAntenna@ 'Bool'+  | PARAM_TAGREADDATA_UNIQUEBYDATA -- ^ @\/reader\/tagReadData\/uniqueByData@ 'Bool'+  | PARAM_TAGREADDATA_UNIQUEBYPROTOCOL -- ^ @\/reader\/tagReadData\/uniqueByProtocol@ 'Bool'+  | PARAM_TAGOP_ANTENNA -- ^ @\/reader\/tagop\/antenna@ 'Word8', or typedef 'System.Hardware.MercuryApi.AntennaPort'+  | PARAM_TAGOP_PROTOCOL -- ^ @\/reader\/tagop\/protocol@ 'TagProtocol'+  | PARAM_TRIGGER_READ_GPI -- ^ @\/reader\/trigger\/read\/Gpi@ ['Word8'], or typedef ['System.Hardware.MercuryApi.PinNumber']+  | PARAM_VERSION_HARDWARE -- ^ @\/reader\/version\/hardware@ 'Text' (read-only)+  | PARAM_VERSION_MODEL -- ^ @\/reader\/version\/model@ 'Text' (read-only)+  | PARAM_PRODUCT_GROUP -- ^ @\/reader\/version\/productGroup@ 'Text' (read-only)+  | PARAM_PRODUCT_GROUP_ID -- ^ @\/reader\/version\/productGroupID@ 'Word16' (read-only)+  | PARAM_PRODUCT_ID -- ^ @\/reader\/version\/productID@ 'Word16' (read-only)+  | PARAM_VERSION_SERIAL -- ^ @\/reader\/version\/serial@ 'Text'+  | PARAM_VERSION_SOFTWARE -- ^ @\/reader\/version\/software@ 'Text' (read-only)+  | PARAM_VERSION_SUPPORTEDPROTOCOLS -- ^ @\/reader\/version\/supportedProtocols@ ['TagProtocol'] (read-only)+  | PARAM_SELECTED_PROTOCOLS+  deriving (Eq, Ord, Show, Read, Bounded, Enum)++instance Hashable Param where+  hash = fromEnum+  salt `hashWithSalt` p = salt `hashWithSalt` fromEnum p++toParam :: RawParam -> Param+toParam #{const TMR_PARAM_NONE} = PARAM_NONE+toParam #{const TMR_PARAM_BAUDRATE} = PARAM_BAUDRATE+toParam #{const TMR_PARAM_PROBEBAUDRATES} = PARAM_PROBEBAUDRATES+toParam #{const TMR_PARAM_COMMANDTIMEOUT} = PARAM_COMMANDTIMEOUT+toParam #{const TMR_PARAM_TRANSPORTTIMEOUT} = PARAM_TRANSPORTTIMEOUT+toParam #{const TMR_PARAM_POWERMODE} = PARAM_POWERMODE+toParam #{const TMR_PARAM_USERMODE} = PARAM_USERMODE+toParam #{const TMR_PARAM_ANTENNA_CHECKPORT} = PARAM_ANTENNA_CHECKPORT+toParam #{const TMR_PARAM_ANTENNA_PORTLIST} = PARAM_ANTENNA_PORTLIST+toParam #{const TMR_PARAM_ANTENNA_CONNECTEDPORTLIST} = PARAM_ANTENNA_CONNECTEDPORTLIST+toParam #{const TMR_PARAM_ANTENNA_PORTSWITCHGPOS} = PARAM_ANTENNA_PORTSWITCHGPOS+toParam #{const TMR_PARAM_ANTENNA_SETTLINGTIMELIST} = PARAM_ANTENNA_SETTLINGTIMELIST+toParam #{const TMR_PARAM_ANTENNA_RETURNLOSS} = PARAM_ANTENNA_RETURNLOSS+toParam #{const TMR_PARAM_ANTENNA_TXRXMAP} = PARAM_ANTENNA_TXRXMAP+toParam #{const TMR_PARAM_GPIO_INPUTLIST} = PARAM_GPIO_INPUTLIST+toParam #{const TMR_PARAM_GPIO_OUTPUTLIST} = PARAM_GPIO_OUTPUTLIST+toParam #{const TMR_PARAM_GEN2_ACCESSPASSWORD} = PARAM_GEN2_ACCESSPASSWORD+toParam #{const TMR_PARAM_GEN2_Q} = PARAM_GEN2_Q+toParam #{const TMR_PARAM_GEN2_TAGENCODING} = PARAM_GEN2_TAGENCODING+toParam #{const TMR_PARAM_GEN2_SESSION} = PARAM_GEN2_SESSION+toParam #{const TMR_PARAM_GEN2_TARGET} = PARAM_GEN2_TARGET+toParam #{const TMR_PARAM_GEN2_BLF} = PARAM_GEN2_BLF+toParam #{const TMR_PARAM_GEN2_TARI} = PARAM_GEN2_TARI+toParam #{const TMR_PARAM_GEN2_WRITEMODE} = PARAM_GEN2_WRITEMODE+toParam #{const TMR_PARAM_GEN2_BAP} = PARAM_GEN2_BAP+toParam #{const TMR_PARAM_GEN2_PROTOCOLEXTENSION} = PARAM_GEN2_PROTOCOLEXTENSION+toParam #{const TMR_PARAM_ISO180006B_BLF} = PARAM_ISO180006B_BLF+toParam #{const TMR_PARAM_ISO180006B_MODULATION_DEPTH} = PARAM_ISO180006B_MODULATION_DEPTH+toParam #{const TMR_PARAM_ISO180006B_DELIMITER} = PARAM_ISO180006B_DELIMITER+toParam #{const TMR_PARAM_READ_ASYNCOFFTIME} = PARAM_READ_ASYNCOFFTIME+toParam #{const TMR_PARAM_READ_ASYNCONTIME} = PARAM_READ_ASYNCONTIME+toParam #{const TMR_PARAM_READ_PLAN} = PARAM_READ_PLAN+toParam #{const TMR_PARAM_RADIO_ENABLEPOWERSAVE} = PARAM_RADIO_ENABLEPOWERSAVE+toParam #{const TMR_PARAM_RADIO_POWERMAX} = PARAM_RADIO_POWERMAX+toParam #{const TMR_PARAM_RADIO_POWERMIN} = PARAM_RADIO_POWERMIN+toParam #{const TMR_PARAM_RADIO_PORTREADPOWERLIST} = PARAM_RADIO_PORTREADPOWERLIST+toParam #{const TMR_PARAM_RADIO_PORTWRITEPOWERLIST} = PARAM_RADIO_PORTWRITEPOWERLIST+toParam #{const TMR_PARAM_RADIO_READPOWER} = PARAM_RADIO_READPOWER+toParam #{const TMR_PARAM_RADIO_WRITEPOWER} = PARAM_RADIO_WRITEPOWER+toParam #{const TMR_PARAM_RADIO_TEMPERATURE} = PARAM_RADIO_TEMPERATURE+toParam #{const TMR_PARAM_TAGREADDATA_RECORDHIGHESTRSSI} = PARAM_TAGREADDATA_RECORDHIGHESTRSSI+toParam #{const TMR_PARAM_TAGREADDATA_REPORTRSSIINDBM} = PARAM_TAGREADDATA_REPORTRSSIINDBM+toParam #{const TMR_PARAM_TAGREADDATA_UNIQUEBYANTENNA} = PARAM_TAGREADDATA_UNIQUEBYANTENNA+toParam #{const TMR_PARAM_TAGREADDATA_UNIQUEBYDATA} = PARAM_TAGREADDATA_UNIQUEBYDATA+toParam #{const TMR_PARAM_TAGOP_ANTENNA} = PARAM_TAGOP_ANTENNA+toParam #{const TMR_PARAM_TAGOP_PROTOCOL} = PARAM_TAGOP_PROTOCOL+toParam #{const TMR_PARAM_VERSION_HARDWARE} = PARAM_VERSION_HARDWARE+toParam #{const TMR_PARAM_VERSION_SERIAL} = PARAM_VERSION_SERIAL+toParam #{const TMR_PARAM_VERSION_MODEL} = PARAM_VERSION_MODEL+toParam #{const TMR_PARAM_VERSION_SOFTWARE} = PARAM_VERSION_SOFTWARE+toParam #{const TMR_PARAM_VERSION_SUPPORTEDPROTOCOLS} = PARAM_VERSION_SUPPORTEDPROTOCOLS+toParam #{const TMR_PARAM_REGION_HOPTABLE} = PARAM_REGION_HOPTABLE+toParam #{const TMR_PARAM_REGION_HOPTIME} = PARAM_REGION_HOPTIME+toParam #{const TMR_PARAM_REGION_ID} = PARAM_REGION_ID+toParam #{const TMR_PARAM_REGION_SUPPORTEDREGIONS} = PARAM_REGION_SUPPORTEDREGIONS+toParam #{const TMR_PARAM_REGION_LBT_ENABLE} = PARAM_REGION_LBT_ENABLE+toParam #{const TMR_PARAM_LICENSE_KEY} = PARAM_LICENSE_KEY+toParam #{const TMR_PARAM_USER_CONFIG} = PARAM_USER_CONFIG+toParam #{const TMR_PARAM_RADIO_ENABLESJC} = PARAM_RADIO_ENABLESJC+toParam #{const TMR_PARAM_EXTENDEDEPC} = PARAM_EXTENDEDEPC+toParam #{const TMR_PARAM_READER_STATISTICS} = PARAM_READER_STATISTICS+toParam #{const TMR_PARAM_READER_STATS} = PARAM_READER_STATS+toParam #{const TMR_PARAM_URI} = PARAM_URI+toParam #{const TMR_PARAM_PRODUCT_GROUP_ID} = PARAM_PRODUCT_GROUP_ID+toParam #{const TMR_PARAM_PRODUCT_GROUP} = PARAM_PRODUCT_GROUP+toParam #{const TMR_PARAM_PRODUCT_ID} = PARAM_PRODUCT_ID+toParam #{const TMR_PARAM_TAGREADATA_TAGOPSUCCESSCOUNT} = PARAM_TAGREADATA_TAGOPSUCCESSCOUNT+toParam #{const TMR_PARAM_TAGREADATA_TAGOPFAILURECOUNT} = PARAM_TAGREADATA_TAGOPFAILURECOUNT+toParam #{const TMR_PARAM_STATUS_ENABLE_ANTENNAREPORT} = PARAM_STATUS_ENABLE_ANTENNAREPORT+toParam #{const TMR_PARAM_STATUS_ENABLE_FREQUENCYREPORT} = PARAM_STATUS_ENABLE_FREQUENCYREPORT+toParam #{const TMR_PARAM_STATUS_ENABLE_TEMPERATUREREPORT} = PARAM_STATUS_ENABLE_TEMPERATUREREPORT+toParam #{const TMR_PARAM_TAGREADDATA_ENABLEREADFILTER} = PARAM_TAGREADDATA_ENABLEREADFILTER+toParam #{const TMR_PARAM_TAGREADDATA_READFILTERTIMEOUT} = PARAM_TAGREADDATA_READFILTERTIMEOUT+toParam #{const TMR_PARAM_TAGREADDATA_UNIQUEBYPROTOCOL} = PARAM_TAGREADDATA_UNIQUEBYPROTOCOL+toParam #{const TMR_PARAM_READER_DESCRIPTION} = PARAM_READER_DESCRIPTION+toParam #{const TMR_PARAM_READER_HOSTNAME} = PARAM_READER_HOSTNAME+toParam #{const TMR_PARAM_CURRENTTIME} = PARAM_CURRENTTIME+toParam #{const TMR_PARAM_READER_WRITE_REPLY_TIMEOUT} = PARAM_READER_WRITE_REPLY_TIMEOUT+toParam #{const TMR_PARAM_READER_WRITE_EARLY_EXIT} = PARAM_READER_WRITE_EARLY_EXIT+toParam #{const TMR_PARAM_READER_STATS_ENABLE} = PARAM_READER_STATS_ENABLE+toParam #{const TMR_PARAM_TRIGGER_READ_GPI} = PARAM_TRIGGER_READ_GPI+toParam #{const TMR_PARAM_METADATAFLAG} = PARAM_METADATAFLAG+toParam #{const TMR_PARAM_LICENSED_FEATURES} = PARAM_LICENSED_FEATURES+toParam #{const TMR_PARAM_SELECTED_PROTOCOLS} = PARAM_SELECTED_PROTOCOLS+toParam _ = PARAM_NONE++fromParam :: Param -> RawParam+fromParam PARAM_NONE = #{const TMR_PARAM_NONE}+fromParam PARAM_BAUDRATE = #{const TMR_PARAM_BAUDRATE}+fromParam PARAM_PROBEBAUDRATES = #{const TMR_PARAM_PROBEBAUDRATES}+fromParam PARAM_COMMANDTIMEOUT = #{const TMR_PARAM_COMMANDTIMEOUT}+fromParam PARAM_TRANSPORTTIMEOUT = #{const TMR_PARAM_TRANSPORTTIMEOUT}+fromParam PARAM_POWERMODE = #{const TMR_PARAM_POWERMODE}+fromParam PARAM_USERMODE = #{const TMR_PARAM_USERMODE}+fromParam PARAM_ANTENNA_CHECKPORT = #{const TMR_PARAM_ANTENNA_CHECKPORT}+fromParam PARAM_ANTENNA_PORTLIST = #{const TMR_PARAM_ANTENNA_PORTLIST}+fromParam PARAM_ANTENNA_CONNECTEDPORTLIST = #{const TMR_PARAM_ANTENNA_CONNECTEDPORTLIST}+fromParam PARAM_ANTENNA_PORTSWITCHGPOS = #{const TMR_PARAM_ANTENNA_PORTSWITCHGPOS}+fromParam PARAM_ANTENNA_SETTLINGTIMELIST = #{const TMR_PARAM_ANTENNA_SETTLINGTIMELIST}+fromParam PARAM_ANTENNA_RETURNLOSS = #{const TMR_PARAM_ANTENNA_RETURNLOSS}+fromParam PARAM_ANTENNA_TXRXMAP = #{const TMR_PARAM_ANTENNA_TXRXMAP}+fromParam PARAM_GPIO_INPUTLIST = #{const TMR_PARAM_GPIO_INPUTLIST}+fromParam PARAM_GPIO_OUTPUTLIST = #{const TMR_PARAM_GPIO_OUTPUTLIST}+fromParam PARAM_GEN2_ACCESSPASSWORD = #{const TMR_PARAM_GEN2_ACCESSPASSWORD}+fromParam PARAM_GEN2_Q = #{const TMR_PARAM_GEN2_Q}+fromParam PARAM_GEN2_TAGENCODING = #{const TMR_PARAM_GEN2_TAGENCODING}+fromParam PARAM_GEN2_SESSION = #{const TMR_PARAM_GEN2_SESSION}+fromParam PARAM_GEN2_TARGET = #{const TMR_PARAM_GEN2_TARGET}+fromParam PARAM_GEN2_BLF = #{const TMR_PARAM_GEN2_BLF}+fromParam PARAM_GEN2_TARI = #{const TMR_PARAM_GEN2_TARI}+fromParam PARAM_GEN2_WRITEMODE = #{const TMR_PARAM_GEN2_WRITEMODE}+fromParam PARAM_GEN2_BAP = #{const TMR_PARAM_GEN2_BAP}+fromParam PARAM_GEN2_PROTOCOLEXTENSION = #{const TMR_PARAM_GEN2_PROTOCOLEXTENSION}+fromParam PARAM_ISO180006B_BLF = #{const TMR_PARAM_ISO180006B_BLF}+fromParam PARAM_ISO180006B_MODULATION_DEPTH = #{const TMR_PARAM_ISO180006B_MODULATION_DEPTH}+fromParam PARAM_ISO180006B_DELIMITER = #{const TMR_PARAM_ISO180006B_DELIMITER}+fromParam PARAM_READ_ASYNCOFFTIME = #{const TMR_PARAM_READ_ASYNCOFFTIME}+fromParam PARAM_READ_ASYNCONTIME = #{const TMR_PARAM_READ_ASYNCONTIME}+fromParam PARAM_READ_PLAN = #{const TMR_PARAM_READ_PLAN}+fromParam PARAM_RADIO_ENABLEPOWERSAVE = #{const TMR_PARAM_RADIO_ENABLEPOWERSAVE}+fromParam PARAM_RADIO_POWERMAX = #{const TMR_PARAM_RADIO_POWERMAX}+fromParam PARAM_RADIO_POWERMIN = #{const TMR_PARAM_RADIO_POWERMIN}+fromParam PARAM_RADIO_PORTREADPOWERLIST = #{const TMR_PARAM_RADIO_PORTREADPOWERLIST}+fromParam PARAM_RADIO_PORTWRITEPOWERLIST = #{const TMR_PARAM_RADIO_PORTWRITEPOWERLIST}+fromParam PARAM_RADIO_READPOWER = #{const TMR_PARAM_RADIO_READPOWER}+fromParam PARAM_RADIO_WRITEPOWER = #{const TMR_PARAM_RADIO_WRITEPOWER}+fromParam PARAM_RADIO_TEMPERATURE = #{const TMR_PARAM_RADIO_TEMPERATURE}+fromParam PARAM_TAGREADDATA_RECORDHIGHESTRSSI = #{const TMR_PARAM_TAGREADDATA_RECORDHIGHESTRSSI}+fromParam PARAM_TAGREADDATA_REPORTRSSIINDBM = #{const TMR_PARAM_TAGREADDATA_REPORTRSSIINDBM}+fromParam PARAM_TAGREADDATA_UNIQUEBYANTENNA = #{const TMR_PARAM_TAGREADDATA_UNIQUEBYANTENNA}+fromParam PARAM_TAGREADDATA_UNIQUEBYDATA = #{const TMR_PARAM_TAGREADDATA_UNIQUEBYDATA}+fromParam PARAM_TAGOP_ANTENNA = #{const TMR_PARAM_TAGOP_ANTENNA}+fromParam PARAM_TAGOP_PROTOCOL = #{const TMR_PARAM_TAGOP_PROTOCOL}+fromParam PARAM_VERSION_HARDWARE = #{const TMR_PARAM_VERSION_HARDWARE}+fromParam PARAM_VERSION_SERIAL = #{const TMR_PARAM_VERSION_SERIAL}+fromParam PARAM_VERSION_MODEL = #{const TMR_PARAM_VERSION_MODEL}+fromParam PARAM_VERSION_SOFTWARE = #{const TMR_PARAM_VERSION_SOFTWARE}+fromParam PARAM_VERSION_SUPPORTEDPROTOCOLS = #{const TMR_PARAM_VERSION_SUPPORTEDPROTOCOLS}+fromParam PARAM_REGION_HOPTABLE = #{const TMR_PARAM_REGION_HOPTABLE}+fromParam PARAM_REGION_HOPTIME = #{const TMR_PARAM_REGION_HOPTIME}+fromParam PARAM_REGION_ID = #{const TMR_PARAM_REGION_ID}+fromParam PARAM_REGION_SUPPORTEDREGIONS = #{const TMR_PARAM_REGION_SUPPORTEDREGIONS}+fromParam PARAM_REGION_LBT_ENABLE = #{const TMR_PARAM_REGION_LBT_ENABLE}+fromParam PARAM_LICENSE_KEY = #{const TMR_PARAM_LICENSE_KEY}+fromParam PARAM_USER_CONFIG = #{const TMR_PARAM_USER_CONFIG}+fromParam PARAM_RADIO_ENABLESJC = #{const TMR_PARAM_RADIO_ENABLESJC}+fromParam PARAM_EXTENDEDEPC = #{const TMR_PARAM_EXTENDEDEPC}+fromParam PARAM_READER_STATISTICS = #{const TMR_PARAM_READER_STATISTICS}+fromParam PARAM_READER_STATS = #{const TMR_PARAM_READER_STATS}+fromParam PARAM_URI = #{const TMR_PARAM_URI}+fromParam PARAM_PRODUCT_GROUP_ID = #{const TMR_PARAM_PRODUCT_GROUP_ID}+fromParam PARAM_PRODUCT_GROUP = #{const TMR_PARAM_PRODUCT_GROUP}+fromParam PARAM_PRODUCT_ID = #{const TMR_PARAM_PRODUCT_ID}+fromParam PARAM_TAGREADATA_TAGOPSUCCESSCOUNT = #{const TMR_PARAM_TAGREADATA_TAGOPSUCCESSCOUNT}+fromParam PARAM_TAGREADATA_TAGOPFAILURECOUNT = #{const TMR_PARAM_TAGREADATA_TAGOPFAILURECOUNT}+fromParam PARAM_STATUS_ENABLE_ANTENNAREPORT = #{const TMR_PARAM_STATUS_ENABLE_ANTENNAREPORT}+fromParam PARAM_STATUS_ENABLE_FREQUENCYREPORT = #{const TMR_PARAM_STATUS_ENABLE_FREQUENCYREPORT}+fromParam PARAM_STATUS_ENABLE_TEMPERATUREREPORT = #{const TMR_PARAM_STATUS_ENABLE_TEMPERATUREREPORT}+fromParam PARAM_TAGREADDATA_ENABLEREADFILTER = #{const TMR_PARAM_TAGREADDATA_ENABLEREADFILTER}+fromParam PARAM_TAGREADDATA_READFILTERTIMEOUT = #{const TMR_PARAM_TAGREADDATA_READFILTERTIMEOUT}+fromParam PARAM_TAGREADDATA_UNIQUEBYPROTOCOL = #{const TMR_PARAM_TAGREADDATA_UNIQUEBYPROTOCOL}+fromParam PARAM_READER_DESCRIPTION = #{const TMR_PARAM_READER_DESCRIPTION}+fromParam PARAM_READER_HOSTNAME = #{const TMR_PARAM_READER_HOSTNAME}+fromParam PARAM_CURRENTTIME = #{const TMR_PARAM_CURRENTTIME}+fromParam PARAM_READER_WRITE_REPLY_TIMEOUT = #{const TMR_PARAM_READER_WRITE_REPLY_TIMEOUT}+fromParam PARAM_READER_WRITE_EARLY_EXIT = #{const TMR_PARAM_READER_WRITE_EARLY_EXIT}+fromParam PARAM_READER_STATS_ENABLE = #{const TMR_PARAM_READER_STATS_ENABLE}+fromParam PARAM_TRIGGER_READ_GPI = #{const TMR_PARAM_TRIGGER_READ_GPI}+fromParam PARAM_METADATAFLAG = #{const TMR_PARAM_METADATAFLAG}+fromParam PARAM_LICENSED_FEATURES = #{const TMR_PARAM_LICENSED_FEATURES}+fromParam PARAM_SELECTED_PROTOCOLS = #{const TMR_PARAM_SELECTED_PROTOCOLS}++paramMax :: RawParam+paramMax = #{const TMR_PARAM_MAX}++-- | For parameters which are expressed in physical units,+-- returns a string describing the units.  Returns 'Nothing'+-- for parameters which are not expressed in physical units.+-- This can be useful for displaying in a user interface,+-- for example.+paramUnits :: Param -> Maybe Text+paramUnits PARAM_COMMANDTIMEOUT = Just "milliseconds"+paramUnits PARAM_TRANSPORTTIMEOUT = Just "milliseconds"+paramUnits PARAM_GEN2_BLF = Just "kHz"+paramUnits PARAM_READ_ASYNCOFFTIME = Just "milliseconds"+paramUnits PARAM_READ_ASYNCONTIME = Just "milliseconds"+paramUnits PARAM_RADIO_POWERMAX = Just "centi-dBm"+paramUnits PARAM_RADIO_POWERMIN = Just "centi-dBm"+paramUnits PARAM_RADIO_PORTREADPOWERLIST = Just "centi-dBm"+paramUnits PARAM_RADIO_PORTWRITEPOWERLIST = Just "centi-dBm"+paramUnits PARAM_RADIO_READPOWER = Just "centi-dBm"+paramUnits PARAM_RADIO_WRITEPOWER = Just "centi-dBm"+paramUnits PARAM_RADIO_TEMPERATURE = Just "degrees C"+paramUnits PARAM_REGION_HOPTABLE = Just "kHz"+paramUnits PARAM_REGION_HOPTIME = Just "milliseconds"+paramUnits PARAM_READER_WRITE_REPLY_TIMEOUT = Just "microseconds"+paramUnits _ = Nothing++-- | The Haskell data type expected for a particular parameter.+data ParamType =+    ParamTypeBool+  | ParamTypeGEN2_WriteMode+  | ParamTypeInt16+  | ParamTypeInt32+  | ParamTypeInt8+  | ParamTypeMetadataFlagList+  | ParamTypePowerMode+  | ParamTypeReadPlan+  | ParamTypeRegion+  | ParamTypeRegionList+  | ParamTypeTagProtocol+  | ParamTypeTagProtocolList+  | ParamTypeText+  | ParamTypeWord16+  | ParamTypeWord32+  | ParamTypeWord32List+  | ParamTypeWord8+  | ParamTypeWord8List+  | ParamTypeUnimplemented+  deriving (Eq, Ord, Show, Read, Bounded, Enum)++-- | Indicates the type expected for a given parameter.+paramType :: Param -> ParamType+paramType PARAM_BAUDRATE = ParamTypeWord32+paramType PARAM_PROBEBAUDRATES = ParamTypeWord32List+paramType PARAM_COMMANDTIMEOUT = ParamTypeWord32+paramType PARAM_TRANSPORTTIMEOUT = ParamTypeWord32+paramType PARAM_POWERMODE = ParamTypePowerMode+paramType PARAM_ANTENNA_CHECKPORT = ParamTypeBool+paramType PARAM_ANTENNA_PORTLIST = ParamTypeWord8List+paramType PARAM_ANTENNA_CONNECTEDPORTLIST = ParamTypeWord8List+paramType PARAM_ANTENNA_PORTSWITCHGPOS = ParamTypeWord8List+paramType PARAM_GPIO_INPUTLIST = ParamTypeWord8List+paramType PARAM_GPIO_OUTPUTLIST = ParamTypeWord8List+paramType PARAM_GEN2_ACCESSPASSWORD = ParamTypeWord32+paramType PARAM_GEN2_WRITEMODE = ParamTypeGEN2_WriteMode+paramType PARAM_READ_ASYNCOFFTIME = ParamTypeWord32+paramType PARAM_READ_ASYNCONTIME = ParamTypeWord32+paramType PARAM_READ_PLAN = ParamTypeReadPlan+paramType PARAM_RADIO_ENABLEPOWERSAVE = ParamTypeBool+paramType PARAM_RADIO_POWERMAX = ParamTypeInt16+paramType PARAM_RADIO_POWERMIN = ParamTypeInt16+paramType PARAM_RADIO_READPOWER = ParamTypeInt32+paramType PARAM_RADIO_WRITEPOWER = ParamTypeInt32+paramType PARAM_RADIO_TEMPERATURE = ParamTypeInt8+paramType PARAM_TAGREADDATA_RECORDHIGHESTRSSI = ParamTypeBool+paramType PARAM_TAGREADDATA_REPORTRSSIINDBM = ParamTypeBool+paramType PARAM_TAGREADDATA_UNIQUEBYANTENNA = ParamTypeBool+paramType PARAM_TAGREADDATA_UNIQUEBYDATA = ParamTypeBool+paramType PARAM_TAGOP_ANTENNA = ParamTypeWord8+paramType PARAM_TAGOP_PROTOCOL = ParamTypeTagProtocol+paramType PARAM_VERSION_HARDWARE = ParamTypeText+paramType PARAM_VERSION_SERIAL = ParamTypeText+paramType PARAM_VERSION_MODEL = ParamTypeText+paramType PARAM_VERSION_SOFTWARE = ParamTypeText+paramType PARAM_VERSION_SUPPORTEDPROTOCOLS = ParamTypeTagProtocolList+paramType PARAM_REGION_HOPTABLE = ParamTypeWord32List+paramType PARAM_REGION_HOPTIME = ParamTypeWord32+paramType PARAM_REGION_ID = ParamTypeRegion+paramType PARAM_REGION_SUPPORTEDREGIONS = ParamTypeRegionList+paramType PARAM_REGION_LBT_ENABLE = ParamTypeBool+paramType PARAM_LICENSE_KEY = ParamTypeWord8List+paramType PARAM_RADIO_ENABLESJC = ParamTypeBool+paramType PARAM_EXTENDEDEPC = ParamTypeBool+paramType PARAM_URI = ParamTypeText+paramType PARAM_PRODUCT_GROUP_ID = ParamTypeWord16+paramType PARAM_PRODUCT_GROUP = ParamTypeText+paramType PARAM_PRODUCT_ID = ParamTypeWord16+paramType PARAM_TAGREADATA_TAGOPSUCCESSCOUNT = ParamTypeWord16+paramType PARAM_TAGREADATA_TAGOPFAILURECOUNT = ParamTypeWord16+paramType PARAM_STATUS_ENABLE_ANTENNAREPORT = ParamTypeBool+paramType PARAM_STATUS_ENABLE_FREQUENCYREPORT = ParamTypeBool+paramType PARAM_STATUS_ENABLE_TEMPERATUREREPORT = ParamTypeBool+paramType PARAM_TAGREADDATA_ENABLEREADFILTER = ParamTypeBool+paramType PARAM_TAGREADDATA_READFILTERTIMEOUT = ParamTypeInt32+paramType PARAM_TAGREADDATA_UNIQUEBYPROTOCOL = ParamTypeBool+paramType PARAM_READER_DESCRIPTION = ParamTypeText+paramType PARAM_READER_HOSTNAME = ParamTypeText+paramType PARAM_READER_WRITE_REPLY_TIMEOUT = ParamTypeWord16+paramType PARAM_READER_WRITE_EARLY_EXIT = ParamTypeBool+paramType PARAM_TRIGGER_READ_GPI = ParamTypeWord8List+paramType PARAM_METADATAFLAG = ParamTypeMetadataFlagList+paramType PARAM_LICENSED_FEATURES = ParamTypeWord8List+paramType _ = ParamTypeUnimplemented++-- | A textual representation of the Haskell type corresponding+-- to a particular 'ParamType'.+displayParamType :: ParamType -> Text+displayParamType ParamTypeBool = "Bool"+displayParamType ParamTypeGEN2_WriteMode = "GEN2_WriteMode"+displayParamType ParamTypeInt16 = "Int16"+displayParamType ParamTypeInt32 = "Int32"+displayParamType ParamTypeInt8 = "Int8"+displayParamType ParamTypePowerMode = "PowerMode"+displayParamType ParamTypeReadPlan = "ReadPlan"+displayParamType ParamTypeRegion = "Region"+displayParamType ParamTypeTagProtocol = "TagProtocol"+displayParamType ParamTypeText = "Text"+displayParamType ParamTypeWord16 = "Word16"+displayParamType ParamTypeWord32 = "Word32"+displayParamType ParamTypeWord8 = "Word8"+displayParamType ParamTypeMetadataFlagList = "[MetadataFlag]"+displayParamType ParamTypeRegionList = "[Region]"+displayParamType ParamTypeTagProtocolList = "[TagProtocol]"+displayParamType ParamTypeWord32List = "[Word32]"+displayParamType ParamTypeWord8List = "[Word8]"+displayParamType _ = "(Not yet implemented)"
+ src/System/Hardware/MercuryApi/ParamValue.hs view
@@ -0,0 +1,145 @@+{-# LANGUAGE OverloadedStrings, FlexibleInstances, DeriveDataTypeable #-}+module System.Hardware.MercuryApi.ParamValue where++import Control.Applicative ( (<$>) )+import Control.Exception ( bracketOnError )+import qualified Data.ByteString as B ( useAsCString, length )+import Data.Text (Text)+import Data.Word ( Word8, Word16, Word32 )+import Foreign+    ( Int8,+      Int16,+      Int32,+      Ptr,+      Storable(peek, poke),+      castPtr,+      with,+      toBool,+      new,+      fromBool,+      free,+      allocaBytes,+      alloca )++import System.Hardware.MercuryApi.Enums+import System.Hardware.MercuryApi.Records++-- | A class for types which can be used as parameter values.+class ParamValue a where+  pType :: a -> ParamType+  pGet :: (Ptr () -> IO ()) -> IO a+  pSet :: a -> (Ptr () -> IO ()) -> IO ()++instance ParamValue Bool where+  pType _ = ParamTypeBool+  pGet f = alloca $ \p -> f (castPtr (p :: Ptr CBool)) >> toBool <$> peek p+  pSet x f = alloca $ \p -> poke p (fromBool x :: CBool) >> f (castPtr p)++instance ParamValue GEN2_WriteMode where+  pType _ = ParamTypeGEN2_WriteMode+  pGet f = alloca $ \p -> f (castPtr p) >> toWriteMode <$> peek p+  pSet x f = alloca $ \p -> poke p (fromWriteMode x) >> f (castPtr p)++instance ParamValue Int16 where+  pType _ = ParamTypeInt16+  pGet f = alloca $ \p -> f (castPtr p) >> peek p+  pSet x f = alloca $ \p -> poke p x >> f (castPtr p)++instance ParamValue Int32 where+  pType _ = ParamTypeInt32+  pGet f = alloca $ \p -> f (castPtr p) >> peek p+  pSet x f = alloca $ \p -> poke p x >> f (castPtr p)++instance ParamValue Int8 where+  pType _ = ParamTypeInt8+  pGet f = alloca $ \p -> f (castPtr p) >> peek p+  pSet x f = alloca $ \p -> poke p x >> f (castPtr p)++instance ParamValue PowerMode where+  pType _ = ParamTypePowerMode+  pGet f = alloca $ \p -> f (castPtr p) >> toPowerMode <$> peek p+  pSet x f = alloca $ \p -> poke p (fromPowerMode x) >> f (castPtr p)++instance ParamValue ReadPlan where+  pType _ = ParamTypeReadPlan+  pGet f = alloca $ \p -> f (castPtr p) >> peek p+  -- Unlike all the other cases, in this case we transfer ownership+  -- to the C code, which will free it later.+  pSet x f = bracketOnError (new x) free (f . castPtr)++instance ParamValue Region where+  pType _ = ParamTypeRegion+  pGet f = alloca $ \p -> f (castPtr p) >> toRegion <$> peek p+  pSet x f = alloca $ \p -> poke p (fromRegion x) >> f (castPtr p)++instance ParamValue TagProtocol where+  pType _ = ParamTypeTagProtocol+  pGet f = alloca $ \p -> f (castPtr p) >> toTagProtocol <$> peek p+  pSet x f = alloca $ \p -> poke p (fromTagProtocol x) >> f (castPtr p)++instance ParamValue Text where+  pType _ = ParamTypeText++  pGet f = do+    let maxLen = maxBound :: Word16+    allocaBytes (fromIntegral maxLen) $ \storage -> do+      let lst = List16+                { l16_list = castPtr storage+                , l16_max = maxLen+                , l16_len = 0 -- unused for TMR_String+                }+      with lst $ \p -> do+        f (castPtr p)+        textFromCString storage++  pSet x f = do+    let bs = textToBS x+    B.useAsCString bs $ \cs -> do+      len' <- castLen "Text" (1 + B.length bs)+      let lst = List16+                { l16_list = castPtr cs+                , l16_max = len'+                , l16_len = 0 -- unused for TMR_String+                }+      with lst $ \p -> f (castPtr p)++instance ParamValue Word16 where+  pType _ = ParamTypeWord16+  pGet f = alloca $ \p -> f (castPtr p) >> peek p+  pSet x f = alloca $ \p -> poke p x >> f (castPtr p)++instance ParamValue Word32 where+  pType _ = ParamTypeWord32+  pGet f = alloca $ \p -> f (castPtr p) >> peek p+  pSet x f = alloca $ \p -> poke p x >> f (castPtr p)++instance ParamValue Word8 where+  pType _ = ParamTypeWord8+  pGet f = alloca $ \p -> f (castPtr p) >> peek p+  pSet x f = alloca $ \p -> poke p x >> f (castPtr p)++instance ParamValue [MetadataFlag] where+  pType _ = ParamTypeMetadataFlagList+  pGet f = alloca $ \p -> f (castPtr p) >> unpackFlags <$> peek p+  pSet x f = alloca $ \p -> poke p (packFlags x) >> f (castPtr p)++instance ParamValue [Region] where+  pType _ = ParamTypeRegionList+  pGet f = map toRegion <$> getList8 f+  pSet x f = setList8 "[Region]" (map fromRegion x) f++instance ParamValue [TagProtocol] where+  pType _ = ParamTypeTagProtocolList+  pGet f = map toTagProtocol <$> getList8 f+  pSet x f = setList8 "[TagProtocol]" (map fromTagProtocol x) f++instance ParamValue [Word32] where+  pType _ = ParamTypeWord32List+  pGet = getList16+  pSet = setList16 "[Word32]"++instance ParamValue [Word8] where+  pType _ = ParamTypeWord8List+  pGet = getList16+  pSet = setList16 "[Word8]"+
+ src/System/Hardware/MercuryApi/Params.hs view
@@ -0,0 +1,613 @@+-- Automatically generated by util/generate-tmr-hsc.pl+{-|+Module      : System.Hardware.MercuryApi.Params+Description : Type-safe parameter access+Copyright   : © Patrick Pelletier, 2017+License     : MIT+Maintainer  : code@funwithsoftware.org+Portability : POSIX, Windows++Individual functions to get and set parameters.  These are+type-checked at compile time, unlike 'paramGet' and 'paramSet',+which are type-checked at runtime.+-}+module System.Hardware.MercuryApi.Params+  ( -- * Type-safe getters and setters+    -- ** \/reader+    paramGetBaudRate+  , paramSetBaudRate+  , paramGetCommandTimeout+  , paramSetCommandTimeout+  , paramGetDescription+  , paramSetDescription+  , paramGetExtendedEpc+  , paramSetExtendedEpc+  , paramGetHostname+  , paramSetHostname+  , paramGetLicenseKey+  , paramSetLicenseKey+  , paramGetLicensedFeatures+  , paramSetLicensedFeatures+  , paramGetMetadataflags+  , paramSetMetadataflags+  , paramGetPowerMode+  , paramSetPowerMode+  , paramGetProbeBaudRates+  , paramSetProbeBaudRates+  , paramGetTransportTimeout+  , paramSetTransportTimeout+  , paramGetUri+    -- ** \/reader\/antenna+  , paramGetAntennaCheckPort+  , paramSetAntennaCheckPort+  , paramGetAntennaConnectedPortList+  , paramGetAntennaPortList+  , paramGetAntennaPortSwitchGpos+  , paramSetAntennaPortSwitchGpos+    -- ** \/reader\/gen2+  , paramGetGen2AccessPassword+  , paramSetGen2AccessPassword+  , paramGetGen2WriteEarlyExit+  , paramSetGen2WriteEarlyExit+  , paramGetGen2WriteMode+  , paramSetGen2WriteMode+  , paramGetGen2WriteReplyTimeout+  , paramSetGen2WriteReplyTimeout+    -- ** \/reader\/gpio+  , paramGetGpioInputList+  , paramSetGpioInputList+  , paramGetGpioOutputList+  , paramSetGpioOutputList+    -- ** \/reader\/radio+  , paramGetRadioEnablePowerSave+  , paramSetRadioEnablePowerSave+  , paramGetRadioEnableSJC+  , paramSetRadioEnableSJC+  , paramGetRadioPowerMax+  , paramGetRadioPowerMin+  , paramGetRadioReadPower+  , paramSetRadioReadPower+  , paramGetRadioTemperature+  , paramGetRadioWritePower+  , paramSetRadioWritePower+    -- ** \/reader\/read+  , paramGetReadAsyncOffTime+  , paramSetReadAsyncOffTime+  , paramGetReadAsyncOnTime+  , paramSetReadAsyncOnTime+  , paramGetReadPlan+  , paramSetReadPlan+    -- ** \/reader\/region+  , paramGetRegionHopTable+  , paramSetRegionHopTable+  , paramGetRegionHopTime+  , paramSetRegionHopTime+  , paramGetRegionId+  , paramSetRegionId+  , paramGetRegionSupportedRegions+    -- ** \/reader\/region\/lbt+  , paramGetRegionLbtEnable+  , paramSetRegionLbtEnable+    -- ** \/reader\/status+  , paramGetStatusAntennaEnable+  , paramSetStatusAntennaEnable+  , paramGetStatusFrequencyEnable+  , paramSetStatusFrequencyEnable+  , paramGetStatusTemperatureEnable+  , paramSetStatusTemperatureEnable+    -- ** \/reader\/tagReadData+  , paramGetTagReadDataEnableReadFilter+  , paramSetTagReadDataEnableReadFilter+  , paramGetTagReadDataReadFilterTimeout+  , paramSetTagReadDataReadFilterTimeout+  , paramGetTagReadDataRecordHighestRssi+  , paramSetTagReadDataRecordHighestRssi+  , paramGetTagReadDataReportRssiInDbm+  , paramSetTagReadDataReportRssiInDbm+  , paramGetTagReadDataTagopFailures+  , paramGetTagReadDataTagopSuccesses+  , paramGetTagReadDataUniqueByAntenna+  , paramSetTagReadDataUniqueByAntenna+  , paramGetTagReadDataUniqueByData+  , paramSetTagReadDataUniqueByData+  , paramGetTagReadDataUniqueByProtocol+  , paramSetTagReadDataUniqueByProtocol+    -- ** \/reader\/tagop+  , paramGetTagopAntenna+  , paramSetTagopAntenna+  , paramGetTagopProtocol+  , paramSetTagopProtocol+    -- ** \/reader\/trigger\/read+  , paramGetTriggerReadGpi+  , paramSetTriggerReadGpi+    -- ** \/reader\/version+  , paramGetVersionHardware+  , paramGetVersionModel+  , paramGetVersionProductGroup+  , paramGetVersionProductGroupID+  , paramGetVersionProductID+  , paramGetVersionSerial+  , paramSetVersionSerial+  , paramGetVersionSoftware+  , paramGetVersionSupportedProtocols+    -- * As strings+  , paramGetString+  , paramSetString+  ) where++import Control.Applicative ( (<$>) )+import Data.Int ( Int8, Int16, Int32 )+import Data.Text (Text)+import qualified Data.Text as T ( unpack, pack )+import Data.Word ( Word8, Word16, Word32 )++import System.Hardware.MercuryApi hiding (read)++-- | Set parameter 'PARAM_BAUDRATE' (@\/reader\/baudRate@)+paramSetBaudRate :: Reader -> Word32 -> IO ()+paramSetBaudRate rdr = paramSet rdr PARAM_BAUDRATE++-- | Get parameter 'PARAM_BAUDRATE' (@\/reader\/baudRate@)+paramGetBaudRate :: Reader -> IO Word32+paramGetBaudRate rdr = paramGet rdr PARAM_BAUDRATE++-- | Set parameter 'PARAM_PROBEBAUDRATES' (@\/reader\/probeBaudRates@)+paramSetProbeBaudRates :: Reader -> [Word32] -> IO ()+paramSetProbeBaudRates rdr = paramSet rdr PARAM_PROBEBAUDRATES++-- | Get parameter 'PARAM_PROBEBAUDRATES' (@\/reader\/probeBaudRates@)+paramGetProbeBaudRates :: Reader -> IO [Word32]+paramGetProbeBaudRates rdr = paramGet rdr PARAM_PROBEBAUDRATES++-- | Set parameter 'PARAM_COMMANDTIMEOUT' (@\/reader\/commandTimeout@) (milliseconds)+paramSetCommandTimeout :: Reader -> Word32 -> IO ()+paramSetCommandTimeout rdr = paramSet rdr PARAM_COMMANDTIMEOUT++-- | Get parameter 'PARAM_COMMANDTIMEOUT' (@\/reader\/commandTimeout@) (milliseconds)+paramGetCommandTimeout :: Reader -> IO Word32+paramGetCommandTimeout rdr = paramGet rdr PARAM_COMMANDTIMEOUT++-- | Set parameter 'PARAM_TRANSPORTTIMEOUT' (@\/reader\/transportTimeout@) (milliseconds)+paramSetTransportTimeout :: Reader -> Word32 -> IO ()+paramSetTransportTimeout rdr = paramSet rdr PARAM_TRANSPORTTIMEOUT++-- | Get parameter 'PARAM_TRANSPORTTIMEOUT' (@\/reader\/transportTimeout@) (milliseconds)+paramGetTransportTimeout :: Reader -> IO Word32+paramGetTransportTimeout rdr = paramGet rdr PARAM_TRANSPORTTIMEOUT++-- | Set parameter 'PARAM_POWERMODE' (@\/reader\/powerMode@)+paramSetPowerMode :: Reader -> PowerMode -> IO ()+paramSetPowerMode rdr = paramSet rdr PARAM_POWERMODE++-- | Get parameter 'PARAM_POWERMODE' (@\/reader\/powerMode@)+paramGetPowerMode :: Reader -> IO PowerMode+paramGetPowerMode rdr = paramGet rdr PARAM_POWERMODE++-- | Set parameter 'PARAM_ANTENNA_CHECKPORT' (@\/reader\/antenna\/checkPort@)+paramSetAntennaCheckPort :: Reader -> Bool -> IO ()+paramSetAntennaCheckPort rdr = paramSet rdr PARAM_ANTENNA_CHECKPORT++-- | Get parameter 'PARAM_ANTENNA_CHECKPORT' (@\/reader\/antenna\/checkPort@)+paramGetAntennaCheckPort :: Reader -> IO Bool+paramGetAntennaCheckPort rdr = paramGet rdr PARAM_ANTENNA_CHECKPORT++-- | Get parameter 'PARAM_ANTENNA_PORTLIST' (@\/reader\/antenna\/portList@)+paramGetAntennaPortList :: Reader -> IO [AntennaPort]+paramGetAntennaPortList rdr = paramGet rdr PARAM_ANTENNA_PORTLIST++-- | Get parameter 'PARAM_ANTENNA_CONNECTEDPORTLIST' (@\/reader\/antenna\/connectedPortList@)+paramGetAntennaConnectedPortList :: Reader -> IO [AntennaPort]+paramGetAntennaConnectedPortList rdr = paramGet rdr PARAM_ANTENNA_CONNECTEDPORTLIST++-- | Set parameter 'PARAM_ANTENNA_PORTSWITCHGPOS' (@\/reader\/antenna\/portSwitchGpos@)+paramSetAntennaPortSwitchGpos :: Reader -> [PinNumber] -> IO ()+paramSetAntennaPortSwitchGpos rdr = paramSet rdr PARAM_ANTENNA_PORTSWITCHGPOS++-- | Get parameter 'PARAM_ANTENNA_PORTSWITCHGPOS' (@\/reader\/antenna\/portSwitchGpos@)+paramGetAntennaPortSwitchGpos :: Reader -> IO [PinNumber]+paramGetAntennaPortSwitchGpos rdr = paramGet rdr PARAM_ANTENNA_PORTSWITCHGPOS++-- | Set parameter 'PARAM_GPIO_INPUTLIST' (@\/reader\/gpio\/inputList@)+paramSetGpioInputList :: Reader -> [PinNumber] -> IO ()+paramSetGpioInputList rdr = paramSet rdr PARAM_GPIO_INPUTLIST++-- | Get parameter 'PARAM_GPIO_INPUTLIST' (@\/reader\/gpio\/inputList@)+paramGetGpioInputList :: Reader -> IO [PinNumber]+paramGetGpioInputList rdr = paramGet rdr PARAM_GPIO_INPUTLIST++-- | Set parameter 'PARAM_GPIO_OUTPUTLIST' (@\/reader\/gpio\/outputList@)+paramSetGpioOutputList :: Reader -> [PinNumber] -> IO ()+paramSetGpioOutputList rdr = paramSet rdr PARAM_GPIO_OUTPUTLIST++-- | Get parameter 'PARAM_GPIO_OUTPUTLIST' (@\/reader\/gpio\/outputList@)+paramGetGpioOutputList :: Reader -> IO [PinNumber]+paramGetGpioOutputList rdr = paramGet rdr PARAM_GPIO_OUTPUTLIST++-- | Set parameter 'PARAM_GEN2_ACCESSPASSWORD' (@\/reader\/gen2\/accessPassword@)+paramSetGen2AccessPassword :: Reader -> GEN2_Password -> IO ()+paramSetGen2AccessPassword rdr = paramSet rdr PARAM_GEN2_ACCESSPASSWORD++-- | Get parameter 'PARAM_GEN2_ACCESSPASSWORD' (@\/reader\/gen2\/accessPassword@)+paramGetGen2AccessPassword :: Reader -> IO GEN2_Password+paramGetGen2AccessPassword rdr = paramGet rdr PARAM_GEN2_ACCESSPASSWORD++-- | Set parameter 'PARAM_GEN2_WRITEMODE' (@\/reader\/gen2\/writeMode@)+paramSetGen2WriteMode :: Reader -> GEN2_WriteMode -> IO ()+paramSetGen2WriteMode rdr = paramSet rdr PARAM_GEN2_WRITEMODE++-- | Get parameter 'PARAM_GEN2_WRITEMODE' (@\/reader\/gen2\/writeMode@)+paramGetGen2WriteMode :: Reader -> IO GEN2_WriteMode+paramGetGen2WriteMode rdr = paramGet rdr PARAM_GEN2_WRITEMODE++-- | Set parameter 'PARAM_READ_ASYNCOFFTIME' (@\/reader\/read\/asyncOffTime@) (milliseconds)+paramSetReadAsyncOffTime :: Reader -> Word32 -> IO ()+paramSetReadAsyncOffTime rdr = paramSet rdr PARAM_READ_ASYNCOFFTIME++-- | Get parameter 'PARAM_READ_ASYNCOFFTIME' (@\/reader\/read\/asyncOffTime@) (milliseconds)+paramGetReadAsyncOffTime :: Reader -> IO Word32+paramGetReadAsyncOffTime rdr = paramGet rdr PARAM_READ_ASYNCOFFTIME++-- | Set parameter 'PARAM_READ_ASYNCONTIME' (@\/reader\/read\/asyncOnTime@) (milliseconds)+paramSetReadAsyncOnTime :: Reader -> Word32 -> IO ()+paramSetReadAsyncOnTime rdr = paramSet rdr PARAM_READ_ASYNCONTIME++-- | Get parameter 'PARAM_READ_ASYNCONTIME' (@\/reader\/read\/asyncOnTime@) (milliseconds)+paramGetReadAsyncOnTime :: Reader -> IO Word32+paramGetReadAsyncOnTime rdr = paramGet rdr PARAM_READ_ASYNCONTIME++-- | Set parameter 'PARAM_READ_PLAN' (@\/reader\/read\/plan@)+paramSetReadPlan :: Reader -> ReadPlan -> IO ()+paramSetReadPlan rdr = paramSet rdr PARAM_READ_PLAN++-- | Get parameter 'PARAM_READ_PLAN' (@\/reader\/read\/plan@)+paramGetReadPlan :: Reader -> IO ReadPlan+paramGetReadPlan rdr = paramGet rdr PARAM_READ_PLAN++-- | Set parameter 'PARAM_RADIO_ENABLEPOWERSAVE' (@\/reader\/radio\/enablePowerSave@)+paramSetRadioEnablePowerSave :: Reader -> Bool -> IO ()+paramSetRadioEnablePowerSave rdr = paramSet rdr PARAM_RADIO_ENABLEPOWERSAVE++-- | Get parameter 'PARAM_RADIO_ENABLEPOWERSAVE' (@\/reader\/radio\/enablePowerSave@)+paramGetRadioEnablePowerSave :: Reader -> IO Bool+paramGetRadioEnablePowerSave rdr = paramGet rdr PARAM_RADIO_ENABLEPOWERSAVE++-- | Get parameter 'PARAM_RADIO_POWERMAX' (@\/reader\/radio\/powerMax@) (centi-dBm)+paramGetRadioPowerMax :: Reader -> IO Int16+paramGetRadioPowerMax rdr = paramGet rdr PARAM_RADIO_POWERMAX++-- | Get parameter 'PARAM_RADIO_POWERMIN' (@\/reader\/radio\/powerMin@) (centi-dBm)+paramGetRadioPowerMin :: Reader -> IO Int16+paramGetRadioPowerMin rdr = paramGet rdr PARAM_RADIO_POWERMIN++-- | Set parameter 'PARAM_RADIO_READPOWER' (@\/reader\/radio\/readPower@) (centi-dBm)+paramSetRadioReadPower :: Reader -> Int32 -> IO ()+paramSetRadioReadPower rdr = paramSet rdr PARAM_RADIO_READPOWER++-- | Get parameter 'PARAM_RADIO_READPOWER' (@\/reader\/radio\/readPower@) (centi-dBm)+paramGetRadioReadPower :: Reader -> IO Int32+paramGetRadioReadPower rdr = paramGet rdr PARAM_RADIO_READPOWER++-- | Set parameter 'PARAM_RADIO_WRITEPOWER' (@\/reader\/radio\/writePower@) (centi-dBm)+paramSetRadioWritePower :: Reader -> Int32 -> IO ()+paramSetRadioWritePower rdr = paramSet rdr PARAM_RADIO_WRITEPOWER++-- | Get parameter 'PARAM_RADIO_WRITEPOWER' (@\/reader\/radio\/writePower@) (centi-dBm)+paramGetRadioWritePower :: Reader -> IO Int32+paramGetRadioWritePower rdr = paramGet rdr PARAM_RADIO_WRITEPOWER++-- | Get parameter 'PARAM_RADIO_TEMPERATURE' (@\/reader\/radio\/temperature@) (degrees C)+paramGetRadioTemperature :: Reader -> IO Int8+paramGetRadioTemperature rdr = paramGet rdr PARAM_RADIO_TEMPERATURE++-- | Set parameter 'PARAM_TAGREADDATA_RECORDHIGHESTRSSI' (@\/reader\/tagReadData\/recordHighestRssi@)+paramSetTagReadDataRecordHighestRssi :: Reader -> Bool -> IO ()+paramSetTagReadDataRecordHighestRssi rdr = paramSet rdr PARAM_TAGREADDATA_RECORDHIGHESTRSSI++-- | Get parameter 'PARAM_TAGREADDATA_RECORDHIGHESTRSSI' (@\/reader\/tagReadData\/recordHighestRssi@)+paramGetTagReadDataRecordHighestRssi :: Reader -> IO Bool+paramGetTagReadDataRecordHighestRssi rdr = paramGet rdr PARAM_TAGREADDATA_RECORDHIGHESTRSSI++-- | Set parameter 'PARAM_TAGREADDATA_REPORTRSSIINDBM' (@\/reader\/tagReadData\/reportRssiInDbm@)+paramSetTagReadDataReportRssiInDbm :: Reader -> Bool -> IO ()+paramSetTagReadDataReportRssiInDbm rdr = paramSet rdr PARAM_TAGREADDATA_REPORTRSSIINDBM++-- | Get parameter 'PARAM_TAGREADDATA_REPORTRSSIINDBM' (@\/reader\/tagReadData\/reportRssiInDbm@)+paramGetTagReadDataReportRssiInDbm :: Reader -> IO Bool+paramGetTagReadDataReportRssiInDbm rdr = paramGet rdr PARAM_TAGREADDATA_REPORTRSSIINDBM++-- | Set parameter 'PARAM_TAGREADDATA_UNIQUEBYANTENNA' (@\/reader\/tagReadData\/uniqueByAntenna@)+paramSetTagReadDataUniqueByAntenna :: Reader -> Bool -> IO ()+paramSetTagReadDataUniqueByAntenna rdr = paramSet rdr PARAM_TAGREADDATA_UNIQUEBYANTENNA++-- | Get parameter 'PARAM_TAGREADDATA_UNIQUEBYANTENNA' (@\/reader\/tagReadData\/uniqueByAntenna@)+paramGetTagReadDataUniqueByAntenna :: Reader -> IO Bool+paramGetTagReadDataUniqueByAntenna rdr = paramGet rdr PARAM_TAGREADDATA_UNIQUEBYANTENNA++-- | Set parameter 'PARAM_TAGREADDATA_UNIQUEBYDATA' (@\/reader\/tagReadData\/uniqueByData@)+paramSetTagReadDataUniqueByData :: Reader -> Bool -> IO ()+paramSetTagReadDataUniqueByData rdr = paramSet rdr PARAM_TAGREADDATA_UNIQUEBYDATA++-- | Get parameter 'PARAM_TAGREADDATA_UNIQUEBYDATA' (@\/reader\/tagReadData\/uniqueByData@)+paramGetTagReadDataUniqueByData :: Reader -> IO Bool+paramGetTagReadDataUniqueByData rdr = paramGet rdr PARAM_TAGREADDATA_UNIQUEBYDATA++-- | Set parameter 'PARAM_TAGOP_ANTENNA' (@\/reader\/tagop\/antenna@)+paramSetTagopAntenna :: Reader -> AntennaPort -> IO ()+paramSetTagopAntenna rdr = paramSet rdr PARAM_TAGOP_ANTENNA++-- | Get parameter 'PARAM_TAGOP_ANTENNA' (@\/reader\/tagop\/antenna@)+paramGetTagopAntenna :: Reader -> IO AntennaPort+paramGetTagopAntenna rdr = paramGet rdr PARAM_TAGOP_ANTENNA++-- | Set parameter 'PARAM_TAGOP_PROTOCOL' (@\/reader\/tagop\/protocol@)+paramSetTagopProtocol :: Reader -> TagProtocol -> IO ()+paramSetTagopProtocol rdr = paramSet rdr PARAM_TAGOP_PROTOCOL++-- | Get parameter 'PARAM_TAGOP_PROTOCOL' (@\/reader\/tagop\/protocol@)+paramGetTagopProtocol :: Reader -> IO TagProtocol+paramGetTagopProtocol rdr = paramGet rdr PARAM_TAGOP_PROTOCOL++-- | Get parameter 'PARAM_VERSION_HARDWARE' (@\/reader\/version\/hardware@)+paramGetVersionHardware :: Reader -> IO Text+paramGetVersionHardware rdr = paramGet rdr PARAM_VERSION_HARDWARE++-- | Set parameter 'PARAM_VERSION_SERIAL' (@\/reader\/version\/serial@)+paramSetVersionSerial :: Reader -> Text -> IO ()+paramSetVersionSerial rdr = paramSet rdr PARAM_VERSION_SERIAL++-- | Get parameter 'PARAM_VERSION_SERIAL' (@\/reader\/version\/serial@)+paramGetVersionSerial :: Reader -> IO Text+paramGetVersionSerial rdr = paramGet rdr PARAM_VERSION_SERIAL++-- | Get parameter 'PARAM_VERSION_MODEL' (@\/reader\/version\/model@)+paramGetVersionModel :: Reader -> IO Text+paramGetVersionModel rdr = paramGet rdr PARAM_VERSION_MODEL++-- | Get parameter 'PARAM_VERSION_SOFTWARE' (@\/reader\/version\/software@)+paramGetVersionSoftware :: Reader -> IO Text+paramGetVersionSoftware rdr = paramGet rdr PARAM_VERSION_SOFTWARE++-- | Get parameter 'PARAM_VERSION_SUPPORTEDPROTOCOLS' (@\/reader\/version\/supportedProtocols@)+paramGetVersionSupportedProtocols :: Reader -> IO [TagProtocol]+paramGetVersionSupportedProtocols rdr = paramGet rdr PARAM_VERSION_SUPPORTEDPROTOCOLS++-- | Set parameter 'PARAM_REGION_HOPTABLE' (@\/reader\/region\/hopTable@) (kHz)+paramSetRegionHopTable :: Reader -> [Word32] -> IO ()+paramSetRegionHopTable rdr = paramSet rdr PARAM_REGION_HOPTABLE++-- | Get parameter 'PARAM_REGION_HOPTABLE' (@\/reader\/region\/hopTable@) (kHz)+paramGetRegionHopTable :: Reader -> IO [Word32]+paramGetRegionHopTable rdr = paramGet rdr PARAM_REGION_HOPTABLE++-- | Set parameter 'PARAM_REGION_HOPTIME' (@\/reader\/region\/hopTime@) (milliseconds)+paramSetRegionHopTime :: Reader -> Word32 -> IO ()+paramSetRegionHopTime rdr = paramSet rdr PARAM_REGION_HOPTIME++-- | Get parameter 'PARAM_REGION_HOPTIME' (@\/reader\/region\/hopTime@) (milliseconds)+paramGetRegionHopTime :: Reader -> IO Word32+paramGetRegionHopTime rdr = paramGet rdr PARAM_REGION_HOPTIME++-- | Set parameter 'PARAM_REGION_ID' (@\/reader\/region\/id@)+paramSetRegionId :: Reader -> Region -> IO ()+paramSetRegionId rdr = paramSet rdr PARAM_REGION_ID++-- | Get parameter 'PARAM_REGION_ID' (@\/reader\/region\/id@)+paramGetRegionId :: Reader -> IO Region+paramGetRegionId rdr = paramGet rdr PARAM_REGION_ID++-- | Get parameter 'PARAM_REGION_SUPPORTEDREGIONS' (@\/reader\/region\/supportedRegions@)+paramGetRegionSupportedRegions :: Reader -> IO [Region]+paramGetRegionSupportedRegions rdr = paramGet rdr PARAM_REGION_SUPPORTEDREGIONS++-- | Set parameter 'PARAM_REGION_LBT_ENABLE' (@\/reader\/region\/lbt\/enable@)+paramSetRegionLbtEnable :: Reader -> Bool -> IO ()+paramSetRegionLbtEnable rdr = paramSet rdr PARAM_REGION_LBT_ENABLE++-- | Get parameter 'PARAM_REGION_LBT_ENABLE' (@\/reader\/region\/lbt\/enable@)+paramGetRegionLbtEnable :: Reader -> IO Bool+paramGetRegionLbtEnable rdr = paramGet rdr PARAM_REGION_LBT_ENABLE++-- | Set parameter 'PARAM_LICENSE_KEY' (@\/reader\/licenseKey@)+paramSetLicenseKey :: Reader -> [Word8] -> IO ()+paramSetLicenseKey rdr = paramSet rdr PARAM_LICENSE_KEY++-- | Get parameter 'PARAM_LICENSE_KEY' (@\/reader\/licenseKey@)+paramGetLicenseKey :: Reader -> IO [Word8]+paramGetLicenseKey rdr = paramGet rdr PARAM_LICENSE_KEY++-- | Set parameter 'PARAM_RADIO_ENABLESJC' (@\/reader\/radio\/enableSJC@)+paramSetRadioEnableSJC :: Reader -> Bool -> IO ()+paramSetRadioEnableSJC rdr = paramSet rdr PARAM_RADIO_ENABLESJC++-- | Get parameter 'PARAM_RADIO_ENABLESJC' (@\/reader\/radio\/enableSJC@)+paramGetRadioEnableSJC :: Reader -> IO Bool+paramGetRadioEnableSJC rdr = paramGet rdr PARAM_RADIO_ENABLESJC++-- | Set parameter 'PARAM_EXTENDEDEPC' (@\/reader\/extendedEpc@)+paramSetExtendedEpc :: Reader -> Bool -> IO ()+paramSetExtendedEpc rdr = paramSet rdr PARAM_EXTENDEDEPC++-- | Get parameter 'PARAM_EXTENDEDEPC' (@\/reader\/extendedEpc@)+paramGetExtendedEpc :: Reader -> IO Bool+paramGetExtendedEpc rdr = paramGet rdr PARAM_EXTENDEDEPC++-- | Get parameter 'PARAM_URI' (@\/reader\/uri@)+paramGetUri :: Reader -> IO Text+paramGetUri rdr = paramGet rdr PARAM_URI++-- | Get parameter 'PARAM_PRODUCT_GROUP_ID' (@\/reader\/version\/productGroupID@)+paramGetVersionProductGroupID :: Reader -> IO Word16+paramGetVersionProductGroupID rdr = paramGet rdr PARAM_PRODUCT_GROUP_ID++-- | Get parameter 'PARAM_PRODUCT_GROUP' (@\/reader\/version\/productGroup@)+paramGetVersionProductGroup :: Reader -> IO Text+paramGetVersionProductGroup rdr = paramGet rdr PARAM_PRODUCT_GROUP++-- | Get parameter 'PARAM_PRODUCT_ID' (@\/reader\/version\/productID@)+paramGetVersionProductID :: Reader -> IO Word16+paramGetVersionProductID rdr = paramGet rdr PARAM_PRODUCT_ID++-- | Get parameter 'PARAM_TAGREADATA_TAGOPSUCCESSCOUNT' (@\/reader\/tagReadData\/tagopSuccesses@)+paramGetTagReadDataTagopSuccesses :: Reader -> IO Word16+paramGetTagReadDataTagopSuccesses rdr = paramGet rdr PARAM_TAGREADATA_TAGOPSUCCESSCOUNT++-- | Get parameter 'PARAM_TAGREADATA_TAGOPFAILURECOUNT' (@\/reader\/tagReadData\/tagopFailures@)+paramGetTagReadDataTagopFailures :: Reader -> IO Word16+paramGetTagReadDataTagopFailures rdr = paramGet rdr PARAM_TAGREADATA_TAGOPFAILURECOUNT++-- | Set parameter 'PARAM_STATUS_ENABLE_ANTENNAREPORT' (@\/reader\/status\/antennaEnable@)+paramSetStatusAntennaEnable :: Reader -> Bool -> IO ()+paramSetStatusAntennaEnable rdr = paramSet rdr PARAM_STATUS_ENABLE_ANTENNAREPORT++-- | Get parameter 'PARAM_STATUS_ENABLE_ANTENNAREPORT' (@\/reader\/status\/antennaEnable@)+paramGetStatusAntennaEnable :: Reader -> IO Bool+paramGetStatusAntennaEnable rdr = paramGet rdr PARAM_STATUS_ENABLE_ANTENNAREPORT++-- | Set parameter 'PARAM_STATUS_ENABLE_FREQUENCYREPORT' (@\/reader\/status\/frequencyEnable@)+paramSetStatusFrequencyEnable :: Reader -> Bool -> IO ()+paramSetStatusFrequencyEnable rdr = paramSet rdr PARAM_STATUS_ENABLE_FREQUENCYREPORT++-- | Get parameter 'PARAM_STATUS_ENABLE_FREQUENCYREPORT' (@\/reader\/status\/frequencyEnable@)+paramGetStatusFrequencyEnable :: Reader -> IO Bool+paramGetStatusFrequencyEnable rdr = paramGet rdr PARAM_STATUS_ENABLE_FREQUENCYREPORT++-- | Set parameter 'PARAM_STATUS_ENABLE_TEMPERATUREREPORT' (@\/reader\/status\/temperatureEnable@)+paramSetStatusTemperatureEnable :: Reader -> Bool -> IO ()+paramSetStatusTemperatureEnable rdr = paramSet rdr PARAM_STATUS_ENABLE_TEMPERATUREREPORT++-- | Get parameter 'PARAM_STATUS_ENABLE_TEMPERATUREREPORT' (@\/reader\/status\/temperatureEnable@)+paramGetStatusTemperatureEnable :: Reader -> IO Bool+paramGetStatusTemperatureEnable rdr = paramGet rdr PARAM_STATUS_ENABLE_TEMPERATUREREPORT++-- | Set parameter 'PARAM_TAGREADDATA_ENABLEREADFILTER' (@\/reader\/tagReadData\/enableReadFilter@)+paramSetTagReadDataEnableReadFilter :: Reader -> Bool -> IO ()+paramSetTagReadDataEnableReadFilter rdr = paramSet rdr PARAM_TAGREADDATA_ENABLEREADFILTER++-- | Get parameter 'PARAM_TAGREADDATA_ENABLEREADFILTER' (@\/reader\/tagReadData\/enableReadFilter@)+paramGetTagReadDataEnableReadFilter :: Reader -> IO Bool+paramGetTagReadDataEnableReadFilter rdr = paramGet rdr PARAM_TAGREADDATA_ENABLEREADFILTER++-- | Set parameter 'PARAM_TAGREADDATA_READFILTERTIMEOUT' (@\/reader\/tagReadData\/readFilterTimeout@)+paramSetTagReadDataReadFilterTimeout :: Reader -> Int32 -> IO ()+paramSetTagReadDataReadFilterTimeout rdr = paramSet rdr PARAM_TAGREADDATA_READFILTERTIMEOUT++-- | Get parameter 'PARAM_TAGREADDATA_READFILTERTIMEOUT' (@\/reader\/tagReadData\/readFilterTimeout@)+paramGetTagReadDataReadFilterTimeout :: Reader -> IO Int32+paramGetTagReadDataReadFilterTimeout rdr = paramGet rdr PARAM_TAGREADDATA_READFILTERTIMEOUT++-- | Set parameter 'PARAM_TAGREADDATA_UNIQUEBYPROTOCOL' (@\/reader\/tagReadData\/uniqueByProtocol@)+paramSetTagReadDataUniqueByProtocol :: Reader -> Bool -> IO ()+paramSetTagReadDataUniqueByProtocol rdr = paramSet rdr PARAM_TAGREADDATA_UNIQUEBYPROTOCOL++-- | Get parameter 'PARAM_TAGREADDATA_UNIQUEBYPROTOCOL' (@\/reader\/tagReadData\/uniqueByProtocol@)+paramGetTagReadDataUniqueByProtocol :: Reader -> IO Bool+paramGetTagReadDataUniqueByProtocol rdr = paramGet rdr PARAM_TAGREADDATA_UNIQUEBYPROTOCOL++-- | Set parameter 'PARAM_READER_DESCRIPTION' (@\/reader\/description@)+paramSetDescription :: Reader -> Text -> IO ()+paramSetDescription rdr = paramSet rdr PARAM_READER_DESCRIPTION++-- | Get parameter 'PARAM_READER_DESCRIPTION' (@\/reader\/description@)+paramGetDescription :: Reader -> IO Text+paramGetDescription rdr = paramGet rdr PARAM_READER_DESCRIPTION++-- | Set parameter 'PARAM_READER_HOSTNAME' (@\/reader\/hostname@)+paramSetHostname :: Reader -> Text -> IO ()+paramSetHostname rdr = paramSet rdr PARAM_READER_HOSTNAME++-- | Get parameter 'PARAM_READER_HOSTNAME' (@\/reader\/hostname@)+paramGetHostname :: Reader -> IO Text+paramGetHostname rdr = paramGet rdr PARAM_READER_HOSTNAME++-- | Set parameter 'PARAM_READER_WRITE_REPLY_TIMEOUT' (@\/reader\/gen2\/writeReplyTimeout@) (microseconds)+paramSetGen2WriteReplyTimeout :: Reader -> Word16 -> IO ()+paramSetGen2WriteReplyTimeout rdr = paramSet rdr PARAM_READER_WRITE_REPLY_TIMEOUT++-- | Get parameter 'PARAM_READER_WRITE_REPLY_TIMEOUT' (@\/reader\/gen2\/writeReplyTimeout@) (microseconds)+paramGetGen2WriteReplyTimeout :: Reader -> IO Word16+paramGetGen2WriteReplyTimeout rdr = paramGet rdr PARAM_READER_WRITE_REPLY_TIMEOUT++-- | Set parameter 'PARAM_READER_WRITE_EARLY_EXIT' (@\/reader\/gen2\/writeEarlyExit@)+paramSetGen2WriteEarlyExit :: Reader -> Bool -> IO ()+paramSetGen2WriteEarlyExit rdr = paramSet rdr PARAM_READER_WRITE_EARLY_EXIT++-- | Get parameter 'PARAM_READER_WRITE_EARLY_EXIT' (@\/reader\/gen2\/writeEarlyExit@)+paramGetGen2WriteEarlyExit :: Reader -> IO Bool+paramGetGen2WriteEarlyExit rdr = paramGet rdr PARAM_READER_WRITE_EARLY_EXIT++-- | Set parameter 'PARAM_TRIGGER_READ_GPI' (@\/reader\/trigger\/read\/Gpi@)+paramSetTriggerReadGpi :: Reader -> [PinNumber] -> IO ()+paramSetTriggerReadGpi rdr = paramSet rdr PARAM_TRIGGER_READ_GPI++-- | Get parameter 'PARAM_TRIGGER_READ_GPI' (@\/reader\/trigger\/read\/Gpi@)+paramGetTriggerReadGpi :: Reader -> IO [PinNumber]+paramGetTriggerReadGpi rdr = paramGet rdr PARAM_TRIGGER_READ_GPI++-- | Set parameter 'PARAM_METADATAFLAG' (@\/reader\/metadataflags@)+paramSetMetadataflags :: Reader -> [MetadataFlag] -> IO ()+paramSetMetadataflags rdr = paramSet rdr PARAM_METADATAFLAG++-- | Get parameter 'PARAM_METADATAFLAG' (@\/reader\/metadataflags@)+paramGetMetadataflags :: Reader -> IO [MetadataFlag]+paramGetMetadataflags rdr = paramGet rdr PARAM_METADATAFLAG++-- | Set parameter 'PARAM_LICENSED_FEATURES' (@\/reader\/licensedFeatures@)+paramSetLicensedFeatures :: Reader -> [Word8] -> IO ()+paramSetLicensedFeatures rdr = paramSet rdr PARAM_LICENSED_FEATURES++-- | Get parameter 'PARAM_LICENSED_FEATURES' (@\/reader\/licensedFeatures@)+paramGetLicensedFeatures :: Reader -> IO [Word8]+paramGetLicensedFeatures rdr = paramGet rdr PARAM_LICENSED_FEATURES++-- | Version of 'paramSet' which converts its argument from a+-- string to the proper type using 'read'.+paramSetString :: Reader -> Param -> Text -> IO ()+paramSetString rdr param txt = do+  let str = T.unpack txt+  case paramType param of+    ParamTypeBool -> paramSet rdr param (read str :: Bool)+    ParamTypeGEN2_WriteMode -> paramSet rdr param (read str :: GEN2_WriteMode)+    ParamTypeInt16 -> paramSet rdr param (read str :: Int16)+    ParamTypeInt32 -> paramSet rdr param (read str :: Int32)+    ParamTypeInt8 -> paramSet rdr param (read str :: Int8)+    ParamTypePowerMode -> paramSet rdr param (read str :: PowerMode)+    ParamTypeReadPlan -> paramSet rdr param (read str :: ReadPlan)+    ParamTypeRegion -> paramSet rdr param (read str :: Region)+    ParamTypeTagProtocol -> paramSet rdr param (read str :: TagProtocol)+    ParamTypeText -> paramSet rdr param (read str :: Text)+    ParamTypeWord16 -> paramSet rdr param (read str :: Word16)+    ParamTypeWord32 -> paramSet rdr param (read str :: Word32)+    ParamTypeWord8 -> paramSet rdr param (read str :: Word8)+    ParamTypeMetadataFlagList -> paramSet rdr param (read str :: [MetadataFlag])+    ParamTypeRegionList -> paramSet rdr param (read str :: [Region])+    ParamTypeTagProtocolList -> paramSet rdr param (read str :: [TagProtocol])+    ParamTypeWord32List -> paramSet rdr param (read str :: [Word32])+    ParamTypeWord8List -> paramSet rdr param (read str :: [Word8])+    _ -> paramSet rdr param (undefined :: Bool) -- force ERROR_UNIMPLEMENTED_PARAM++-- | Version of 'paramGet' which converts its result to a+-- string using 'show'.+paramGetString :: Reader -> Param -> IO Text+paramGetString rdr param =+  T.pack <$>+  case paramType param of+    ParamTypeBool -> show <$> (paramGet rdr param :: IO Bool)+    ParamTypeGEN2_WriteMode -> show <$> (paramGet rdr param :: IO GEN2_WriteMode)+    ParamTypeInt16 -> show <$> (paramGet rdr param :: IO Int16)+    ParamTypeInt32 -> show <$> (paramGet rdr param :: IO Int32)+    ParamTypeInt8 -> show <$> (paramGet rdr param :: IO Int8)+    ParamTypePowerMode -> show <$> (paramGet rdr param :: IO PowerMode)+    ParamTypeReadPlan -> show <$> (paramGet rdr param :: IO ReadPlan)+    ParamTypeRegion -> show <$> (paramGet rdr param :: IO Region)+    ParamTypeTagProtocol -> show <$> (paramGet rdr param :: IO TagProtocol)+    ParamTypeText -> show <$> (paramGet rdr param :: IO Text)+    ParamTypeWord16 -> show <$> (paramGet rdr param :: IO Word16)+    ParamTypeWord32 -> show <$> (paramGet rdr param :: IO Word32)+    ParamTypeWord8 -> show <$> (paramGet rdr param :: IO Word8)+    ParamTypeMetadataFlagList -> show <$> (paramGet rdr param :: IO [MetadataFlag])+    ParamTypeRegionList -> show <$> (paramGet rdr param :: IO [Region])+    ParamTypeTagProtocolList -> show <$> (paramGet rdr param :: IO [TagProtocol])+    ParamTypeWord32List -> show <$> (paramGet rdr param :: IO [Word32])+    ParamTypeWord8List -> show <$> (paramGet rdr param :: IO [Word8])+    _ -> show <$> (paramGet rdr param :: IO Bool) -- force ERROR_UNIMPLEMENTED_PARAM+
+ src/System/Hardware/MercuryApi/Records.hsc view
@@ -0,0 +1,828 @@+{-# LANGUAGE OverloadedStrings, FlexibleInstances, DeriveDataTypeable #-}+module System.Hardware.MercuryApi.Records where++import Control.Applicative ( Applicative((<*>)), (<$>) )+import Control.Exception ( Exception, throwIO )+import Data.ByteString (ByteString)+import qualified Data.ByteString as B+import Data.Maybe ( mapMaybe, fromMaybe )+import Data.Monoid ( (<>) )+import Data.Text (Text)+import qualified Data.Text as T ( pack )+import qualified Data.Text.Encoding as T+    ( encodeUtf8, decodeUtf8With )+import qualified Data.Text.Encoding.Error as T ( lenientDecode )+import Data.Typeable ( Typeable )+import Data.Word ( Word8, Word16, Word32, Word64 )+import Foreign+    ( Int32,+      Ptr,+      nullPtr,+      plusPtr,+      Storable(alignment, peek, peekByteOff, poke, pokeByteOff, sizeOf),+      Bits((.&.), (.|.), shiftL),+      castPtr,+      with,+      toBool,+      fromBool,+      withArrayLen,+      pokeArray,+      peekArray,+      copyArray,+      allocaArray )+import Foreign.C ( CString )++import System.Hardware.MercuryApi.Enums++#include <tm_reader.h>+#include <glue.h>+#include <stdbool.h>++-- | A GPIO pin number.  On the M6e Nano, these are numbered 1-4.+type PinNumber = Word8++-- | An antenna number.  On the+-- <https://www.sparkfun.com/products/14066 SparkFun Simultaneous RFID Reader>,+-- there is a single antenna with the number 1.+type AntennaPort = Word8++-- | A 32-bit password (access or kill) in the Gen2 protocol.+type GEN2_Password = Word32++-- | milliseconds since 1\/1\/1970 UTC+type MillisecondsSinceEpoch = Word64++-- | Version number of the Mercury API C library.+apiVersion :: Text+apiVersion = #{const_str TMR_VERSION}++type CBool = #{type bool}+newtype ReaderEtc = ReaderEtc ()++cFalse, cTrue :: CBool+cFalse = 0+cTrue = 1++toBool' :: CBool -> Bool+toBool' = toBool++fromBool' :: Bool -> CBool+fromBool' = fromBool++sizeofReaderEtc :: Int+sizeofReaderEtc = #{size ReaderEtc}++uriPtr :: Ptr ReaderEtc -> CString+uriPtr = #{ptr ReaderEtc, uri}++-- I'm not sure what encoding MercuryApi uses for its strings.+-- I'm guessing UTF-8 for now, but the encoding is encapsulated in+-- these two functions (textFromBS and textToBS) so it can be+-- easily changed.+textFromBS :: ByteString -> Text+textFromBS = T.decodeUtf8With T.lenientDecode++textToBS :: Text -> ByteString+textToBS = T.encodeUtf8++textFromCString :: CString -> IO Text+textFromCString cs = textFromBS <$> B.packCString cs++-- | Indicates whether to read or write the lock bits in+-- 'TagOp_GEN2_BlockPermaLock'.+data ReadWrite = Read !Int       -- ^ number of words of lock bits to read+               | Write ![Word16] -- ^ lock bits to write+               deriving (Eq, Ord, Show, Read)++fromReadWrite :: ReadWrite -> (Word8, [Word16])+fromReadWrite (Read n) = (0, replicate n 0)+fromReadWrite (Write ws) = (1, ws)++toReadWrite :: (Word8, [Word16]) -> ReadWrite+toReadWrite (0, ws) = Read $ length ws+toReadWrite (1, ws) = Write ws+toReadWrite (x, _)  = error $ "didn't expect ReadWrite to be " ++ show x++-- This exception is never seen by the user.  It is caught+-- internally and turned into a MercuryException (with some added fields).+data ParamException = ParamException StatusType Status Text+  deriving (Eq, Ord, Show, Read, Typeable)++instance Exception ParamException++castLen' :: Integral a => a -> Text -> Int -> IO a+castLen' bound description x = do+  let tShow = T.pack . show+      maxLen = fromIntegral bound+  if x > maxLen+    then throwIO ( ParamException ERROR_TYPE_MISC ERROR_TOO_BIG $+                   description <> " had length " <> tShow x <>+                   " but maximum is " <> tShow maxLen )+    else return $ fromIntegral x++castLen :: (Integral a, Bounded a) => Text -> Int -> IO a+castLen = castLen' maxBound++-- | A ReadPlan record specifies the antennas, protocols, and filters+-- to use for a search (read).+--+-- Currently, only @SimpleReadPlan@ is supported.+data ReadPlan =+  SimpleReadPlan+  { rpWeight        :: !Word32          -- ^ The relative weight of this read plan+  , rpEnableAutonomousRead :: !Bool     -- ^ Option for Autonomous read+  , rpAntennas      :: ![AntennaPort]   -- ^ The list of antennas to read on+  , rpProtocol      :: !TagProtocol     -- ^ The protocol to use for reading+  , rpFilter        :: !(Maybe TagFilter) -- ^ The filter to apply to reading+  , rpTagop         :: !(Maybe TagOp)   -- ^ The tag operation to apply to+                                        -- each read tag+  , rpUseFastSearch :: !Bool            -- ^ Option to use the FastSearch+  , rpStopOnCount   :: !(Maybe Word32)  -- ^ Number of tags to be read+  , rpTriggerRead   :: !(Maybe [Word8]) -- ^ The list of GPI ports which should+                                        -- be used to trigger the read+  } deriving (Eq, Ord, Show, Read)++antennasInfo :: Ptr ReadPlan -> (Ptr List16, Word16, Ptr Word8, Text)+antennasInfo rp =+  ( #{ptr ReadPlanEtc, plan.u.simple.antennas} rp+  , #{const GLUE_MAX_ANTENNAS}+  , #{ptr ReadPlanEtc, antennas} rp+  , "rpAntennas"+  )++gpiListInfo :: Ptr ReadPlan -> (Ptr List16, Word16, Ptr Word8, Text)+gpiListInfo rp =+  ( #{ptr ReadPlanEtc, plan.u.simple.triggerRead.gpiList} rp+  , #{const GLUE_MAX_GPIPORTS}+  , #{ptr ReadPlanEtc, gpiPorts} rp+  , "rpTriggerRead"+  )++readPlanTypeSimple :: #{type TMR_ReadPlanType}+readPlanTypeSimple = #{const TMR_READ_PLAN_TYPE_SIMPLE}++instance Storable ReadPlan where+  sizeOf _ = #{size ReadPlanEtc}+  alignment _ = 8++  poke p x = do+    #{poke ReadPlanEtc, plan.type} p readPlanTypeSimple+    #{poke ReadPlanEtc, plan.weight} p (rpWeight x)+    #{poke ReadPlanEtc, plan.enableAutonomousRead} p+      (fromBool' $ rpEnableAutonomousRead x)+    pokeList16 (antennasInfo p) (rpAntennas x)+    #{poke ReadPlanEtc, plan.u.simple.protocol} p+      (fromTagProtocol $ rpProtocol x)+    case rpFilter x of+      Nothing -> #{poke ReadPlanEtc, plan.u.simple.filter} p nullPtr+      Just f -> do+        #{poke ReadPlanEtc, filter} p f+        #{poke ReadPlanEtc, plan.u.simple.filter} p (#{ptr ReadPlanEtc, filter} p)+    case rpTagop x of+      Nothing -> #{poke ReadPlanEtc, plan.u.simple.tagop} p nullPtr+      Just op -> do+        #{poke ReadPlanEtc, tagop} p op+        #{poke ReadPlanEtc, plan.u.simple.tagop} p (#{ptr ReadPlanEtc, tagop} p)+    #{poke ReadPlanEtc, plan.u.simple.useFastSearch} p+      (fromBool' $ rpUseFastSearch x)+    let (stop, nTags) = case rpStopOnCount x of+                          Nothing -> (cFalse, 0)+                          Just n -> (cTrue, n)+    #{poke ReadPlanEtc, plan.u.simple.stopOnCount.stopNTriggerStatus} p stop+    #{poke ReadPlanEtc, plan.u.simple.stopOnCount.noOfTags} p nTags+    let (enable, ports) = case rpTriggerRead x of+                            Nothing -> (cFalse, [])+                            Just ps -> (cTrue, ps)+    #{poke ReadPlanEtc, plan.u.simple.triggerRead.enable} p enable+    pokeList16 (gpiListInfo p) ports++  peek p = do+    weight <- #{peek ReadPlanEtc, plan.weight} p+    enableAutonomousRead <- #{peek ReadPlanEtc, plan.enableAutonomousRead} p+    antennas <- peekList16 (antennasInfo p)+    protocol <- #{peek ReadPlanEtc, plan.u.simple.protocol} p+    fPtr <- #{peek ReadPlanEtc, plan.u.simple.filter} p+    filt <- if fPtr == nullPtr+            then return Nothing+            else Just <$> peek fPtr+    opPtr <- #{peek ReadPlanEtc, plan.u.simple.tagop} p+    op <- if opPtr == nullPtr+          then return Nothing+          else Just <$> peek opPtr+    useFastSearch <- #{peek ReadPlanEtc, plan.u.simple.useFastSearch} p+    stop <- #{peek ReadPlanEtc, plan.u.simple.stopOnCount.stopNTriggerStatus} p+    stopOnCount <- if toBool' stop+                   then Just <$> #{peek ReadPlanEtc, plan.u.simple.stopOnCount.noOfTags} p+                   else return Nothing+    enable <- #{peek ReadPlanEtc, plan.u.simple.triggerRead.enable} p+    triggerRead <- if toBool' enable+                   then Just <$> peekList16 (gpiListInfo p)+                   else return Nothing+    return $ SimpleReadPlan+      { rpWeight = weight+      , rpEnableAutonomousRead = toBool' enableAutonomousRead+      , rpAntennas = antennas+      , rpProtocol = toTagProtocol protocol+      , rpFilter = filt+      , rpTagop = op+      , rpUseFastSearch = toBool' useFastSearch+      , rpStopOnCount = stopOnCount+      , rpTriggerRead = triggerRead+      }++-- | Filter on EPC length, or on a Gen2 bank.+data FilterOn = FilterOnBank GEN2_Bank+              | FilterOnEpcLength+              deriving (Eq, Ord, Show, Read)++instance Storable FilterOn where+  sizeOf _ = #{size TMR_GEN2_Bank}+  alignment _ = 8++  poke p FilterOnEpcLength = do+    let p' = castPtr p :: Ptr RawBank+    poke p' #{const TMR_GEN2_EPC_LENGTH_FILTER}++  poke p (FilterOnBank bank) = do+    let p' = castPtr p :: Ptr RawBank+    poke p' (fromBank bank)++  peek p = do+    x <- peek (castPtr p)+    if x == #{const TMR_GEN2_EPC_LENGTH_FILTER}+      then return FilterOnEpcLength+      else return $ FilterOnBank $ toBank x++-- | Filter on EPC data, or on Gen2-specific information.+data TagFilter = TagFilterEPC TagData+               | TagFilterGen2+               { tfInvert        :: !Bool        -- ^ Whether to invert the+                                                 -- selection (deselect tags+                                                 -- that meet the comparison)+               , tfFilterOn      :: !FilterOn    -- ^ The memory bank in which+                                                 -- to compare the mask+               , tfBitPointer    :: !Word32      -- ^ The location (in bits) at+                                                 -- which to begin comparing+                                                 -- the mask+               , tfMaskBitLength :: !Word16      -- ^ The length (in bits) of+                                                 -- the mask+               , tfMask          :: !ByteString  -- ^ The mask value to compare+                                                 -- with the specified region+                                                 -- of tag memory, MSB first+               }+               deriving (Eq, Ord, Show, Read)++instance Storable TagFilter where+  sizeOf _ = #{size TagFilterEtc}+  alignment _ = 8++  poke p (TagFilterEPC td) = do+    #{poke TagFilterEtc, filter.type} p+      (#{const TMR_FILTER_TYPE_TAG_DATA} :: #{type TMR_FilterType})+    #{poke TagFilterEtc, filter.u.tagData} p td++  poke p tf@(TagFilterGen2 {}) = do+    #{poke TagFilterEtc, filter.type} p+      (#{const TMR_FILTER_TYPE_GEN2_SELECT} :: #{type TMR_FilterType})+    #{poke TagFilterEtc, filter.u.gen2Select.invert} p (fromBool' $ tfInvert tf)+    #{poke TagFilterEtc, filter.u.gen2Select.bank} p (tfFilterOn tf)+    #{poke TagFilterEtc, filter.u.gen2Select.bitPointer} p (tfBitPointer tf)+    #{poke TagFilterEtc, filter.u.gen2Select.maskBitLength} p (tfMaskBitLength tf)+    let maskLenBytes = fromIntegral $ (tfMaskBitLength tf + 7) `div` 8+        origLen = B.length (tfMask tf)+        bs = if origLen < maskLenBytes+               then tfMask tf <> B.pack (replicate (maskLenBytes - origLen) 0)+               else tfMask tf+    B.useAsCStringLen bs $ \(cs, len) -> do+      len' <- castLen' #{const GLUE_MAX_MASK} "tfMask" len+      copyArray (#{ptr TagFilterEtc, mask} p) cs (fromIntegral len')+    #{poke TagFilterEtc, filter.u.gen2Select.mask} p (#{ptr TagFilterEtc, mask} p)++  peek p = do+    ft <- #{peek TagFilterEtc, filter.type} p :: IO #{type TMR_FilterType}+    case ft of+      #{const TMR_FILTER_TYPE_TAG_DATA} ->+        TagFilterEPC <$> #{peek TagFilterEtc, filter.u.tagData} p+      #{const TMR_FILTER_TYPE_GEN2_SELECT} ->+        TagFilterGen2+        <$> (toBool' <$> #{peek TagFilterEtc, filter.u.gen2Select.invert} p)+        <*> #{peek TagFilterEtc, filter.u.gen2Select.bank} p+        <*> #{peek TagFilterEtc, filter.u.gen2Select.bitPointer} p+        <*> #{peek TagFilterEtc, filter.u.gen2Select.maskBitLength} p+        <*> peekMask p++peekMask :: Ptr TagFilter -> IO ByteString+peekMask p = do+  bitLength <- #{peek TagFilterEtc, filter.u.gen2Select.maskBitLength} p :: IO Word32+  let len = fromIntegral $ (bitLength + 7) `div` 8+  maskPtr <- #{peek TagFilterEtc, filter.u.gen2Select.mask} p+  B.packCStringLen (maskPtr, len)++packBits :: Num b => (a -> b) -> [a] -> b+packBits from flags = sum $ map from flags++unpackBits :: (Bounded a, Enum a, Num b, Bits b) => (a -> b) -> b -> [a]+unpackBits from x = mapMaybe f [minBound..maxBound]+  where f flag = if (x .&. from flag) == 0+                 then Nothing+                 else Just flag++packFlags :: [MetadataFlag] -> RawMetadataFlag+packFlags = packBits fromMetadataFlag++unpackFlags :: RawMetadataFlag -> [MetadataFlag]+unpackFlags = unpackBits fromMetadataFlag++packFlags16 :: [MetadataFlag] -> Word16+packFlags16 = fromIntegral . packFlags++unpackFlags16 :: Word16 -> [MetadataFlag]+unpackFlags16 = unpackFlags . fromIntegral++packExtraBanks :: [GEN2_Bank] -> RawBank+packExtraBanks = packBits fromExtraBank++unpackExtraBanks :: RawBank -> [GEN2_Bank]+unpackExtraBanks = unpackBits fromExtraBank++packLockBits :: [GEN2_LockBits] -> RawLockBits+packLockBits = packBits fromLockBits++unpackLockBits :: RawLockBits -> [GEN2_LockBits]+unpackLockBits = unpackBits fromLockBits++packLockBits16 :: [GEN2_LockBits] -> Word16+packLockBits16 = fromIntegral . packLockBits++unpackLockBits16 :: Word16 -> [GEN2_LockBits]+unpackLockBits16 = unpackLockBits . fromIntegral++peekArrayAsByteString :: Ptr Word8 -> Ptr Word8 -> IO ByteString+peekArrayAsByteString arrayPtr lenPtr = do+  len <- peek lenPtr+  B.packCStringLen (castPtr arrayPtr, fromIntegral len)++pokeArrayAsByteString :: Text+                      -> Word8+                      -> Ptr Word8+                      -> Ptr Word8+                      -> ByteString+                      -> IO ()+pokeArrayAsByteString desc maxLen arrayPtr lenPtr bs = do+  B.useAsCStringLen bs $ \(cs, len) -> do+    len' <- castLen' maxLen desc len+    copyArray arrayPtr (castPtr cs) (fromIntegral len')+    poke lenPtr len'++peekListAsByteString :: Ptr List16 -> IO ByteString+peekListAsByteString listPtr = do+  lst <- peek listPtr+  B.packCStringLen (castPtr $ l16_list lst, fromIntegral $ l16_len lst)++peekArrayAsList :: Storable a => Ptr a -> Ptr Word8 -> IO [a]+peekArrayAsList arrayPtr lenPtr = do+  len <- peek lenPtr+  peekArray (fromIntegral len) arrayPtr++peekListAsList :: Storable a => Ptr List16 -> Ptr a -> IO [a]+peekListAsList listPtr _ = do+  lst <- peek listPtr+  peekArray (fromIntegral $ l16_len lst) (castPtr $ l16_list lst)++pokeListAsList :: Storable a+               => Text+               -> Word16+               -> Ptr List16+               -> Ptr a+               -> [a]+               -> IO ()+pokeListAsList desc maxLen listPtr storage xs = do+  withArrayLen xs $ \len tmpPtr -> do+    len' <- castLen' maxLen desc len+    copyArray storage tmpPtr len+    let lst = List16+              { l16_list = castPtr storage+              , l16_max = maxLen+              , l16_len = len'+              }+    poke listPtr lst++peekMaybe :: (Storable a, Storable b)+          => (Ptr a -> IO a)+          -> (b -> Bool)+          -> Ptr a+          -> Ptr b+          -> IO (Maybe a)+peekMaybe oldPeek cond justP condP = do+  c <- peek condP+  if cond c+    then Just <$> oldPeek justP+    else return Nothing++pokeGen2TagData :: Ptr GEN2_TagData+                -> Ptr RawTagProtocol+                -> Maybe GEN2_TagData+                -> IO ()+pokeGen2TagData pGen2 _ mGen2 = do+  let gen2 = fromMaybe (GEN2_TagData B.empty) mGen2+  poke pGen2 gen2++peekSplit64 :: Ptr Word32 -> Ptr Word32 -> IO Word64+peekSplit64 pLow pHigh = do+  lo <- fromIntegral <$> peek pLow+  hi <- fromIntegral <$> peek pHigh+  return $ lo .|. (hi `shiftL` 32)++peekPtr :: Storable a => Ptr (Ptr a) -> Ptr a -> IO a+peekPtr pp _ = do+  p <- peek pp+  peek p++pokePtr :: Storable a => Ptr (Ptr a) -> Ptr a -> a -> IO ()+pokePtr pp p x = do+  poke p x+  poke pp p++pokeOr :: (Storable a, Bits a) => Ptr a -> a -> IO ()+pokeOr p x = do+  old <- peek p+  poke p (x .|. old)++data List16 =+  List16+  { l16_list :: !(Ptr ())+  , l16_max :: !(Word16)+  , l16_len :: !(Word16)+  }++instance Storable List16 where+  sizeOf _ = #{size List16}+  alignment _ = 8+  peek p = List16+           <$> #{peek List16, list} p+           <*> #{peek List16, max} p+           <*> #{peek List16, len} p+  poke p x = do+    #{poke List16, list} p (l16_list x)+    #{poke List16, max} p (l16_max x)+    #{poke List16, len} p (l16_len x)++getList16 :: Storable a => (Ptr () -> IO ()) -> IO [a]+getList16 f = do+  let maxLen = maxBound :: Word16+  allocaArray (fromIntegral maxLen) $ \storage -> do+    let lst = List16+              { l16_list = castPtr storage+              , l16_max = maxLen+              , l16_len = 0+              }+    with lst $ \p -> do+      f (castPtr p)+      lst' <- peek p+      peekArray (fromIntegral (l16_len lst')) storage++setList16 :: Storable a => Text -> [a] -> (Ptr () -> IO ()) -> IO ()+setList16 t x f = do+  withArrayLen x $ \len storage -> do+    len' <- castLen t len+    let lst = List16+              { l16_list = castPtr storage+              , l16_max = len'+              , l16_len = len'+              }+    with lst $ \p -> f (castPtr p)++pokeList16 :: Storable a => (Ptr List16, Word16, Ptr a, Text) -> [a] -> IO ()+pokeList16 (lp, maxLen, storage, name) ws = do+  len <- castLen' maxLen name (length ws)+  poke lp $ List16+    { l16_list = castPtr storage+    , l16_max = maxLen+    , l16_len = len+    }+  pokeArray storage ws++peekList16 :: Storable a => (Ptr List16, Word16, Ptr a, Text) -> IO [a]+peekList16 (lp, _, _, _) = do+  lst <- peek lp+  peekArray (fromIntegral $ l16_len lst) (castPtr $ l16_list lst)++data List8 =+  List8+  { l8_list :: !(Ptr ())+  , l8_max :: !(Word8)+  , l8_len :: !(Word8)+  }++instance Storable List8 where+  sizeOf _ = #{size List8}+  alignment _ = 8+  peek p = List8+           <$> #{peek List8, list} p+           <*> #{peek List8, max} p+           <*> #{peek List8, len} p+  poke p x = do+    #{poke List8, list} p (l8_list x)+    #{poke List8, max} p (l8_max x)+    #{poke List8, len} p (l8_len x)++getList8 :: Storable a => (Ptr () -> IO ()) -> IO [a]+getList8 f = do+  let maxLen = maxBound :: Word8+  allocaArray (fromIntegral maxLen) $ \storage -> do+    let lst = List8+              { l8_list = castPtr storage+              , l8_max = maxLen+              , l8_len = 0+              }+    with lst $ \p -> do+      f (castPtr p)+      lst' <- peek p+      peekArray (fromIntegral (l8_len lst')) storage++setList8 :: Storable a => Text -> [a] -> (Ptr () -> IO ()) -> IO ()+setList8 t x f = do+  withArrayLen x $ \len storage -> do+    len' <- castLen t len+    let lst = List8+              { l8_list = castPtr storage+              , l8_max = len'+              , l8_len = len'+              }+    with lst $ \p -> f (castPtr p)++pokeList8 :: Storable a => (Ptr List8, Word8, Ptr a, Text) -> [a] -> IO ()+pokeList8 (lp, maxLen, storage, name) ws = do+  len <- castLen' maxLen name (length ws)+  poke lp $ List8+    { l8_list = castPtr storage+    , l8_max = maxLen+    , l8_len = len+    }+  pokeArray storage ws++peekList8 :: Storable a => (Ptr List8, Word8, Ptr a, Text) -> IO [a]+peekList8 (lp, _, _, _) = do+  lst <- peek lp+  peekArray (fromIntegral $ l8_len lst) (castPtr $ l8_list lst)++-- | Gen2-specific per-tag data+newtype GEN2_TagData =+  GEN2_TagData+  { g2Pc :: ByteString -- ^ Tag PC+  } deriving (Eq, Ord, Show, Read)++instance Storable GEN2_TagData where+  sizeOf _ = #{size TMR_GEN2_TagData}+  alignment _ = 8++  peek p =+    GEN2_TagData+      <$> peekArrayAsByteString (#{ptr TMR_GEN2_TagData, pc} p) (#{ptr TMR_GEN2_TagData, pcByteCount} p)++  poke p x = do+    pokeArrayAsByteString "pc" #{const TMR_GEN2_MAX_PC_BYTE_COUNT} (#{ptr TMR_GEN2_TagData, pc} p) (#{ptr TMR_GEN2_TagData, pcByteCount} p) (g2Pc x)++-- | A record to represent RFID tags.+data TagData =+  TagData+  { tdEpc :: !ByteString -- ^ Tag EPC+  , tdProtocol :: !TagProtocol -- ^ Protocol of the tag+  , tdCrc :: !Word16 -- ^ Tag CRC+  , tdGen2 :: !(Maybe (GEN2_TagData)) -- ^ Gen2-specific tag information+  } deriving (Eq, Ord, Show, Read)++instance Storable TagData where+  sizeOf _ = #{size TMR_TagData}+  alignment _ = 8++  peek p =+    TagData+      <$> peekArrayAsByteString (#{ptr TMR_TagData, epc} p) (#{ptr TMR_TagData, epcByteCount} p)+      <*> (toTagProtocol <$> #{peek TMR_TagData, protocol} p)+      <*> #{peek TMR_TagData, crc} p+      <*> peekMaybe (peek) (== (#{const TMR_TAG_PROTOCOL_GEN2} :: RawTagProtocol)) (#{ptr TMR_TagData, u.gen2} p) (#{ptr TMR_TagData, protocol} p)++  poke p x = do+    pokeArrayAsByteString "epc" #{const TMR_MAX_EPC_BYTE_COUNT} (#{ptr TMR_TagData, epc} p) (#{ptr TMR_TagData, epcByteCount} p) (tdEpc x)+    #{poke TMR_TagData, protocol} p (fromTagProtocol $ tdProtocol x)+    #{poke TMR_TagData, crc} p (tdCrc x)+    pokeGen2TagData (#{ptr TMR_TagData, u.gen2} p) (#{ptr TMR_TagData, protocol} p) (tdGen2 x)++-- | The identity and state of a single GPIO pin.+data GpioPin =+  GpioPin+  { gpId :: !PinNumber -- ^ The ID number of the pin.+  , gpHigh :: !Bool -- ^ Whether the pin is in the high state.+  , gpOutput :: !Bool -- ^ The direction of the pin+  } deriving (Eq, Ord, Show, Read)++instance Storable GpioPin where+  sizeOf _ = #{size TMR_GpioPin}+  alignment _ = 8++  peek p =+    GpioPin+      <$> #{peek TMR_GpioPin, id} p+      <*> (toBool' <$> #{peek TMR_GpioPin, high} p)+      <*> (toBool' <$> #{peek TMR_GpioPin, output} p)++  poke p x = do+    #{poke TMR_GpioPin, id} p (gpId x)+    #{poke TMR_GpioPin, high} p (fromBool' $ gpHigh x)+    #{poke TMR_GpioPin, output} p (fromBool' $ gpOutput x)++-- | A record to represent a read of an RFID tag.+-- Provides access to the metadata of the read event,+-- such as the time of the read, the antenna that read the tag,+-- and the number of times the tag was seen by the air protocol.+data TagReadData =+  TagReadData+  { trTag :: !TagData -- ^ The tag that was read+  , trMetadataFlags :: ![MetadataFlag] -- ^ The set of metadata items below that are valid+  , trPhase :: !Word16 -- ^ Tag response phase+  , trAntenna :: !AntennaPort -- ^ Antenna where the tag was read+  , trGpio :: ![GpioPin] -- ^ State of GPIO pins at the moment of the tag read+  , trReadCount :: !Word32 -- ^ Number of times the tag was read+  , trRssi :: !Int32 -- ^ Strength of the signal received from the tag+  , trFrequency :: !Word32 -- ^ RF carrier frequency the tag was read with+  , trTimestamp :: !MillisecondsSinceEpoch -- ^ Absolute time of the read, in milliseconds since 1\/1\/1970 UTC+  , trData :: !ByteString -- ^ Data read from the tag+  , trEpcMemData :: !ByteString -- ^ Read EPC bank data bytes  (Only if 'GEN2_BANK_EPC' is present in 'opExtraBanks')+  , trTidMemData :: !ByteString -- ^ Read TID bank data bytes  (Only if 'GEN2_BANK_TID' is present in 'opExtraBanks')+  , trUserMemData :: !ByteString -- ^ Read USER bank data bytes  (Only if 'GEN2_BANK_USER' is present in 'opExtraBanks')+  , trReservedMemData :: !ByteString -- ^ Read RESERVED bank data bytes  (Only if 'GEN2_BANK_RESERVED' is present in 'opExtraBanks')+  } deriving (Eq, Ord, Show, Read)++instance Storable TagReadData where+  sizeOf _ = #{size TMR_TagReadData}+  alignment _ = 8++  peek p =+    TagReadData+      <$> #{peek TMR_TagReadData, tag} p+      <*> (unpackFlags16 <$> #{peek TMR_TagReadData, metadataFlags} p)+      <*> #{peek TMR_TagReadData, phase} p+      <*> #{peek TMR_TagReadData, antenna} p+      <*> peekArrayAsList (#{ptr TMR_TagReadData, gpio} p) (#{ptr TMR_TagReadData, gpioCount} p)+      <*> #{peek TMR_TagReadData, readCount} p+      <*> #{peek TMR_TagReadData, rssi} p+      <*> #{peek TMR_TagReadData, frequency} p+      <*> peekSplit64 (#{ptr TMR_TagReadData, timestampLow} p) (#{ptr TMR_TagReadData, timestampHigh} p)+      <*> peekListAsByteString (#{ptr TMR_TagReadData, data} p)+      <*> peekListAsByteString (#{ptr TMR_TagReadData, epcMemData} p)+      <*> peekListAsByteString (#{ptr TMR_TagReadData, tidMemData} p)+      <*> peekListAsByteString (#{ptr TMR_TagReadData, userMemData} p)+      <*> peekListAsByteString (#{ptr TMR_TagReadData, reservedMemData} p)++  poke p x = error "poke not implemented for TagReadData"++-- | An operation that can be performed on a tag.  Can be used+-- as an argument to 'System.Hardware.MercuryApi.executeTagOp',+-- or can be embedded into a 'System.Hardware.MercuryApi.ReadPlan'.+-- (However, on the M6e Nano, only 'TagOp_GEN2_ReadData' may be+-- embedded in a 'System.Hardware.MercuryApi.ReadPlan'.)+data TagOp =+    TagOp_GEN2_ReadData+    { opBank :: !GEN2_Bank -- ^ Gen2 memory bank to operate on+    , opExtraBanks :: ![GEN2_Bank] -- ^ Additional Gen2 memory banks to read from  (seems buggy, though; I\'ve had strange results with it)+    , opWordAddress :: !Word32 -- ^ Word address to start at+    , opLen :: !Word8 -- ^ Number of words to read+    }+  | TagOp_GEN2_WriteTag+    { opEpc :: !TagData -- ^ Tag EPC+    }+  | TagOp_GEN2_WriteData+    { opBank :: !GEN2_Bank -- ^ Gen2 memory bank to operate on+    , opWordAddress :: !Word32 -- ^ Word address to start at+    , opData :: ![Word16] -- ^ Data to write+    }+  | TagOp_GEN2_Lock+    { opMask :: ![GEN2_LockBits] -- ^ Bitmask indicating which lock bits to change+    , opAction :: ![GEN2_LockBits] -- ^ New values of each bit specified in the mask+    , opAccessPassword :: !GEN2_Password -- ^ Access Password to use to lock the tag+    }+  | TagOp_GEN2_Kill+    { opPassword :: !GEN2_Password -- ^ Kill password to use to kill the tag+    }+  | TagOp_GEN2_BlockWrite+    { opBank :: !GEN2_Bank -- ^ Gen2 memory bank to operate on+    , opWordPtr :: !Word32 -- ^ The word address to start at+    , opData :: ![Word16] -- ^ The data to write+    }+  | TagOp_GEN2_BlockErase+    { opBank :: !GEN2_Bank -- ^ Gen2 memory bank to operate on+    , opWordPtr :: !Word32 -- ^ The word address to start at+    , opWordCount :: !Word8 -- ^ Number of words to erase+    }+  | TagOp_GEN2_BlockPermaLock+    { opBank :: !GEN2_Bank -- ^ Gen2 memory bank to operate on+    , opBlockPtr :: !Word32 -- ^ The starting word address to lock+    , opReadWrite :: !ReadWrite -- ^ Read lock status or write it?+    }+  deriving (Eq, Ord, Show, Read)++instance Storable TagOp where+  sizeOf _ = #{size TagOpEtc}+  alignment _ = 8++  peek p = do+    x <- #{peek TagOpEtc, tagop.type} p :: IO #{type TMR_TagOpType}+    case x of+      #{const TMR_TAGOP_GEN2_READDATA} -> do+        TagOp_GEN2_ReadData+          <$> ((toBank . (.&. 3)) <$> #{peek TagOpEtc, tagop.u.gen2.u.readData.bank} p)+          <*> (unpackExtraBanks <$> #{peek TagOpEtc, tagop.u.gen2.u.readData.bank} p)+          <*> #{peek TagOpEtc, tagop.u.gen2.u.readData.wordAddress} p+          <*> #{peek TagOpEtc, tagop.u.gen2.u.readData.len} p+      #{const TMR_TAGOP_GEN2_WRITETAG} -> do+        TagOp_GEN2_WriteTag+          <$> peekPtr (#{ptr TagOpEtc, tagop.u.gen2.u.writeTag.epcptr} p) (#{ptr TagOpEtc, u.epc} p)+      #{const TMR_TAGOP_GEN2_WRITEDATA} -> do+        TagOp_GEN2_WriteData+          <$> ((toBank . (.&. 3)) <$> #{peek TagOpEtc, tagop.u.gen2.u.writeData.bank} p)+          <*> #{peek TagOpEtc, tagop.u.gen2.u.writeData.wordAddress} p+          <*> peekListAsList (#{ptr TagOpEtc, tagop.u.gen2.u.writeData.data} p) (#{ptr TagOpEtc, u.data16} p)+      #{const TMR_TAGOP_GEN2_LOCK} -> do+        TagOp_GEN2_Lock+          <$> (unpackLockBits16 <$> #{peek TagOpEtc, tagop.u.gen2.u.lock.mask} p)+          <*> (unpackLockBits16 <$> #{peek TagOpEtc, tagop.u.gen2.u.lock.action} p)+          <*> #{peek TagOpEtc, tagop.u.gen2.u.lock.accessPassword} p+      #{const TMR_TAGOP_GEN2_KILL} -> do+        TagOp_GEN2_Kill+          <$> #{peek TagOpEtc, tagop.u.gen2.u.kill.password} p+      #{const TMR_TAGOP_GEN2_BLOCKWRITE} -> do+        TagOp_GEN2_BlockWrite+          <$> ((toBank . (.&. 3)) <$> #{peek TagOpEtc, tagop.u.gen2.u.blockWrite.bank} p)+          <*> #{peek TagOpEtc, tagop.u.gen2.u.blockWrite.wordPtr} p+          <*> peekListAsList (#{ptr TagOpEtc, tagop.u.gen2.u.blockWrite.data} p) (#{ptr TagOpEtc, u.data16} p)+      #{const TMR_TAGOP_GEN2_BLOCKERASE} -> do+        TagOp_GEN2_BlockErase+          <$> ((toBank . (.&. 3)) <$> #{peek TagOpEtc, tagop.u.gen2.u.blockErase.bank} p)+          <*> #{peek TagOpEtc, tagop.u.gen2.u.blockErase.wordPtr} p+          <*> #{peek TagOpEtc, tagop.u.gen2.u.blockErase.wordCount} p+      #{const TMR_TAGOP_GEN2_BLOCKPERMALOCK} -> do+        rw <- #{peek TagOpEtc, tagop.u.gen2.u.blockPermaLock.readLock} p+        ws <- peekListAsList (#{ptr TagOpEtc, tagop.u.gen2.u.blockPermaLock.mask} p) (#{ptr TagOpEtc, u.data16} p)+        TagOp_GEN2_BlockPermaLock+          <$> ((toBank . (.&. 3)) <$> #{peek TagOpEtc, tagop.u.gen2.u.blockPermaLock.bank} p)+          <*> #{peek TagOpEtc, tagop.u.gen2.u.blockPermaLock.blockPtr} p+          <*> (return $ toReadWrite (rw, ws))++  poke p x@(TagOp_GEN2_ReadData {}) = do+    #{poke TagOpEtc, tagop.type} p (#{const TMR_TAGOP_GEN2_READDATA} :: #{type TMR_TagOpType})+    #{poke TagOpEtc, tagop.u.gen2.u.readData.bank} p (fromBank $ opBank x)+    pokeOr (#{ptr TagOpEtc, tagop.u.gen2.u.readData.bank} p) (packExtraBanks $ opExtraBanks x)+    #{poke TagOpEtc, tagop.u.gen2.u.readData.wordAddress} p (opWordAddress x)+    #{poke TagOpEtc, tagop.u.gen2.u.readData.len} p (opLen x)++  poke p x@(TagOp_GEN2_WriteTag {}) = do+    #{poke TagOpEtc, tagop.type} p (#{const TMR_TAGOP_GEN2_WRITETAG} :: #{type TMR_TagOpType})+    pokePtr (#{ptr TagOpEtc, tagop.u.gen2.u.writeTag.epcptr} p) (#{ptr TagOpEtc, u.epc} p) (opEpc x)++  poke p x@(TagOp_GEN2_WriteData {}) = do+    #{poke TagOpEtc, tagop.type} p (#{const TMR_TAGOP_GEN2_WRITEDATA} :: #{type TMR_TagOpType})+    #{poke TagOpEtc, tagop.u.gen2.u.writeData.bank} p (fromBank $ opBank x)+    #{poke TagOpEtc, tagop.u.gen2.u.writeData.wordAddress} p (opWordAddress x)+    pokeListAsList "data" #{const GLUE_MAX_DATA16} (#{ptr TagOpEtc, tagop.u.gen2.u.writeData.data} p) (#{ptr TagOpEtc, u.data16} p) (opData x)++  poke p x@(TagOp_GEN2_Lock {}) = do+    #{poke TagOpEtc, tagop.type} p (#{const TMR_TAGOP_GEN2_LOCK} :: #{type TMR_TagOpType})+    #{poke TagOpEtc, tagop.u.gen2.u.lock.mask} p (packLockBits16 $ opMask x)+    #{poke TagOpEtc, tagop.u.gen2.u.lock.action} p (packLockBits16 $ opAction x)+    #{poke TagOpEtc, tagop.u.gen2.u.lock.accessPassword} p (opAccessPassword x)++  poke p x@(TagOp_GEN2_Kill {}) = do+    #{poke TagOpEtc, tagop.type} p (#{const TMR_TAGOP_GEN2_KILL} :: #{type TMR_TagOpType})+    #{poke TagOpEtc, tagop.u.gen2.u.kill.password} p (opPassword x)++  poke p x@(TagOp_GEN2_BlockWrite {}) = do+    #{poke TagOpEtc, tagop.type} p (#{const TMR_TAGOP_GEN2_BLOCKWRITE} :: #{type TMR_TagOpType})+    #{poke TagOpEtc, tagop.u.gen2.u.blockWrite.bank} p (fromBank $ opBank x)+    #{poke TagOpEtc, tagop.u.gen2.u.blockWrite.wordPtr} p (opWordPtr x)+    pokeListAsList "data" #{const GLUE_MAX_DATA16} (#{ptr TagOpEtc, tagop.u.gen2.u.blockWrite.data} p) (#{ptr TagOpEtc, u.data16} p) (opData x)++  poke p x@(TagOp_GEN2_BlockErase {}) = do+    #{poke TagOpEtc, tagop.type} p (#{const TMR_TAGOP_GEN2_BLOCKERASE} :: #{type TMR_TagOpType})+    #{poke TagOpEtc, tagop.u.gen2.u.blockErase.bank} p (fromBank $ opBank x)+    #{poke TagOpEtc, tagop.u.gen2.u.blockErase.wordPtr} p (opWordPtr x)+    #{poke TagOpEtc, tagop.u.gen2.u.blockErase.wordCount} p (opWordCount x)++  poke p x@(TagOp_GEN2_BlockPermaLock {}) = do+    let (rw, ws) = fromReadWrite $ opReadWrite x+    #{poke TagOpEtc, tagop.type} p (#{const TMR_TAGOP_GEN2_BLOCKPERMALOCK} :: #{type TMR_TagOpType})+    #{poke TagOpEtc, tagop.u.gen2.u.blockPermaLock.readLock} p rw+    #{poke TagOpEtc, tagop.u.gen2.u.blockPermaLock.bank} p (fromBank $ opBank x)+    #{poke TagOpEtc, tagop.u.gen2.u.blockPermaLock.blockPtr} p (opBlockPtr x)+    pokeListAsList "mask" #{const GLUE_MAX_DATA16} (#{ptr TagOpEtc, tagop.u.gen2.u.blockPermaLock.mask} p) (#{ptr TagOpEtc, u.data16} p) ws++tagOpName :: TagOp -> Text+tagOpName TagOp_GEN2_ReadData {} = "TagOp_GEN2_ReadData"+tagOpName TagOp_GEN2_WriteTag {} = "TagOp_GEN2_WriteTag"+tagOpName TagOp_GEN2_WriteData {} = "TagOp_GEN2_WriteData"+tagOpName TagOp_GEN2_Lock {} = "TagOp_GEN2_Lock"+tagOpName TagOp_GEN2_Kill {} = "TagOp_GEN2_Kill"+tagOpName TagOp_GEN2_BlockWrite {} = "TagOp_GEN2_BlockWrite"+tagOpName TagOp_GEN2_BlockErase {} = "TagOp_GEN2_BlockErase"+tagOpName TagOp_GEN2_BlockPermaLock {} = "TagOp_GEN2_BlockPermaLock"+
+ src/System/Hardware/MercuryApi/Testing.hsc view
@@ -0,0 +1,320 @@+{-# LANGUAGE OverloadedStrings #-}+{-# OPTIONS_HADDOCK hide #-}+{-|+Module      : System.Hardware.MercuryApi.Testing+Description : A serial transport for MercuryApi which replays data from a file+Copyright   : © Patrick Pelletier, 2017+License     : MIT+Maintainer  : code@funwithsoftware.org++This module is not meant to be used by the end user.  It exists for the+automated tests.  It provides a handler for URIs of the form+test:///path/to/file, where the file is in the format produced by+'opcodeListener'.  When Mercury API reads from the transport, the data+from a "Received:" line is returned.  When Mercury API writes to the+transport, the data is compared to the data in the "Sending:" line.+If the data does not match, an error message is printed, and+TMR_ERROR_TIMEOUT is returned.  (Timeout was chosen because it's the only+error that seems to be consistently propagated from the transport by+Mercury API.)+-}++module System.Hardware.MercuryApi.Testing+  ( registerTransportInit+  ) where++import Control.Applicative ( Applicative((<*>)), (<$>) )+import Control.Concurrent ( threadDelay )+import Control.Exception ( IOException, try )+import Control.Monad ( when )+import qualified Data.ByteString as B+import qualified Data.ByteString.Char8 as B8 ( unpack )+import Data.Char ( isDigit )+import Data.IORef ( IORef, writeIORef, readIORef, newIORef )+import Data.Monoid ( (<>) )+import qualified Data.Text as T+import qualified Data.Text.Encoding as T ( encodeUtf8 )+import qualified Data.Text.IO as T ( readFile, putStrLn )+import Data.Word ( Word8, Word32 )+import Foreign+    ( newStablePtr,+      Ptr,+      FunPtr,+      nullPtr,+      Storable(alignment, peek, peekByteOff, poke, pokeByteOff, sizeOf),+      freeStablePtr,+      deRefStablePtr,+      castStablePtrToPtr,+      castPtrToStablePtr,+      nullFunPtr,+      castPtr,+      copyArray )+import Foreign.C ( CString, withCAString, peekCAString )+import System.Info ( os )+import qualified System.IO.Unsafe as U ( unsafePerformIO )++import System.Hardware.MercuryApi hiding (read)++#include <tm_reader.h>+#include <glue.h>++type RawStatus = Word32++successStatus :: RawStatus+successStatus = #{const TMR_SUCCESS}++failureStatus :: RawStatus+failureStatus = #{const TMR_ERROR_TIMEOUT}++data SerialState =+  SerialState+  { ssFilename :: String+  , ssNext :: IORef [T.Text]+  , ssLeftover :: IORef B.ByteString+  , ssSendTime :: IORef Double+  }++data SerialTransport =+  SerialTransport+  { stCookie :: Ptr ()+  , stOpen :: FunPtr (Ptr SerialTransport -> IO RawStatus)+  , stSendBytes :: FunPtr (Ptr SerialTransport -> Word32 -> Ptr Word8 -> Word32 -> IO RawStatus)+  , stReceiveBytes :: FunPtr (Ptr SerialTransport -> Word32 -> Ptr Word32 -> Ptr Word8 -> Word32 -> IO RawStatus)+  , stSetBaudRate :: FunPtr (Ptr SerialTransport -> Word32 -> IO RawStatus)+  , stShutdown :: FunPtr (Ptr SerialTransport -> IO RawStatus)+  , stFlush :: FunPtr (Ptr SerialTransport -> IO RawStatus)+  }++instance Storable SerialTransport where+  sizeOf _ = #{size TMR_SR_SerialTransport}+  alignment _ = 8++  peek p =+    SerialTransport+    <$> #{peek TMR_SR_SerialTransport, cookie}       p+    <*> #{peek TMR_SR_SerialTransport, open}         p+    <*> #{peek TMR_SR_SerialTransport, sendBytes}    p+    <*> #{peek TMR_SR_SerialTransport, receiveBytes} p+    <*> #{peek TMR_SR_SerialTransport, setBaudRate}  p+    <*> #{peek TMR_SR_SerialTransport, shutdown}     p+    <*> #{peek TMR_SR_SerialTransport, flush}        p++  poke p x = do+    #{poke TMR_SR_SerialTransport, cookie}       p (stCookie x)+    #{poke TMR_SR_SerialTransport, open}         p (stOpen x)+    #{poke TMR_SR_SerialTransport, sendBytes}    p (stSendBytes x)+    #{poke TMR_SR_SerialTransport, receiveBytes} p (stReceiveBytes x)+    #{poke TMR_SR_SerialTransport, setBaudRate}  p (stSetBaudRate x)+    #{poke TMR_SR_SerialTransport, shutdown}     p (stShutdown x)+    #{poke TMR_SR_SerialTransport, flush}        p (stFlush x)++foreign import ccall "tm_reader.h TMR_setSerialTransport"+    c_TMR_setSerialTransport :: CString+                             -> FunPtr (Ptr SerialTransport -> Ptr () -> CString -> IO RawStatus)+                             -> IO RawStatus++foreign import ccall "wrapper"+    wrapOneArg :: (Ptr SerialTransport -> IO RawStatus)+               -> IO (FunPtr (Ptr SerialTransport -> IO RawStatus))++foreign import ccall "wrapper"+    wrapSendBytes :: (Ptr SerialTransport -> Word32 -> Ptr Word8 -> Word32 -> IO RawStatus)+                  -> IO (FunPtr (Ptr SerialTransport -> Word32 -> Ptr Word8 -> Word32 -> IO RawStatus))++foreign import ccall "wrapper"+    wrapReceiveBytes :: (Ptr SerialTransport -> Word32 -> Ptr Word32 -> Ptr Word8 -> Word32 -> IO RawStatus)+                     -> IO (FunPtr (Ptr SerialTransport -> Word32 -> Ptr Word32 -> Ptr Word8 -> Word32 -> IO RawStatus))++foreign import ccall "wrapper"+    wrapInit :: (Ptr SerialTransport -> Ptr () -> CString -> IO RawStatus)+             -> IO (FunPtr (Ptr SerialTransport -> Ptr () -> CString -> IO RawStatus))++funOpen :: FunPtr (Ptr SerialTransport -> IO RawStatus)+{-# NOINLINE funOpen #-}+funOpen = U.unsafePerformIO $ wrapOneArg testOpen++funSendBytes :: FunPtr (Ptr SerialTransport -> Word32 -> Ptr Word8 -> Word32 -> IO RawStatus)+{-# NOINLINE funSendBytes #-}+funSendBytes = U.unsafePerformIO $ wrapSendBytes testSendBytes++funReceiveBytes :: FunPtr (Ptr SerialTransport -> Word32 -> Ptr Word32 -> Ptr Word8 -> Word32 -> IO RawStatus)+{-# NOINLINE funReceiveBytes #-}+funReceiveBytes = U.unsafePerformIO $ wrapReceiveBytes testReceiveBytes++funShutdown :: FunPtr (Ptr SerialTransport -> IO RawStatus)+{-# NOINLINE funShutdown #-}+funShutdown = U.unsafePerformIO $ wrapOneArg testShutdown++funFlush :: FunPtr (Ptr SerialTransport -> IO RawStatus)+{-# NOINLINE funFlush #-}+funFlush = U.unsafePerformIO $ wrapOneArg testFlush++funTransportInit :: FunPtr (Ptr SerialTransport -> Ptr () -> CString -> IO RawStatus)+{-# NOINLINE funTransportInit #-}+funTransportInit = U.unsafePerformIO $ wrapInit testTransportInit++mkSerialTransport :: Ptr () -> SerialTransport+mkSerialTransport cookie =+  SerialTransport+  { stCookie = cookie+  , stOpen = funOpen+  , stSendBytes = funSendBytes+  , stReceiveBytes = funReceiveBytes+  , stSetBaudRate = nullFunPtr+  , stShutdown = funShutdown+  , stFlush = funFlush+  }++getState :: Ptr SerialTransport -> IO SerialState+getState p = do+  st <- peek p+  let stable = castPtrToStablePtr $ stCookie st+  deRefStablePtr stable++printIOException :: IOException -> IO ()+printIOException = print++testOpen :: Ptr SerialTransport -> IO RawStatus+testOpen p = do+  ss <- getState p+  eth <- try $ T.readFile (ssFilename ss)+  case eth of+    Left exc -> do+      printIOException exc+      return failureStatus+    Right txt -> do+      writeIORef (ssNext ss) (T.lines txt)+      return successStatus++parseTransportLine :: T.Text -> (Maybe TransportDirection, B.ByteString)+parseTransportLine txt =+  let txt' = T.takeWhile (/= '|') txt+      f d = if d == "Sending" then Tx else Rx+      (dir, mbs) = case T.splitOn ":" txt' of+                     [x] -> (Nothing, hexToBytes $ T.filter (/= ' ') x)+                     [d, x] -> (Just (f d),+                                Just $ T.encodeUtf8 $ T.dropWhile (not . isDigit) x)+                     _ -> (Nothing, Just "")+  in case mbs of+       Nothing -> (dir, "barf!")+       Just bs -> (dir, bs)++parseTransport :: [T.Text]+               -> Maybe (TransportDirection, B.ByteString, Double, [T.Text])+parseTransport [] = Nothing+parseTransport (t:ts) =+  let (Just dir, bs) = parseTransportLine t+      rest = takeWhile ((== Nothing) . fst) $ map parseTransportLine ts+      leftover = drop (length rest) ts+      bss = map snd rest+      tm = read $ B8.unpack bs+  in Just (dir, B.concat bss, tm, leftover)++takeNext :: SerialState -> IO (Maybe (TransportDirection, B.ByteString, Double))+takeNext ss = do+  let ref = ssNext ss+  ts <- readIORef ref+  let result = parseTransport ts+  case result of+    Nothing -> return Nothing+    Just (dir, bs, tm, ts') -> do+      writeIORef ref ts'+      return $ Just (dir, bs, tm)++testSendBytes :: Ptr SerialTransport+              -> Word32+              -> Ptr Word8+              -> Word32+              -> IO RawStatus+testSendBytes p len msg _ = do+  ss <- getState p+  nxt <- takeNext ss+  case nxt of+    Just (Tx, expected, tm) -> do+      writeIORef (ssSendTime ss) tm+      actual <- B.packCStringLen (castPtr msg, fromIntegral len)+      if actual == expected+        then return successStatus+        else do+        T.putStrLn ("expected <" <> bytesToHex expected <>+                    ">, but got <" <> bytesToHex actual <> ">")+        return failureStatus+    x -> do+      putStrLn $ "expected Tx, but got " ++ show x+      return failureStatus++computeDelay :: Double -> Double -> Int+computeDelay oldTime newTime =+  -- convert seconds to microseconds, and add a fudge factor of 10%+  ceiling $ (newTime - oldTime) * 1.1e6++getNextBytes :: SerialState -> IO (Either RawStatus B.ByteString)+getNextBytes ss = do+  leftover <- readIORef (ssLeftover ss)+  if B.null leftover+    then do+    nxt <- takeNext ss+    case nxt of+      Just (Rx, bs, tm) -> do+        sendTime <- readIORef (ssSendTime ss)+        threadDelay $ computeDelay sendTime tm+        return $ Right bs+      x -> do+        putStrLn $ "expected Rx, but got " ++ show x+        return $ Left failureStatus+    else return $ Right leftover++testReceiveBytes :: Ptr SerialTransport+                 -> Word32+                 -> Ptr Word32+                 -> Ptr Word8+                 -> Word32+                 -> IO RawStatus+testReceiveBytes p len returnLen msg _ = do+  ss <- getState p+  eth <- getNextBytes ss+  case eth of+    Left status -> return status+    Right bs -> do+      let (bs1, bs2) = B.splitAt (fromIntegral len) bs+      B.useAsCStringLen bs1 $ \(pChar, bsLen) -> do+        poke returnLen (fromIntegral len)+        copyArray msg (castPtr pChar) bsLen+      writeIORef (ssLeftover ss) bs2+      return successStatus++testFlush :: Ptr SerialTransport -> IO RawStatus+testFlush _ = return successStatus++testShutdown :: Ptr SerialTransport -> IO RawStatus+testShutdown p = do+  st <- peek p+  let stable = castPtrToStablePtr $ stCookie st+  freeStablePtr stable+  poke p st { stCookie = nullPtr }+  return successStatus++-- Somehow in Windows, we end up with an absolute path that+-- starts with "/C:", which doesn't work, so we need to strip+-- the leading slash.+hackPath :: String -> String -> String+hackPath "mingw32" = dropWhile (== '/')+hackPath _ = id++testTransportInit :: Ptr SerialTransport -> Ptr () -> CString -> IO RawStatus+testTransportInit p _ cstr = do+  fname <- hackPath os <$> peekCAString cstr+  ref <- newIORef []+  ref2 <- newIORef ""+  ref3 <- newIORef 0+  let ss = SerialState fname ref ref2 ref3+  stable <- newStablePtr ss+  let st = mkSerialTransport $ castStablePtrToPtr stable+  poke p st+  return successStatus++registerTransportInit :: IO ()+registerTransportInit = do+  withCAString "test" $ \name -> do+    status <- c_TMR_setSerialTransport name funTransportInit+    when (status /= successStatus) $ fail "TMR_setSerialTransport failed"
+ tests/blockErase.result view
@@ -0,0 +1,5 @@+Right 1+Right (TagReadData {trTag = TagData {tdEpc = "\226\NULQ\134\SOH\a\SOH\135\ap\196\193", tdProtocol = TAG_PROTOCOL_GEN2, tdCrc = 47646, tdGen2 = Just (GEN2_TagData {g2Pc = "0\NUL"})}, trMetadataFlags = [METADATA_FLAG_READCOUNT,METADATA_FLAG_RSSI,METADATA_FLAG_ANTENNAID,METADATA_FLAG_FREQUENCY,METADATA_FLAG_TIMESTAMP,METADATA_FLAG_PHASE,METADATA_FLAG_PROTOCOL,METADATA_FLAG_DATA,METADATA_FLAG_GPIO_STATUS], trPhase = 174, trAntenna = 1, trGpio = [GpioPin {gpId = 1, gpHigh = False, gpOutput = False},GpioPin {gpId = 2, gpHigh = False, gpOutput = False},GpioPin {gpId = 3, gpHigh = False, gpOutput = False},GpioPin {gpId = 4, gpHigh = False, gpOutput = False}], trReadCount = 18, trRssi = -44, trFrequency = 922600, trTimestamp = 0, trData = "", trEpcMemData = "", trTidMemData = "", trUserMemData = "", trReservedMemData = ""})+Right ""+Right 1+Right (TagReadData {trTag = TagData {tdEpc = "\226\NULQ\134\SOH\a\SOH\135\ap\196\193", tdProtocol = TAG_PROTOCOL_GEN2, tdCrc = 47646, tdGen2 = Just (GEN2_TagData {g2Pc = "0\NUL"})}, trMetadataFlags = [METADATA_FLAG_READCOUNT,METADATA_FLAG_RSSI,METADATA_FLAG_ANTENNAID,METADATA_FLAG_FREQUENCY,METADATA_FLAG_TIMESTAMP,METADATA_FLAG_PHASE,METADATA_FLAG_PROTOCOL,METADATA_FLAG_DATA,METADATA_FLAG_GPIO_STATUS], trPhase = 174, trAntenna = 1, trGpio = [GpioPin {gpId = 1, gpHigh = False, gpOutput = False},GpioPin {gpId = 2, gpHigh = False, gpOutput = False},GpioPin {gpId = 3, gpHigh = False, gpOutput = False},GpioPin {gpId = 4, gpHigh = False, gpOutput = False}], trReadCount = 22, trRssi = -40, trFrequency = 918400, trTimestamp = 0, trData = "\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL", trEpcMemData = "", trTidMemData = "", trUserMemData = "", trReservedMemData = ""})
+ tests/blockErase.transport view
@@ -0,0 +1,118 @@+Sending: VERSION                       1733450.679602521+         ff 00 03 1d 0c                                    |.....|+Received:VERSION                       1733450.684134700+         ff 14 03 00 00 14 12 08  00 30 00 00 02 20 16 12  |.........0... ..|+         13 01 07 01 02 00 00 00  10 1b 05                 |...........|+Sending: GET_CURRENT_PROGRAM           1733450.684657205+         ff 00 0c 1d 03                                    |.....|+Received:GET_CURRENT_PROGRAM           1733450.686277606+         ff 01 0c 00 00 52 63 03                           |.....Rc.|+Sending: GET_POWER_MODE                1733450.686375908+         ff 00 68 1d 67                                    |..h.g|+Received:GET_POWER_MODE                1733450.688135301+         ff 01 68 00 00 00 a4 bf                           |..h.....|+Sending: GET_READER_OPTIONAL_PARAMS    1733450.688284351+         ff 02 6a 01 0e 2e 40                              |..j...@|+Received:GET_READER_OPTIONAL_PARAMS    1733450.690435237+         ff 03 6a 00 00 01 0e 00  30 44                    |..j.....0D|+Sending: GET_READER_OPTIONAL_PARAMS    1733450.698289611+         ff 02 6a 01 12 2e 5c                              |..j...\|+Received:GET_READER_OPTIONAL_PARAMS    1733450.700384916+         ff 04 6a 00 00 01 12 00  00 69 af                 |..j......i.|+Sending: GET_TAG_PROTOCOL              1733450.700490046+         ff 00 63 1d 6c                                    |..c.l|+Received:GET_TAG_PROTOCOL              1733450.702188454+         ff 02 63 00 00 00 05 21  46                       |..c....!F|+Sending: GET_ANTENNA_PORT              1733450.702288657+         ff 01 61 05 bd b8                                 |..a...|+Received:GET_ANTENNA_PORT              1733450.704364082+         ff 03 61 00 00 05 01 00  61 df                    |..a.....a.|+Sending: GET_READER_OPTIONAL_PARAMS    1733450.704576636+         ff 02 6a 01 0c 2e 42                              |..j...B|+Received:GET_READER_OPTIONAL_PARAMS    1733450.706714766+         ff 03 6a 00 00 01 0c 01  32 45                    |..j.....2E|+Sending: GET_READER_OPTIONAL_PARAMS    1733450.706873798+         ff 02 6a 01 0d 2e 43                              |..j...C|+Received:GET_READER_OPTIONAL_PARAMS    1733450.709308529+         ff 06 6a 00 00 01 0d 00  00 00 00 15 43           |..j.........C|+Sending: SET_REGION                    1733450.709501081+         ff 01 97 0d 4b b0                                 |....K.|+Received:SET_REGION                    1733450.711348767+         ff 00 97 00 00 77 9e                              |.....w.|+Sending: SET_READ_TX_POWER             1733450.711558562+         ff 02 92 08 98 49 c1                              |.....I.|+Received:SET_READ_TX_POWER             1733450.713440798+         ff 00 92 00 00 27 3b                              |.....';|+Sending: SET_WRITE_TX_POWER            1733450.713578366+         ff 02 94 08 98 29 07                              |.....).|+Received:SET_WRITE_TX_POWER            1733450.715466506+         ff 00 94 00 00 47 fd                              |.....G.|+Sending: SET_ANTENNA_PORT              1733450.715640398+         ff 02 91 01 01 70 3b                              |.....p;|+Received:SET_ANTENNA_PORT              1733450.717565537+         ff 00 91 00 00 17 58                              |......X|+Sending: SET_READER_OPTIONAL_PARAMS    1733450.717697069+         ff 03 9a 01 06 01 a9 5c                           |.......\|+Received:SET_READER_OPTIONAL_PARAMS    1733450.719718857+         ff 00 9a 00 00 a6 33                              |......3|+Sending: GET_READER_STATS              1733450.719880829+         ff 03 6c 01 9f 41 89 7b                           |..l..A.{|+Received:GET_READER_STATS              1733450.722077569+         ff 03 6c 00 00 01 9f 41  86 9c                    |..l....A..|+Sending: CLEAR_TAG_ID_BUFFER           1733450.722247530+         ff 00 2a 1d 25                                    |..*.%|+Received:CLEAR_TAG_ID_BUFFER           1733450.723941906+         ff 00 2a 00 00 01 e8                              |..*....|+Sending: SET_ANTENNA_PORT              1733450.724084225+         ff 03 91 02 01 01 42 c5                           |......B.|+Received:SET_ANTENNA_PORT              1733450.726101108+         ff 00 91 00 00 17 58                              |......X|+Sending: READ_TAG_ID_MULTIPLE          1733450.726243987+         ff 16 22 03 00 13 03 e8  00 00 00 00 00 00 00 00  |..".............|+         40 00 01 02 03 04 05 06  07 8f 1e                 |@..........|+Received:READ_TAG_ID_MULTIPLE          1733451.734947047+         ff 07 22 00 00 03 00 13  00 00 00 01 65 8a        |..".........e.|+Sending: GET_TAG_ID_BUFFER             1733451.735124397+         ff 03 29 01 ff 00 1b 03                           |..).....|+Received:GET_TAG_ID_BUFFER             1733451.740349899+         ff 26 29 00 00 01 ff 00  01 12 d4 11 0e 13 e8 00  |.&).............|+         00 03 07 00 ae 05 00 00  00 00 80 30 00 e2 00 51  |...........0...Q|+         86 01 07 01 87 07 70 c4  c1 ba 1e 47 2c           |......p....G,|+Sending: ERASE_BLOCK_TAG_SPECIFIC      1733451.740792941+         ff 1c 2e 03 e8 00 41 00  00 00 00 00 60 e2 00 51  |......A.....`..Q|+         86 01 07 01 87 07 70 c4  c1 00 00 00 00 03 04 36  |......p........6|+         2a                                                |*|+Received:ERASE_BLOCK_TAG_SPECIFIC      1733451.774187155+         ff 00 2e 00 00 41 6c                              |.....Al|+Sending: GET_READER_STATS              1733451.774381812+         ff 03 6c 01 9f 41 89 7b                           |..l..A.{|+Received:GET_READER_STATS              1733451.776784092+         ff 03 6c 00 00 01 9f 41  86 9c                    |..l....A..|+Sending: CLEAR_TAG_ID_BUFFER           1733451.776983355+         ff 00 2a 1d 25                                    |..*.%|+Received:CLEAR_TAG_ID_BUFFER           1733451.778708021+         ff 00 2a 00 00 01 e8                              |..*....|+Sending: SET_ANTENNA_PORT              1733451.778890524+         ff 03 91 02 01 01 42 c5                           |......B.|+Received:SET_ANTENNA_PORT              1733451.780914629+         ff 00 91 00 00 17 58                              |......X|+Sending: READ_TAG_ID_MULTIPLE          1733451.781081920+         ff 11 22 00 00 17 03 e8  01 09 28 07 d0 00 03 00  |..".......(.....|+         00 00 00 20 49 70                                 |... Ip|+Received:READ_TAG_ID_MULTIPLE          1733452.808667838+         ff 4d 22 00 00 00 00 17  00 00 00 01 01 28 00 16  |.M"..........(..|+         00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|+         00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|+         00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|+         00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|+         00 00 e4 bf                                       |....|+Sending: GET_TAG_ID_BUFFER             1733452.809593767+         ff 03 29 01 ff 00 1b 03                           |..).....|+Received:GET_TAG_ID_BUFFER             1733452.820884567+         ff 66 29 00 00 01 ff 00  01 16 d8 11 0e 03 80 00  |.f).............|+         00 01 8f 00 ae 05 02 00  00 00 00 00 00 00 00 00  |................|+         00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|+         00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|+         00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|+         00 00 00 00 00 00 00 00  00 00 80 30 00 e2 00 51  |...........0...Q|+         86 01 07 01 87 07 70 c4  c1 ba 1e 4b f7           |......p....K.|
+ tests/blockPermalockRead.result view
@@ -0,0 +1,3 @@+Right 1+Right (TagReadData {trTag = TagData {tdEpc = "\226\NUL\NUL\NAK\134\SO\SOH\134\DLEP\178\ENQ", tdProtocol = TAG_PROTOCOL_GEN2, tdCrc = 17157, tdGen2 = Just (GEN2_TagData {g2Pc = "4\NUL"})}, trMetadataFlags = [METADATA_FLAG_READCOUNT,METADATA_FLAG_RSSI,METADATA_FLAG_ANTENNAID,METADATA_FLAG_FREQUENCY,METADATA_FLAG_TIMESTAMP,METADATA_FLAG_PHASE,METADATA_FLAG_PROTOCOL,METADATA_FLAG_DATA,METADATA_FLAG_GPIO_STATUS], trPhase = 174, trAntenna = 1, trGpio = [GpioPin {gpId = 1, gpHigh = False, gpOutput = False},GpioPin {gpId = 2, gpHigh = False, gpOutput = False},GpioPin {gpId = 3, gpHigh = False, gpOutput = False},GpioPin {gpId = 4, gpHigh = False, gpOutput = False}], trReadCount = 29, trRssi = -36, trFrequency = 922600, trTimestamp = 0, trData = "", trEpcMemData = "", trTidMemData = "", trUserMemData = "", trReservedMemData = ""})+Right "\NUL\NUL"
+ tests/blockPermalockRead.transport view
@@ -0,0 +1,86 @@+Sending: VERSION                       1829051.749487169+         ff 00 03 1d 0c                                    |.....|+Received:VERSION                       1829051.754158098+         ff 14 03 00 00 14 12 08  00 30 00 00 02 20 16 12  |.........0... ..|+         13 01 07 01 02 00 00 00  10 1b 05                 |...........|+Sending: GET_CURRENT_PROGRAM           1829051.754732547+         ff 00 0c 1d 03                                    |.....|+Received:GET_CURRENT_PROGRAM           1829051.756325310+         ff 01 0c 00 00 52 63 03                           |.....Rc.|+Sending: GET_POWER_MODE                1829051.756433837+         ff 00 68 1d 67                                    |..h.g|+Received:GET_POWER_MODE                1829051.758001346+         ff 01 68 00 00 00 a4 bf                           |..h.....|+Sending: GET_READER_OPTIONAL_PARAMS    1829051.758097441+         ff 02 6a 01 0e 2e 40                              |..j...@|+Received:GET_READER_OPTIONAL_PARAMS    1829051.760214239+         ff 03 6a 00 00 01 0e 00  30 44                    |..j.....0D|+Sending: GET_READER_OPTIONAL_PARAMS    1829051.768183546+         ff 02 6a 01 12 2e 5c                              |..j...\|+Received:GET_READER_OPTIONAL_PARAMS    1829051.770281602+         ff 04 6a 00 00 01 12 00  00 69 af                 |..j......i.|+Sending: GET_TAG_PROTOCOL              1829051.770397735+         ff 00 63 1d 6c                                    |..c.l|+Received:GET_TAG_PROTOCOL              1829051.772015315+         ff 02 63 00 00 00 05 21  46                       |..c....!F|+Sending: GET_ANTENNA_PORT              1829051.772120484+         ff 01 61 05 bd b8                                 |..a...|+Received:GET_ANTENNA_PORT              1829051.774081569+         ff 03 61 00 00 05 01 00  61 df                    |..a.....a.|+Sending: GET_READER_OPTIONAL_PARAMS    1829051.774218216+         ff 02 6a 01 0c 2e 42                              |..j...B|+Received:GET_READER_OPTIONAL_PARAMS    1829051.776219065+         ff 03 6a 00 00 01 0c 01  32 45                    |..j.....2E|+Sending: GET_READER_OPTIONAL_PARAMS    1829051.776383680+         ff 02 6a 01 0d 2e 43                              |..j...C|+Received:GET_READER_OPTIONAL_PARAMS    1829051.778820450+         ff 06 6a 00 00 01 0d 00  00 00 00 15 43           |..j.........C|+Sending: SET_REGION                    1829051.779002895+         ff 01 97 0d 4b b0                                 |....K.|+Received:SET_REGION                    1829051.780904919+         ff 00 97 00 00 77 9e                              |.....w.|+Sending: SET_READ_TX_POWER             1829051.781086964+         ff 02 92 08 98 49 c1                              |.....I.|+Received:SET_READ_TX_POWER             1829051.782951692+         ff 00 92 00 00 27 3b                              |.....';|+Sending: SET_WRITE_TX_POWER            1829051.783084670+         ff 02 94 08 98 29 07                              |.....).|+Received:SET_WRITE_TX_POWER            1829051.784973813+         ff 00 94 00 00 47 fd                              |.....G.|+Sending: SET_ANTENNA_PORT              1829051.785227705+         ff 02 91 01 01 70 3b                              |.....p;|+Received:SET_ANTENNA_PORT              1829051.787167999+         ff 00 91 00 00 17 58                              |......X|+Sending: SET_READER_OPTIONAL_PARAMS    1829051.787303537+         ff 03 9a 01 06 01 a9 5c                           |.......\|+Received:SET_READER_OPTIONAL_PARAMS    1829051.789354238+         ff 00 9a 00 00 a6 33                              |......3|+Sending: GET_READER_STATS              1829051.789507837+         ff 03 6c 01 9f 41 89 7b                           |..l..A.{|+Received:GET_READER_STATS              1829051.791778681+         ff 03 6c 00 00 01 9f 41  86 9c                    |..l....A..|+Sending: CLEAR_TAG_ID_BUFFER           1829051.791937775+         ff 00 2a 1d 25                                    |..*.%|+Received:CLEAR_TAG_ID_BUFFER           1829051.793646752+         ff 00 2a 00 00 01 e8                              |..*....|+Sending: SET_ANTENNA_PORT              1829051.793796892+         ff 03 91 02 01 01 42 c5                           |......B.|+Received:SET_ANTENNA_PORT              1829051.795843593+         ff 00 91 00 00 17 58                              |......X|+Sending: READ_TAG_ID_MULTIPLE          1829051.795998706+         ff 1a 22 03 00 13 03 e8  00 00 00 00 00 00 00 00  |..".............|+         60 70 65 72 6d 61 6c 6f  63 6b 20 6d 65 0d 10     |`permalock me..|+Received:READ_TAG_ID_MULTIPLE          1829052.807263318+         ff 07 22 00 00 03 00 13  00 00 00 01 65 8a        |..".........e.|+Sending: GET_TAG_ID_BUFFER             1829052.807500776+         ff 03 29 01 ff 00 1b 03                           |..).....|+Received:GET_TAG_ID_BUFFER             1829052.813042126+         ff 26 29 00 00 01 ff 00  01 1d dc 11 0e 13 e8 00  |.&).............|+         00 03 66 00 ae 05 00 00  00 00 80 34 00 e2 00 00  |..f........4....|+         15 86 0e 01 86 10 50 b2  05 43 05 c6 5e           |......P..C..^|+Sending: ERASE_BLOCK_TAG_SPECIFIC      1829052.816943258+         ff 1e 2e 03 e8 00 41 01  00 00 00 00 60 e2 00 00  |......A.....`...|+         15 86 0e 01 86 10 50 b2  05 00 00 03 00 00 00 00  |......P.........|+         01 66 1b                                          |.f.|+Received:ERASE_BLOCK_TAG_SPECIFIC      1829052.840513132+         ff 04 2e 00 00 41 01 00  00 de 5f                 |.....A...._|
+ tests/blockPermalockWrite.result view
@@ -0,0 +1,38 @@+Right 1+Right (TagReadData {trTag = TagData {tdEpc = "\226\NUL\NUL\NAK\134\SO\SOH\134\DLEP\178\ENQ", tdProtocol = TAG_PROTOCOL_GEN2, tdCrc = 17157, tdGen2 = Just (GEN2_TagData {g2Pc = "4\NUL"})}, trMetadataFlags = [METADATA_FLAG_READCOUNT,METADATA_FLAG_RSSI,METADATA_FLAG_ANTENNAID,METADATA_FLAG_FREQUENCY,METADATA_FLAG_TIMESTAMP,METADATA_FLAG_PHASE,METADATA_FLAG_PROTOCOL,METADATA_FLAG_DATA,METADATA_FLAG_GPIO_STATUS], trPhase = 174, trAntenna = 1, trGpio = [GpioPin {gpId = 1, gpHigh = False, gpOutput = False},GpioPin {gpId = 2, gpHigh = False, gpOutput = False},GpioPin {gpId = 3, gpHigh = False, gpOutput = False},GpioPin {gpId = 4, gpHigh = False, gpOutput = False}], trReadCount = 29, trRssi = -36, trFrequency = 922600, trTimestamp = 0, trData = "", trEpcMemData = "", trTidMemData = "", trUserMemData = "", trReservedMemData = ""})+Right ""+Left (MercuryException {meStatusType = ERROR_TYPE_CODE, meStatus = ERROR_PROTOCOL_WRITE_FAILED, meMessage = "Tag write operation failed", meLocation = "executeTagOp", meParam = "TagOp_GEN2_WriteData", meUri = ""})+Left (MercuryException {meStatusType = ERROR_TYPE_CODE, meStatus = ERROR_PROTOCOL_WRITE_FAILED, meMessage = "Tag write operation failed", meLocation = "executeTagOp", meParam = "TagOp_GEN2_WriteData", meUri = ""})+Left (MercuryException {meStatusType = ERROR_TYPE_CODE, meStatus = ERROR_PROTOCOL_WRITE_FAILED, meMessage = "Tag write operation failed", meLocation = "executeTagOp", meParam = "TagOp_GEN2_WriteData", meUri = ""})+Left (MercuryException {meStatusType = ERROR_TYPE_CODE, meStatus = ERROR_PROTOCOL_WRITE_FAILED, meMessage = "Tag write operation failed", meLocation = "executeTagOp", meParam = "TagOp_GEN2_WriteData", meUri = ""})+Right ""+Right ""+Right ""+Right ""+Left (MercuryException {meStatusType = ERROR_TYPE_CODE, meStatus = ERROR_PROTOCOL_WRITE_FAILED, meMessage = "Tag write operation failed", meLocation = "executeTagOp", meParam = "TagOp_GEN2_WriteData", meUri = ""})+Left (MercuryException {meStatusType = ERROR_TYPE_CODE, meStatus = ERROR_PROTOCOL_WRITE_FAILED, meMessage = "Tag write operation failed", meLocation = "executeTagOp", meParam = "TagOp_GEN2_WriteData", meUri = ""})+Left (MercuryException {meStatusType = ERROR_TYPE_CODE, meStatus = ERROR_PROTOCOL_WRITE_FAILED, meMessage = "Tag write operation failed", meLocation = "executeTagOp", meParam = "TagOp_GEN2_WriteData", meUri = ""})+Left (MercuryException {meStatusType = ERROR_TYPE_CODE, meStatus = ERROR_PROTOCOL_WRITE_FAILED, meMessage = "Tag write operation failed", meLocation = "executeTagOp", meParam = "TagOp_GEN2_WriteData", meUri = ""})+Right ""+Right ""+Right ""+Right ""+Left (MercuryException {meStatusType = ERROR_TYPE_CODE, meStatus = ERROR_PROTOCOL_WRITE_FAILED, meMessage = "Tag write operation failed", meLocation = "executeTagOp", meParam = "TagOp_GEN2_WriteData", meUri = ""})+Left (MercuryException {meStatusType = ERROR_TYPE_CODE, meStatus = ERROR_PROTOCOL_WRITE_FAILED, meMessage = "Tag write operation failed", meLocation = "executeTagOp", meParam = "TagOp_GEN2_WriteData", meUri = ""})+Left (MercuryException {meStatusType = ERROR_TYPE_CODE, meStatus = ERROR_PROTOCOL_WRITE_FAILED, meMessage = "Tag write operation failed", meLocation = "executeTagOp", meParam = "TagOp_GEN2_WriteData", meUri = ""})+Left (MercuryException {meStatusType = ERROR_TYPE_CODE, meStatus = ERROR_PROTOCOL_WRITE_FAILED, meMessage = "Tag write operation failed", meLocation = "executeTagOp", meParam = "TagOp_GEN2_WriteData", meUri = ""})+Right ""+Right ""+Right ""+Right ""+Left (MercuryException {meStatusType = ERROR_TYPE_CODE, meStatus = ERROR_PROTOCOL_WRITE_FAILED, meMessage = "Tag write operation failed", meLocation = "executeTagOp", meParam = "TagOp_GEN2_WriteData", meUri = ""})+Left (MercuryException {meStatusType = ERROR_TYPE_CODE, meStatus = ERROR_PROTOCOL_WRITE_FAILED, meMessage = "Tag write operation failed", meLocation = "executeTagOp", meParam = "TagOp_GEN2_WriteData", meUri = ""})+Left (MercuryException {meStatusType = ERROR_TYPE_CODE, meStatus = ERROR_PROTOCOL_WRITE_FAILED, meMessage = "Tag write operation failed", meLocation = "executeTagOp", meParam = "TagOp_GEN2_WriteData", meUri = ""})+Left (MercuryException {meStatusType = ERROR_TYPE_CODE, meStatus = ERROR_PROTOCOL_WRITE_FAILED, meMessage = "Tag write operation failed", meLocation = "executeTagOp", meParam = "TagOp_GEN2_WriteData", meUri = ""})+Right ""+Right ""+Right ""+Right ""+Right 1+Right (TagReadData {trTag = TagData {tdEpc = "\226\NUL\NUL\NAK\134\SO\SOH\134\DLEP\178\ENQ", tdProtocol = TAG_PROTOCOL_GEN2, tdCrc = 17157, tdGen2 = Just (GEN2_TagData {g2Pc = "4\NUL"})}, trMetadataFlags = [METADATA_FLAG_READCOUNT,METADATA_FLAG_RSSI,METADATA_FLAG_ANTENNAID,METADATA_FLAG_FREQUENCY,METADATA_FLAG_TIMESTAMP,METADATA_FLAG_PHASE,METADATA_FLAG_PROTOCOL,METADATA_FLAG_DATA,METADATA_FLAG_GPIO_STATUS], trPhase = 174, trAntenna = 1, trGpio = [GpioPin {gpId = 1, gpHigh = False, gpOutput = False},GpioPin {gpId = 2, gpHigh = False, gpOutput = False},GpioPin {gpId = 3, gpHigh = False, gpOutput = False},GpioPin {gpId = 4, gpHigh = False, gpOutput = False}], trReadCount = 22, trRssi = -34, trFrequency = 921600, trTimestamp = 0, trData = "permaloc\NUL\EOT\NUL\ENQ\NUL\ACK\NUL\a        \NUL\f\NUL\r\NUL\SO\NUL\SI        \NUL\DC4\NUL\NAK\NUL\SYN\NUL\ETB        \NUL\FS\NUL\GS\NUL\RS\NUL\US", trEpcMemData = "", trTidMemData = "", trUserMemData = "", trReservedMemData = ""})+Right "\170\NUL"
+ tests/blockPermalockWrite.transport view
@@ -0,0 +1,284 @@+Sending: VERSION                       1829749.010225401+         ff 00 03 1d 0c                                    |.....|+Received:VERSION                       1829749.013984210+         ff 14 03 00 00 14 12 08  00 30 00 00 02 20 16 12  |.........0... ..|+         13 01 07 01 02 00 00 00  10 1b 05                 |...........|+Sending: GET_CURRENT_PROGRAM           1829749.014793598+         ff 00 0c 1d 03                                    |.....|+Received:GET_CURRENT_PROGRAM           1829749.016562806+         ff 01 0c 00 00 52 63 03                           |.....Rc.|+Sending: GET_POWER_MODE                1829749.016810252+         ff 00 68 1d 67                                    |..h.g|+Received:GET_POWER_MODE                1829749.018482575+         ff 01 68 00 00 00 a4 bf                           |..h.....|+Sending: GET_READER_OPTIONAL_PARAMS    1829749.018608322+         ff 02 6a 01 0e 2e 40                              |..j...@|+Received:GET_READER_OPTIONAL_PARAMS    1829749.020623429+         ff 03 6a 00 00 01 0e 00  30 44                    |..j.....0D|+Sending: GET_READER_OPTIONAL_PARAMS    1829749.021754159+         ff 02 6a 01 12 2e 5c                              |..j...\|+Received:GET_READER_OPTIONAL_PARAMS    1829749.023878015+         ff 04 6a 00 00 01 12 00  00 69 af                 |..j......i.|+Sending: GET_TAG_PROTOCOL              1829749.024026326+         ff 00 63 1d 6c                                    |..c.l|+Received:GET_TAG_PROTOCOL              1829749.025740344+         ff 02 63 00 00 00 05 21  46                       |..c....!F|+Sending: GET_ANTENNA_PORT              1829749.025881277+         ff 01 61 05 bd b8                                 |..a...|+Received:GET_ANTENNA_PORT              1829749.027831871+         ff 03 61 00 00 05 01 00  61 df                    |..a.....a.|+Sending: GET_READER_OPTIONAL_PARAMS    1829749.027988101+         ff 02 6a 01 0c 2e 42                              |..j...B|+Received:GET_READER_OPTIONAL_PARAMS    1829749.029953161+         ff 03 6a 00 00 01 0c 01  32 45                    |..j.....2E|+Sending: GET_READER_OPTIONAL_PARAMS    1829749.030069038+         ff 02 6a 01 0d 2e 43                              |..j...C|+Received:GET_READER_OPTIONAL_PARAMS    1829749.032468987+         ff 06 6a 00 00 01 0d 00  00 00 00 15 43           |..j.........C|+Sending: SET_REGION                    1829749.032668048+         ff 01 97 0d 4b b0                                 |....K.|+Received:SET_REGION                    1829749.034531357+         ff 00 97 00 00 77 9e                              |.....w.|+Sending: SET_READ_TX_POWER             1829749.034720522+         ff 02 92 08 98 49 c1                              |.....I.|+Received:SET_READ_TX_POWER             1829749.036607567+         ff 00 92 00 00 27 3b                              |.....';|+Sending: SET_WRITE_TX_POWER            1829749.036735988+         ff 02 94 08 98 29 07                              |.....).|+Received:SET_WRITE_TX_POWER            1829749.038506907+         ff 00 94 00 00 47 fd                              |.....G.|+Sending: SET_ANTENNA_PORT              1829749.038650766+         ff 02 91 01 01 70 3b                              |.....p;|+Received:SET_ANTENNA_PORT              1829749.040334163+         ff 00 91 00 00 17 58                              |......X|+Sending: SET_READER_OPTIONAL_PARAMS    1829749.040436892+         ff 03 9a 01 06 01 a9 5c                           |.......\|+Received:SET_READER_OPTIONAL_PARAMS    1829749.042469035+         ff 00 9a 00 00 a6 33                              |......3|+Sending: GET_READER_STATS              1829749.042628435+         ff 03 6c 01 9f 41 89 7b                           |..l..A.{|+Received:GET_READER_STATS              1829749.044924815+         ff 03 6c 00 00 01 9f 41  86 9c                    |..l....A..|+Sending: CLEAR_TAG_ID_BUFFER           1829749.045087626+         ff 00 2a 1d 25                                    |..*.%|+Received:CLEAR_TAG_ID_BUFFER           1829749.046781026+         ff 00 2a 00 00 01 e8                              |..*....|+Sending: SET_ANTENNA_PORT              1829749.046931097+         ff 03 91 02 01 01 42 c5                           |......B.|+Received:SET_ANTENNA_PORT              1829749.048977941+         ff 00 91 00 00 17 58                              |......X|+Sending: READ_TAG_ID_MULTIPLE          1829749.049135083+         ff 1a 22 03 00 13 03 e8  00 00 00 00 00 00 00 00  |..".............|+         60 70 65 72 6d 61 6c 6f  63 6b 20 6d 65 0d 10     |`permalock me..|+Received:READ_TAG_ID_MULTIPLE          1829750.056628187+         ff 07 22 00 00 03 00 13  00 00 00 01 65 8a        |..".........e.|+Sending: GET_TAG_ID_BUFFER             1829750.056804295+         ff 03 29 01 ff 00 1b 03                           |..).....|+Received:GET_TAG_ID_BUFFER             1829750.062018018+         ff 26 29 00 00 01 ff 00  01 1d dc 11 0e 13 e8 00  |.&).............|+         00 03 0b 00 ae 05 00 00  00 00 80 34 00 e2 00 00  |...........4....|+         15 86 0e 01 86 10 50 b2  05 43 05 9e 57           |......P..C..W|+Sending: ERASE_BLOCK_TAG_SPECIFIC      1829750.065369420+         ff 20 2e 03 e8 00 41 01  00 00 00 00 60 e2 00 00  |. ....A.....`...|+         15 86 0e 01 86 10 50 b2  05 00 01 03 00 00 00 00  |......P.........|+         01 aa 00 60 1e                                    |...`.|+Received:ERASE_BLOCK_TAG_SPECIFIC      1829750.112401542+         ff 00 2e 00 00 41 6c                              |.....Al|+Sending: WRITE_TAG_DATA                1829750.112821077+         ff 1b 24 03 e8 01 00 00  00 00 03 00 00 00 00 60  |..$............`|+         e2 00 00 15 86 0e 01 86  10 50 b2 05 00 00 12 f7  |.........P......|+Received:WRITE_TAG_DATA                1829751.142148716+         ff 00 24 04 06 e4 20                              |..$... |+Sending: WRITE_TAG_DATA                1829751.142397556+         ff 1b 24 03 e8 01 00 00  00 01 03 00 00 00 00 60  |..$............`|+         e2 00 00 15 86 0e 01 86  10 50 b2 05 00 01 cc e9  |.........P......|+Received:WRITE_TAG_DATA                1829752.152142164+         ff 00 24 04 06 e4 20                              |..$... |+Sending: WRITE_TAG_DATA                1829752.152418941+         ff 1b 24 03 e8 01 00 00  00 02 03 00 00 00 00 60  |..$............`|+         e2 00 00 15 86 0e 01 86  10 50 b2 05 00 02 be ea  |.........P......|+Received:WRITE_TAG_DATA                1829753.171222351+         ff 00 24 04 06 e4 20                              |..$... |+Sending: WRITE_TAG_DATA                1829753.171502860+         ff 1b 24 03 e8 01 00 00  00 03 03 00 00 00 00 60  |..$............`|+         e2 00 00 15 86 0e 01 86  10 50 b2 05 00 03 60 f4  |.........P....`.|+Received:WRITE_TAG_DATA                1829754.193508531+         ff 00 24 04 06 e4 20                              |..$... |+Sending: WRITE_TAG_DATA                1829754.193796103+         ff 1b 24 03 e8 01 00 00  00 04 03 00 00 00 00 60  |..$............`|+         e2 00 00 15 86 0e 01 86  10 50 b2 05 00 04 5a ec  |.........P....Z.|+Received:WRITE_TAG_DATA                1829754.222549247+         ff 00 24 00 00 e0 26                              |..$...&|+Sending: WRITE_TAG_DATA                1829754.222738514+         ff 1b 24 03 e8 01 00 00  00 05 03 00 00 00 00 60  |..$............`|+         e2 00 00 15 86 0e 01 86  10 50 b2 05 00 05 84 f2  |.........P......|+Received:WRITE_TAG_DATA                1829754.251609957+         ff 00 24 00 00 e0 26                              |..$...&|+Sending: WRITE_TAG_DATA                1829754.251872514+         ff 1b 24 03 e8 01 00 00  00 06 03 00 00 00 00 60  |..$............`|+         e2 00 00 15 86 0e 01 86  10 50 b2 05 00 06 f6 f1  |.........P......|+Received:WRITE_TAG_DATA                1829754.280762468+         ff 00 24 00 00 e0 26                              |..$...&|+Sending: WRITE_TAG_DATA                1829754.281006941+         ff 1b 24 03 e8 01 00 00  00 07 03 00 00 00 00 60  |..$............`|+         e2 00 00 15 86 0e 01 86  10 50 b2 05 00 07 28 ef  |.........P....(.|+Received:WRITE_TAG_DATA                1829754.309970159+         ff 00 24 00 00 e0 26                              |..$...&|+Sending: WRITE_TAG_DATA                1829754.310172608+         ff 1b 24 03 e8 01 00 00  00 08 03 00 00 00 00 60  |..$............`|+         e2 00 00 15 86 0e 01 86  10 50 b2 05 00 08 82 c1  |.........P......|+Received:WRITE_TAG_DATA                1829755.346791842+         ff 00 24 04 06 e4 20                              |..$... |+Sending: WRITE_TAG_DATA                1829755.347092306+         ff 1b 24 03 e8 01 00 00  00 09 03 00 00 00 00 60  |..$............`|+         e2 00 00 15 86 0e 01 86  10 50 b2 05 00 09 5c df  |.........P....\.|+Received:WRITE_TAG_DATA                1829756.380042974+         ff 00 24 04 06 e4 20                              |..$... |+Sending: WRITE_TAG_DATA                1829756.380287524+         ff 1b 24 03 e8 01 00 00  00 0a 03 00 00 00 00 60  |..$............`|+         e2 00 00 15 86 0e 01 86  10 50 b2 05 00 0a 2e dc  |.........P......|+Received:WRITE_TAG_DATA                1829757.407129848+         ff 00 24 04 06 e4 20                              |..$... |+Sending: WRITE_TAG_DATA                1829757.407368360+         ff 1b 24 03 e8 01 00 00  00 0b 03 00 00 00 00 60  |..$............`|+         e2 00 00 15 86 0e 01 86  10 50 b2 05 00 0b f0 c2  |.........P......|+Received:WRITE_TAG_DATA                1829758.440289154+         ff 00 24 04 06 e4 20                              |..$... |+Sending: WRITE_TAG_DATA                1829758.440490255+         ff 1b 24 03 e8 01 00 00  00 0c 03 00 00 00 00 60  |..$............`|+         e2 00 00 15 86 0e 01 86  10 50 b2 05 00 0c ca da  |.........P......|+Received:WRITE_TAG_DATA                1829758.469259190+         ff 00 24 00 00 e0 26                              |..$...&|+Sending: WRITE_TAG_DATA                1829758.469522032+         ff 1b 24 03 e8 01 00 00  00 0d 03 00 00 00 00 60  |..$............`|+         e2 00 00 15 86 0e 01 86  10 50 b2 05 00 0d 14 c4  |.........P......|+Received:WRITE_TAG_DATA                1829758.498531273+         ff 00 24 00 00 e0 26                              |..$...&|+Sending: WRITE_TAG_DATA                1829758.498805425+         ff 1b 24 03 e8 01 00 00  00 0e 03 00 00 00 00 60  |..$............`|+         e2 00 00 15 86 0e 01 86  10 50 b2 05 00 0e 66 c7  |.........P....f.|+Received:WRITE_TAG_DATA                1829758.527733252+         ff 00 24 00 00 e0 26                              |..$...&|+Sending: WRITE_TAG_DATA                1829758.527982849+         ff 1b 24 03 e8 01 00 00  00 0f 03 00 00 00 00 60  |..$............`|+         e2 00 00 15 86 0e 01 86  10 50 b2 05 00 0f b8 d9  |.........P......|+Received:WRITE_TAG_DATA                1829758.556692351+         ff 00 24 00 00 e0 26                              |..$...&|+Sending: WRITE_TAG_DATA                1829758.556900495+         ff 1b 24 03 e8 01 00 00  00 10 03 00 00 00 00 60  |..$............`|+         e2 00 00 15 86 0e 01 86  10 50 b2 05 00 10 22 ba  |.........P....".|+Received:WRITE_TAG_DATA                1829759.593563381+         ff 00 24 04 06 e4 20                              |..$... |+Sending: WRITE_TAG_DATA                1829759.593731843+         ff 1b 24 03 e8 01 00 00  00 11 03 00 00 00 00 60  |..$............`|+         e2 00 00 15 86 0e 01 86  10 50 b2 05 00 11 fc a4  |.........P......|+Received:WRITE_TAG_DATA                1829760.623955751+         ff 00 24 04 06 e4 20                              |..$... |+Sending: WRITE_TAG_DATA                1829760.624235451+         ff 1b 24 03 e8 01 00 00  00 12 03 00 00 00 00 60  |..$............`|+         e2 00 00 15 86 0e 01 86  10 50 b2 05 00 12 8e a7  |.........P......|+Received:WRITE_TAG_DATA                1829761.652961247+         ff 00 24 04 06 e4 20                              |..$... |+Sending: WRITE_TAG_DATA                1829761.653243691+         ff 1b 24 03 e8 01 00 00  00 13 03 00 00 00 00 60  |..$............`|+         e2 00 00 15 86 0e 01 86  10 50 b2 05 00 13 50 b9  |.........P....P.|+Received:WRITE_TAG_DATA                1829762.665276942+         ff 00 24 04 06 e4 20                              |..$... |+Sending: WRITE_TAG_DATA                1829762.665494236+         ff 1b 24 03 e8 01 00 00  00 14 03 00 00 00 00 60  |..$............`|+         e2 00 00 15 86 0e 01 86  10 50 b2 05 00 14 6a a1  |.........P....j.|+Received:WRITE_TAG_DATA                1829762.694120598+         ff 00 24 00 00 e0 26                              |..$...&|+Sending: WRITE_TAG_DATA                1829762.694383889+         ff 1b 24 03 e8 01 00 00  00 15 03 00 00 00 00 60  |..$............`|+         e2 00 00 15 86 0e 01 86  10 50 b2 05 00 15 b4 bf  |.........P......|+Received:WRITE_TAG_DATA                1829762.751451949+         ff 00 24 00 00 e0 26                              |..$...&|+Sending: WRITE_TAG_DATA                1829762.751713427+         ff 1b 24 03 e8 01 00 00  00 16 03 00 00 00 00 60  |..$............`|+         e2 00 00 15 86 0e 01 86  10 50 b2 05 00 16 c6 bc  |.........P......|+Received:WRITE_TAG_DATA                1829762.780199308+         ff 00 24 00 00 e0 26                              |..$...&|+Sending: WRITE_TAG_DATA                1829762.780457877+         ff 1b 24 03 e8 01 00 00  00 17 03 00 00 00 00 60  |..$............`|+         e2 00 00 15 86 0e 01 86  10 50 b2 05 00 17 18 a2  |.........P......|+Received:WRITE_TAG_DATA                1829762.809239881+         ff 00 24 00 00 e0 26                              |..$...&|+Sending: WRITE_TAG_DATA                1829762.809503379+         ff 1b 24 03 e8 01 00 00  00 18 03 00 00 00 00 60  |..$............`|+         e2 00 00 15 86 0e 01 86  10 50 b2 05 00 18 b2 8c  |.........P......|+Received:WRITE_TAG_DATA                1829763.842151363+         ff 00 24 04 06 e4 20                              |..$... |+Sending: WRITE_TAG_DATA                1829763.842308880+         ff 1b 24 03 e8 01 00 00  00 19 03 00 00 00 00 60  |..$............`|+         e2 00 00 15 86 0e 01 86  10 50 b2 05 00 19 6c 92  |.........P....l.|+Received:WRITE_TAG_DATA                1829764.873162970+         ff 00 24 04 06 e4 20                              |..$... |+Sending: WRITE_TAG_DATA                1829764.873443541+         ff 1b 24 03 e8 01 00 00  00 1a 03 00 00 00 00 60  |..$............`|+         e2 00 00 15 86 0e 01 86  10 50 b2 05 00 1a 1e 91  |.........P......|+Received:WRITE_TAG_DATA                1829765.879579000+         ff 00 24 04 06 e4 20                              |..$... |+Sending: WRITE_TAG_DATA                1829765.879851392+         ff 1b 24 03 e8 01 00 00  00 1b 03 00 00 00 00 60  |..$............`|+         e2 00 00 15 86 0e 01 86  10 50 b2 05 00 1b c0 8f  |.........P......|+Received:WRITE_TAG_DATA                1829766.888892450+         ff 00 24 04 06 e4 20                              |..$... |+Sending: WRITE_TAG_DATA                1829766.889180097+         ff 1b 24 03 e8 01 00 00  00 1c 03 00 00 00 00 60  |..$............`|+         e2 00 00 15 86 0e 01 86  10 50 b2 05 00 1c fa 97  |.........P......|+Received:WRITE_TAG_DATA                1829766.918023959+         ff 00 24 00 00 e0 26                              |..$...&|+Sending: WRITE_TAG_DATA                1829766.918292458+         ff 1b 24 03 e8 01 00 00  00 1d 03 00 00 00 00 60  |..$............`|+         e2 00 00 15 86 0e 01 86  10 50 b2 05 00 1d 24 89  |.........P....$.|+Received:WRITE_TAG_DATA                1829766.946906138+         ff 00 24 00 00 e0 26                              |..$...&|+Sending: WRITE_TAG_DATA                1829766.947094131+         ff 1b 24 03 e8 01 00 00  00 1e 03 00 00 00 00 60  |..$............`|+         e2 00 00 15 86 0e 01 86  10 50 b2 05 00 1e 56 8a  |.........P....V.|+Received:WRITE_TAG_DATA                1829766.975771316+         ff 00 24 00 00 e0 26                              |..$...&|+Sending: WRITE_TAG_DATA                1829766.976106491+         ff 1b 24 03 e8 01 00 00  00 1f 03 00 00 00 00 60  |..$............`|+         e2 00 00 15 86 0e 01 86  10 50 b2 05 00 1f 88 94  |.........P......|+Received:WRITE_TAG_DATA                1829767.004705226+         ff 00 24 00 00 e0 26                              |..$...&|+Sending: GET_READER_STATS              1829767.004898988+         ff 03 6c 01 9f 41 89 7b                           |..l..A.{|+Received:GET_READER_STATS              1829767.007163224+         ff 03 6c 00 00 01 9f 41  86 9c                    |..l....A..|+Sending: CLEAR_TAG_ID_BUFFER           1829767.007420284+         ff 00 2a 1d 25                                    |..*.%|+Received:CLEAR_TAG_ID_BUFFER           1829767.009235148+         ff 00 2a 00 00 01 e8                              |..*....|+Sending: SET_ANTENNA_PORT              1829767.009451929+         ff 03 91 02 01 01 42 c5                           |......B.|+Received:SET_ANTENNA_PORT              1829767.011452983+         ff 00 91 00 00 17 58                              |......X|+Sending: READ_TAG_ID_MULTIPLE          1829767.011619788+         ff 11 22 00 00 17 03 e8  01 09 28 07 d0 00 03 00  |..".......(.....|+         00 00 00 20 49 70                                 |... Ip|+Received:READ_TAG_ID_MULTIPLE          1829768.032941727+         ff 4d 22 00 00 00 00 17  00 00 00 01 01 28 00 16  |.M"..........(..|+         00 00 70 65 72 6d 61 6c  6f 63 00 04 00 05 00 06  |..permaloc......|+         00 07 20 20 20 20 20 20  20 20 00 0c 00 0d 00 0e  |..        ......|+         00 0f 20 20 20 20 20 20  20 20 00 14 00 15 00 16  |..        ......|+         00 17 20 20 20 20 20 20  20 20 00 1c 00 1d 00 1e  |..        ......|+         00 1f c4 38                                       |...8|+Sending: GET_TAG_ID_BUFFER             1829768.033538854+         ff 03 29 01 ff 00 1b 03                           |..).....|+Received:GET_TAG_ID_BUFFER             1829768.044502944+         ff 66 29 00 00 01 ff 00  01 16 de 11 0e 10 00 00  |.f).............|+         00 00 16 00 ae 05 02 00  70 65 72 6d 61 6c 6f 63  |........permaloc|+         00 04 00 05 00 06 00 07  20 20 20 20 20 20 20 20  |........        |+         00 0c 00 0d 00 0e 00 0f  20 20 20 20 20 20 20 20  |........        |+         00 14 00 15 00 16 00 17  20 20 20 20 20 20 20 20  |........        |+         00 1c 00 1d 00 1e 00 1f  00 00 80 34 00 e2 00 00  |...........4....|+         15 86 0e 01 86 10 50 b2  05 43 05 90 67           |......P..C..g|+Sending: ERASE_BLOCK_TAG_SPECIFIC      1829768.045283520+         ff 1e 2e 03 e8 00 41 01  00 00 00 00 60 e2 00 00  |......A.....`...|+         15 86 0e 01 86 10 50 b2  05 00 00 03 00 00 00 00  |......P.........|+         01 66 1b                                          |.f.|+Received:ERASE_BLOCK_TAG_SPECIFIC      1829768.068511562+         ff 04 2e 00 00 41 01 aa  00 74 5f                 |.....A...t_|
+ tests/blockWrite.result view
@@ -0,0 +1,5 @@+Right 1+Right (TagReadData {trTag = TagData {tdEpc = "\226\NULQ\134\SOH\a\SOH\135\ap\196\193", tdProtocol = TAG_PROTOCOL_GEN2, tdCrc = 47646, tdGen2 = Just (GEN2_TagData {g2Pc = "0\NUL"})}, trMetadataFlags = [METADATA_FLAG_READCOUNT,METADATA_FLAG_RSSI,METADATA_FLAG_ANTENNAID,METADATA_FLAG_FREQUENCY,METADATA_FLAG_TIMESTAMP,METADATA_FLAG_PHASE,METADATA_FLAG_PROTOCOL,METADATA_FLAG_DATA,METADATA_FLAG_GPIO_STATUS], trPhase = 174, trAntenna = 1, trGpio = [GpioPin {gpId = 1, gpHigh = False, gpOutput = False},GpioPin {gpId = 2, gpHigh = False, gpOutput = False},GpioPin {gpId = 3, gpHigh = False, gpOutput = False},GpioPin {gpId = 4, gpHigh = False, gpOutput = False}], trReadCount = 22, trRssi = -42, trFrequency = 922600, trTimestamp = 0, trData = "", trEpcMemData = "", trTidMemData = "", trUserMemData = "", trReservedMemData = ""})+Right ""+Right 1+Right (TagReadData {trTag = TagData {tdEpc = "\226\NULQ\134\SOH\a\SOH\135\ap\196\193", tdProtocol = TAG_PROTOCOL_GEN2, tdCrc = 47646, tdGen2 = Just (GEN2_TagData {g2Pc = "0\NUL"})}, trMetadataFlags = [METADATA_FLAG_READCOUNT,METADATA_FLAG_RSSI,METADATA_FLAG_ANTENNAID,METADATA_FLAG_FREQUENCY,METADATA_FLAG_TIMESTAMP,METADATA_FLAG_PHASE,METADATA_FLAG_PROTOCOL,METADATA_FLAG_DATA,METADATA_FLAG_GPIO_STATUS], trPhase = 174, trAntenna = 1, trGpio = [GpioPin {gpId = 1, gpHigh = False, gpOutput = False},GpioPin {gpId = 2, gpHigh = False, gpOutput = False},GpioPin {gpId = 3, gpHigh = False, gpOutput = False},GpioPin {gpId = 4, gpHigh = False, gpOutput = False}], trReadCount = 21, trRssi = -40, trFrequency = 918400, trTimestamp = 0, trData = "\NUL\SOH\STX\ETX\EOT\ENQ\ACK\a\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL456789:;<=>?", trEpcMemData = "", trTidMemData = "", trUserMemData = "", trReservedMemData = ""})
+ tests/blockWrite.transport view
@@ -0,0 +1,118 @@+Sending: VERSION                       1733235.445865270+         ff 00 03 1d 0c                                    |.....|+Received:VERSION                       1733235.450593149+         ff 14 03 00 00 14 12 08  00 30 00 00 02 20 16 12  |.........0... ..|+         13 01 07 01 02 00 00 00  10 1b 05                 |...........|+Sending: GET_CURRENT_PROGRAM           1733235.451166815+         ff 00 0c 1d 03                                    |.....|+Received:GET_CURRENT_PROGRAM           1733235.452792849+         ff 01 0c 00 00 52 63 03                           |.....Rc.|+Sending: GET_POWER_MODE                1733235.452909508+         ff 00 68 1d 67                                    |..h.g|+Received:GET_POWER_MODE                1733235.454483132+         ff 01 68 00 00 00 a4 bf                           |..h.....|+Sending: GET_READER_OPTIONAL_PARAMS    1733235.454584834+         ff 02 6a 01 0e 2e 40                              |..j...@|+Received:GET_READER_OPTIONAL_PARAMS    1733235.456720836+         ff 03 6a 00 00 01 0e 00  30 44                    |..j.....0D|+Sending: GET_READER_OPTIONAL_PARAMS    1733235.464524663+         ff 02 6a 01 12 2e 5c                              |..j...\|+Received:GET_READER_OPTIONAL_PARAMS    1733235.466891122+         ff 04 6a 00 00 01 12 00  00 69 af                 |..j......i.|+Sending: GET_TAG_PROTOCOL              1733235.467046237+         ff 00 63 1d 6c                                    |..c.l|+Received:GET_TAG_PROTOCOL              1733235.468960694+         ff 02 63 00 00 00 05 21  46                       |..c....!F|+Sending: GET_ANTENNA_PORT              1733235.469176660+         ff 01 61 05 bd b8                                 |..a...|+Received:GET_ANTENNA_PORT              1733235.471205061+         ff 03 61 00 00 05 01 00  61 df                    |..a.....a.|+Sending: GET_READER_OPTIONAL_PARAMS    1733235.471393661+         ff 02 6a 01 0c 2e 42                              |..j...B|+Received:GET_READER_OPTIONAL_PARAMS    1733235.473331463+         ff 03 6a 00 00 01 0c 01  32 45                    |..j.....2E|+Sending: GET_READER_OPTIONAL_PARAMS    1733235.473436213+         ff 02 6a 01 0d 2e 43                              |..j...C|+Received:GET_READER_OPTIONAL_PARAMS    1733235.475652405+         ff 06 6a 00 00 01 0d 00  00 00 00 15 43           |..j.........C|+Sending: SET_REGION                    1733235.475787800+         ff 01 97 0d 4b b0                                 |....K.|+Received:SET_REGION                    1733235.477440297+         ff 00 97 00 00 77 9e                              |.....w.|+Sending: SET_READ_TX_POWER             1733235.477572174+         ff 02 92 08 98 49 c1                              |.....I.|+Received:SET_READ_TX_POWER             1733235.479231984+         ff 00 92 00 00 27 3b                              |.....';|+Sending: SET_WRITE_TX_POWER            1733235.479325942+         ff 02 94 08 98 29 07                              |.....).|+Received:SET_WRITE_TX_POWER            1733235.480974365+         ff 00 94 00 00 47 fd                              |.....G.|+Sending: SET_ANTENNA_PORT              1733235.481085977+         ff 02 91 01 01 70 3b                              |.....p;|+Received:SET_ANTENNA_PORT              1733235.482945579+         ff 00 91 00 00 17 58                              |......X|+Sending: SET_READER_OPTIONAL_PARAMS    1733235.483086775+         ff 03 9a 01 06 01 a9 5c                           |.......\|+Received:SET_READER_OPTIONAL_PARAMS    1733235.485124382+         ff 00 9a 00 00 a6 33                              |......3|+Sending: GET_READER_STATS              1733235.485409960+         ff 03 6c 01 9f 41 89 7b                           |..l..A.{|+Received:GET_READER_STATS              1733235.487718897+         ff 03 6c 00 00 01 9f 41  86 9c                    |..l....A..|+Sending: CLEAR_TAG_ID_BUFFER           1733235.487877132+         ff 00 2a 1d 25                                    |..*.%|+Received:CLEAR_TAG_ID_BUFFER           1733235.489434618+         ff 00 2a 00 00 01 e8                              |..*....|+Sending: SET_ANTENNA_PORT              1733235.489576531+         ff 03 91 02 01 01 42 c5                           |......B.|+Received:SET_ANTENNA_PORT              1733235.491653350+         ff 00 91 00 00 17 58                              |......X|+Sending: READ_TAG_ID_MULTIPLE          1733235.491795994+         ff 10 22 03 00 13 03 e8  00 00 00 00 00 00 00 00  |..".............|+         10 00 00 86 a3                                    |.....|+Received:READ_TAG_ID_MULTIPLE          1733236.497741270+         ff 07 22 00 00 03 00 13  00 00 00 01 65 8a        |..".........e.|+Sending: GET_TAG_ID_BUFFER             1733236.498026395+         ff 03 29 01 ff 00 1b 03                           |..).....|+Received:GET_TAG_ID_BUFFER             1733236.503600010+         ff 26 29 00 00 01 ff 00  01 16 d6 11 0e 13 e8 00  |.&).............|+         00 03 29 00 ae 05 00 00  00 00 80 30 00 e2 00 51  |..)........0...Q|+         86 01 07 01 87 07 70 c4  c1 ba 1e 08 aa           |......p......|+Sending: WRITE_TAG_SPECIFIC            1733236.504361013+         ff 26 2d 03 e8 00 41 00  c7 00 00 00 00 60 e2 00  |.&-...A......`..|+         51 86 01 07 01 87 07 70  c4 c1 00 03 00 00 00 00  |Q......p........|+         04 00 01 02 03 04 05 06  07 f3 66                 |..........f|+Received:WRITE_TAG_SPECIFIC            1733236.536904406+         ff 04 2d 00 00 00 41 00  c7 46 73                 |..-...A..Fs|+Sending: GET_READER_STATS              1733236.537262949+         ff 03 6c 01 9f 41 89 7b                           |..l..A.{|+Received:GET_READER_STATS              1733236.539475858+         ff 03 6c 00 00 01 9f 41  86 9c                    |..l....A..|+Sending: CLEAR_TAG_ID_BUFFER           1733236.539649148+         ff 00 2a 1d 25                                    |..*.%|+Received:CLEAR_TAG_ID_BUFFER           1733236.541393558+         ff 00 2a 00 00 01 e8                              |..*....|+Sending: SET_ANTENNA_PORT              1733236.541581880+         ff 03 91 02 01 01 42 c5                           |......B.|+Received:SET_ANTENNA_PORT              1733236.543666695+         ff 00 91 00 00 17 58                              |......X|+Sending: READ_TAG_ID_MULTIPLE          1733236.543972909+         ff 11 22 00 00 17 03 e8  01 09 28 07 d0 00 03 00  |..".......(.....|+         00 00 00 20 49 70                                 |... Ip|+Received:READ_TAG_ID_MULTIPLE          1733237.559689784+         ff 4d 22 00 00 00 00 17  00 00 00 01 01 28 00 15  |.M"..........(..|+         00 00 00 01 02 03 04 05  06 07 00 00 00 00 00 00  |................|+         00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|+         00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|+         00 00 00 00 00 00 34 35  36 37 38 39 3a 3b 3c 3d  |......456789:;<=|+         3e 3f 14 7a                                       |>?.z|+Sending: GET_TAG_ID_BUFFER             1733237.560562427+         ff 03 29 01 ff 00 1b 03                           |..).....|+Received:GET_TAG_ID_BUFFER             1733237.571772759+         ff 66 29 00 00 01 ff 00  01 15 d8 11 0e 03 80 00  |.f).............|+         00 01 a1 00 ae 05 02 00  00 01 02 03 04 05 06 07  |................|+         00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|+         00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|+         00 00 00 00 00 00 00 00  00 00 00 00 34 35 36 37  |............4567|+         38 39 3a 3b 3c 3d 3e 3f  00 00 80 30 00 e2 00 51  |89:;<=>?...0...Q|+         86 01 07 01 87 07 70 c4  c1 ba 1e 59 6d           |......p....Ym|
+ tests/gpi.result view
@@ -0,0 +1,1 @@+Right [GpioPin {gpId = 1, gpHigh = False, gpOutput = False},GpioPin {gpId = 2, gpHigh = False, gpOutput = False},GpioPin {gpId = 3, gpHigh = False, gpOutput = False},GpioPin {gpId = 4, gpHigh = True, gpOutput = False}]
+ tests/gpi.transport view
@@ -0,0 +1,58 @@+Sending: VERSION                       1618349.830532032+         ff 00 03 1d 0c                                    |.....|+Received:VERSION                       1618349.834088647+         ff 14 03 00 00 14 12 08  00 30 00 00 02 20 16 12  |.........0... ..|+         13 01 07 01 02 00 00 00  10 1b 05                 |...........|+Sending: GET_CURRENT_PROGRAM           1618349.834651661+         ff 00 0c 1d 03                                    |.....|+Received:GET_CURRENT_PROGRAM           1618349.836219541+         ff 01 0c 00 00 52 63 03                           |.....Rc.|+Sending: GET_POWER_MODE                1618349.836338063+         ff 00 68 1d 67                                    |..h.g|+Received:GET_POWER_MODE                1618349.838107299+         ff 01 68 00 00 00 a4 bf                           |..h.....|+Sending: GET_READER_OPTIONAL_PARAMS    1618349.838259128+         ff 02 6a 01 0e 2e 40                              |..j...@|+Received:GET_READER_OPTIONAL_PARAMS    1618349.840405018+         ff 03 6a 00 00 01 0e 00  30 44                    |..j.....0D|+Sending: GET_READER_OPTIONAL_PARAMS    1618349.841446339+         ff 02 6a 01 12 2e 5c                              |..j...\|+Received:GET_READER_OPTIONAL_PARAMS    1618349.843738766+         ff 04 6a 00 00 01 12 00  00 69 af                 |..j......i.|+Sending: GET_TAG_PROTOCOL              1618349.843921112+         ff 00 63 1d 6c                                    |..c.l|+Received:GET_TAG_PROTOCOL              1618349.845804952+         ff 02 63 00 00 00 05 21  46                       |..c....!F|+Sending: GET_ANTENNA_PORT              1618349.845969838+         ff 01 61 05 bd b8                                 |..a...|+Received:GET_ANTENNA_PORT              1618349.848073650+         ff 03 61 00 00 05 01 00  61 df                    |..a.....a.|+Sending: GET_READER_OPTIONAL_PARAMS    1618349.848306062+         ff 02 6a 01 0c 2e 42                              |..j...B|+Received:GET_READER_OPTIONAL_PARAMS    1618349.850482317+         ff 03 6a 00 00 01 0c 01  32 45                    |..j.....2E|+Sending: GET_READER_OPTIONAL_PARAMS    1618349.850695273+         ff 02 6a 01 0d 2e 43                              |..j...C|+Received:GET_READER_OPTIONAL_PARAMS    1618349.853152056+         ff 06 6a 00 00 01 0d 00  00 00 00 15 43           |..j.........C|+Sending: SET_USER_GPIO_OUTPUTS         1618349.853335246+         ff 04 96 01 01 00 00 2d  68                       |.......-h|+Received:SET_USER_GPIO_OUTPUTS         1618349.855303359+         ff 00 96 00 00 67 bf                              |.....g.|+Sending: SET_USER_GPIO_OUTPUTS         1618349.855484441+         ff 04 96 01 02 00 00 1d  0b                       |.........|+Received:SET_USER_GPIO_OUTPUTS         1618349.857372145+         ff 00 96 00 00 67 bf                              |.....g.|+Sending: SET_USER_GPIO_OUTPUTS         1618349.857457353+         ff 04 96 01 03 00 00 0d  2a                       |........*|+Received:SET_USER_GPIO_OUTPUTS         1618349.859481273+         ff 00 96 00 00 67 bf                              |.....g.|+Sending: SET_USER_GPIO_OUTPUTS         1618349.859607401+         ff 04 96 01 04 00 00 7d  cd                       |.......}.|+Received:SET_USER_GPIO_OUTPUTS         1618349.861699382+         ff 00 96 00 00 67 bf                              |.....g.|+Sending: GET_USER_GPIO_INPUTS          1618349.861992903+         ff 01 66 01 ba bc                                 |..f...|+Received:GET_USER_GPIO_INPUTS          1618349.864881787+         ff 0d 66 00 00 01 01 00  00 02 00 00 03 00 00 04  |..f.............|+         00 01 64 46                                       |..dF|
+ tests/gpo.result view
+ tests/gpo.transport view
@@ -0,0 +1,117 @@+Sending: VERSION                       1618318.942992850+         ff 00 03 1d 0c                                    |.....|+Received:VERSION                       1618318.946535066+         ff 14 03 00 00 14 12 08  00 30 00 00 02 20 16 12  |.........0... ..|+         13 01 07 01 02 00 00 00  10 1b 05                 |...........|+Sending: GET_CURRENT_PROGRAM           1618318.947020444+         ff 00 0c 1d 03                                    |.....|+Received:GET_CURRENT_PROGRAM           1618318.948566726+         ff 01 0c 00 00 52 63 03                           |.....Rc.|+Sending: GET_POWER_MODE                1618318.948717066+         ff 00 68 1d 67                                    |..h.g|+Received:GET_POWER_MODE                1618318.950309705+         ff 01 68 00 00 00 a4 bf                           |..h.....|+Sending: GET_READER_OPTIONAL_PARAMS    1618318.950404769+         ff 02 6a 01 0e 2e 40                              |..j...@|+Received:GET_READER_OPTIONAL_PARAMS    1618318.952376555+         ff 03 6a 00 00 01 0e 00  30 44                    |..j.....0D|+Sending: GET_READER_OPTIONAL_PARAMS    1618318.953236827+         ff 02 6a 01 12 2e 5c                              |..j...\|+Received:GET_READER_OPTIONAL_PARAMS    1618318.955499201+         ff 04 6a 00 00 01 12 00  00 69 af                 |..j......i.|+Sending: GET_TAG_PROTOCOL              1618318.955666882+         ff 00 63 1d 6c                                    |..c.l|+Received:GET_TAG_PROTOCOL              1618318.957566645+         ff 02 63 00 00 00 05 21  46                       |..c....!F|+Sending: GET_ANTENNA_PORT              1618318.957735305+         ff 01 61 05 bd b8                                 |..a...|+Received:GET_ANTENNA_PORT              1618318.959879076+         ff 03 61 00 00 05 01 00  61 df                    |..a.....a.|+Sending: GET_READER_OPTIONAL_PARAMS    1618318.960104443+         ff 02 6a 01 0c 2e 42                              |..j...B|+Received:GET_READER_OPTIONAL_PARAMS    1618318.962299514+         ff 03 6a 00 00 01 0c 01  32 45                    |..j.....2E|+Sending: GET_READER_OPTIONAL_PARAMS    1618318.962561529+         ff 02 6a 01 0d 2e 43                              |..j...C|+Received:GET_READER_OPTIONAL_PARAMS    1618318.965031538+         ff 06 6a 00 00 01 0d 00  00 00 00 15 43           |..j.........C|+Sending: SET_USER_GPIO_OUTPUTS         1618318.965276377+         ff 04 96 01 01 01 00 2c  68                       |.......,h|+Received:SET_USER_GPIO_OUTPUTS         1618318.967228964+         ff 00 96 00 00 67 bf                              |.....g.|+Sending: SET_USER_GPIO_OUTPUTS         1618318.967416136+         ff 04 96 01 02 01 00 1c  0b                       |.........|+Received:SET_USER_GPIO_OUTPUTS         1618318.969281000+         ff 00 96 00 00 67 bf                              |.....g.|+Sending: SET_USER_GPIO_OUTPUTS         1618318.969370599+         ff 04 96 01 03 01 00 0c  2a                       |........*|+Received:SET_USER_GPIO_OUTPUTS         1618318.971406485+         ff 00 96 00 00 67 bf                              |.....g.|+Sending: SET_USER_GPIO_OUTPUTS         1618318.971538137+         ff 04 96 01 04 01 00 7c  cd                       |.......|.|+Received:SET_USER_GPIO_OUTPUTS         1618318.973585255+         ff 00 96 00 00 67 bf                              |.....g.|+Sending: SET_USER_GPIO_OUTPUTS         1618318.973773431+         ff 02 96 01 01 00 dc                              |.......|+Received:SET_USER_GPIO_OUTPUTS         1618318.975520311+         ff 00 96 00 00 67 bf                              |.....g.|+Sending: SET_USER_GPIO_OUTPUTS         1618318.975658272+         ff 02 96 02 00 03 dd                              |.......|+Received:SET_USER_GPIO_OUTPUTS         1618318.977385363+         ff 00 96 00 00 67 bf                              |.....g.|+Sending: SET_USER_GPIO_OUTPUTS         1618318.977471678+         ff 02 96 03 00 02 dd                              |.......|+Received:SET_USER_GPIO_OUTPUTS         1618318.979121138+         ff 00 96 00 00 67 bf                              |.....g.|+Sending: SET_USER_GPIO_OUTPUTS         1618318.979212246+         ff 02 96 04 00 05 dd                              |.......|+Received:SET_USER_GPIO_OUTPUTS         1618318.981086248+         ff 00 96 00 00 67 bf                              |.....g.|+Sending: SET_USER_GPIO_OUTPUTS         1618318.981222933+         ff 02 96 01 00 00 dd                              |.......|+Received:SET_USER_GPIO_OUTPUTS         1618318.983093686+         ff 00 96 00 00 67 bf                              |.....g.|+Sending: SET_USER_GPIO_OUTPUTS         1618318.983221881+         ff 02 96 02 01 03 dc                              |.......|+Received:SET_USER_GPIO_OUTPUTS         1618318.985118247+         ff 00 96 00 00 67 bf                              |.....g.|+Sending: SET_USER_GPIO_OUTPUTS         1618318.985257581+         ff 02 96 03 00 02 dd                              |.......|+Received:SET_USER_GPIO_OUTPUTS         1618318.987180140+         ff 00 96 00 00 67 bf                              |.....g.|+Sending: SET_USER_GPIO_OUTPUTS         1618318.987332353+         ff 02 96 04 00 05 dd                              |.......|+Received:SET_USER_GPIO_OUTPUTS         1618318.989201090+         ff 00 96 00 00 67 bf                              |.....g.|+Sending: SET_USER_GPIO_OUTPUTS         1618318.989345414+         ff 02 96 01 00 00 dd                              |.......|+Received:SET_USER_GPIO_OUTPUTS         1618318.991214250+         ff 00 96 00 00 67 bf                              |.....g.|+Sending: SET_USER_GPIO_OUTPUTS         1618318.991343106+         ff 02 96 02 00 03 dd                              |.......|+Received:SET_USER_GPIO_OUTPUTS         1618318.993198749+         ff 00 96 00 00 67 bf                              |.....g.|+Sending: SET_USER_GPIO_OUTPUTS         1618318.993376145+         ff 02 96 03 01 02 dc                              |.......|+Received:SET_USER_GPIO_OUTPUTS         1618318.995161980+         ff 00 96 00 00 67 bf                              |.....g.|+Sending: SET_USER_GPIO_OUTPUTS         1618318.995420491+         ff 02 96 04 00 05 dd                              |.......|+Received:SET_USER_GPIO_OUTPUTS         1618318.997327262+         ff 00 96 00 00 67 bf                              |.....g.|+Sending: SET_USER_GPIO_OUTPUTS         1618318.997461552+         ff 02 96 01 00 00 dd                              |.......|+Received:SET_USER_GPIO_OUTPUTS         1618318.999330677+         ff 00 96 00 00 67 bf                              |.....g.|+Sending: SET_USER_GPIO_OUTPUTS         1618318.999462362+         ff 02 96 02 00 03 dd                              |.......|+Received:SET_USER_GPIO_OUTPUTS         1618319.001219823+         ff 00 96 00 00 67 bf                              |.....g.|+Sending: SET_USER_GPIO_OUTPUTS         1618319.001349635+         ff 02 96 03 00 02 dd                              |.......|+Received:SET_USER_GPIO_OUTPUTS         1618319.002983389+         ff 00 96 00 00 67 bf                              |.....g.|+Sending: SET_USER_GPIO_OUTPUTS         1618319.003060700+         ff 02 96 04 01 05 dc                              |.......|+Received:SET_USER_GPIO_OUTPUTS         1618319.004690734+         ff 00 96 00 00 67 bf                              |.....g.|
+ tests/kill.result view
@@ -0,0 +1,5 @@+Right 1+Right (TagReadData {trTag = TagData {tdEpc = "\226\NUL\NUL\NAK\134\SO\SOH\134\DLEP\178\ENQ", tdProtocol = TAG_PROTOCOL_GEN2, tdCrc = 17157, tdGen2 = Just (GEN2_TagData {g2Pc = "4\NUL"})}, trMetadataFlags = [METADATA_FLAG_READCOUNT,METADATA_FLAG_RSSI,METADATA_FLAG_ANTENNAID,METADATA_FLAG_FREQUENCY,METADATA_FLAG_TIMESTAMP,METADATA_FLAG_PHASE,METADATA_FLAG_PROTOCOL,METADATA_FLAG_DATA,METADATA_FLAG_GPIO_STATUS], trPhase = 174, trAntenna = 1, trGpio = [GpioPin {gpId = 1, gpHigh = False, gpOutput = False},GpioPin {gpId = 2, gpHigh = False, gpOutput = False},GpioPin {gpId = 3, gpHigh = False, gpOutput = False},GpioPin {gpId = 4, gpHigh = False, gpOutput = False}], trReadCount = 27, trRssi = -36, trFrequency = 922600, trTimestamp = 0, trData = "", trEpcMemData = "", trTidMemData = "", trUserMemData = "", trReservedMemData = ""})+Right ""+Right ""+Right 0
+ tests/kill.transport view
@@ -0,0 +1,111 @@+Sending: VERSION                       1831074.447420502+         ff 00 03 1d 0c                                    |.....|+Received:VERSION                       1831074.452022120+         ff 14 03 00 00 14 12 08  00 30 00 00 02 20 16 12  |.........0... ..|+         13 01 07 01 02 00 00 00  10 1b 05                 |...........|+Sending: GET_CURRENT_PROGRAM           1831074.452559544+         ff 00 0c 1d 03                                    |.....|+Received:GET_CURRENT_PROGRAM           1831074.454340797+         ff 01 0c 00 00 52 63 03                           |.....Rc.|+Sending: GET_POWER_MODE                1831074.454531231+         ff 00 68 1d 67                                    |..h.g|+Received:GET_POWER_MODE                1831074.456343322+         ff 01 68 00 00 00 a4 bf                           |..h.....|+Sending: GET_READER_OPTIONAL_PARAMS    1831074.456488564+         ff 02 6a 01 0e 2e 40                              |..j...@|+Received:GET_READER_OPTIONAL_PARAMS    1831074.458682283+         ff 03 6a 00 00 01 0e 00  30 44                    |..j.....0D|+Sending: GET_READER_OPTIONAL_PARAMS    1831074.466612730+         ff 02 6a 01 12 2e 5c                              |..j...\|+Received:GET_READER_OPTIONAL_PARAMS    1831074.468769754+         ff 04 6a 00 00 01 12 00  00 69 af                 |..j......i.|+Sending: GET_TAG_PROTOCOL              1831074.468885509+         ff 00 63 1d 6c                                    |..c.l|+Received:GET_TAG_PROTOCOL              1831074.470567920+         ff 02 63 00 00 00 05 21  46                       |..c....!F|+Sending: GET_ANTENNA_PORT              1831074.470671618+         ff 01 61 05 bd b8                                 |..a...|+Received:GET_ANTENNA_PORT              1831074.472597812+         ff 03 61 00 00 05 01 00  61 df                    |..a.....a.|+Sending: GET_READER_OPTIONAL_PARAMS    1831074.472737097+         ff 02 6a 01 0c 2e 42                              |..j...B|+Received:GET_READER_OPTIONAL_PARAMS    1831074.474854214+         ff 03 6a 00 00 01 0c 01  32 45                    |..j.....2E|+Sending: GET_READER_OPTIONAL_PARAMS    1831074.475006893+         ff 02 6a 01 0d 2e 43                              |..j...C|+Received:GET_READER_OPTIONAL_PARAMS    1831074.477456734+         ff 06 6a 00 00 01 0d 00  00 00 00 15 43           |..j.........C|+Sending: SET_REGION                    1831074.477619146+         ff 01 97 0d 4b b0                                 |....K.|+Received:SET_REGION                    1831074.479492124+         ff 00 97 00 00 77 9e                              |.....w.|+Sending: SET_READ_TX_POWER             1831074.479681964+         ff 02 92 08 98 49 c1                              |.....I.|+Received:SET_READ_TX_POWER             1831074.481432960+         ff 00 92 00 00 27 3b                              |.....';|+Sending: SET_WRITE_TX_POWER            1831074.481527235+         ff 02 94 08 98 29 07                              |.....).|+Received:SET_WRITE_TX_POWER            1831074.483390045+         ff 00 94 00 00 47 fd                              |.....G.|+Sending: SET_ANTENNA_PORT              1831074.483543623+         ff 02 91 01 01 70 3b                              |.....p;|+Received:SET_ANTENNA_PORT              1831074.485442387+         ff 00 91 00 00 17 58                              |......X|+Sending: SET_READER_OPTIONAL_PARAMS    1831074.485576255+         ff 03 9a 01 06 01 a9 5c                           |.......\|+Received:SET_READER_OPTIONAL_PARAMS    1831074.487606924+         ff 00 9a 00 00 a6 33                              |......3|+Sending: GET_READER_STATS              1831074.487818404+         ff 03 6c 01 9f 41 89 7b                           |..l..A.{|+Received:GET_READER_STATS              1831074.490136003+         ff 03 6c 00 00 01 9f 41  86 9c                    |..l....A..|+Sending: CLEAR_TAG_ID_BUFFER           1831074.490291027+         ff 00 2a 1d 25                                    |..*.%|+Received:CLEAR_TAG_ID_BUFFER           1831074.492017214+         ff 00 2a 00 00 01 e8                              |..*....|+Sending: SET_ANTENNA_PORT              1831074.492271773+         ff 03 91 02 01 01 42 c5                           |......B.|+Received:SET_ANTENNA_PORT              1831074.494357801+         ff 00 91 00 00 17 58                              |......X|+Sending: READ_TAG_ID_MULTIPLE          1831074.494526919+         ff 1e 22 03 00 13 03 e8  00 00 00 00 00 00 00 00  |..".............|+         80 70 65 72 6d 61 6c 6f  63 00 04 00 05 00 06 00  |.permaloc.......|+         07 3b 60                                          |.;`|+Received:READ_TAG_ID_MULTIPLE          1831075.503599087+         ff 07 22 00 00 03 00 13  00 00 00 01 65 8a        |..".........e.|+Sending: GET_TAG_ID_BUFFER             1831075.503916938+         ff 03 29 01 ff 00 1b 03                           |..).....|+Received:GET_TAG_ID_BUFFER             1831075.509398749+         ff 26 29 00 00 01 ff 00  01 1b dc 11 0e 13 e8 00  |.&).............|+         00 03 08 00 ae 05 00 00  00 00 80 34 00 e2 00 00  |...........4....|+         15 86 0e 01 86 10 50 b2  05 43 05 f6 ff           |......P..C...|+Sending: WRITE_TAG_DATA                1831075.513325167+         ff 1d 24 03 e8 01 00 00  00 00 00 00 00 00 00 60  |..$............`|+         e2 00 00 15 86 0e 01 86  10 50 b2 05 be ad ea d1  |.........P......|+         15 be                                             |..|+Received:WRITE_TAG_DATA                1831075.551566490+         ff 00 24 00 00 e0 26                              |..$...&|+Sending: KILL_TAG                      1831075.551883959+         ff 15 26 03 e8 01 be ad  ea d1 00 60 e2 00 00 15  |..&........`....|+         86 0e 01 86 10 50 b2 05  9f 2a                    |.....P...*|+Received:KILL_TAG                      1831075.605610474+         ff 00 26 00 00 c0 64                              |..&...d|+Sending: GET_READER_STATS              1831075.605904821+         ff 03 6c 01 9f 41 89 7b                           |..l..A.{|+Received:GET_READER_STATS              1831075.608102121+         ff 03 6c 00 00 01 9f 41  86 9c                    |..l....A..|+Sending: CLEAR_TAG_ID_BUFFER           1831075.608299737+         ff 00 2a 1d 25                                    |..*.%|+Received:CLEAR_TAG_ID_BUFFER           1831075.610065410+         ff 00 2a 00 00 01 e8                              |..*....|+Sending: SET_ANTENNA_PORT              1831075.610229640+         ff 03 91 02 01 01 42 c5                           |......B.|+Received:SET_ANTENNA_PORT              1831075.612277145+         ff 00 91 00 00 17 58                              |......X|+Sending: READ_TAG_ID_MULTIPLE          1831075.612456260+         ff 22 22 01 00 17 03 e8  00 00 00 00 60 e2 00 00  |."".........`...|+         15 86 0e 01 86 10 50 b2  05 01 09 28 07 d0 00 03  |......P....(....|+         00 00 00 00 20 88 da                              |.... ..|+Received:READ_TAG_ID_MULTIPLE          1831076.620853129+         ff 0d 22 04 00 01 00 17  00 00 00 00 01 28 00 00  |.."..........(..|+         00 00 d8 88                                       |....|
+ tests/lock.result view
@@ -0,0 +1,7 @@+Right 1+Right (TagReadData {trTag = TagData {tdEpc = "\226\NULQ\134\SOH\a\SOH\135\ap\196\193", tdProtocol = TAG_PROTOCOL_GEN2, tdCrc = 47646, tdGen2 = Just (GEN2_TagData {g2Pc = "0\NUL"})}, trMetadataFlags = [METADATA_FLAG_READCOUNT,METADATA_FLAG_RSSI,METADATA_FLAG_ANTENNAID,METADATA_FLAG_FREQUENCY,METADATA_FLAG_TIMESTAMP,METADATA_FLAG_PHASE,METADATA_FLAG_PROTOCOL,METADATA_FLAG_DATA,METADATA_FLAG_GPIO_STATUS], trPhase = 174, trAntenna = 1, trGpio = [GpioPin {gpId = 1, gpHigh = False, gpOutput = False},GpioPin {gpId = 2, gpHigh = False, gpOutput = False},GpioPin {gpId = 3, gpHigh = False, gpOutput = False},GpioPin {gpId = 4, gpHigh = False, gpOutput = False}], trReadCount = 21, trRssi = -41, trFrequency = 922600, trTimestamp = 0, trData = "", trEpcMemData = "", trTidMemData = "", trUserMemData = "", trReservedMemData = ""})+Right ""+Right ""+Left (MercuryException {meStatusType = ERROR_TYPE_CODE, meStatus = ERROR_PROTOCOL_WRITE_FAILED, meMessage = "Tag write operation failed", meLocation = "executeTagOp", meParam = "TagOp_GEN2_WriteData", meUri = ""})+Right ""+Right ""
+ tests/lock.transport view
@@ -0,0 +1,109 @@+Sending: VERSION                       1790605.584555826+         ff 00 03 1d 0c                                    |.....|+Received:VERSION                       1790605.588060962+         ff 14 03 00 00 14 12 08  00 30 00 00 02 20 16 12  |.........0... ..|+         13 01 07 01 02 00 00 00  10 1b 05                 |...........|+Sending: GET_CURRENT_PROGRAM           1790605.588579065+         ff 00 0c 1d 03                                    |.....|+Received:GET_CURRENT_PROGRAM           1790605.590133584+         ff 01 0c 00 00 52 63 03                           |.....Rc.|+Sending: GET_POWER_MODE                1790605.590279389+         ff 00 68 1d 67                                    |..h.g|+Received:GET_POWER_MODE                1790605.591896715+         ff 01 68 00 00 00 a4 bf                           |..h.....|+Sending: GET_READER_OPTIONAL_PARAMS    1790605.591990509+         ff 02 6a 01 0e 2e 40                              |..j...@|+Received:GET_READER_OPTIONAL_PARAMS    1790605.593926208+         ff 03 6a 00 00 01 0e 00  30 44                    |..j.....0D|+Sending: GET_READER_OPTIONAL_PARAMS    1790605.594787483+         ff 02 6a 01 12 2e 5c                              |..j...\|+Received:GET_READER_OPTIONAL_PARAMS    1790605.597048243+         ff 04 6a 00 00 01 12 00  00 69 af                 |..j......i.|+Sending: GET_TAG_PROTOCOL              1790605.597237617+         ff 00 63 1d 6c                                    |..c.l|+Received:GET_TAG_PROTOCOL              1790605.599164222+         ff 02 63 00 00 00 05 21  46                       |..c....!F|+Sending: GET_ANTENNA_PORT              1790605.599333871+         ff 01 61 05 bd b8                                 |..a...|+Received:GET_ANTENNA_PORT              1790605.601513969+         ff 03 61 00 00 05 01 00  61 df                    |..a.....a.|+Sending: GET_READER_OPTIONAL_PARAMS    1790605.601889295+         ff 02 6a 01 0c 2e 42                              |..j...B|+Received:GET_READER_OPTIONAL_PARAMS    1790605.604146998+         ff 03 6a 00 00 01 0c 01  32 45                    |..j.....2E|+Sending: GET_READER_OPTIONAL_PARAMS    1790605.604339750+         ff 02 6a 01 0d 2e 43                              |..j...C|+Received:GET_READER_OPTIONAL_PARAMS    1790605.606640416+         ff 06 6a 00 00 01 0d 00  00 00 00 15 43           |..j.........C|+Sending: SET_REGION                    1790605.606780094+         ff 01 97 0d 4b b0                                 |....K.|+Received:SET_REGION                    1790605.608595882+         ff 00 97 00 00 77 9e                              |.....w.|+Sending: SET_READ_TX_POWER             1790605.608799467+         ff 02 92 08 98 49 c1                              |.....I.|+Received:SET_READ_TX_POWER             1790605.610710783+         ff 00 92 00 00 27 3b                              |.....';|+Sending: SET_WRITE_TX_POWER            1790605.610861534+         ff 02 94 08 98 29 07                              |.....).|+Received:SET_WRITE_TX_POWER            1790605.612720664+         ff 00 94 00 00 47 fd                              |.....G.|+Sending: SET_ANTENNA_PORT              1790605.612904299+         ff 02 91 01 01 70 3b                              |.....p;|+Received:SET_ANTENNA_PORT              1790605.614647207+         ff 00 91 00 00 17 58                              |......X|+Sending: SET_READER_OPTIONAL_PARAMS    1790605.614754132+         ff 03 9a 01 06 01 a9 5c                           |.......\|+Received:SET_READER_OPTIONAL_PARAMS    1790605.616556454+         ff 00 9a 00 00 a6 33                              |......3|+Sending: GET_READER_STATS              1790605.616652209+         ff 03 6c 01 9f 41 89 7b                           |..l..A.{|+Received:GET_READER_STATS              1790605.618851953+         ff 03 6c 00 00 01 9f 41  86 9c                    |..l....A..|+Sending: CLEAR_TAG_ID_BUFFER           1790605.619014686+         ff 00 2a 1d 25                                    |..*.%|+Received:CLEAR_TAG_ID_BUFFER           1790605.620740423+         ff 00 2a 00 00 01 e8                              |..*....|+Sending: SET_ANTENNA_PORT              1790605.620890824+         ff 03 91 02 01 01 42 c5                           |......B.|+Received:SET_ANTENNA_PORT              1790605.622843141+         ff 00 91 00 00 17 58                              |......X|+Sending: READ_TAG_ID_MULTIPLE          1790605.623000323+         ff 10 22 03 00 13 03 e8  00 00 00 00 00 00 00 00  |..".............|+         10 00 00 86 a3                                    |.....|+Received:READ_TAG_ID_MULTIPLE          1790606.630500088+         ff 07 22 00 00 03 00 13  00 00 00 01 65 8a        |..".........e.|+Sending: GET_TAG_ID_BUFFER             1790606.630747461+         ff 03 29 01 ff 00 1b 03                           |..).....|+Received:GET_TAG_ID_BUFFER             1790606.636238404+         ff 26 29 00 00 01 ff 00  01 15 d7 11 0e 13 e8 00  |.&).............|+         00 03 cd 00 ae 05 00 00  00 00 80 30 00 e2 00 51  |...........0...Q|+         86 01 07 01 87 07 70 c4  c1 ba 1e db e1           |......p......|+Sending: WRITE_TAG_DATA                1790606.636934933+         ff 1d 24 03 e8 01 00 00  00 02 00 00 00 00 00 60  |..$............`|+         e2 00 51 86 01 07 01 87  07 70 c4 c1 00 00 30 39  |..Q......p....09|+         a7 0f                                             |..|+Received:WRITE_TAG_DATA                1790606.677344468+         ff 00 24 00 00 e0 26                              |..$...&|+Sending: LOCK_TAG                      1790606.677604774+         ff 18 25 03 e8 01 00 00  30 39 00 02 00 02 60 e2  |..%.....09....`.|+         00 51 86 01 07 01 87 07  70 c4 c1 eb 70           |.Q......p...p|+Received:LOCK_TAG                      1790606.736355478+         ff 00 25 00 00 f0 07                              |..%....|+Sending: WRITE_TAG_DATA                1790606.736556271+         ff 29 24 03 e8 01 00 00  00 00 03 00 00 00 00 60  |.)$............`|+         e2 00 51 86 01 07 01 87  07 70 c4 c1 54 68 69 73  |..Q......p..This|+         20 73 68 6f 75 6c 64 20  66 61 69 6c dd 94        | should fail..|+Received:WRITE_TAG_DATA                1790607.750972661+         ff 00 24 04 06 e4 20                              |..$... |+Sending: LOCK_TAG                      1790607.751291468+         ff 18 25 03 e8 01 00 00  30 39 00 02 00 00 60 e2  |..%.....09....`.|+         00 51 86 01 07 01 87 07  70 c4 c1 ed 9a           |.Q......p....|+Received:LOCK_TAG                      1790607.821038416+         ff 00 25 00 00 f0 07                              |..%....|+Sending: WRITE_TAG_DATA                1790607.821243325+         ff 2d 24 03 e8 01 00 00  00 00 03 00 00 00 00 60  |.-$............`|+         e2 00 51 86 01 07 01 87  07 70 c4 c1 54 68 69 73  |..Q......p..This|+         20 73 68 6f 75 6c 64 20  73 75 63 63 65 65 64 00  | should succeed.|+         69 0c                                             |i.|+Received:WRITE_TAG_DATA                1790607.950912849+         ff 00 24 00 00 e0 26                              |..$...&|
+ tests/param-test.hs view
@@ -0,0 +1,832 @@+-- Automatically generated by util/generate-tmr-hsc.pl+{-# LANGUAGE OverloadedStrings #-}++import Test.HUnit ( Test(..), runTestTT, assertEqual )++import qualified System.Hardware.MercuryApi as TMR++main = runTestTT tests++testBaudRate :: Test+testBaudRate = TestCase $ do+  assertEqual "TMR.paramName TMR.PARAM_BAUDRATE"+    "/reader/baudRate"+    (TMR.paramName TMR.PARAM_BAUDRATE)+  assertEqual "TMR.paramID \"/reader/baudRate\""+    TMR.PARAM_BAUDRATE+    (TMR.paramID "/reader/baudRate")++testProbeBaudRates :: Test+testProbeBaudRates = TestCase $ do+  assertEqual "TMR.paramName TMR.PARAM_PROBEBAUDRATES"+    "/reader/probeBaudRates"+    (TMR.paramName TMR.PARAM_PROBEBAUDRATES)+  assertEqual "TMR.paramID \"/reader/probeBaudRates\""+    TMR.PARAM_PROBEBAUDRATES+    (TMR.paramID "/reader/probeBaudRates")++testCommandTimeout :: Test+testCommandTimeout = TestCase $ do+  assertEqual "TMR.paramName TMR.PARAM_COMMANDTIMEOUT"+    "/reader/commandTimeout"+    (TMR.paramName TMR.PARAM_COMMANDTIMEOUT)+  assertEqual "TMR.paramID \"/reader/commandTimeout\""+    TMR.PARAM_COMMANDTIMEOUT+    (TMR.paramID "/reader/commandTimeout")++testTransportTimeout :: Test+testTransportTimeout = TestCase $ do+  assertEqual "TMR.paramName TMR.PARAM_TRANSPORTTIMEOUT"+    "/reader/transportTimeout"+    (TMR.paramName TMR.PARAM_TRANSPORTTIMEOUT)+  assertEqual "TMR.paramID \"/reader/transportTimeout\""+    TMR.PARAM_TRANSPORTTIMEOUT+    (TMR.paramID "/reader/transportTimeout")++testPowerMode :: Test+testPowerMode = TestCase $ do+  assertEqual "TMR.paramName TMR.PARAM_POWERMODE"+    "/reader/powerMode"+    (TMR.paramName TMR.PARAM_POWERMODE)+  assertEqual "TMR.paramID \"/reader/powerMode\""+    TMR.PARAM_POWERMODE+    (TMR.paramID "/reader/powerMode")++testUserMode :: Test+testUserMode = TestCase $ do+  assertEqual "TMR.paramName TMR.PARAM_USERMODE"+    "/reader/userMode"+    (TMR.paramName TMR.PARAM_USERMODE)+  assertEqual "TMR.paramID \"/reader/userMode\""+    TMR.PARAM_USERMODE+    (TMR.paramID "/reader/userMode")++testAntennaCheckPort :: Test+testAntennaCheckPort = TestCase $ do+  assertEqual "TMR.paramName TMR.PARAM_ANTENNA_CHECKPORT"+    "/reader/antenna/checkPort"+    (TMR.paramName TMR.PARAM_ANTENNA_CHECKPORT)+  assertEqual "TMR.paramID \"/reader/antenna/checkPort\""+    TMR.PARAM_ANTENNA_CHECKPORT+    (TMR.paramID "/reader/antenna/checkPort")++testAntennaPortList :: Test+testAntennaPortList = TestCase $ do+  assertEqual "TMR.paramName TMR.PARAM_ANTENNA_PORTLIST"+    "/reader/antenna/portList"+    (TMR.paramName TMR.PARAM_ANTENNA_PORTLIST)+  assertEqual "TMR.paramID \"/reader/antenna/portList\""+    TMR.PARAM_ANTENNA_PORTLIST+    (TMR.paramID "/reader/antenna/portList")++testAntennaConnectedPortList :: Test+testAntennaConnectedPortList = TestCase $ do+  assertEqual "TMR.paramName TMR.PARAM_ANTENNA_CONNECTEDPORTLIST"+    "/reader/antenna/connectedPortList"+    (TMR.paramName TMR.PARAM_ANTENNA_CONNECTEDPORTLIST)+  assertEqual "TMR.paramID \"/reader/antenna/connectedPortList\""+    TMR.PARAM_ANTENNA_CONNECTEDPORTLIST+    (TMR.paramID "/reader/antenna/connectedPortList")++testAntennaPortSwitchGpos :: Test+testAntennaPortSwitchGpos = TestCase $ do+  assertEqual "TMR.paramName TMR.PARAM_ANTENNA_PORTSWITCHGPOS"+    "/reader/antenna/portSwitchGpos"+    (TMR.paramName TMR.PARAM_ANTENNA_PORTSWITCHGPOS)+  assertEqual "TMR.paramID \"/reader/antenna/portSwitchGpos\""+    TMR.PARAM_ANTENNA_PORTSWITCHGPOS+    (TMR.paramID "/reader/antenna/portSwitchGpos")++testAntennaSettlingTimeList :: Test+testAntennaSettlingTimeList = TestCase $ do+  assertEqual "TMR.paramName TMR.PARAM_ANTENNA_SETTLINGTIMELIST"+    "/reader/antenna/settlingTimeList"+    (TMR.paramName TMR.PARAM_ANTENNA_SETTLINGTIMELIST)+  assertEqual "TMR.paramID \"/reader/antenna/settlingTimeList\""+    TMR.PARAM_ANTENNA_SETTLINGTIMELIST+    (TMR.paramID "/reader/antenna/settlingTimeList")++testAntennaReturnLoss :: Test+testAntennaReturnLoss = TestCase $ do+  assertEqual "TMR.paramName TMR.PARAM_ANTENNA_RETURNLOSS"+    "/reader/antenna/returnLoss"+    (TMR.paramName TMR.PARAM_ANTENNA_RETURNLOSS)+  assertEqual "TMR.paramID \"/reader/antenna/returnLoss\""+    TMR.PARAM_ANTENNA_RETURNLOSS+    (TMR.paramID "/reader/antenna/returnLoss")++testAntennaTxRxMap :: Test+testAntennaTxRxMap = TestCase $ do+  assertEqual "TMR.paramName TMR.PARAM_ANTENNA_TXRXMAP"+    "/reader/antenna/txRxMap"+    (TMR.paramName TMR.PARAM_ANTENNA_TXRXMAP)+  assertEqual "TMR.paramID \"/reader/antenna/txRxMap\""+    TMR.PARAM_ANTENNA_TXRXMAP+    (TMR.paramID "/reader/antenna/txRxMap")++testGpioInputList :: Test+testGpioInputList = TestCase $ do+  assertEqual "TMR.paramName TMR.PARAM_GPIO_INPUTLIST"+    "/reader/gpio/inputList"+    (TMR.paramName TMR.PARAM_GPIO_INPUTLIST)+  assertEqual "TMR.paramID \"/reader/gpio/inputList\""+    TMR.PARAM_GPIO_INPUTLIST+    (TMR.paramID "/reader/gpio/inputList")++testGpioOutputList :: Test+testGpioOutputList = TestCase $ do+  assertEqual "TMR.paramName TMR.PARAM_GPIO_OUTPUTLIST"+    "/reader/gpio/outputList"+    (TMR.paramName TMR.PARAM_GPIO_OUTPUTLIST)+  assertEqual "TMR.paramID \"/reader/gpio/outputList\""+    TMR.PARAM_GPIO_OUTPUTLIST+    (TMR.paramID "/reader/gpio/outputList")++testGen2AccessPassword :: Test+testGen2AccessPassword = TestCase $ do+  assertEqual "TMR.paramName TMR.PARAM_GEN2_ACCESSPASSWORD"+    "/reader/gen2/accessPassword"+    (TMR.paramName TMR.PARAM_GEN2_ACCESSPASSWORD)+  assertEqual "TMR.paramID \"/reader/gen2/accessPassword\""+    TMR.PARAM_GEN2_ACCESSPASSWORD+    (TMR.paramID "/reader/gen2/accessPassword")++testGen2Q :: Test+testGen2Q = TestCase $ do+  assertEqual "TMR.paramName TMR.PARAM_GEN2_Q"+    "/reader/gen2/q"+    (TMR.paramName TMR.PARAM_GEN2_Q)+  assertEqual "TMR.paramID \"/reader/gen2/q\""+    TMR.PARAM_GEN2_Q+    (TMR.paramID "/reader/gen2/q")++testGen2TagEncoding :: Test+testGen2TagEncoding = TestCase $ do+  assertEqual "TMR.paramName TMR.PARAM_GEN2_TAGENCODING"+    "/reader/gen2/tagEncoding"+    (TMR.paramName TMR.PARAM_GEN2_TAGENCODING)+  assertEqual "TMR.paramID \"/reader/gen2/tagEncoding\""+    TMR.PARAM_GEN2_TAGENCODING+    (TMR.paramID "/reader/gen2/tagEncoding")++testGen2Session :: Test+testGen2Session = TestCase $ do+  assertEqual "TMR.paramName TMR.PARAM_GEN2_SESSION"+    "/reader/gen2/session"+    (TMR.paramName TMR.PARAM_GEN2_SESSION)+  assertEqual "TMR.paramID \"/reader/gen2/session\""+    TMR.PARAM_GEN2_SESSION+    (TMR.paramID "/reader/gen2/session")++testGen2Target :: Test+testGen2Target = TestCase $ do+  assertEqual "TMR.paramName TMR.PARAM_GEN2_TARGET"+    "/reader/gen2/target"+    (TMR.paramName TMR.PARAM_GEN2_TARGET)+  assertEqual "TMR.paramID \"/reader/gen2/target\""+    TMR.PARAM_GEN2_TARGET+    (TMR.paramID "/reader/gen2/target")++testGen2BLF :: Test+testGen2BLF = TestCase $ do+  assertEqual "TMR.paramName TMR.PARAM_GEN2_BLF"+    "/reader/gen2/BLF"+    (TMR.paramName TMR.PARAM_GEN2_BLF)+  assertEqual "TMR.paramID \"/reader/gen2/BLF\""+    TMR.PARAM_GEN2_BLF+    (TMR.paramID "/reader/gen2/BLF")++testGen2Tari :: Test+testGen2Tari = TestCase $ do+  assertEqual "TMR.paramName TMR.PARAM_GEN2_TARI"+    "/reader/gen2/tari"+    (TMR.paramName TMR.PARAM_GEN2_TARI)+  assertEqual "TMR.paramID \"/reader/gen2/tari\""+    TMR.PARAM_GEN2_TARI+    (TMR.paramID "/reader/gen2/tari")++testGen2WriteMode :: Test+testGen2WriteMode = TestCase $ do+  assertEqual "TMR.paramName TMR.PARAM_GEN2_WRITEMODE"+    "/reader/gen2/writeMode"+    (TMR.paramName TMR.PARAM_GEN2_WRITEMODE)+  assertEqual "TMR.paramID \"/reader/gen2/writeMode\""+    TMR.PARAM_GEN2_WRITEMODE+    (TMR.paramID "/reader/gen2/writeMode")++testGen2Bap :: Test+testGen2Bap = TestCase $ do+  assertEqual "TMR.paramName TMR.PARAM_GEN2_BAP"+    "/reader/gen2/bap"+    (TMR.paramName TMR.PARAM_GEN2_BAP)+  assertEqual "TMR.paramID \"/reader/gen2/bap\""+    TMR.PARAM_GEN2_BAP+    (TMR.paramID "/reader/gen2/bap")++testGen2ProtocolExtension :: Test+testGen2ProtocolExtension = TestCase $ do+  assertEqual "TMR.paramName TMR.PARAM_GEN2_PROTOCOLEXTENSION"+    "/reader/gen2/protocolExtension"+    (TMR.paramName TMR.PARAM_GEN2_PROTOCOLEXTENSION)+  assertEqual "TMR.paramID \"/reader/gen2/protocolExtension\""+    TMR.PARAM_GEN2_PROTOCOLEXTENSION+    (TMR.paramID "/reader/gen2/protocolExtension")++testIso180006bBLF :: Test+testIso180006bBLF = TestCase $ do+  assertEqual "TMR.paramName TMR.PARAM_ISO180006B_BLF"+    "/reader/iso180006b/BLF"+    (TMR.paramName TMR.PARAM_ISO180006B_BLF)+  assertEqual "TMR.paramID \"/reader/iso180006b/BLF\""+    TMR.PARAM_ISO180006B_BLF+    (TMR.paramID "/reader/iso180006b/BLF")++testIso180006bModulationDepth :: Test+testIso180006bModulationDepth = TestCase $ do+  assertEqual "TMR.paramName TMR.PARAM_ISO180006B_MODULATION_DEPTH"+    "/reader/iso180006b/modulationDepth"+    (TMR.paramName TMR.PARAM_ISO180006B_MODULATION_DEPTH)+  assertEqual "TMR.paramID \"/reader/iso180006b/modulationDepth\""+    TMR.PARAM_ISO180006B_MODULATION_DEPTH+    (TMR.paramID "/reader/iso180006b/modulationDepth")++testIso180006bDelimiter :: Test+testIso180006bDelimiter = TestCase $ do+  assertEqual "TMR.paramName TMR.PARAM_ISO180006B_DELIMITER"+    "/reader/iso180006b/delimiter"+    (TMR.paramName TMR.PARAM_ISO180006B_DELIMITER)+  assertEqual "TMR.paramID \"/reader/iso180006b/delimiter\""+    TMR.PARAM_ISO180006B_DELIMITER+    (TMR.paramID "/reader/iso180006b/delimiter")++testReadAsyncOffTime :: Test+testReadAsyncOffTime = TestCase $ do+  assertEqual "TMR.paramName TMR.PARAM_READ_ASYNCOFFTIME"+    "/reader/read/asyncOffTime"+    (TMR.paramName TMR.PARAM_READ_ASYNCOFFTIME)+  assertEqual "TMR.paramID \"/reader/read/asyncOffTime\""+    TMR.PARAM_READ_ASYNCOFFTIME+    (TMR.paramID "/reader/read/asyncOffTime")++testReadAsyncOnTime :: Test+testReadAsyncOnTime = TestCase $ do+  assertEqual "TMR.paramName TMR.PARAM_READ_ASYNCONTIME"+    "/reader/read/asyncOnTime"+    (TMR.paramName TMR.PARAM_READ_ASYNCONTIME)+  assertEqual "TMR.paramID \"/reader/read/asyncOnTime\""+    TMR.PARAM_READ_ASYNCONTIME+    (TMR.paramID "/reader/read/asyncOnTime")++testReadPlan :: Test+testReadPlan = TestCase $ do+  assertEqual "TMR.paramName TMR.PARAM_READ_PLAN"+    "/reader/read/plan"+    (TMR.paramName TMR.PARAM_READ_PLAN)+  assertEqual "TMR.paramID \"/reader/read/plan\""+    TMR.PARAM_READ_PLAN+    (TMR.paramID "/reader/read/plan")++testRadioEnablePowerSave :: Test+testRadioEnablePowerSave = TestCase $ do+  assertEqual "TMR.paramName TMR.PARAM_RADIO_ENABLEPOWERSAVE"+    "/reader/radio/enablePowerSave"+    (TMR.paramName TMR.PARAM_RADIO_ENABLEPOWERSAVE)+  assertEqual "TMR.paramID \"/reader/radio/enablePowerSave\""+    TMR.PARAM_RADIO_ENABLEPOWERSAVE+    (TMR.paramID "/reader/radio/enablePowerSave")++testRadioPowerMax :: Test+testRadioPowerMax = TestCase $ do+  assertEqual "TMR.paramName TMR.PARAM_RADIO_POWERMAX"+    "/reader/radio/powerMax"+    (TMR.paramName TMR.PARAM_RADIO_POWERMAX)+  assertEqual "TMR.paramID \"/reader/radio/powerMax\""+    TMR.PARAM_RADIO_POWERMAX+    (TMR.paramID "/reader/radio/powerMax")++testRadioPowerMin :: Test+testRadioPowerMin = TestCase $ do+  assertEqual "TMR.paramName TMR.PARAM_RADIO_POWERMIN"+    "/reader/radio/powerMin"+    (TMR.paramName TMR.PARAM_RADIO_POWERMIN)+  assertEqual "TMR.paramID \"/reader/radio/powerMin\""+    TMR.PARAM_RADIO_POWERMIN+    (TMR.paramID "/reader/radio/powerMin")++testRadioPortReadPowerList :: Test+testRadioPortReadPowerList = TestCase $ do+  assertEqual "TMR.paramName TMR.PARAM_RADIO_PORTREADPOWERLIST"+    "/reader/radio/portReadPowerList"+    (TMR.paramName TMR.PARAM_RADIO_PORTREADPOWERLIST)+  assertEqual "TMR.paramID \"/reader/radio/portReadPowerList\""+    TMR.PARAM_RADIO_PORTREADPOWERLIST+    (TMR.paramID "/reader/radio/portReadPowerList")++testRadioPortWritePowerList :: Test+testRadioPortWritePowerList = TestCase $ do+  assertEqual "TMR.paramName TMR.PARAM_RADIO_PORTWRITEPOWERLIST"+    "/reader/radio/portWritePowerList"+    (TMR.paramName TMR.PARAM_RADIO_PORTWRITEPOWERLIST)+  assertEqual "TMR.paramID \"/reader/radio/portWritePowerList\""+    TMR.PARAM_RADIO_PORTWRITEPOWERLIST+    (TMR.paramID "/reader/radio/portWritePowerList")++testRadioReadPower :: Test+testRadioReadPower = TestCase $ do+  assertEqual "TMR.paramName TMR.PARAM_RADIO_READPOWER"+    "/reader/radio/readPower"+    (TMR.paramName TMR.PARAM_RADIO_READPOWER)+  assertEqual "TMR.paramID \"/reader/radio/readPower\""+    TMR.PARAM_RADIO_READPOWER+    (TMR.paramID "/reader/radio/readPower")++testRadioWritePower :: Test+testRadioWritePower = TestCase $ do+  assertEqual "TMR.paramName TMR.PARAM_RADIO_WRITEPOWER"+    "/reader/radio/writePower"+    (TMR.paramName TMR.PARAM_RADIO_WRITEPOWER)+  assertEqual "TMR.paramID \"/reader/radio/writePower\""+    TMR.PARAM_RADIO_WRITEPOWER+    (TMR.paramID "/reader/radio/writePower")++testRadioTemperature :: Test+testRadioTemperature = TestCase $ do+  assertEqual "TMR.paramName TMR.PARAM_RADIO_TEMPERATURE"+    "/reader/radio/temperature"+    (TMR.paramName TMR.PARAM_RADIO_TEMPERATURE)+  assertEqual "TMR.paramID \"/reader/radio/temperature\""+    TMR.PARAM_RADIO_TEMPERATURE+    (TMR.paramID "/reader/radio/temperature")++testTagReadDataRecordHighestRssi :: Test+testTagReadDataRecordHighestRssi = TestCase $ do+  assertEqual "TMR.paramName TMR.PARAM_TAGREADDATA_RECORDHIGHESTRSSI"+    "/reader/tagReadData/recordHighestRssi"+    (TMR.paramName TMR.PARAM_TAGREADDATA_RECORDHIGHESTRSSI)+  assertEqual "TMR.paramID \"/reader/tagReadData/recordHighestRssi\""+    TMR.PARAM_TAGREADDATA_RECORDHIGHESTRSSI+    (TMR.paramID "/reader/tagReadData/recordHighestRssi")++testTagReadDataReportRssiInDbm :: Test+testTagReadDataReportRssiInDbm = TestCase $ do+  assertEqual "TMR.paramName TMR.PARAM_TAGREADDATA_REPORTRSSIINDBM"+    "/reader/tagReadData/reportRssiInDbm"+    (TMR.paramName TMR.PARAM_TAGREADDATA_REPORTRSSIINDBM)+  assertEqual "TMR.paramID \"/reader/tagReadData/reportRssiInDbm\""+    TMR.PARAM_TAGREADDATA_REPORTRSSIINDBM+    (TMR.paramID "/reader/tagReadData/reportRssiInDbm")++testTagReadDataUniqueByAntenna :: Test+testTagReadDataUniqueByAntenna = TestCase $ do+  assertEqual "TMR.paramName TMR.PARAM_TAGREADDATA_UNIQUEBYANTENNA"+    "/reader/tagReadData/uniqueByAntenna"+    (TMR.paramName TMR.PARAM_TAGREADDATA_UNIQUEBYANTENNA)+  assertEqual "TMR.paramID \"/reader/tagReadData/uniqueByAntenna\""+    TMR.PARAM_TAGREADDATA_UNIQUEBYANTENNA+    (TMR.paramID "/reader/tagReadData/uniqueByAntenna")++testTagReadDataUniqueByData :: Test+testTagReadDataUniqueByData = TestCase $ do+  assertEqual "TMR.paramName TMR.PARAM_TAGREADDATA_UNIQUEBYDATA"+    "/reader/tagReadData/uniqueByData"+    (TMR.paramName TMR.PARAM_TAGREADDATA_UNIQUEBYDATA)+  assertEqual "TMR.paramID \"/reader/tagReadData/uniqueByData\""+    TMR.PARAM_TAGREADDATA_UNIQUEBYDATA+    (TMR.paramID "/reader/tagReadData/uniqueByData")++testTagopAntenna :: Test+testTagopAntenna = TestCase $ do+  assertEqual "TMR.paramName TMR.PARAM_TAGOP_ANTENNA"+    "/reader/tagop/antenna"+    (TMR.paramName TMR.PARAM_TAGOP_ANTENNA)+  assertEqual "TMR.paramID \"/reader/tagop/antenna\""+    TMR.PARAM_TAGOP_ANTENNA+    (TMR.paramID "/reader/tagop/antenna")++testTagopProtocol :: Test+testTagopProtocol = TestCase $ do+  assertEqual "TMR.paramName TMR.PARAM_TAGOP_PROTOCOL"+    "/reader/tagop/protocol"+    (TMR.paramName TMR.PARAM_TAGOP_PROTOCOL)+  assertEqual "TMR.paramID \"/reader/tagop/protocol\""+    TMR.PARAM_TAGOP_PROTOCOL+    (TMR.paramID "/reader/tagop/protocol")++testVersionHardware :: Test+testVersionHardware = TestCase $ do+  assertEqual "TMR.paramName TMR.PARAM_VERSION_HARDWARE"+    "/reader/version/hardware"+    (TMR.paramName TMR.PARAM_VERSION_HARDWARE)+  assertEqual "TMR.paramID \"/reader/version/hardware\""+    TMR.PARAM_VERSION_HARDWARE+    (TMR.paramID "/reader/version/hardware")++testVersionSerial :: Test+testVersionSerial = TestCase $ do+  assertEqual "TMR.paramName TMR.PARAM_VERSION_SERIAL"+    "/reader/version/serial"+    (TMR.paramName TMR.PARAM_VERSION_SERIAL)+  assertEqual "TMR.paramID \"/reader/version/serial\""+    TMR.PARAM_VERSION_SERIAL+    (TMR.paramID "/reader/version/serial")++testVersionModel :: Test+testVersionModel = TestCase $ do+  assertEqual "TMR.paramName TMR.PARAM_VERSION_MODEL"+    "/reader/version/model"+    (TMR.paramName TMR.PARAM_VERSION_MODEL)+  assertEqual "TMR.paramID \"/reader/version/model\""+    TMR.PARAM_VERSION_MODEL+    (TMR.paramID "/reader/version/model")++testVersionSoftware :: Test+testVersionSoftware = TestCase $ do+  assertEqual "TMR.paramName TMR.PARAM_VERSION_SOFTWARE"+    "/reader/version/software"+    (TMR.paramName TMR.PARAM_VERSION_SOFTWARE)+  assertEqual "TMR.paramID \"/reader/version/software\""+    TMR.PARAM_VERSION_SOFTWARE+    (TMR.paramID "/reader/version/software")++testVersionSupportedProtocols :: Test+testVersionSupportedProtocols = TestCase $ do+  assertEqual "TMR.paramName TMR.PARAM_VERSION_SUPPORTEDPROTOCOLS"+    "/reader/version/supportedProtocols"+    (TMR.paramName TMR.PARAM_VERSION_SUPPORTEDPROTOCOLS)+  assertEqual "TMR.paramID \"/reader/version/supportedProtocols\""+    TMR.PARAM_VERSION_SUPPORTEDPROTOCOLS+    (TMR.paramID "/reader/version/supportedProtocols")++testRegionHopTable :: Test+testRegionHopTable = TestCase $ do+  assertEqual "TMR.paramName TMR.PARAM_REGION_HOPTABLE"+    "/reader/region/hopTable"+    (TMR.paramName TMR.PARAM_REGION_HOPTABLE)+  assertEqual "TMR.paramID \"/reader/region/hopTable\""+    TMR.PARAM_REGION_HOPTABLE+    (TMR.paramID "/reader/region/hopTable")++testRegionHopTime :: Test+testRegionHopTime = TestCase $ do+  assertEqual "TMR.paramName TMR.PARAM_REGION_HOPTIME"+    "/reader/region/hopTime"+    (TMR.paramName TMR.PARAM_REGION_HOPTIME)+  assertEqual "TMR.paramID \"/reader/region/hopTime\""+    TMR.PARAM_REGION_HOPTIME+    (TMR.paramID "/reader/region/hopTime")++testRegionId :: Test+testRegionId = TestCase $ do+  assertEqual "TMR.paramName TMR.PARAM_REGION_ID"+    "/reader/region/id"+    (TMR.paramName TMR.PARAM_REGION_ID)+  assertEqual "TMR.paramID \"/reader/region/id\""+    TMR.PARAM_REGION_ID+    (TMR.paramID "/reader/region/id")++testRegionSupportedRegions :: Test+testRegionSupportedRegions = TestCase $ do+  assertEqual "TMR.paramName TMR.PARAM_REGION_SUPPORTEDREGIONS"+    "/reader/region/supportedRegions"+    (TMR.paramName TMR.PARAM_REGION_SUPPORTEDREGIONS)+  assertEqual "TMR.paramID \"/reader/region/supportedRegions\""+    TMR.PARAM_REGION_SUPPORTEDREGIONS+    (TMR.paramID "/reader/region/supportedRegions")++testRegionLbtEnable :: Test+testRegionLbtEnable = TestCase $ do+  assertEqual "TMR.paramName TMR.PARAM_REGION_LBT_ENABLE"+    "/reader/region/lbt/enable"+    (TMR.paramName TMR.PARAM_REGION_LBT_ENABLE)+  assertEqual "TMR.paramID \"/reader/region/lbt/enable\""+    TMR.PARAM_REGION_LBT_ENABLE+    (TMR.paramID "/reader/region/lbt/enable")++testLicenseKey :: Test+testLicenseKey = TestCase $ do+  assertEqual "TMR.paramName TMR.PARAM_LICENSE_KEY"+    "/reader/licenseKey"+    (TMR.paramName TMR.PARAM_LICENSE_KEY)+  assertEqual "TMR.paramID \"/reader/licenseKey\""+    TMR.PARAM_LICENSE_KEY+    (TMR.paramID "/reader/licenseKey")++testUserConfig :: Test+testUserConfig = TestCase $ do+  assertEqual "TMR.paramName TMR.PARAM_USER_CONFIG"+    "/reader/userConfig"+    (TMR.paramName TMR.PARAM_USER_CONFIG)+  assertEqual "TMR.paramID \"/reader/userConfig\""+    TMR.PARAM_USER_CONFIG+    (TMR.paramID "/reader/userConfig")++testRadioEnableSJC :: Test+testRadioEnableSJC = TestCase $ do+  assertEqual "TMR.paramName TMR.PARAM_RADIO_ENABLESJC"+    "/reader/radio/enableSJC"+    (TMR.paramName TMR.PARAM_RADIO_ENABLESJC)+  assertEqual "TMR.paramID \"/reader/radio/enableSJC\""+    TMR.PARAM_RADIO_ENABLESJC+    (TMR.paramID "/reader/radio/enableSJC")++testExtendedEpc :: Test+testExtendedEpc = TestCase $ do+  assertEqual "TMR.paramName TMR.PARAM_EXTENDEDEPC"+    "/reader/extendedEpc"+    (TMR.paramName TMR.PARAM_EXTENDEDEPC)+  assertEqual "TMR.paramID \"/reader/extendedEpc\""+    TMR.PARAM_EXTENDEDEPC+    (TMR.paramID "/reader/extendedEpc")++testStatistics :: Test+testStatistics = TestCase $ do+  assertEqual "TMR.paramName TMR.PARAM_READER_STATISTICS"+    "/reader/statistics"+    (TMR.paramName TMR.PARAM_READER_STATISTICS)+  assertEqual "TMR.paramID \"/reader/statistics\""+    TMR.PARAM_READER_STATISTICS+    (TMR.paramID "/reader/statistics")++testStats :: Test+testStats = TestCase $ do+  assertEqual "TMR.paramName TMR.PARAM_READER_STATS"+    "/reader/stats"+    (TMR.paramName TMR.PARAM_READER_STATS)+  assertEqual "TMR.paramID \"/reader/stats\""+    TMR.PARAM_READER_STATS+    (TMR.paramID "/reader/stats")++testUri :: Test+testUri = TestCase $ do+  assertEqual "TMR.paramName TMR.PARAM_URI"+    "/reader/uri"+    (TMR.paramName TMR.PARAM_URI)+  assertEqual "TMR.paramID \"/reader/uri\""+    TMR.PARAM_URI+    (TMR.paramID "/reader/uri")++testVersionProductGroupID :: Test+testVersionProductGroupID = TestCase $ do+  assertEqual "TMR.paramName TMR.PARAM_PRODUCT_GROUP_ID"+    "/reader/version/productGroupID"+    (TMR.paramName TMR.PARAM_PRODUCT_GROUP_ID)+  assertEqual "TMR.paramID \"/reader/version/productGroupID\""+    TMR.PARAM_PRODUCT_GROUP_ID+    (TMR.paramID "/reader/version/productGroupID")++testVersionProductGroup :: Test+testVersionProductGroup = TestCase $ do+  assertEqual "TMR.paramName TMR.PARAM_PRODUCT_GROUP"+    "/reader/version/productGroup"+    (TMR.paramName TMR.PARAM_PRODUCT_GROUP)+  assertEqual "TMR.paramID \"/reader/version/productGroup\""+    TMR.PARAM_PRODUCT_GROUP+    (TMR.paramID "/reader/version/productGroup")++testVersionProductID :: Test+testVersionProductID = TestCase $ do+  assertEqual "TMR.paramName TMR.PARAM_PRODUCT_ID"+    "/reader/version/productID"+    (TMR.paramName TMR.PARAM_PRODUCT_ID)+  assertEqual "TMR.paramID \"/reader/version/productID\""+    TMR.PARAM_PRODUCT_ID+    (TMR.paramID "/reader/version/productID")++testTagReadDataTagopSuccesses :: Test+testTagReadDataTagopSuccesses = TestCase $ do+  assertEqual "TMR.paramName TMR.PARAM_TAGREADATA_TAGOPSUCCESSCOUNT"+    "/reader/tagReadData/tagopSuccesses"+    (TMR.paramName TMR.PARAM_TAGREADATA_TAGOPSUCCESSCOUNT)+  assertEqual "TMR.paramID \"/reader/tagReadData/tagopSuccesses\""+    TMR.PARAM_TAGREADATA_TAGOPSUCCESSCOUNT+    (TMR.paramID "/reader/tagReadData/tagopSuccesses")++testTagReadDataTagopFailures :: Test+testTagReadDataTagopFailures = TestCase $ do+  assertEqual "TMR.paramName TMR.PARAM_TAGREADATA_TAGOPFAILURECOUNT"+    "/reader/tagReadData/tagopFailures"+    (TMR.paramName TMR.PARAM_TAGREADATA_TAGOPFAILURECOUNT)+  assertEqual "TMR.paramID \"/reader/tagReadData/tagopFailures\""+    TMR.PARAM_TAGREADATA_TAGOPFAILURECOUNT+    (TMR.paramID "/reader/tagReadData/tagopFailures")++testStatusAntennaEnable :: Test+testStatusAntennaEnable = TestCase $ do+  assertEqual "TMR.paramName TMR.PARAM_STATUS_ENABLE_ANTENNAREPORT"+    "/reader/status/antennaEnable"+    (TMR.paramName TMR.PARAM_STATUS_ENABLE_ANTENNAREPORT)+  assertEqual "TMR.paramID \"/reader/status/antennaEnable\""+    TMR.PARAM_STATUS_ENABLE_ANTENNAREPORT+    (TMR.paramID "/reader/status/antennaEnable")++testStatusFrequencyEnable :: Test+testStatusFrequencyEnable = TestCase $ do+  assertEqual "TMR.paramName TMR.PARAM_STATUS_ENABLE_FREQUENCYREPORT"+    "/reader/status/frequencyEnable"+    (TMR.paramName TMR.PARAM_STATUS_ENABLE_FREQUENCYREPORT)+  assertEqual "TMR.paramID \"/reader/status/frequencyEnable\""+    TMR.PARAM_STATUS_ENABLE_FREQUENCYREPORT+    (TMR.paramID "/reader/status/frequencyEnable")++testStatusTemperatureEnable :: Test+testStatusTemperatureEnable = TestCase $ do+  assertEqual "TMR.paramName TMR.PARAM_STATUS_ENABLE_TEMPERATUREREPORT"+    "/reader/status/temperatureEnable"+    (TMR.paramName TMR.PARAM_STATUS_ENABLE_TEMPERATUREREPORT)+  assertEqual "TMR.paramID \"/reader/status/temperatureEnable\""+    TMR.PARAM_STATUS_ENABLE_TEMPERATUREREPORT+    (TMR.paramID "/reader/status/temperatureEnable")++testTagReadDataEnableReadFilter :: Test+testTagReadDataEnableReadFilter = TestCase $ do+  assertEqual "TMR.paramName TMR.PARAM_TAGREADDATA_ENABLEREADFILTER"+    "/reader/tagReadData/enableReadFilter"+    (TMR.paramName TMR.PARAM_TAGREADDATA_ENABLEREADFILTER)+  assertEqual "TMR.paramID \"/reader/tagReadData/enableReadFilter\""+    TMR.PARAM_TAGREADDATA_ENABLEREADFILTER+    (TMR.paramID "/reader/tagReadData/enableReadFilter")++testTagReadDataReadFilterTimeout :: Test+testTagReadDataReadFilterTimeout = TestCase $ do+  assertEqual "TMR.paramName TMR.PARAM_TAGREADDATA_READFILTERTIMEOUT"+    "/reader/tagReadData/readFilterTimeout"+    (TMR.paramName TMR.PARAM_TAGREADDATA_READFILTERTIMEOUT)+  assertEqual "TMR.paramID \"/reader/tagReadData/readFilterTimeout\""+    TMR.PARAM_TAGREADDATA_READFILTERTIMEOUT+    (TMR.paramID "/reader/tagReadData/readFilterTimeout")++testTagReadDataUniqueByProtocol :: Test+testTagReadDataUniqueByProtocol = TestCase $ do+  assertEqual "TMR.paramName TMR.PARAM_TAGREADDATA_UNIQUEBYPROTOCOL"+    "/reader/tagReadData/uniqueByProtocol"+    (TMR.paramName TMR.PARAM_TAGREADDATA_UNIQUEBYPROTOCOL)+  assertEqual "TMR.paramID \"/reader/tagReadData/uniqueByProtocol\""+    TMR.PARAM_TAGREADDATA_UNIQUEBYPROTOCOL+    (TMR.paramID "/reader/tagReadData/uniqueByProtocol")++testDescription :: Test+testDescription = TestCase $ do+  assertEqual "TMR.paramName TMR.PARAM_READER_DESCRIPTION"+    "/reader/description"+    (TMR.paramName TMR.PARAM_READER_DESCRIPTION)+  assertEqual "TMR.paramID \"/reader/description\""+    TMR.PARAM_READER_DESCRIPTION+    (TMR.paramID "/reader/description")++testHostname :: Test+testHostname = TestCase $ do+  assertEqual "TMR.paramName TMR.PARAM_READER_HOSTNAME"+    "/reader/hostname"+    (TMR.paramName TMR.PARAM_READER_HOSTNAME)+  assertEqual "TMR.paramID \"/reader/hostname\""+    TMR.PARAM_READER_HOSTNAME+    (TMR.paramID "/reader/hostname")++testCurrentTime :: Test+testCurrentTime = TestCase $ do+  assertEqual "TMR.paramName TMR.PARAM_CURRENTTIME"+    "/reader/currentTime"+    (TMR.paramName TMR.PARAM_CURRENTTIME)+  assertEqual "TMR.paramID \"/reader/currentTime\""+    TMR.PARAM_CURRENTTIME+    (TMR.paramID "/reader/currentTime")++testGen2WriteReplyTimeout :: Test+testGen2WriteReplyTimeout = TestCase $ do+  assertEqual "TMR.paramName TMR.PARAM_READER_WRITE_REPLY_TIMEOUT"+    "/reader/gen2/writeReplyTimeout"+    (TMR.paramName TMR.PARAM_READER_WRITE_REPLY_TIMEOUT)+  assertEqual "TMR.paramID \"/reader/gen2/writeReplyTimeout\""+    TMR.PARAM_READER_WRITE_REPLY_TIMEOUT+    (TMR.paramID "/reader/gen2/writeReplyTimeout")++testGen2WriteEarlyExit :: Test+testGen2WriteEarlyExit = TestCase $ do+  assertEqual "TMR.paramName TMR.PARAM_READER_WRITE_EARLY_EXIT"+    "/reader/gen2/writeEarlyExit"+    (TMR.paramName TMR.PARAM_READER_WRITE_EARLY_EXIT)+  assertEqual "TMR.paramID \"/reader/gen2/writeEarlyExit\""+    TMR.PARAM_READER_WRITE_EARLY_EXIT+    (TMR.paramID "/reader/gen2/writeEarlyExit")++testStatsEnable :: Test+testStatsEnable = TestCase $ do+  assertEqual "TMR.paramName TMR.PARAM_READER_STATS_ENABLE"+    "/reader/stats/enable"+    (TMR.paramName TMR.PARAM_READER_STATS_ENABLE)+  assertEqual "TMR.paramID \"/reader/stats/enable\""+    TMR.PARAM_READER_STATS_ENABLE+    (TMR.paramID "/reader/stats/enable")++testTriggerReadGpi :: Test+testTriggerReadGpi = TestCase $ do+  assertEqual "TMR.paramName TMR.PARAM_TRIGGER_READ_GPI"+    "/reader/trigger/read/Gpi"+    (TMR.paramName TMR.PARAM_TRIGGER_READ_GPI)+  assertEqual "TMR.paramID \"/reader/trigger/read/Gpi\""+    TMR.PARAM_TRIGGER_READ_GPI+    (TMR.paramID "/reader/trigger/read/Gpi")++testMetadataflags :: Test+testMetadataflags = TestCase $ do+  assertEqual "TMR.paramName TMR.PARAM_METADATAFLAG"+    "/reader/metadataflags"+    (TMR.paramName TMR.PARAM_METADATAFLAG)+  assertEqual "TMR.paramID \"/reader/metadataflags\""+    TMR.PARAM_METADATAFLAG+    (TMR.paramID "/reader/metadataflags")++testLicensedFeatures :: Test+testLicensedFeatures = TestCase $ do+  assertEqual "TMR.paramName TMR.PARAM_LICENSED_FEATURES"+    "/reader/licensedFeatures"+    (TMR.paramName TMR.PARAM_LICENSED_FEATURES)+  assertEqual "TMR.paramID \"/reader/licensedFeatures\""+    TMR.PARAM_LICENSED_FEATURES+    (TMR.paramID "/reader/licensedFeatures")++tests :: Test+tests = TestList+  [ TestLabel "testBaudRate" testBaudRate+  , TestLabel "testProbeBaudRates" testProbeBaudRates+  , TestLabel "testCommandTimeout" testCommandTimeout+  , TestLabel "testTransportTimeout" testTransportTimeout+  , TestLabel "testPowerMode" testPowerMode+  , TestLabel "testUserMode" testUserMode+  , TestLabel "testAntennaCheckPort" testAntennaCheckPort+  , TestLabel "testAntennaPortList" testAntennaPortList+  , TestLabel "testAntennaConnectedPortList" testAntennaConnectedPortList+  , TestLabel "testAntennaPortSwitchGpos" testAntennaPortSwitchGpos+  , TestLabel "testAntennaSettlingTimeList" testAntennaSettlingTimeList+  , TestLabel "testAntennaReturnLoss" testAntennaReturnLoss+  , TestLabel "testAntennaTxRxMap" testAntennaTxRxMap+  , TestLabel "testGpioInputList" testGpioInputList+  , TestLabel "testGpioOutputList" testGpioOutputList+  , TestLabel "testGen2AccessPassword" testGen2AccessPassword+  , TestLabel "testGen2Q" testGen2Q+  , TestLabel "testGen2TagEncoding" testGen2TagEncoding+  , TestLabel "testGen2Session" testGen2Session+  , TestLabel "testGen2Target" testGen2Target+  , TestLabel "testGen2BLF" testGen2BLF+  , TestLabel "testGen2Tari" testGen2Tari+  , TestLabel "testGen2WriteMode" testGen2WriteMode+  , TestLabel "testGen2Bap" testGen2Bap+  , TestLabel "testGen2ProtocolExtension" testGen2ProtocolExtension+  , TestLabel "testIso180006bBLF" testIso180006bBLF+  , TestLabel "testIso180006bModulationDepth" testIso180006bModulationDepth+  , TestLabel "testIso180006bDelimiter" testIso180006bDelimiter+  , TestLabel "testReadAsyncOffTime" testReadAsyncOffTime+  , TestLabel "testReadAsyncOnTime" testReadAsyncOnTime+  , TestLabel "testReadPlan" testReadPlan+  , TestLabel "testRadioEnablePowerSave" testRadioEnablePowerSave+  , TestLabel "testRadioPowerMax" testRadioPowerMax+  , TestLabel "testRadioPowerMin" testRadioPowerMin+  , TestLabel "testRadioPortReadPowerList" testRadioPortReadPowerList+  , TestLabel "testRadioPortWritePowerList" testRadioPortWritePowerList+  , TestLabel "testRadioReadPower" testRadioReadPower+  , TestLabel "testRadioWritePower" testRadioWritePower+  , TestLabel "testRadioTemperature" testRadioTemperature+  , TestLabel "testTagReadDataRecordHighestRssi" testTagReadDataRecordHighestRssi+  , TestLabel "testTagReadDataReportRssiInDbm" testTagReadDataReportRssiInDbm+  , TestLabel "testTagReadDataUniqueByAntenna" testTagReadDataUniqueByAntenna+  , TestLabel "testTagReadDataUniqueByData" testTagReadDataUniqueByData+  , TestLabel "testTagopAntenna" testTagopAntenna+  , TestLabel "testTagopProtocol" testTagopProtocol+  , TestLabel "testVersionHardware" testVersionHardware+  , TestLabel "testVersionSerial" testVersionSerial+  , TestLabel "testVersionModel" testVersionModel+  , TestLabel "testVersionSoftware" testVersionSoftware+  , TestLabel "testVersionSupportedProtocols" testVersionSupportedProtocols+  , TestLabel "testRegionHopTable" testRegionHopTable+  , TestLabel "testRegionHopTime" testRegionHopTime+  , TestLabel "testRegionId" testRegionId+  , TestLabel "testRegionSupportedRegions" testRegionSupportedRegions+  , TestLabel "testRegionLbtEnable" testRegionLbtEnable+  , TestLabel "testLicenseKey" testLicenseKey+  , TestLabel "testUserConfig" testUserConfig+  , TestLabel "testRadioEnableSJC" testRadioEnableSJC+  , TestLabel "testExtendedEpc" testExtendedEpc+  , TestLabel "testStatistics" testStatistics+  , TestLabel "testStats" testStats+  , TestLabel "testUri" testUri+  , TestLabel "testVersionProductGroupID" testVersionProductGroupID+  , TestLabel "testVersionProductGroup" testVersionProductGroup+  , TestLabel "testVersionProductID" testVersionProductID+  , TestLabel "testTagReadDataTagopSuccesses" testTagReadDataTagopSuccesses+  , TestLabel "testTagReadDataTagopFailures" testTagReadDataTagopFailures+  , TestLabel "testStatusAntennaEnable" testStatusAntennaEnable+  , TestLabel "testStatusFrequencyEnable" testStatusFrequencyEnable+  , TestLabel "testStatusTemperatureEnable" testStatusTemperatureEnable+  , TestLabel "testTagReadDataEnableReadFilter" testTagReadDataEnableReadFilter+  , TestLabel "testTagReadDataReadFilterTimeout" testTagReadDataReadFilterTimeout+  , TestLabel "testTagReadDataUniqueByProtocol" testTagReadDataUniqueByProtocol+  , TestLabel "testDescription" testDescription+  , TestLabel "testHostname" testHostname+  , TestLabel "testCurrentTime" testCurrentTime+  , TestLabel "testGen2WriteReplyTimeout" testGen2WriteReplyTimeout+  , TestLabel "testGen2WriteEarlyExit" testGen2WriteEarlyExit+  , TestLabel "testStatsEnable" testStatsEnable+  , TestLabel "testTriggerReadGpi" testTriggerReadGpi+  , TestLabel "testMetadataflags" testMetadataflags+  , TestLabel "testLicensedFeatures" testLicensedFeatures+  ]
+ tests/params.result view
@@ -0,0 +1,77 @@+Right [PARAM_BAUDRATE,PARAM_PROBEBAUDRATES,PARAM_COMMANDTIMEOUT,PARAM_TRANSPORTTIMEOUT,PARAM_POWERMODE,PARAM_USERMODE,PARAM_ANTENNA_CHECKPORT,PARAM_ANTENNA_PORTLIST,PARAM_ANTENNA_CONNECTEDPORTLIST,PARAM_ANTENNA_PORTSWITCHGPOS,PARAM_ANTENNA_SETTLINGTIMELIST,PARAM_ANTENNA_RETURNLOSS,PARAM_ANTENNA_TXRXMAP,PARAM_GPIO_INPUTLIST,PARAM_GPIO_OUTPUTLIST,PARAM_GEN2_ACCESSPASSWORD,PARAM_GEN2_Q,PARAM_GEN2_TAGENCODING,PARAM_GEN2_SESSION,PARAM_GEN2_TARGET,PARAM_GEN2_BLF,PARAM_GEN2_TARI,PARAM_GEN2_WRITEMODE,PARAM_GEN2_BAP,PARAM_GEN2_PROTOCOLEXTENSION,PARAM_ISO180006B_MODULATION_DEPTH,PARAM_ISO180006B_DELIMITER,PARAM_READ_ASYNCOFFTIME,PARAM_READ_ASYNCONTIME,PARAM_READ_PLAN,PARAM_RADIO_ENABLEPOWERSAVE,PARAM_RADIO_POWERMAX,PARAM_RADIO_POWERMIN,PARAM_RADIO_PORTREADPOWERLIST,PARAM_RADIO_PORTWRITEPOWERLIST,PARAM_RADIO_READPOWER,PARAM_RADIO_WRITEPOWER,PARAM_RADIO_TEMPERATURE,PARAM_TAGREADDATA_RECORDHIGHESTRSSI,PARAM_TAGREADDATA_REPORTRSSIINDBM,PARAM_TAGREADDATA_UNIQUEBYANTENNA,PARAM_TAGREADDATA_UNIQUEBYDATA,PARAM_TAGOP_ANTENNA,PARAM_TAGOP_PROTOCOL,PARAM_VERSION_HARDWARE,PARAM_VERSION_SERIAL,PARAM_VERSION_MODEL,PARAM_VERSION_SOFTWARE,PARAM_VERSION_SUPPORTEDPROTOCOLS,PARAM_REGION_HOPTABLE,PARAM_REGION_HOPTIME,PARAM_REGION_ID,PARAM_REGION_SUPPORTEDREGIONS,PARAM_REGION_LBT_ENABLE,PARAM_LICENSE_KEY,PARAM_USER_CONFIG,PARAM_RADIO_ENABLESJC,PARAM_EXTENDEDEPC,PARAM_READER_STATISTICS,PARAM_READER_STATS,PARAM_URI,PARAM_PRODUCT_GROUP_ID,PARAM_PRODUCT_GROUP,PARAM_PRODUCT_ID,PARAM_TAGREADATA_TAGOPSUCCESSCOUNT,PARAM_TAGREADATA_TAGOPFAILURECOUNT,PARAM_STATUS_ENABLE_ANTENNAREPORT,PARAM_STATUS_ENABLE_FREQUENCYREPORT,PARAM_STATUS_ENABLE_TEMPERATUREREPORT,PARAM_TAGREADDATA_ENABLEREADFILTER,PARAM_TAGREADDATA_READFILTERTIMEOUT,PARAM_TAGREADDATA_UNIQUEBYPROTOCOL,PARAM_READER_WRITE_REPLY_TIMEOUT,PARAM_READER_WRITE_EARLY_EXIT,PARAM_READER_STATS_ENABLE,PARAM_TRIGGER_READ_GPI,PARAM_METADATAFLAG]+Right "115200"+Right "[9600,115200,921600,19200,38400,57600,230400,460800]"+Right "1000"+Right "10000"+Right "POWER_MODE_FULL"+Left (MercuryException {meStatusType = ERROR_TYPE_BINDING, meStatus = ERROR_UNIMPLEMENTED_PARAM, meMessage = "The given parameter is not yet implemented in the Haskell binding.", meLocation = "paramGet", meParam = "PARAM_USERMODE", meUri = ""})+Right "False"+Right "[1]"+Right "[]"+Right "[]"+Left (MercuryException {meStatusType = ERROR_TYPE_BINDING, meStatus = ERROR_UNIMPLEMENTED_PARAM, meMessage = "The given parameter is not yet implemented in the Haskell binding.", meLocation = "paramGet", meParam = "PARAM_ANTENNA_SETTLINGTIMELIST", meUri = ""})+Left (MercuryException {meStatusType = ERROR_TYPE_BINDING, meStatus = ERROR_UNIMPLEMENTED_PARAM, meMessage = "The given parameter is not yet implemented in the Haskell binding.", meLocation = "paramGet", meParam = "PARAM_ANTENNA_RETURNLOSS", meUri = ""})+Left (MercuryException {meStatusType = ERROR_TYPE_BINDING, meStatus = ERROR_UNIMPLEMENTED_PARAM, meMessage = "The given parameter is not yet implemented in the Haskell binding.", meLocation = "paramGet", meParam = "PARAM_ANTENNA_TXRXMAP", meUri = ""})+Right "[1,2,3,4]"+Right "[]"+Right "0"+Left (MercuryException {meStatusType = ERROR_TYPE_BINDING, meStatus = ERROR_UNIMPLEMENTED_PARAM, meMessage = "The given parameter is not yet implemented in the Haskell binding.", meLocation = "paramGet", meParam = "PARAM_GEN2_Q", meUri = ""})+Left (MercuryException {meStatusType = ERROR_TYPE_BINDING, meStatus = ERROR_UNIMPLEMENTED_PARAM, meMessage = "The given parameter is not yet implemented in the Haskell binding.", meLocation = "paramGet", meParam = "PARAM_GEN2_TAGENCODING", meUri = ""})+Left (MercuryException {meStatusType = ERROR_TYPE_BINDING, meStatus = ERROR_UNIMPLEMENTED_PARAM, meMessage = "The given parameter is not yet implemented in the Haskell binding.", meLocation = "paramGet", meParam = "PARAM_GEN2_SESSION", meUri = ""})+Left (MercuryException {meStatusType = ERROR_TYPE_BINDING, meStatus = ERROR_UNIMPLEMENTED_PARAM, meMessage = "The given parameter is not yet implemented in the Haskell binding.", meLocation = "paramGet", meParam = "PARAM_GEN2_TARGET", meUri = ""})+Left (MercuryException {meStatusType = ERROR_TYPE_BINDING, meStatus = ERROR_UNIMPLEMENTED_PARAM, meMessage = "The given parameter is not yet implemented in the Haskell binding.", meLocation = "paramGet", meParam = "PARAM_GEN2_BLF", meUri = ""})+Left (MercuryException {meStatusType = ERROR_TYPE_BINDING, meStatus = ERROR_UNIMPLEMENTED_PARAM, meMessage = "The given parameter is not yet implemented in the Haskell binding.", meLocation = "paramGet", meParam = "PARAM_GEN2_TARI", meUri = ""})+Right "GEN2_WORD_ONLY"+Left (MercuryException {meStatusType = ERROR_TYPE_BINDING, meStatus = ERROR_UNIMPLEMENTED_PARAM, meMessage = "The given parameter is not yet implemented in the Haskell binding.", meLocation = "paramGet", meParam = "PARAM_GEN2_BAP", meUri = ""})+Left (MercuryException {meStatusType = ERROR_TYPE_BINDING, meStatus = ERROR_UNIMPLEMENTED_PARAM, meMessage = "The given parameter is not yet implemented in the Haskell binding.", meLocation = "paramGet", meParam = "PARAM_GEN2_PROTOCOLEXTENSION", meUri = ""})+Left (MercuryException {meStatusType = ERROR_TYPE_BINDING, meStatus = ERROR_UNIMPLEMENTED_PARAM, meMessage = "The given parameter is not yet implemented in the Haskell binding.", meLocation = "paramGet", meParam = "PARAM_ISO180006B_MODULATION_DEPTH", meUri = ""})+Left (MercuryException {meStatusType = ERROR_TYPE_BINDING, meStatus = ERROR_UNIMPLEMENTED_PARAM, meMessage = "The given parameter is not yet implemented in the Haskell binding.", meLocation = "paramGet", meParam = "PARAM_ISO180006B_DELIMITER", meUri = ""})+Right "0"+Right "250"+Right "SimpleReadPlan {rpWeight = 1, rpEnableAutonomousRead = False, rpAntennas = [], rpProtocol = TAG_PROTOCOL_GEN2, rpFilter = Nothing, rpTagop = Nothing, rpUseFastSearch = False, rpStopOnCount = Nothing, rpTriggerRead = Nothing}"+Right "False"+Right "2700"+Right "0"+Left (MercuryException {meStatusType = ERROR_TYPE_BINDING, meStatus = ERROR_UNIMPLEMENTED_PARAM, meMessage = "The given parameter is not yet implemented in the Haskell binding.", meLocation = "paramGet", meParam = "PARAM_RADIO_PORTREADPOWERLIST", meUri = ""})+Left (MercuryException {meStatusType = ERROR_TYPE_BINDING, meStatus = ERROR_UNIMPLEMENTED_PARAM, meMessage = "The given parameter is not yet implemented in the Haskell binding.", meLocation = "paramGet", meParam = "PARAM_RADIO_PORTWRITEPOWERLIST", meUri = ""})+Right "2300"+Right "2300"+Right "35"+Right "False"+Right "True"+Right "True"+Right "False"+Right "0"+Right "TAG_PROTOCOL_GEN2"+Right "\"30.00.00.02\""+Right "\"45160067701130324A\""+Right "\"M6e Nano\""+Right "\"01.07.01.02-20.16.12.13-BL14.12.08.00\""+Right "[TAG_PROTOCOL_GEN2]"+Right "[]"+Right "0"+Right "REGION_NONE"+Right "[REGION_NA2,REGION_NA3,REGION_IN,REGION_JP,REGION_PRC,REGION_EU3,REGION_KR2,REGION_AU,REGION_NZ,REGION_OPEN]"+Right "False"+Left (MercuryException {meStatusType = ERROR_TYPE_MISC, meStatus = ERROR_UNSUPPORTED, meMessage = "Unsupported operation", meLocation = "paramGet", meParam = "PARAM_LICENSE_KEY", meUri = ""})+Left (MercuryException {meStatusType = ERROR_TYPE_BINDING, meStatus = ERROR_UNIMPLEMENTED_PARAM, meMessage = "The given parameter is not yet implemented in the Haskell binding.", meLocation = "paramGet", meParam = "PARAM_USER_CONFIG", meUri = ""})+Left (MercuryException {meStatusType = ERROR_TYPE_CODE, meStatus = ERROR_MSG_INVALID_PARAMETER_VALUE, meMessage = "Parameter to command is invalid", meLocation = "paramGet", meParam = "PARAM_RADIO_ENABLESJC", meUri = ""})+Left (MercuryException {meStatusType = ERROR_TYPE_MISC, meStatus = ERROR_UNSUPPORTED, meMessage = "Unsupported operation", meLocation = "paramGet", meParam = "PARAM_EXTENDEDEPC", meUri = ""})+Left (MercuryException {meStatusType = ERROR_TYPE_BINDING, meStatus = ERROR_UNIMPLEMENTED_PARAM, meMessage = "The given parameter is not yet implemented in the Haskell binding.", meLocation = "paramGet", meParam = "PARAM_READER_STATISTICS", meUri = ""})+Left (MercuryException {meStatusType = ERROR_TYPE_BINDING, meStatus = ERROR_UNIMPLEMENTED_PARAM, meMessage = "The given parameter is not yet implemented in the Haskell binding.", meLocation = "paramGet", meParam = "PARAM_READER_STATS", meUri = ""})+Right "0"+Right "\"Embedded Reader\""+Right "17"+Right "0"+Right "0"+Right "False"+Right "False"+Right "False"+Right "True"+Right "-1"+Right "True"+Right "20000"+Right "True"+Left (MercuryException {meStatusType = ERROR_TYPE_BINDING, meStatus = ERROR_UNIMPLEMENTED_PARAM, meMessage = "The given parameter is not yet implemented in the Haskell binding.", meLocation = "paramGet", meParam = "PARAM_READER_STATS_ENABLE", meUri = ""})+Right "[]"+Right "[METADATA_FLAG_READCOUNT,METADATA_FLAG_RSSI,METADATA_FLAG_ANTENNAID,METADATA_FLAG_FREQUENCY,METADATA_FLAG_TIMESTAMP,METADATA_FLAG_PHASE,METADATA_FLAG_PROTOCOL,METADATA_FLAG_DATA,METADATA_FLAG_GPIO_STATUS]"
+ tests/params.transport view
@@ -0,0 +1,205 @@+Sending: VERSION                       1843103.979368518+         ff 00 03 1d 0c                                    |.....|+Received:VERSION                       1843103.983059307+         ff 14 03 00 00 14 12 08  00 30 00 00 02 20 16 12  |.........0... ..|+         13 01 07 01 02 00 00 00  10 1b 05                 |...........|+Sending: GET_CURRENT_PROGRAM           1843103.983838682+         ff 00 0c 1d 03                                    |.....|+Received:GET_CURRENT_PROGRAM           1843103.985476488+         ff 01 0c 00 00 52 63 03                           |.....Rc.|+Sending: GET_POWER_MODE                1843103.985614147+         ff 00 68 1d 67                                    |..h.g|+Received:GET_POWER_MODE                1843103.987230565+         ff 01 68 00 00 00 a4 bf                           |..h.....|+Sending: GET_READER_OPTIONAL_PARAMS    1843103.987381864+         ff 02 6a 01 0e 2e 40                              |..j...@|+Received:GET_READER_OPTIONAL_PARAMS    1843103.989369325+         ff 03 6a 00 00 01 0e 00  30 44                    |..j.....0D|+Sending: GET_READER_OPTIONAL_PARAMS    1843103.990399529+         ff 02 6a 01 12 2e 5c                              |..j...\|+Received:GET_READER_OPTIONAL_PARAMS    1843103.992509632+         ff 04 6a 00 00 01 12 00  00 69 af                 |..j......i.|+Sending: GET_TAG_PROTOCOL              1843103.992625025+         ff 00 63 1d 6c                                    |..c.l|+Received:GET_TAG_PROTOCOL              1843103.994284660+         ff 02 63 00 00 00 05 21  46                       |..c....!F|+Sending: GET_ANTENNA_PORT              1843103.994386061+         ff 01 61 05 bd b8                                 |..a...|+Received:GET_ANTENNA_PORT              1843103.996347817+         ff 03 61 00 00 05 01 00  61 df                    |..a.....a.|+Sending: GET_READER_OPTIONAL_PARAMS    1843103.996501945+         ff 02 6a 01 0c 2e 42                              |..j...B|+Received:GET_READER_OPTIONAL_PARAMS    1843103.998612904+         ff 03 6a 00 00 01 0c 01  32 45                    |..j.....2E|+Sending: GET_READER_OPTIONAL_PARAMS    1843103.998778861+         ff 02 6a 01 0d 2e 43                              |..j...C|+Received:GET_READER_OPTIONAL_PARAMS    1843104.001433875+         ff 06 6a 00 00 01 0d 00  00 00 00 15 43           |..j.........C|+Sending: GET_PROTOCOL_PARAM            1843104.001631010+         ff 02 6b 05 10 3a 7f                              |..k..:.|+Received:GET_PROTOCOL_PARAM            1843104.003624443+         ff 03 6b 00 00 05 10 00  18 74                    |..k......t|+Sending: GET_PROTOCOL_PARAM            1843104.003810694+         ff 02 6b 05 11 3a 7e                              |..k..:~|+Received:GET_PROTOCOL_PARAM            1843104.005731032+         ff 03 6b 00 00 05 11 00  19 74                    |..k......t|+Sending: GET_PROTOCOL_PARAM            1843104.005829147+         ff 02 6b 03 10 3c 7f                              |..k..<.|+Received:GET_PROTOCOL_PARAM            1843104.007681136+         ff 02 6b 04 02 03 10 67  74                       |..k....gt|+Sending: GET_POWER_MODE                1843104.008160154+         ff 00 68 1d 67                                    |..h.g|+Received:GET_POWER_MODE                1843104.009771473+         ff 01 68 00 00 00 a4 bf                           |..h.....|+Sending: GET_READER_OPTIONAL_PARAMS    1843104.009907376+         ff 02 6a 01 04 2e 4a                              |..j...J|+Received:GET_READER_OPTIONAL_PARAMS    1843104.011909258+         ff 03 6a 00 00 01 04 00  3a 44                    |..j.....:D|+Sending: GET_ANTENNA_PORT              1843104.012113365+         ff 01 61 05 bd b8                                 |..a...|+Received:GET_ANTENNA_PORT              1843104.014034668+         ff 03 61 00 00 05 01 00  61 df                    |..a.....a.|+Sending: GET_READER_OPTIONAL_PARAMS    1843104.014143851+         ff 02 6a 01 03 2e 4d                              |..j...M|+Received:GET_READER_OPTIONAL_PARAMS    1843104.016090782+         ff 03 6a 00 00 01 03 00  3d 44                    |..j.....=D|+Sending: GET_USER_GPIO_INPUTS          1843104.016234473+         ff 01 66 01 ba bc                                 |..f...|+Received:GET_USER_GPIO_INPUTS          1843104.019013964+         ff 0d 66 00 00 01 01 00  00 02 00 00 03 00 00 04  |..f.............|+         00 01 64 46                                       |..dF|+Sending: SET_USER_GPIO_OUTPUTS         1843104.019180809+         ff 01 96 01 4a bc                                 |....J.|+Received:SET_USER_GPIO_OUTPUTS         1843104.020925470+         ff 02 96 00 00 01 00 28  e1                       |.......(.|+Sending: SET_USER_GPIO_OUTPUTS         1843104.021029058+         ff 01 96 02 4a bf                                 |....J.|+Received:SET_USER_GPIO_OUTPUTS         1843104.022778563+         ff 02 96 00 00 02 00 2b  e1                       |.......+.|+Sending: SET_USER_GPIO_OUTPUTS         1843104.022877259+         ff 01 96 03 4a be                                 |....J.|+Received:SET_USER_GPIO_OUTPUTS         1843104.024651688+         ff 02 96 00 00 03 00 2a  e1                       |.......*.|+Sending: SET_USER_GPIO_OUTPUTS         1843104.024743719+         ff 01 96 04 4a b9                                 |....J.|+Received:SET_USER_GPIO_OUTPUTS         1843104.026471869+         ff 02 96 00 00 04 00 2d  e1                       |.......-.|+Sending: GET_USER_GPIO_INPUTS          1843104.026579568+         ff 01 66 01 ba bc                                 |..f...|+Received:GET_USER_GPIO_INPUTS          1843104.029296517+         ff 0d 66 00 00 01 01 00  00 02 00 00 03 00 00 04  |..f.............|+         00 01 64 46                                       |..dF|+Sending: SET_USER_GPIO_OUTPUTS         1843104.029482652+         ff 01 96 01 4a bc                                 |....J.|+Received:SET_USER_GPIO_OUTPUTS         1843104.031180966+         ff 02 96 00 00 01 00 28  e1                       |.......(.|+Sending: SET_USER_GPIO_OUTPUTS         1843104.031264482+         ff 01 96 02 4a bf                                 |....J.|+Received:SET_USER_GPIO_OUTPUTS         1843104.032969922+         ff 02 96 00 00 02 00 2b  e1                       |.......+.|+Sending: SET_USER_GPIO_OUTPUTS         1843104.033060371+         ff 01 96 03 4a be                                 |....J.|+Received:SET_USER_GPIO_OUTPUTS         1843104.034797771+         ff 02 96 00 00 03 00 2a  e1                       |.......*.|+Sending: SET_USER_GPIO_OUTPUTS         1843104.034908477+         ff 01 96 04 4a b9                                 |....J.|+Received:SET_USER_GPIO_OUTPUTS         1843104.036642853+         ff 02 96 00 00 04 00 2d  e1                       |.......-.|+Sending: GET_READER_OPTIONAL_PARAMS    1843104.037128667+         ff 02 6a 01 01 2e 4f                              |..j...O|+Received:GET_READER_OPTIONAL_PARAMS    1843104.039429448+         ff 03 6a 00 00 01 01 00  3f 44                    |..j.....?D|+Sending: GET_READ_TX_POWER             1843104.039533356+         ff 01 62 01 be bc                                 |..b...|+Received:GET_READ_TX_POWER             1843104.041734922+         ff 07 62 00 00 01 08 fc  0a 8c 00 00 61 d4        |..b.........a.|+Sending: GET_READ_TX_POWER             1843104.041857989+         ff 01 62 01 be bc                                 |..b...|+Received:GET_READ_TX_POWER             1843104.044036236+         ff 07 62 00 00 01 08 fc  0a 8c 00 00 61 d4        |..b.........a.|+Sending: GET_READ_TX_POWER             1843104.044218533+         ff 01 62 00 be bd                                 |..b...|+Received:GET_READ_TX_POWER             1843104.046018204+         ff 03 62 00 00 00 08 fc  a3 5a                    |..b......Z|+Sending: GET_WRITE_TX_POWER            1843104.046120446+         ff 01 64 00 b8 bd                                 |..d...|+Received:GET_WRITE_TX_POWER            1843104.047914131+         ff 03 64 00 00 00 08 fc  84 c3                    |..d.......|+Sending: GET_TEMPERATURE               1843104.048045772+         ff 00 72 1d 7d                                    |..r.}|+Received:GET_TEMPERATURE               1843104.049703789+         ff 01 72 00 00 23 48 24                           |..r..#H$|+Sending: GET_READER_OPTIONAL_PARAMS    1843104.049820007+         ff 02 6a 01 06 2e 48                              |..j...H|+Received:GET_READER_OPTIONAL_PARAMS    1843104.051713229+         ff 03 6a 00 00 01 06 00  38 44                    |..j.....8D|+Sending: GET_READER_OPTIONAL_PARAMS    1843104.051813518+         ff 02 6a 01 09 2e 47                              |..j...G|+Received:GET_READER_OPTIONAL_PARAMS    1843104.053740315+         ff 03 6a 00 00 01 09 01  37 45                    |..j.....7E|+Sending: GET_READER_OPTIONAL_PARAMS    1843104.053832664+         ff 02 6a 01 00 2e 4e                              |..j...N|+Received:GET_READER_OPTIONAL_PARAMS    1843104.055718413+         ff 03 6a 00 00 01 00 00  3e 44                    |..j.....>D|+Sending: GET_READER_OPTIONAL_PARAMS    1843104.055836782+         ff 02 6a 01 08 2e 46                              |..j...F|+Received:GET_READER_OPTIONAL_PARAMS    1843104.057753904+         ff 03 6a 00 00 01 08 01  36 45                    |..j.....6E|+Sending: HW_VERSION                    1843104.057897168+         ff 02 10 00 40 f0 d3                              |....@..|+Received:HW_VERSION                    1843104.061630608+         ff 16 10 00 00 00 40 40  12 34 35 31 36 30 30 36  |......@@.4516006|+         37 37 30 31 31 33 30 33  32 34 41 49 5b           |7701130324AI[|+Sending: GET_AVAILABLE_PROTOCOLS       1843104.061908417+         ff 00 70 1d 7f                                    |..p..|+Received:GET_AVAILABLE_PROTOCOLS       1843104.063540235+         ff 02 70 00 00 00 05 3b  75                       |..p....;u|+Sending: GET_FREQ_HOP_TABLE            1843104.063639212+         ff 00 65 1d 6a                                    |..e.j|+Received:GET_FREQ_HOP_TABLE            1843104.065051814+         ff 00 65 00 00 b8 c3                              |..e....|+Sending: GET_FREQ_HOP_TABLE            1843104.065156915+         ff 01 65 01 b9 bc                                 |..e...|+Received:GET_FREQ_HOP_TABLE            1843104.067154924+         ff 05 65 00 00 01 00 00  00 00 4a fc              |..e.......J.|+Sending: GET_REGION                    1843104.067269349+         ff 00 67 1d 68                                    |..g.h|+Received:GET_REGION                    1843104.068830337+         ff 01 67 00 00 00 b4 81                           |..g.....|+Sending: GET_AVAILABLE_REGIONS         1843104.068952705+         ff 00 71 1d 7e                                    |..q.~|+Received:GET_AVAILABLE_REGIONS         1843104.071334737+         ff 0a 71 00 00 0d 0e 04  05 06 08 09 0b 0c ff 1f  |..q.............|+         dd                                                |.|+Sending: GET_REGION                    1843104.071554255+         ff 02 67 01 40 ff a3                              |..g.@..|+Received:GET_REGION                    1843104.073190991+         ff 00 67 01 05 99 84                              |..g....|+Sending: GET_READER_OPTIONAL_PARAMS    1843104.073326217+         ff 02 6a 01 0a 2e 44                              |..j...D|+Received:GET_READER_OPTIONAL_PARAMS    1843104.075080659+         ff 01 6a 01 05 01 d7 fd                           |..j.....|+Sending: GET_READER_OPTIONAL_PARAMS    1843104.075274228+         ff 02 6a 01 12 2e 5c                              |..j...\|+Received:GET_READER_OPTIONAL_PARAMS    1843104.077342544+         ff 04 6a 00 00 01 12 00  00 69 af                 |..j......i.|+Sending: GET_READER_OPTIONAL_PARAMS    1843104.077450135+         ff 02 6a 01 13 2e 5d                              |..j...]|+Received:GET_READER_OPTIONAL_PARAMS    1843104.079492585+         ff 04 6a 00 00 01 13 00  11 79 9f                 |..j......y.|+Sending: GET_READER_OPTIONAL_PARAMS    1843104.079611942+         ff 02 6a 01 0b 2e 45                              |..j...E|+Received:GET_READER_OPTIONAL_PARAMS    1843104.081555871+         ff 03 6a 00 00 01 0b 00  35 44                    |..j.....5D|+Sending: GET_PROTOCOL_PARAM            1843104.081659619+         ff 02 6b 05 3f 3a 50                              |..k.?:P|+Received:GET_PROTOCOL_PARAM            1843104.083816779+         ff 05 6b 00 00 05 3f 00  4e 20 4d 14              |..k...?.N M.|+Sending: GET_PROTOCOL_PARAM            1843104.083938210+         ff 02 6b 05 3f 3a 50                              |..k.?:P|+Received:GET_PROTOCOL_PARAM            1843104.086023365+         ff 05 6b 00 00 05 3f 00  4e 20 4d 14              |..k...?.N M.|+Sending: GET_READER_OPTIONAL_PARAMS    1843104.086194598+         ff 02 6a 01 1e 2e 50                              |..j...P|+Received:GET_READER_OPTIONAL_PARAMS    1843104.088095725+         ff 03 6a 00 00 01 1e 00  20 44                    |..j..... D|
+ tests/read.result view
@@ -0,0 +1,17 @@+Right 16+Right (TagReadData {trTag = TagData {tdEpc = "\226\NUL\NUL\NAK\134\SO\SOH\128\DLE\128\175\207", tdProtocol = TAG_PROTOCOL_GEN2, tdCrc = 7064, tdGen2 = Just (GEN2_TagData {g2Pc = "0\NUL"})}, trMetadataFlags = [METADATA_FLAG_READCOUNT,METADATA_FLAG_RSSI,METADATA_FLAG_ANTENNAID,METADATA_FLAG_FREQUENCY,METADATA_FLAG_TIMESTAMP,METADATA_FLAG_PHASE,METADATA_FLAG_PROTOCOL,METADATA_FLAG_DATA,METADATA_FLAG_GPIO_STATUS], trPhase = 174, trAntenna = 1, trGpio = [GpioPin {gpId = 1, gpHigh = False, gpOutput = False},GpioPin {gpId = 2, gpHigh = False, gpOutput = False},GpioPin {gpId = 3, gpHigh = False, gpOutput = False},GpioPin {gpId = 4, gpHigh = False, gpOutput = False}], trReadCount = 10, trRssi = -44, trFrequency = 922600, trTimestamp = 0, trData = "", trEpcMemData = "", trTidMemData = "", trUserMemData = "", trReservedMemData = ""})+Right (TagReadData {trTag = TagData {tdEpc = "\226\NUL\NUL\NAK\134\SO\SOH\DLE\DLEP\177g", tdProtocol = TAG_PROTOCOL_GEN2, tdCrc = 19480, tdGen2 = Just (GEN2_TagData {g2Pc = "0\NUL"})}, trMetadataFlags = [METADATA_FLAG_READCOUNT,METADATA_FLAG_RSSI,METADATA_FLAG_ANTENNAID,METADATA_FLAG_FREQUENCY,METADATA_FLAG_TIMESTAMP,METADATA_FLAG_PHASE,METADATA_FLAG_PROTOCOL,METADATA_FLAG_DATA,METADATA_FLAG_GPIO_STATUS], trPhase = 174, trAntenna = 1, trGpio = [GpioPin {gpId = 1, gpHigh = False, gpOutput = False},GpioPin {gpId = 2, gpHigh = False, gpOutput = False},GpioPin {gpId = 3, gpHigh = False, gpOutput = False},GpioPin {gpId = 4, gpHigh = False, gpOutput = False}], trReadCount = 9, trRssi = -47, trFrequency = 922600, trTimestamp = 0, trData = "", trEpcMemData = "", trTidMemData = "", trUserMemData = "", trReservedMemData = ""})+Right (TagReadData {trTag = TagData {tdEpc = "\226\NUL\NUL\NAK\134\SO\STX\SYN\DLE\128\176\GS", tdProtocol = TAG_PROTOCOL_GEN2, tdCrc = 50693, tdGen2 = Just (GEN2_TagData {g2Pc = "0\NUL"})}, trMetadataFlags = [METADATA_FLAG_READCOUNT,METADATA_FLAG_RSSI,METADATA_FLAG_ANTENNAID,METADATA_FLAG_FREQUENCY,METADATA_FLAG_TIMESTAMP,METADATA_FLAG_PHASE,METADATA_FLAG_PROTOCOL,METADATA_FLAG_DATA,METADATA_FLAG_GPIO_STATUS], trPhase = 174, trAntenna = 1, trGpio = [GpioPin {gpId = 1, gpHigh = False, gpOutput = False},GpioPin {gpId = 2, gpHigh = False, gpOutput = False},GpioPin {gpId = 3, gpHigh = False, gpOutput = False},GpioPin {gpId = 4, gpHigh = False, gpOutput = False}], trReadCount = 10, trRssi = -36, trFrequency = 922600, trTimestamp = 0, trData = "", trEpcMemData = "", trTidMemData = "", trUserMemData = "", trReservedMemData = ""})+Right (TagReadData {trTag = TagData {tdEpc = "\226\NUL\NUL\NAK\134\SO\STXC\DLE\128\176V", tdProtocol = TAG_PROTOCOL_GEN2, tdCrc = 2511, tdGen2 = Just (GEN2_TagData {g2Pc = "0\NUL"})}, trMetadataFlags = [METADATA_FLAG_READCOUNT,METADATA_FLAG_RSSI,METADATA_FLAG_ANTENNAID,METADATA_FLAG_FREQUENCY,METADATA_FLAG_TIMESTAMP,METADATA_FLAG_PHASE,METADATA_FLAG_PROTOCOL,METADATA_FLAG_DATA,METADATA_FLAG_GPIO_STATUS], trPhase = 174, trAntenna = 1, trGpio = [GpioPin {gpId = 1, gpHigh = False, gpOutput = False},GpioPin {gpId = 2, gpHigh = False, gpOutput = False},GpioPin {gpId = 3, gpHigh = False, gpOutput = False},GpioPin {gpId = 4, gpHigh = False, gpOutput = False}], trReadCount = 9, trRssi = -50, trFrequency = 919600, trTimestamp = 0, trData = "", trEpcMemData = "", trTidMemData = "", trUserMemData = "", trReservedMemData = ""})+Right (TagReadData {trTag = TagData {tdEpc = "\226\NUL\NUL\NAK\134\SO\NULF\DLEP\176\231", tdProtocol = TAG_PROTOCOL_GEN2, tdCrc = 29622, tdGen2 = Just (GEN2_TagData {g2Pc = "0\NUL"})}, trMetadataFlags = [METADATA_FLAG_READCOUNT,METADATA_FLAG_RSSI,METADATA_FLAG_ANTENNAID,METADATA_FLAG_FREQUENCY,METADATA_FLAG_TIMESTAMP,METADATA_FLAG_PHASE,METADATA_FLAG_PROTOCOL,METADATA_FLAG_DATA,METADATA_FLAG_GPIO_STATUS], trPhase = 171, trAntenna = 1, trGpio = [GpioPin {gpId = 1, gpHigh = False, gpOutput = False},GpioPin {gpId = 2, gpHigh = False, gpOutput = False},GpioPin {gpId = 3, gpHigh = False, gpOutput = False},GpioPin {gpId = 4, gpHigh = False, gpOutput = False}], trReadCount = 7, trRssi = -53, trFrequency = 919600, trTimestamp = 0, trData = "", trEpcMemData = "", trTidMemData = "", trUserMemData = "", trReservedMemData = ""})+Right (TagReadData {trTag = TagData {tdEpc = "\226\NUL\NUL\NAK\134\SO\NUL0\DLEP\176\199", tdProtocol = TAG_PROTOCOL_GEN2, tdCrc = 34775, tdGen2 = Just (GEN2_TagData {g2Pc = "0\NUL"})}, trMetadataFlags = [METADATA_FLAG_READCOUNT,METADATA_FLAG_RSSI,METADATA_FLAG_ANTENNAID,METADATA_FLAG_FREQUENCY,METADATA_FLAG_TIMESTAMP,METADATA_FLAG_PHASE,METADATA_FLAG_PROTOCOL,METADATA_FLAG_DATA,METADATA_FLAG_GPIO_STATUS], trPhase = 174, trAntenna = 1, trGpio = [GpioPin {gpId = 1, gpHigh = False, gpOutput = False},GpioPin {gpId = 2, gpHigh = False, gpOutput = False},GpioPin {gpId = 3, gpHigh = False, gpOutput = False},GpioPin {gpId = 4, gpHigh = False, gpOutput = False}], trReadCount = 9, trRssi = -45, trFrequency = 922600, trTimestamp = 0, trData = "", trEpcMemData = "", trTidMemData = "", trUserMemData = "", trReservedMemData = ""})+Right (TagReadData {trTag = TagData {tdEpc = "\226\NUL\NUL\NAK\134\SO\NUL4\DLEP\176\213", tdProtocol = TAG_PROTOCOL_GEN2, tdCrc = 15522, tdGen2 = Just (GEN2_TagData {g2Pc = "0\NUL"})}, trMetadataFlags = [METADATA_FLAG_READCOUNT,METADATA_FLAG_RSSI,METADATA_FLAG_ANTENNAID,METADATA_FLAG_FREQUENCY,METADATA_FLAG_TIMESTAMP,METADATA_FLAG_PHASE,METADATA_FLAG_PROTOCOL,METADATA_FLAG_DATA,METADATA_FLAG_GPIO_STATUS], trPhase = 174, trAntenna = 1, trGpio = [GpioPin {gpId = 1, gpHigh = False, gpOutput = False},GpioPin {gpId = 2, gpHigh = False, gpOutput = False},GpioPin {gpId = 3, gpHigh = False, gpOutput = False},GpioPin {gpId = 4, gpHigh = False, gpOutput = False}], trReadCount = 8, trRssi = -47, trFrequency = 922600, trTimestamp = 0, trData = "", trEpcMemData = "", trTidMemData = "", trUserMemData = "", trReservedMemData = ""})+Right (TagReadData {trTag = TagData {tdEpc = "\226\NUL\NUL\NAK\134\SO\STX3\DLE\128\176E", tdProtocol = TAG_PROTOCOL_GEN2, tdCrc = 13851, tdGen2 = Just (GEN2_TagData {g2Pc = "0\NUL"})}, trMetadataFlags = [METADATA_FLAG_READCOUNT,METADATA_FLAG_RSSI,METADATA_FLAG_ANTENNAID,METADATA_FLAG_FREQUENCY,METADATA_FLAG_TIMESTAMP,METADATA_FLAG_PHASE,METADATA_FLAG_PROTOCOL,METADATA_FLAG_DATA,METADATA_FLAG_GPIO_STATUS], trPhase = 174, trAntenna = 1, trGpio = [GpioPin {gpId = 1, gpHigh = False, gpOutput = False},GpioPin {gpId = 2, gpHigh = False, gpOutput = False},GpioPin {gpId = 3, gpHigh = False, gpOutput = False},GpioPin {gpId = 4, gpHigh = False, gpOutput = False}], trReadCount = 5, trRssi = -50, trFrequency = 919600, trTimestamp = 0, trData = "", trEpcMemData = "", trTidMemData = "", trUserMemData = "", trReservedMemData = ""})+Right (TagReadData {trTag = TagData {tdEpc = "\226\NUL\NUL\NAK\134\SO\NUL\129\DLEP\177-", tdProtocol = TAG_PROTOCOL_GEN2, tdCrc = 27885, tdGen2 = Just (GEN2_TagData {g2Pc = "0\NUL"})}, trMetadataFlags = [METADATA_FLAG_READCOUNT,METADATA_FLAG_RSSI,METADATA_FLAG_ANTENNAID,METADATA_FLAG_FREQUENCY,METADATA_FLAG_TIMESTAMP,METADATA_FLAG_PHASE,METADATA_FLAG_PROTOCOL,METADATA_FLAG_DATA,METADATA_FLAG_GPIO_STATUS], trPhase = 171, trAntenna = 1, trGpio = [GpioPin {gpId = 1, gpHigh = False, gpOutput = False},GpioPin {gpId = 2, gpHigh = False, gpOutput = False},GpioPin {gpId = 3, gpHigh = False, gpOutput = False},GpioPin {gpId = 4, gpHigh = False, gpOutput = False}], trReadCount = 10, trRssi = -41, trFrequency = 922600, trTimestamp = 0, trData = "", trEpcMemData = "", trTidMemData = "", trUserMemData = "", trReservedMemData = ""})+Right (TagReadData {trTag = TagData {tdEpc = "\226\NUL\NUL\NAK\134\SO\STXD\DLE\128\176O", tdProtocol = TAG_PROTOCOL_GEN2, tdCrc = 60675, tdGen2 = Just (GEN2_TagData {g2Pc = "0\NUL"})}, trMetadataFlags = [METADATA_FLAG_READCOUNT,METADATA_FLAG_RSSI,METADATA_FLAG_ANTENNAID,METADATA_FLAG_FREQUENCY,METADATA_FLAG_TIMESTAMP,METADATA_FLAG_PHASE,METADATA_FLAG_PROTOCOL,METADATA_FLAG_DATA,METADATA_FLAG_GPIO_STATUS], trPhase = 174, trAntenna = 1, trGpio = [GpioPin {gpId = 1, gpHigh = False, gpOutput = False},GpioPin {gpId = 2, gpHigh = False, gpOutput = False},GpioPin {gpId = 3, gpHigh = False, gpOutput = False},GpioPin {gpId = 4, gpHigh = False, gpOutput = False}], trReadCount = 8, trRssi = -46, trFrequency = 922600, trTimestamp = 0, trData = "", trEpcMemData = "", trTidMemData = "", trUserMemData = "", trReservedMemData = ""})+Right (TagReadData {trTag = TagData {tdEpc = "\226\NUL\NUL\NAK\134\SO\STX\130\DLE\144\174\134", tdProtocol = TAG_PROTOCOL_GEN2, tdCrc = 14404, tdGen2 = Just (GEN2_TagData {g2Pc = "0\NUL"})}, trMetadataFlags = [METADATA_FLAG_READCOUNT,METADATA_FLAG_RSSI,METADATA_FLAG_ANTENNAID,METADATA_FLAG_FREQUENCY,METADATA_FLAG_TIMESTAMP,METADATA_FLAG_PHASE,METADATA_FLAG_PROTOCOL,METADATA_FLAG_DATA,METADATA_FLAG_GPIO_STATUS], trPhase = 168, trAntenna = 1, trGpio = [GpioPin {gpId = 1, gpHigh = False, gpOutput = False},GpioPin {gpId = 2, gpHigh = False, gpOutput = False},GpioPin {gpId = 3, gpHigh = False, gpOutput = False},GpioPin {gpId = 4, gpHigh = False, gpOutput = False}], trReadCount = 4, trRssi = -58, trFrequency = 919600, trTimestamp = 0, trData = "", trEpcMemData = "", trTidMemData = "", trUserMemData = "", trReservedMemData = ""})+Right (TagReadData {trTag = TagData {tdEpc = "\226\NUL\NUL\NAK\134\SO\NULT\DLEP\176\247", tdProtocol = TAG_PROTOCOL_GEN2, tdCrc = 8542, tdGen2 = Just (GEN2_TagData {g2Pc = "0\NUL"})}, trMetadataFlags = [METADATA_FLAG_READCOUNT,METADATA_FLAG_RSSI,METADATA_FLAG_ANTENNAID,METADATA_FLAG_FREQUENCY,METADATA_FLAG_TIMESTAMP,METADATA_FLAG_PHASE,METADATA_FLAG_PROTOCOL,METADATA_FLAG_DATA,METADATA_FLAG_GPIO_STATUS], trPhase = 174, trAntenna = 1, trGpio = [GpioPin {gpId = 1, gpHigh = False, gpOutput = False},GpioPin {gpId = 2, gpHigh = False, gpOutput = False},GpioPin {gpId = 3, gpHigh = False, gpOutput = False},GpioPin {gpId = 4, gpHigh = False, gpOutput = False}], trReadCount = 2, trRssi = -58, trFrequency = 919600, trTimestamp = 0, trData = "", trEpcMemData = "", trTidMemData = "", trUserMemData = "", trReservedMemData = ""})+Right (TagReadData {trTag = TagData {tdEpc = "\226\NUL\NUL\NAK\134\SO\SOH&\DLEP\177\135", tdProtocol = TAG_PROTOCOL_GEN2, tdCrc = 28765, tdGen2 = Just (GEN2_TagData {g2Pc = "0\NUL"})}, trMetadataFlags = [METADATA_FLAG_READCOUNT,METADATA_FLAG_RSSI,METADATA_FLAG_ANTENNAID,METADATA_FLAG_FREQUENCY,METADATA_FLAG_TIMESTAMP,METADATA_FLAG_PHASE,METADATA_FLAG_PROTOCOL,METADATA_FLAG_DATA,METADATA_FLAG_GPIO_STATUS], trPhase = 168, trAntenna = 1, trGpio = [GpioPin {gpId = 1, gpHigh = False, gpOutput = False},GpioPin {gpId = 2, gpHigh = False, gpOutput = False},GpioPin {gpId = 3, gpHigh = False, gpOutput = False},GpioPin {gpId = 4, gpHigh = False, gpOutput = False}], trReadCount = 6, trRssi = -56, trFrequency = 919600, trTimestamp = 0, trData = "", trEpcMemData = "", trTidMemData = "", trUserMemData = "", trReservedMemData = ""})+Right (TagReadData {trTag = TagData {tdEpc = "\226\NUL\NUL\NAK\134\SO\NUL%\DLEP\176\189", tdProtocol = TAG_PROTOCOL_GEN2, tdCrc = 32519, tdGen2 = Just (GEN2_TagData {g2Pc = "0\NUL"})}, trMetadataFlags = [METADATA_FLAG_READCOUNT,METADATA_FLAG_RSSI,METADATA_FLAG_ANTENNAID,METADATA_FLAG_FREQUENCY,METADATA_FLAG_TIMESTAMP,METADATA_FLAG_PHASE,METADATA_FLAG_PROTOCOL,METADATA_FLAG_DATA,METADATA_FLAG_GPIO_STATUS], trPhase = 171, trAntenna = 1, trGpio = [GpioPin {gpId = 1, gpHigh = False, gpOutput = False},GpioPin {gpId = 2, gpHigh = False, gpOutput = False},GpioPin {gpId = 3, gpHigh = False, gpOutput = False},GpioPin {gpId = 4, gpHigh = False, gpOutput = False}], trReadCount = 3, trRssi = -54, trFrequency = 919600, trTimestamp = 0, trData = "", trEpcMemData = "", trTidMemData = "", trUserMemData = "", trReservedMemData = ""})+Right (TagReadData {trTag = TagData {tdEpc = "\226\NUL\NUL\NAK\134\SO\NUL%\DLE`\178\217", tdProtocol = TAG_PROTOCOL_GEN2, tdCrc = 61666, tdGen2 = Just (GEN2_TagData {g2Pc = "0\NUL"})}, trMetadataFlags = [METADATA_FLAG_READCOUNT,METADATA_FLAG_RSSI,METADATA_FLAG_ANTENNAID,METADATA_FLAG_FREQUENCY,METADATA_FLAG_TIMESTAMP,METADATA_FLAG_PHASE,METADATA_FLAG_PROTOCOL,METADATA_FLAG_DATA,METADATA_FLAG_GPIO_STATUS], trPhase = 174, trAntenna = 1, trGpio = [GpioPin {gpId = 1, gpHigh = False, gpOutput = False},GpioPin {gpId = 2, gpHigh = False, gpOutput = False},GpioPin {gpId = 3, gpHigh = False, gpOutput = False},GpioPin {gpId = 4, gpHigh = False, gpOutput = False}], trReadCount = 10, trRssi = -48, trFrequency = 922600, trTimestamp = 0, trData = "", trEpcMemData = "", trTidMemData = "", trUserMemData = "", trReservedMemData = ""})+Right (TagReadData {trTag = TagData {tdEpc = "\226\NUL\NUL\NAK\134\SO\SOH\137\DLEP\177\255", tdProtocol = TAG_PROTOCOL_GEN2, tdCrc = 49247, tdGen2 = Just (GEN2_TagData {g2Pc = "0\NUL"})}, trMetadataFlags = [METADATA_FLAG_READCOUNT,METADATA_FLAG_RSSI,METADATA_FLAG_ANTENNAID,METADATA_FLAG_FREQUENCY,METADATA_FLAG_TIMESTAMP,METADATA_FLAG_PHASE,METADATA_FLAG_PROTOCOL,METADATA_FLAG_DATA,METADATA_FLAG_GPIO_STATUS], trPhase = 171, trAntenna = 1, trGpio = [GpioPin {gpId = 1, gpHigh = False, gpOutput = False},GpioPin {gpId = 2, gpHigh = False, gpOutput = False},GpioPin {gpId = 3, gpHigh = False, gpOutput = False},GpioPin {gpId = 4, gpHigh = False, gpOutput = False}], trReadCount = 3, trRssi = -53, trFrequency = 922600, trTimestamp = 0, trData = "", trEpcMemData = "", trTidMemData = "", trUserMemData = "", trReservedMemData = ""})
+ tests/read.transport view
@@ -0,0 +1,119 @@+Sending: VERSION                       1605291.034818992+         ff 00 03 1d 0c                                    |.....|+Received:VERSION                       1605291.039468075+         ff 14 03 00 00 14 12 08  00 30 00 00 02 20 16 12  |.........0... ..|+         13 01 07 01 02 00 00 00  10 1b 05                 |...........|+Sending: GET_CURRENT_PROGRAM           1605291.039998471+         ff 00 0c 1d 03                                    |.....|+Received:GET_CURRENT_PROGRAM           1605291.041600004+         ff 01 0c 00 00 52 63 03                           |.....Rc.|+Sending: GET_POWER_MODE                1605291.041699340+         ff 00 68 1d 67                                    |..h.g|+Received:GET_POWER_MODE                1605291.043273969+         ff 01 68 00 00 00 a4 bf                           |..h.....|+Sending: GET_READER_OPTIONAL_PARAMS    1605291.043372336+         ff 02 6a 01 0e 2e 40                              |..j...@|+Received:GET_READER_OPTIONAL_PARAMS    1605291.045325490+         ff 03 6a 00 00 01 0e 00  30 44                    |..j.....0D|+Sending: GET_READER_OPTIONAL_PARAMS    1605291.045461142+         ff 02 6a 01 12 2e 5c                              |..j...\|+Received:GET_READER_OPTIONAL_PARAMS    1605291.052225601+         ff 04 6a 00 00 01 12 00  00 69 af                 |..j......i.|+Sending: GET_TAG_PROTOCOL              1605291.052352051+         ff 00 63 1d 6c                                    |..c.l|+Received:GET_TAG_PROTOCOL              1605291.053966261+         ff 02 63 00 00 00 05 21  46                       |..c....!F|+Sending: GET_ANTENNA_PORT              1605291.054063294+         ff 01 61 05 bd b8                                 |..a...|+Received:GET_ANTENNA_PORT              1605291.055938871+         ff 03 61 00 00 05 01 00  61 df                    |..a.....a.|+Sending: GET_READER_OPTIONAL_PARAMS    1605291.056043464+         ff 02 6a 01 0c 2e 42                              |..j...B|+Received:GET_READER_OPTIONAL_PARAMS    1605291.058027930+         ff 03 6a 00 00 01 0c 01  32 45                    |..j.....2E|+Sending: GET_READER_OPTIONAL_PARAMS    1605291.058132382+         ff 02 6a 01 0d 2e 43                              |..j...C|+Received:GET_READER_OPTIONAL_PARAMS    1605291.060352548+         ff 06 6a 00 00 01 0d 00  00 00 00 15 43           |..j.........C|+Sending: SET_REGION                    1605291.060484598+         ff 01 97 0d 4b b0                                 |....K.|+Received:SET_REGION                    1605291.062121507+         ff 00 97 00 00 77 9e                              |.....w.|+Sending: SET_READ_TX_POWER             1605291.062221101+         ff 02 92 08 98 49 c1                              |.....I.|+Received:SET_READ_TX_POWER             1605291.063918471+         ff 00 92 00 00 27 3b                              |.....';|+Sending: SET_WRITE_TX_POWER            1605291.064004619+         ff 02 94 08 98 29 07                              |.....).|+Received:SET_WRITE_TX_POWER            1605291.065708786+         ff 00 94 00 00 47 fd                              |.....G.|+Sending: SET_ANTENNA_PORT              1605291.065801253+         ff 02 91 01 01 70 3b                              |.....p;|+Received:SET_ANTENNA_PORT              1605291.067461716+         ff 00 91 00 00 17 58                              |......X|+Sending: SET_READER_OPTIONAL_PARAMS    1605291.067548954+         ff 03 9a 01 06 01 a9 5c                           |.......\|+Received:SET_READER_OPTIONAL_PARAMS    1605291.069282407+         ff 00 9a 00 00 a6 33                              |......3|+Sending: GET_READER_STATS              1605291.069357329+         ff 03 6c 01 9f 41 89 7b                           |..l..A.{|+Received:GET_READER_STATS              1605291.071382570+         ff 03 6c 00 00 01 9f 41  86 9c                    |..l....A..|+Sending: CLEAR_TAG_ID_BUFFER           1605291.071487748+         ff 00 2a 1d 25                                    |..*.%|+Received:CLEAR_TAG_ID_BUFFER           1605291.072970630+         ff 00 2a 00 00 01 e8                              |..*....|+Sending: SET_ANTENNA_PORT              1605291.073060872+         ff 03 91 02 01 01 42 c5                           |......B.|+Received:SET_ANTENNA_PORT              1605291.074807197+         ff 00 91 00 00 17 58                              |......X|+Sending: READ_TAG_ID_MULTIPLE          1605291.074915830+         ff 05 22 00 00 13 03 e8  29 05                    |..".....).|+Received:READ_TAG_ID_MULTIPLE          1605292.082519826+         ff 07 22 00 00 00 00 13  00 00 00 10 8b 49        |.."..........I|+Sending: GET_TAG_ID_BUFFER             1605292.082851068+         ff 03 29 01 ff 00 1b 03                           |..).....|+Received:GET_TAG_ID_BUFFER             1605292.106795041+         ff f2 29 00 00 01 ff 00  07 0a d4 11 0e 13 e8 00  |..).............|+         00 03 34 00 ae 05 00 00  00 00 80 30 00 e2 00 00  |..4........0....|+         15 86 0e 01 80 10 80 af  cf 1b 98 09 d1 11 0e 13  |................|+         e8 00 00 03 23 00 ae 05  00 00 00 00 80 30 00 e2  |....#........0..|+         00 00 15 86 0e 01 10 10  50 b1 67 4c 18 0a dc 11  |........P.gL....|+         0e 13 e8 00 00 03 28 00  ae 05 00 00 00 00 80 30  |......(........0|+         00 e2 00 00 15 86 0e 02  16 10 80 b0 1d c6 05 09  |................|+         ce 11 0e 08 30 00 00 00  b7 00 ae 05 00 00 00 00  |....0...........|+         80 30 00 e2 00 00 15 86  0e 02 43 10 80 b0 56 09  |.0........C...V.|+         cf 07 cb 11 0e 08 30 00  00 00 e8 00 ab 05 00 00  |......0.........|+         00 00 80 30 00 e2 00 00  15 86 0e 00 46 10 50 b0  |...0........F.P.|+         e7 73 b6 09 d3 11 0e 13  e8 00 00 03 10 00 ae 05  |.s..............|+         00 00 00 00 80 30 00 e2  00 00 15 86 0e 00 30 10  |.....0........0.|+         50 b0 c7 87 d7 08 d1 11  0e 13 e8 00 00 03 5d 00  |P.............].|+         ae 05 00 00 00 00 80 30  00 e2 00 00 15 86 0e 00  |.......0........|+         34 10 50 b0 d5 3c a2 14  c0                       |4.P..<...|+Sending: GET_TAG_ID_BUFFER             1605292.109544685+         ff 03 29 01 ff 00 1b 03                           |..).....|+Received:GET_TAG_ID_BUFFER             1605292.133518195+         ff f2 29 00 00 01 ff 00  07 05 ce 11 0e 08 30 00  |..)...........0.|+         00 01 5c 00 ae 05 00 00  00 00 80 30 00 e2 00 00  |..\........0....|+         15 86 0e 02 33 10 80 b0  45 36 1b 0a d7 11 0e 13  |....3...E6......|+         e8 00 00 03 16 00 ab 05  00 00 00 00 80 30 00 e2  |.............0..|+         00 00 15 86 0e 00 81 10  50 b1 2d 6c ed 08 d2 11  |........P.-l....|+         0e 13 e8 00 00 03 39 00  ae 05 00 00 00 00 80 30  |......9........0|+         00 e2 00 00 15 86 0e 02  44 10 80 b0 4f ed 03 04  |........D...O...|+         c6 11 0e 08 30 00 00 00  4d 00 a8 05 00 00 00 00  |....0...M.......|+         80 30 00 e2 00 00 15 86  0e 02 82 10 90 ae 86 38  |.0.............8|+         44 02 c6 11 0e 08 30 00  00 00 54 00 ae 05 00 00  |D.....0...T.....|+         00 00 80 30 00 e2 00 00  15 86 0e 00 54 10 50 b0  |...0........T.P.|+         f7 21 5e 06 c8 11 0e 08  30 00 00 00 5b 00 a8 05  |.!^.....0...[...|+         00 00 00 00 80 30 00 e2  00 00 15 86 0e 01 26 10  |.....0........&.|+         50 b1 87 70 5d 03 ca 11  0e 08 30 00 00 00 64 00  |P..p].....0...d.|+         ab 05 00 00 00 00 80 30  00 e2 00 00 15 86 0e 00  |.......0........|+         25 10 50 b0 bd 7f 07 a0  95                       |%.P......|+Sending: GET_TAG_ID_BUFFER             1605292.136180386+         ff 03 29 01 ff 00 1b 03                           |..).....|+Received:GET_TAG_ID_BUFFER             1605292.144773020+         ff 48 29 00 00 01 ff 00  02 0a d0 11 0e 13 e8 00  |.H).............|+         00 03 1b 00 ae 05 00 00  00 00 80 30 00 e2 00 00  |...........0....|+         15 86 0e 00 25 10 60 b2  d9 f0 e2 03 cb 11 0e 13  |....%.`.........|+         e8 00 00 03 78 00 ab 05  00 00 00 00 80 30 00 e2  |....x........0..|+         00 00 15 86 0e 01 89 10  50 b1 ff c0 5f 3f 43     |........P..._?C|
+ tests/readUser.result view
@@ -0,0 +1,3 @@+Right 2+Right (TagReadData {trTag = TagData {tdEpc = "\226\NUL\NUL\NAK\134\DC2\NULu%\DLE\EM|", tdProtocol = TAG_PROTOCOL_GEN2, tdCrc = 4362, tdGen2 = Just (GEN2_TagData {g2Pc = "4\NUL"})}, trMetadataFlags = [METADATA_FLAG_READCOUNT,METADATA_FLAG_RSSI,METADATA_FLAG_ANTENNAID,METADATA_FLAG_FREQUENCY,METADATA_FLAG_TIMESTAMP,METADATA_FLAG_PHASE,METADATA_FLAG_PROTOCOL,METADATA_FLAG_DATA,METADATA_FLAG_GPIO_STATUS], trPhase = 174, trAntenna = 1, trGpio = [GpioPin {gpId = 1, gpHigh = False, gpOutput = False},GpioPin {gpId = 2, gpHigh = False, gpOutput = False},GpioPin {gpId = 3, gpHigh = False, gpOutput = False},GpioPin {gpId = 4, gpHigh = False, gpOutput = False}], trReadCount = 15, trRssi = -46, trFrequency = 924800, trTimestamp = 0, trData = "Engineer's Mini-Notebook: Forumulas, Symbols & Circuits\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL", trEpcMemData = "", trTidMemData = "", trUserMemData = "", trReservedMemData = ""})+Right (TagReadData {trTag = TagData {tdEpc = "\226\NULQ\134\SOH\a\SOH\135\DC4\NUL\135|", tdProtocol = TAG_PROTOCOL_GEN2, tdCrc = 12577, tdGen2 = Just (GEN2_TagData {g2Pc = "4\NUL"})}, trMetadataFlags = [METADATA_FLAG_READCOUNT,METADATA_FLAG_RSSI,METADATA_FLAG_ANTENNAID,METADATA_FLAG_FREQUENCY,METADATA_FLAG_TIMESTAMP,METADATA_FLAG_PHASE,METADATA_FLAG_PROTOCOL,METADATA_FLAG_DATA,METADATA_FLAG_GPIO_STATUS], trPhase = 171, trAntenna = 1, trGpio = [GpioPin {gpId = 1, gpHigh = False, gpOutput = False},GpioPin {gpId = 2, gpHigh = False, gpOutput = False},GpioPin {gpId = 3, gpHigh = False, gpOutput = False},GpioPin {gpId = 4, gpHigh = False, gpOutput = False}], trReadCount = 13, trRssi = -56, trFrequency = 924800, trTimestamp = 0, trData = "Bananagrams\NUL!\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL", trEpcMemData = "", trTidMemData = "", trUserMemData = "", trReservedMemData = ""})
+ tests/readUser.transport view
@@ -0,0 +1,95 @@+Sending: VERSION                       1605849.767314237+         ff 00 03 1d 0c                                    |.....|+Received:VERSION                       1605849.771061295+         ff 14 03 00 00 14 12 08  00 30 00 00 02 20 16 12  |.........0... ..|+         13 01 07 01 02 00 00 00  10 1b 05                 |...........|+Sending: GET_CURRENT_PROGRAM           1605849.771844202+         ff 00 0c 1d 03                                    |.....|+Received:GET_CURRENT_PROGRAM           1605849.773508249+         ff 01 0c 00 00 52 63 03                           |.....Rc.|+Sending: GET_POWER_MODE                1605849.773657114+         ff 00 68 1d 67                                    |..h.g|+Received:GET_POWER_MODE                1605849.775283044+         ff 01 68 00 00 00 a4 bf                           |..h.....|+Sending: GET_READER_OPTIONAL_PARAMS    1605849.775394058+         ff 02 6a 01 0e 2e 40                              |..j...@|+Received:GET_READER_OPTIONAL_PARAMS    1605849.777364867+         ff 03 6a 00 00 01 0e 00  30 44                    |..j.....0D|+Sending: GET_READER_OPTIONAL_PARAMS    1605849.778223622+         ff 02 6a 01 12 2e 5c                              |..j...\|+Received:GET_READER_OPTIONAL_PARAMS    1605849.780317241+         ff 04 6a 00 00 01 12 00  00 69 af                 |..j......i.|+Sending: GET_TAG_PROTOCOL              1605849.780444570+         ff 00 63 1d 6c                                    |..c.l|+Received:GET_TAG_PROTOCOL              1605849.782118781+         ff 02 63 00 00 00 05 21  46                       |..c....!F|+Sending: GET_ANTENNA_PORT              1605849.782238880+         ff 01 61 05 bd b8                                 |..a...|+Received:GET_ANTENNA_PORT              1605849.784171112+         ff 03 61 00 00 05 01 00  61 df                    |..a.....a.|+Sending: GET_READER_OPTIONAL_PARAMS    1605849.784313721+         ff 02 6a 01 0c 2e 42                              |..j...B|+Received:GET_READER_OPTIONAL_PARAMS    1605849.786271469+         ff 03 6a 00 00 01 0c 01  32 45                    |..j.....2E|+Sending: GET_READER_OPTIONAL_PARAMS    1605849.786379534+         ff 02 6a 01 0d 2e 43                              |..j...C|+Received:GET_READER_OPTIONAL_PARAMS    1605849.788780013+         ff 06 6a 00 00 01 0d 00  00 00 00 15 43           |..j.........C|+Sending: SET_REGION                    1605849.788979855+         ff 01 97 0d 4b b0                                 |....K.|+Received:SET_REGION                    1605849.790714839+         ff 00 97 00 00 77 9e                              |.....w.|+Sending: SET_READ_TX_POWER             1605849.790866384+         ff 02 92 08 98 49 c1                              |.....I.|+Received:SET_READ_TX_POWER             1605849.792519783+         ff 00 92 00 00 27 3b                              |.....';|+Sending: SET_WRITE_TX_POWER            1605849.792614109+         ff 02 94 08 98 29 07                              |.....).|+Received:SET_WRITE_TX_POWER            1605849.794407465+         ff 00 94 00 00 47 fd                              |.....G.|+Sending: SET_ANTENNA_PORT              1605849.794567169+         ff 02 91 01 01 70 3b                              |.....p;|+Received:SET_ANTENNA_PORT              1605849.796480969+         ff 00 91 00 00 17 58                              |......X|+Sending: SET_READER_OPTIONAL_PARAMS    1605849.796618312+         ff 03 9a 01 06 01 a9 5c                           |.......\|+Received:SET_READER_OPTIONAL_PARAMS    1605849.798632728+         ff 00 9a 00 00 a6 33                              |......3|+Sending: GET_READER_STATS              1605849.798778108+         ff 03 6c 01 9f 41 89 7b                           |..l..A.{|+Received:GET_READER_STATS              1605849.801082510+         ff 03 6c 00 00 01 9f 41  86 9c                    |..l....A..|+Sending: CLEAR_TAG_ID_BUFFER           1605849.801242465+         ff 00 2a 1d 25                                    |..*.%|+Received:CLEAR_TAG_ID_BUFFER           1605849.802925103+         ff 00 2a 00 00 01 e8                              |..*....|+Sending: SET_ANTENNA_PORT              1605849.803069867+         ff 03 91 02 01 01 42 c5                           |......B.|+Received:SET_ANTENNA_PORT              1605849.805117395+         ff 00 91 00 00 17 58                              |......X|+Sending: READ_TAG_ID_MULTIPLE          1605849.805311145+         ff 11 22 00 00 17 03 e8  01 09 28 07 d0 00 03 00  |..".......(.....|+         00 00 00 20 49 70                                 |... Ip|+Received:READ_TAG_ID_MULTIPLE          1605850.819217037+         ff 4d 22 00 00 00 00 17  00 00 00 02 01 28 00 1a  |.M"..........(..|+         00 02 45 6e 67 69 6e 65  65 72 27 73 20 4d 69 6e  |..Engineer's Min|+         69 2d 4e 6f 74 65 62 6f  6f 6b 3a 20 46 6f 72 75  |i-Notebook: Foru|+         6d 75 6c 61 73 2c 20 53  79 6d 62 6f 6c 73 20 26  |mulas, Symbols &|+         20 43 69 72 63 75 69 74  73 00 00 00 00 00 00 00  | Circuits.......|+         00 00 53 de                                       |..S.|+Sending: GET_TAG_ID_BUFFER             1605850.820236496+         ff 03 29 01 ff 00 1b 03                           |..).....|+Received:GET_TAG_ID_BUFFER             1605850.840283979+         ff c8 29 00 00 01 ff 00  02 0f d2 11 0e 1c 80 00  |..).............|+         00 02 e8 00 ae 05 02 00  45 6e 67 69 6e 65 65 72  |........Engineer|+         27 73 20 4d 69 6e 69 2d  4e 6f 74 65 62 6f 6f 6b  |'s Mini-Notebook|+         3a 20 46 6f 72 75 6d 75  6c 61 73 2c 20 53 79 6d  |: Forumulas, Sym|+         62 6f 6c 73 20 26 20 43  69 72 63 75 69 74 73 00  |bols & Circuits.|+         00 00 00 00 00 00 00 00  00 00 80 34 00 e2 00 00  |...........4....|+         15 86 12 00 75 25 10 19  7c 11 0a 0d c8 11 0e 1c  |....u%..|.......|+         80 00 00 02 ba 00 ab 05  02 00 42 61 6e 61 6e 61  |..........Banana|+         67 72 61 6d 73 00 21 00  00 00 00 00 00 00 00 00  |grams.!.........|+         00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|+         00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|+         00 00 00 00 00 00 00 00  00 00 00 00 80 34 00 e2  |.............4..|+         00 51 86 01 07 01 87 14  00 87 7c 31 21 76 a4     |.Q........|1!v.|
+ tests/replay.hs view
@@ -0,0 +1,496 @@+{-# LANGUAGE OverloadedStrings #-}++import Control.Exception ( throw, try )+import Control.Monad ( when, void, forM_ )+import qualified Data.ByteString as B ( pack )+import Data.List ( maximumBy, delete )+import Data.Monoid ( (<>) )+import Data.Ord ( comparing )+import qualified Data.Text as T ( empty, pack )+import Options.Applicative+    ( Alternative(many),+      Applicative((<*>)),+      Parser,+      helper,+      execParser,+      value,+      switch,+      strOption,+      str,+      short,+      metavar,+      long,+      info,+      help,+      header,+      fullDesc,+      argument,+      (<$>) )+import System.Directory ( makeAbsolute )+import System.IO+    ( Handle,+      IOMode(ReadMode, WriteMode),+      withFile,+      hPutStrLn,+      hGetLine )+import System.Info ( os )++import qualified System.Hardware.MercuryApi as TMR+import qualified System.Hardware.MercuryApi.Params as TMR+import qualified System.Hardware.MercuryApi.Testing as TMR++data TestDirection = Record | Playback++data TestState =+  TestState+  { tsDirection :: TestDirection+  , tsHandle :: Handle+  }++type TestFunc = TMR.Reader -> TestState -> IO ()++suppressUri :: Either TMR.MercuryException a -> Either TMR.MercuryException a+suppressUri (Left exc) = Left exc { TMR.meUri = T.empty }+suppressUri x = x++check :: (Read a, Show a, Eq a) => TestState -> IO a -> IO a+check ts f = do+  eth' <- try f+  let eth = suppressUri eth'+  case tsDirection ts of+    Record -> hPutStrLn (tsHandle ts) (show eth)+    Playback -> do+      ln <- hGetLine (tsHandle ts)+      let expected = read ln :: (Read a => Either TMR.MercuryException a)+      when (expected /= eth) $ do+        putStrLn "expected:"+        putStrLn ln+        putStrLn "but got:"+        print eth+        fail "test failed"+  return $ case eth of+             Left exc -> throw exc -- only thrown if caller looks at result+             Right x -> x++runTest :: String -> TestDirection -> String -> TestFunc -> IO ()+runTest uri dir name func = do+  putStrLn $ "running test: " ++ name+  let fname = "tests/" ++ name+      transportFile = fname ++ ".transport"+      resultFile = fname ++ ".result"+  case dir of+    Record -> do+      withFile transportFile WriteMode $ \hTransport -> do+        withFile resultFile WriteMode $ \hResult -> do+          TMR.withReader (T.pack uri) $ \rdr -> do+            listener <- TMR.opcodeListener hTransport+            TMR.addTransportListener rdr listener+            TMR.paramSetTransportTimeout rdr 10000+            TMR.connect rdr+            func rdr (TestState dir hResult)+    Playback -> do+      absFile <- makeAbsolute transportFile+      withFile resultFile ReadMode $ \hResult -> do+        TMR.withReader (T.pack $ "test://" ++ absFile) $ \rdr -> do+          TMR.paramSetTransportTimeout rdr 10000+          TMR.connect rdr+          func rdr (TestState dir hResult)++setRegionAndPower :: TMR.Reader -> IO ()+setRegionAndPower rdr = do+  -- pwr <- TMR.paramGetRadioPowerMax rdr+  TMR.paramSetBasics rdr TMR.REGION_NA2 2200 TMR.sparkFunAntennas+  TMR.paramSetTagReadDataRecordHighestRssi rdr True++readUser =+  TMR.TagOp_GEN2_ReadData+  { TMR.opBank = TMR.GEN2_BANK_USER+  , TMR.opExtraBanks = []+  , TMR.opWordAddress = 0+  , TMR.opLen = 32+  }++emptyUserDataFilter :: TMR.TagFilter+emptyUserDataFilter = TMR.mkFilterGen2 TMR.GEN2_BANK_USER 0 $ B.pack [0, 0]++testParams :: TestFunc+testParams rdr ts = do+  params <- check ts $ TMR.paramList rdr+  let params' = TMR.PARAM_URI `delete` params -- because URI will be different+  forM_ params' $ \param -> do+    check ts $ TMR.paramGetString rdr param++testRead :: TestFunc+testRead rdr ts = do+  setRegionAndPower rdr++  tags <- TMR.read rdr 1000+  check ts $ return $ length tags+  forM_ tags $ \tag -> do+    check ts $ return tag { TMR.trTimestamp = 0 }++testReadUser :: TestFunc+testReadUser rdr ts = do+  setRegionAndPower rdr+  TMR.paramSetReadPlanTagop rdr (Just readUser)++  tags <- TMR.read rdr 1000+  check ts $ return $ length tags+  forM_ tags $ \tag -> do+    check ts $ return tag { TMR.trTimestamp = 0 }++testWrite :: TestFunc+testWrite rdr ts = do+  setRegionAndPower rdr+  TMR.paramSetReadPlanFilter rdr (Just emptyUserDataFilter)++  tags <- TMR.read rdr 1000+  check ts $ return $ length tags+  let trd = maximumBy (comparing TMR.trRssi) tags+  check ts $ return trd { TMR.trTimestamp = 0 }++  let epcFilt = TMR.TagFilterEPC (TMR.trTag trd)+      words = TMR.packBytesIntoWords "I am Groot"+      opWrite = TMR.TagOp_GEN2_WriteData+                { TMR.opBank = TMR.GEN2_BANK_USER+                , TMR.opWordAddress = 0+                , TMR.opData = words+                }+  check ts $ TMR.executeTagOp rdr opWrite (Just epcFilt)++  TMR.paramSetReadPlanFilter rdr Nothing+  TMR.paramSetReadPlanTagop rdr (Just readUser)+  tags2 <- TMR.read rdr 1000+  check ts $ return $ length tags2+  forM_ tags2 $ \tag -> do+    check ts $ return tag { TMR.trTimestamp = 0 }++testWriteEpc :: TestFunc+testWriteEpc rdr ts = do+  setRegionAndPower rdr+  TMR.paramSetReadPlanFilter rdr (Just emptyUserDataFilter)++  tags <- TMR.read rdr 1000+  check ts $ return $ length tags+  let trd = maximumBy (comparing TMR.trRssi) tags+  check ts $ return trd { TMR.trTimestamp = 0 }++  let tag = TMR.trTag trd+      epcFilt = TMR.TagFilterEPC tag+      Just newEpc = TMR.hexToBytes "0123456789abcdef"+      newTag = tag { TMR.tdEpc = newEpc }+      opWrite = TMR.TagOp_GEN2_WriteTag newTag++  check ts $ TMR.executeTagOp rdr opWrite (Just epcFilt)++  TMR.paramSetReadPlanFilter rdr Nothing+  TMR.paramSetReadPlanTagop rdr (Just readUser)+  tags2 <- TMR.read rdr 1000+  check ts $ return $ length tags2+  forM_ tags2 $ \tag -> do+    check ts $ return tag { TMR.trTimestamp = 0 }++  let epcFilt2 = TMR.TagFilterEPC newTag+      opWrite2 = TMR.TagOp_GEN2_WriteTag tag++  void $ check ts $ TMR.executeTagOp rdr opWrite2 (Just epcFilt2)++testLock :: TestFunc+testLock rdr ts = do+  setRegionAndPower rdr+  TMR.paramSetReadPlanFilter rdr (Just emptyUserDataFilter)++  -- find a tag+  tags <- TMR.read rdr 1000+  check ts $ return $ length tags+  let trd = maximumBy (comparing TMR.trRssi) tags+  check ts $ return trd { TMR.trTimestamp = 0 }++  -- write access password+  let password = 12345+      epcFilt = TMR.TagFilterEPC (TMR.trTag trd)+      opWrite = TMR.TagOp_GEN2_WriteData+                { TMR.opBank = TMR.GEN2_BANK_RESERVED+                , TMR.opWordAddress = TMR.accessPasswordAddress+                , TMR.opData = TMR.passwordToWords password+                }+  check ts $ TMR.executeTagOp rdr opWrite (Just epcFilt)++  -- lock user bank+  let opLock = TMR.TagOp_GEN2_Lock+               { TMR.opMask   = [TMR.GEN2_LOCK_BITS_USER]+               , TMR.opAction = [TMR.GEN2_LOCK_BITS_USER]+               , TMR.opAccessPassword = password+               }+  check ts $ TMR.executeTagOp rdr opLock (Just epcFilt)++  -- attempt to write data; should fail+  let opWrite2 = TMR.TagOp_GEN2_WriteData+                 { TMR.opBank = TMR.GEN2_BANK_USER+                 , TMR.opWordAddress = 0+                 , TMR.opData = TMR.packBytesIntoWords "This should fail"+                 }+  check ts $ TMR.executeTagOp rdr opWrite2 (Just epcFilt)++  -- unlock user bank+  let opUnlock = TMR.TagOp_GEN2_Lock+                 { TMR.opMask   = [TMR.GEN2_LOCK_BITS_USER]+                 , TMR.opAction = []+                 , TMR.opAccessPassword = password+                 }+  check ts $ TMR.executeTagOp rdr opUnlock (Just epcFilt)++  -- attempt to write data; should succeed+  let opWrite3 = TMR.TagOp_GEN2_WriteData+                 { TMR.opBank = TMR.GEN2_BANK_USER+                 , TMR.opWordAddress = 0+                 , TMR.opData = TMR.packBytesIntoWords "This should succeed"+                 }+  void $ check ts $ TMR.executeTagOp rdr opWrite3 (Just epcFilt)++sequentialBytes = B.pack [0..7]++testBlockWrite :: TestFunc+testBlockWrite rdr ts = do+  setRegionAndPower rdr+  TMR.paramSetReadPlanFilter rdr (Just emptyUserDataFilter)++  tags <- TMR.read rdr 1000+  check ts $ return $ length tags+  let trd = maximumBy (comparing TMR.trRssi) tags+  check ts $ return trd { TMR.trTimestamp = 0 }++  let epcFilt = TMR.TagFilterEPC (TMR.trTag trd)+      words = TMR.packBytesIntoWords sequentialBytes+      opWrite = TMR.TagOp_GEN2_BlockWrite+                { TMR.opBank = TMR.GEN2_BANK_USER+                , TMR.opWordPtr = 0+                , TMR.opData = words+                }+  check ts $ TMR.executeTagOp rdr opWrite (Just epcFilt)++  TMR.paramSetReadPlanFilter rdr Nothing+  TMR.paramSetReadPlanTagop rdr (Just readUser)+  tags2 <- TMR.read rdr 1000+  check ts $ return $ length tags2+  forM_ tags2 $ \tag -> do+    check ts $ return tag { TMR.trTimestamp = 0 }++sequentialUserDataFilter :: TMR.TagFilter+sequentialUserDataFilter = TMR.mkFilterGen2 TMR.GEN2_BANK_USER 0 sequentialBytes++testBlockErase :: TestFunc+testBlockErase rdr ts = do+  setRegionAndPower rdr+  TMR.paramSetReadPlanFilter rdr (Just sequentialUserDataFilter)++  tags <- TMR.read rdr 1000+  check ts $ return $ length tags+  let trd = maximumBy (comparing TMR.trRssi) tags+  check ts $ return trd { TMR.trTimestamp = 0 }++  let epcFilt = TMR.TagFilterEPC (TMR.trTag trd)+      opErase = TMR.TagOp_GEN2_BlockErase+                { TMR.opBank = TMR.GEN2_BANK_USER+                , TMR.opWordPtr = 0+                , TMR.opWordCount = 4+                }+  check ts $ TMR.executeTagOp rdr opErase (Just epcFilt)++  TMR.paramSetReadPlanFilter rdr Nothing+  TMR.paramSetReadPlanTagop rdr (Just readUser)+  tags2 <- TMR.read rdr 1000+  check ts $ return $ length tags2+  forM_ tags2 $ \tag -> do+    check ts $ return tag { TMR.trTimestamp = 0 }++permalockMeFilter :: TMR.TagFilter+permalockMeFilter = TMR.mkFilterGen2 TMR.GEN2_BANK_USER 0 "permalock me"++testBlockPermalockRead :: TestFunc+testBlockPermalockRead rdr ts = do+  setRegionAndPower rdr+  TMR.paramSetReadPlanFilter rdr (Just permalockMeFilter)++  tags <- TMR.read rdr 1000+  check ts $ return $ length tags+  let trd = maximumBy (comparing TMR.trRssi) tags+  check ts $ return trd { TMR.trTimestamp = 0 }++  let epcFilt = TMR.TagFilterEPC (TMR.trTag trd)+      opPermalock = TMR.TagOp_GEN2_BlockPermaLock+                    { TMR.opBank = TMR.GEN2_BANK_USER+                    , TMR.opBlockPtr = 0+                    , TMR.opReadWrite = TMR.Read 1+                    }+  void $ check ts $ TMR.executeTagOp rdr opPermalock (Just epcFilt)++testBlockPermalockWrite :: TestFunc+testBlockPermalockWrite rdr ts = do+  setRegionAndPower rdr+  TMR.paramSetReadPlanFilter rdr (Just permalockMeFilter)++  tags <- TMR.read rdr 1000+  check ts $ return $ length tags+  let trd = maximumBy (comparing TMR.trRssi) tags+  check ts $ return trd { TMR.trTimestamp = 0 }++  let epcFilt = TMR.TagFilterEPC (TMR.trTag trd)+      opPermalock = TMR.TagOp_GEN2_BlockPermaLock+                    { TMR.opBank = TMR.GEN2_BANK_USER+                    , TMR.opBlockPtr = 0+                    , TMR.opReadWrite = TMR.Write [0xaa00]+                    }+  check ts $ TMR.executeTagOp rdr opPermalock (Just epcFilt)++  forM_ [0..31] $ \word -> do+    let opWrite = TMR.TagOp_GEN2_WriteData+                  { TMR.opBank = TMR.GEN2_BANK_USER+                  , TMR.opWordAddress = word+                  , TMR.opData = [fromIntegral word]+                  }+    check ts $ TMR.executeTagOp rdr opWrite (Just epcFilt)++  TMR.paramSetReadPlanFilter rdr Nothing+  TMR.paramSetReadPlanTagop rdr (Just readUser)+  tags2 <- TMR.read rdr 1000+  check ts $ return $ length tags2+  forM_ tags2 $ \tag -> do+    check ts $ return tag { TMR.trTimestamp = 0 }++  let opPermalock2 = TMR.TagOp_GEN2_BlockPermaLock+                     { TMR.opBank = TMR.GEN2_BANK_USER+                     , TMR.opBlockPtr = 0+                     , TMR.opReadWrite = TMR.Read 1+                     }+  void $ check ts $ TMR.executeTagOp rdr opPermalock2 (Just epcFilt)++killMeFilter :: TMR.TagFilter+killMeFilter =+  TMR.mkFilterGen2 TMR.GEN2_BANK_USER 0 $ "permaloc" <> B.pack [0,4,0,5,0,6,0,7]++testKill :: TestFunc+testKill rdr ts = do+  setRegionAndPower rdr+  TMR.paramSetReadPlanFilter rdr (Just killMeFilter)++  -- find a tag+  tags <- TMR.read rdr 1000+  check ts $ return $ length tags+  let trd = maximumBy (comparing TMR.trRssi) tags+  check ts $ return trd { TMR.trTimestamp = 0 }++  -- write access password+  let password = 0xbeadead1+      epcFilt = TMR.TagFilterEPC (TMR.trTag trd)+      opWrite = TMR.TagOp_GEN2_WriteData+                { TMR.opBank = TMR.GEN2_BANK_RESERVED+                , TMR.opWordAddress = TMR.killPasswordAddress+                , TMR.opData = TMR.passwordToWords password+                }+  check ts $ TMR.executeTagOp rdr opWrite (Just epcFilt)++  -- kill+  let opKill = TMR.TagOp_GEN2_Kill password+  check ts $ TMR.executeTagOp rdr opKill (Just epcFilt)++  -- still alive?+  TMR.paramSetReadPlanFilter rdr (Just epcFilt)+  TMR.paramSetReadPlanTagop rdr (Just readUser)+  tags2 <- TMR.read rdr 1000+  void $ check ts $ return $ length tags2++mkPin :: TMR.PinNumber -> TMR.PinNumber -> TMR.GpioPin+mkPin highPin pin =+  TMR.GpioPin+  { TMR.gpId = pin+  , TMR.gpHigh = highPin == pin+  , TMR.gpOutput = True+  }++testGpo :: TestFunc+testGpo rdr ts = do+  let pins = [1..4]++  TMR.paramSetGpioOutputList rdr pins+  forM_ pins $ \pin -> do+    TMR.gpoSet rdr $ map (mkPin pin) pins++testGpi :: TestFunc+testGpi rdr ts = do+  let pins = [1..4]++  TMR.paramSetGpioInputList rdr pins+  void $ check ts $ TMR.gpiGet rdr++tests :: [(String, TestFunc)]+tests =+  [ ("params", testParams)+  , ("read", testRead)+  , ("readUser", testReadUser)+  , ("write", testWrite)+  , ("writeEpc", testWriteEpc)+  , ("lock", testLock)+  , ("blockWrite", testBlockWrite)+  , ("blockErase", testBlockErase)+  , ("blockPermalockRead", testBlockPermalockRead)+  , ("blockPermalockWrite", testBlockPermalockWrite)+  , ("kill", testKill)+  , ("gpo", testGpo)+  , ("gpi", testGpi)+  ]++allTests = map fst tests++runTests :: String -> TestDirection -> [String] -> IO ()+runTests uri dir ts = do+  forM_ ts $ \t -> do+    let mf = t `lookup` tests+    case mf of+      Nothing -> fail $ "no test named " ++ t+      Just f -> runTest uri dir t f++defUri :: String+defUri = case os of+           "darwin" -> "tmr:///dev/cu.SLAB_USBtoUART"+           "mingw32" -> "tmr:///COM4"+           _ -> "tmr:///dev/ttyUSB0"++data Opts = Opts+  { oUri :: String+  , oRecord :: Bool+  , oTests :: [String]+  }++optUri :: Parser String+optUri = strOption (long "uri" <>+                    short 'u' <>+                    metavar "URI" <>+                    help ("Reader to connect to (default " ++ defUri ++ ")") <>+                    value defUri)++optRecord :: Parser Bool+optRecord = switch (long "record" <>+                    short 'R' <>+                    help "record a new test from a physical reader")++opts :: Parser Opts+opts = Opts+  <$> optUri+  <*> optRecord+  <*> many (argument str (metavar "TESTS..."))++opts' = info (helper <*> opts)+  ( fullDesc <>+    header "replay - automated tests that use a simulated reader" )++main = do+  TMR.registerTransportInit+  o <- execParser opts'++  let dir = if oRecord o then Record else Playback+  let ts = case oTests o of+             [] -> allTests+             xs -> xs++  runTests (oUri o) dir ts
+ tests/unit.hs view
@@ -0,0 +1,82 @@+{-# LANGUAGE OverloadedStrings #-}++import qualified Data.ByteString as B ( ByteString )+import Data.Monoid ((<>))+import qualified Data.Text as T ( Text )+import Test.HUnit ( Assertion, Test(..), runTestTT, assertEqual )++import qualified System.Hardware.MercuryApi as TMR++helloWorld :: B.ByteString+helloWorld = "Hello, World!"++defacedBadFacade :: T.Text+defacedBadFacade = "DefacedBadFacade"++defacedBadFacadeBin :: B.ByteString+defacedBadFacadeBin = "\222\250\206\219\173\250\202\222"++-- http://www.adafruit.com/datasheets/CSN-A2%20User%20Manual.pdf+phrase :: B.ByteString+phrase = "thoroughly remove the uncommon words of anguish"++testDataHelpers :: Assertion+testDataHelpers = do+  assertEqual "TMR.packBytesIntoWords helloWorld"+    [18533,27756,28460,8279,28530,27748,8448]+    (TMR.packBytesIntoWords helloWorld)+  assertEqual "TMR.passwordToWords 0xbeadead1"+    [0xbead, 0xead1]+    (TMR.passwordToWords 0xbeadead1)++testHex :: Assertion+testHex = do+  assertEqual "TMR.bytesToHex defacedBadFacadeBin"+    "DEFACEDBADFACADE"+    (TMR.bytesToHex defacedBadFacadeBin)+  assertEqual "TMR.bytesToHexWithSpaces defacedBadFacadeBin"+    "de fa ce db ad fa ca de"+    (TMR.bytesToHexWithSpaces defacedBadFacadeBin)+  assertEqual "TMR.hexToBytes defacedBadFacade"+    (Just defacedBadFacadeBin)+    (TMR.hexToBytes defacedBadFacade)+  assertEqual "TMR.hexToBytes $ \"0x\" <> defacedBadFacade"+    (Just defacedBadFacadeBin)+    (TMR.hexToBytes $ "0x" <> defacedBadFacade)+  assertEqual "TMR.hexToBytes \"XXYYZZ\""+    Nothing+    (TMR.hexToBytes "XXYYZZ")+  assertEqual "TMR.hexToBytes \"0dd\""+    Nothing+    (TMR.hexToBytes "0dd")++testTimestamp :: Assertion+testTimestamp = do+  assertEqual "TMR.displayTimestamp 0"+    "1970-01-01T00:00:00.000Z"+    (TMR.displayTimestamp 0)+  assertEqual "TMR.displayTimestamp 123456789"+    "1970-01-02T10:17:36.789Z"+    (TMR.displayTimestamp 123456789)+  assertEqual "TMR.displayTimestamp 1513728000000"+    "2017-12-20T00:00:00.000Z"+    (TMR.displayTimestamp 1513728000000)++testData :: Assertion+testData = do+  assertEqual "TMR.displayData phrase"+    [ "74 68 6f 72 6f 75 67 68  6c 79 20 72 65 6d 6f 76  |thoroughly remov|"+    , "65 20 74 68 65 20 75 6e  63 6f 6d 6d 6f 6e 20 77  |e the uncommon w|"+    , "6f 72 64 73 20 6f 66 20  61 6e 67 75 69 73 68     |ords of anguish|"+    ]+    (TMR.displayData phrase)++tests :: Test+tests = TestList+  [ TestLabel "testDataHelpers" (TestCase testDataHelpers)+  , TestLabel "testHex" (TestCase testHex)+  , TestLabel "testTimestamp" (TestCase testTimestamp)+  , TestLabel "testData" (TestCase testData)+  ]++main = runTestTT tests
+ tests/write.result view
@@ -0,0 +1,5 @@+Right 1+Right (TagReadData {trTag = TagData {tdEpc = "\226\NULQ\134\SOH\a\SOH\135\ap\196\193", tdProtocol = TAG_PROTOCOL_GEN2, tdCrc = 47646, tdGen2 = Just (GEN2_TagData {g2Pc = "0\NUL"})}, trMetadataFlags = [METADATA_FLAG_READCOUNT,METADATA_FLAG_RSSI,METADATA_FLAG_ANTENNAID,METADATA_FLAG_FREQUENCY,METADATA_FLAG_TIMESTAMP,METADATA_FLAG_PHASE,METADATA_FLAG_PROTOCOL,METADATA_FLAG_DATA,METADATA_FLAG_GPIO_STATUS], trPhase = 171, trAntenna = 1, trGpio = [GpioPin {gpId = 1, gpHigh = False, gpOutput = False},GpioPin {gpId = 2, gpHigh = False, gpOutput = False},GpioPin {gpId = 3, gpHigh = False, gpOutput = False},GpioPin {gpId = 4, gpHigh = False, gpOutput = False}], trReadCount = 20, trRssi = -47, trFrequency = 922600, trTimestamp = 0, trData = "", trEpcMemData = "", trTidMemData = "", trUserMemData = "", trReservedMemData = ""})+Right ""+Right 1+Right (TagReadData {trTag = TagData {tdEpc = "\226\NULQ\134\SOH\a\SOH\135\ap\196\193", tdProtocol = TAG_PROTOCOL_GEN2, tdCrc = 18363, tdGen2 = Just (GEN2_TagData {g2Pc = "4\NUL"})}, trMetadataFlags = [METADATA_FLAG_READCOUNT,METADATA_FLAG_RSSI,METADATA_FLAG_ANTENNAID,METADATA_FLAG_FREQUENCY,METADATA_FLAG_TIMESTAMP,METADATA_FLAG_PHASE,METADATA_FLAG_PROTOCOL,METADATA_FLAG_DATA,METADATA_FLAG_GPIO_STATUS], trPhase = 174, trAntenna = 1, trGpio = [GpioPin {gpId = 1, gpHigh = False, gpOutput = False},GpioPin {gpId = 2, gpHigh = False, gpOutput = False},GpioPin {gpId = 3, gpHigh = False, gpOutput = False},GpioPin {gpId = 4, gpHigh = False, gpOutput = False}], trReadCount = 22, trRssi = -44, trFrequency = 918400, trTimestamp = 0, trData = "I am Groot\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL", trEpcMemData = "", trTidMemData = "", trUserMemData = "", trReservedMemData = ""})
+ tests/write.transport view
@@ -0,0 +1,118 @@+Sending: VERSION                       1608598.103811784+         ff 00 03 1d 0c                                    |.....|+Received:VERSION                       1608598.108389815+         ff 14 03 00 00 14 12 08  00 30 00 00 02 20 16 12  |.........0... ..|+         13 01 07 01 02 00 00 00  10 1b 05                 |...........|+Sending: GET_CURRENT_PROGRAM           1608598.108962046+         ff 00 0c 1d 03                                    |.....|+Received:GET_CURRENT_PROGRAM           1608598.110812682+         ff 01 0c 00 00 52 63 03                           |.....Rc.|+Sending: GET_POWER_MODE                1608598.110958814+         ff 00 68 1d 67                                    |..h.g|+Received:GET_POWER_MODE                1608598.112779756+         ff 01 68 00 00 00 a4 bf                           |..h.....|+Sending: GET_READER_OPTIONAL_PARAMS    1608598.112934335+         ff 02 6a 01 0e 2e 40                              |..j...@|+Received:GET_READER_OPTIONAL_PARAMS    1608598.114918110+         ff 03 6a 00 00 01 0e 00  30 44                    |..j.....0D|+Sending: GET_READER_OPTIONAL_PARAMS    1608598.121893539+         ff 02 6a 01 12 2e 5c                              |..j...\|+Received:GET_READER_OPTIONAL_PARAMS    1608598.124219487+         ff 04 6a 00 00 01 12 00  00 69 af                 |..j......i.|+Sending: GET_TAG_PROTOCOL              1608598.124500941+         ff 00 63 1d 6c                                    |..c.l|+Received:GET_TAG_PROTOCOL              1608598.126413019+         ff 02 63 00 00 00 05 21  46                       |..c....!F|+Sending: GET_ANTENNA_PORT              1608598.126563793+         ff 01 61 05 bd b8                                 |..a...|+Received:GET_ANTENNA_PORT              1608598.128513171+         ff 03 61 00 00 05 01 00  61 df                    |..a.....a.|+Sending: GET_READER_OPTIONAL_PARAMS    1608598.128660983+         ff 02 6a 01 0c 2e 42                              |..j...B|+Received:GET_READER_OPTIONAL_PARAMS    1608598.130614928+         ff 03 6a 00 00 01 0c 01  32 45                    |..j.....2E|+Sending: GET_READER_OPTIONAL_PARAMS    1608598.130747717+         ff 02 6a 01 0d 2e 43                              |..j...C|+Received:GET_READER_OPTIONAL_PARAMS    1608598.133116871+         ff 06 6a 00 00 01 0d 00  00 00 00 15 43           |..j.........C|+Sending: SET_REGION                    1608598.133294161+         ff 01 97 0d 4b b0                                 |....K.|+Received:SET_REGION                    1608598.135127143+         ff 00 97 00 00 77 9e                              |.....w.|+Sending: SET_READ_TX_POWER             1608598.135314487+         ff 02 92 08 98 49 c1                              |.....I.|+Received:SET_READ_TX_POWER             1608598.137182683+         ff 00 92 00 00 27 3b                              |.....';|+Sending: SET_WRITE_TX_POWER            1608598.137317673+         ff 02 94 08 98 29 07                              |.....).|+Received:SET_WRITE_TX_POWER            1608598.139181408+         ff 00 94 00 00 47 fd                              |.....G.|+Sending: SET_ANTENNA_PORT              1608598.139334656+         ff 02 91 01 01 70 3b                              |.....p;|+Received:SET_ANTENNA_PORT              1608598.141248843+         ff 00 91 00 00 17 58                              |......X|+Sending: SET_READER_OPTIONAL_PARAMS    1608598.141391398+         ff 03 9a 01 06 01 a9 5c                           |.......\|+Received:SET_READER_OPTIONAL_PARAMS    1608598.143471456+         ff 00 9a 00 00 a6 33                              |......3|+Sending: GET_READER_STATS              1608598.143757271+         ff 03 6c 01 9f 41 89 7b                           |..l..A.{|+Received:GET_READER_STATS              1608598.146075706+         ff 03 6c 00 00 01 9f 41  86 9c                    |..l....A..|+Sending: CLEAR_TAG_ID_BUFFER           1608598.146245646+         ff 00 2a 1d 25                                    |..*.%|+Received:CLEAR_TAG_ID_BUFFER           1608598.147965998+         ff 00 2a 00 00 01 e8                              |..*....|+Sending: SET_ANTENNA_PORT              1608598.148106117+         ff 03 91 02 01 01 42 c5                           |......B.|+Received:SET_ANTENNA_PORT              1608598.150175988+         ff 00 91 00 00 17 58                              |......X|+Sending: READ_TAG_ID_MULTIPLE          1608598.150440445+         ff 10 22 03 00 13 03 e8  00 00 00 00 00 00 00 00  |..".............|+         10 00 00 86 a3                                    |.....|+Received:READ_TAG_ID_MULTIPLE          1608599.160809727+         ff 07 22 00 00 03 00 13  00 00 00 01 65 8a        |..".........e.|+Sending: GET_TAG_ID_BUFFER             1608599.161120138+         ff 03 29 01 ff 00 1b 03                           |..).....|+Received:GET_TAG_ID_BUFFER             1608599.166592092+         ff 26 29 00 00 01 ff 00  01 14 d1 11 0e 13 e8 00  |.&).............|+         00 03 29 00 ab 05 00 00  00 00 80 30 00 e2 00 51  |..)........0...Q|+         86 01 07 01 87 07 70 c4  c1 ba 1e 92 d7           |......p......|+Sending: WRITE_TAG_DATA                1608599.170450637+         ff 23 24 03 e8 01 00 00  00 00 03 00 00 00 00 60  |.#$............`|+         e2 00 51 86 01 07 01 87  07 70 c4 c1 49 20 61 6d  |..Q......p..I am|+         20 47 72 6f 6f 74 a6 6a                           | Groot.j|+Received:WRITE_TAG_DATA                1608599.246089019+         ff 00 24 00 00 e0 26                              |..$...&|+Sending: GET_READER_STATS              1608599.246448176+         ff 03 6c 01 9f 41 89 7b                           |..l..A.{|+Received:GET_READER_STATS              1608599.248747520+         ff 03 6c 00 00 01 9f 41  86 9c                    |..l....A..|+Sending: CLEAR_TAG_ID_BUFFER           1608599.248930668+         ff 00 2a 1d 25                                    |..*.%|+Received:CLEAR_TAG_ID_BUFFER           1608599.250666122+         ff 00 2a 00 00 01 e8                              |..*....|+Sending: SET_ANTENNA_PORT              1608599.250844006+         ff 03 91 02 01 01 42 c5                           |......B.|+Received:SET_ANTENNA_PORT              1608599.252846522+         ff 00 91 00 00 17 58                              |......X|+Sending: READ_TAG_ID_MULTIPLE          1608599.253118475+         ff 11 22 00 00 17 03 e8  01 09 28 07 d0 00 03 00  |..".......(.....|+         00 00 00 20 49 70                                 |... Ip|+Received:READ_TAG_ID_MULTIPLE          1608600.265874100+         ff 4d 22 00 00 00 00 17  00 00 00 01 01 28 00 16  |.M"..........(..|+         00 00 49 20 61 6d 20 47  72 6f 6f 74 00 00 00 00  |..I am Groot....|+         00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|+         00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|+         00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|+         00 00 90 9a                                       |....|+Sending: GET_TAG_ID_BUFFER             1608600.266777939+         ff 03 29 01 ff 00 1b 03                           |..).....|+Received:GET_TAG_ID_BUFFER             1608600.278056115+         ff 66 29 00 00 01 ff 00  01 16 d4 11 0e 03 80 00  |.f).............|+         00 01 a0 00 ae 05 02 00  49 20 61 6d 20 47 72 6f  |........I am Gro|+         6f 74 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |ot..............|+         00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|+         00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|+         00 00 00 00 00 00 00 00  00 00 80 34 00 e2 00 51  |...........4...Q|+         86 01 07 01 87 07 70 c4  c1 47 bb 9a c1           |......p..G...|
+ tests/writeEpc.result view
@@ -0,0 +1,6 @@+Right 1+Right (TagReadData {trTag = TagData {tdEpc = "\226\NULQ\134\SOH\a\SOH\135\ap\196\193", tdProtocol = TAG_PROTOCOL_GEN2, tdCrc = 47646, tdGen2 = Just (GEN2_TagData {g2Pc = "0\NUL"})}, trMetadataFlags = [METADATA_FLAG_READCOUNT,METADATA_FLAG_RSSI,METADATA_FLAG_ANTENNAID,METADATA_FLAG_FREQUENCY,METADATA_FLAG_TIMESTAMP,METADATA_FLAG_PHASE,METADATA_FLAG_PROTOCOL,METADATA_FLAG_DATA,METADATA_FLAG_GPIO_STATUS], trPhase = 174, trAntenna = 1, trGpio = [GpioPin {gpId = 1, gpHigh = False, gpOutput = False},GpioPin {gpId = 2, gpHigh = False, gpOutput = False},GpioPin {gpId = 3, gpHigh = False, gpOutput = False},GpioPin {gpId = 4, gpHigh = False, gpOutput = False}], trReadCount = 31, trRssi = -47, trFrequency = 922600, trTimestamp = 0, trData = "", trEpcMemData = "", trTidMemData = "", trUserMemData = "", trReservedMemData = ""})+Right ""+Right 1+Right (TagReadData {trTag = TagData {tdEpc = "\SOH#Eg\137\171\205\239", tdProtocol = TAG_PROTOCOL_GEN2, tdCrc = 36510, tdGen2 = Just (GEN2_TagData {g2Pc = " \NUL"})}, trMetadataFlags = [METADATA_FLAG_READCOUNT,METADATA_FLAG_RSSI,METADATA_FLAG_ANTENNAID,METADATA_FLAG_FREQUENCY,METADATA_FLAG_TIMESTAMP,METADATA_FLAG_PHASE,METADATA_FLAG_PROTOCOL,METADATA_FLAG_DATA,METADATA_FLAG_GPIO_STATUS], trPhase = 171, trAntenna = 1, trGpio = [GpioPin {gpId = 1, gpHigh = False, gpOutput = False},GpioPin {gpId = 2, gpHigh = False, gpOutput = False},GpioPin {gpId = 3, gpHigh = False, gpOutput = False},GpioPin {gpId = 4, gpHigh = False, gpOutput = False}], trReadCount = 22, trRssi = -45, trFrequency = 918400, trTimestamp = 0, trData = "\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL", trEpcMemData = "", trTidMemData = "", trUserMemData = "", trReservedMemData = ""})+Right ""
+ tests/writeEpc.transport view
@@ -0,0 +1,124 @@+Sending: VERSION                       1783113.335963260+         ff 00 03 1d 0c                                    |.....|+Received:VERSION                       1783113.340546799+         ff 14 03 00 00 14 12 08  00 30 00 00 02 20 16 12  |.........0... ..|+         13 01 07 01 02 00 00 00  10 1b 05                 |...........|+Sending: GET_CURRENT_PROGRAM           1783113.341025567+         ff 00 0c 1d 03                                    |.....|+Received:GET_CURRENT_PROGRAM           1783113.342675574+         ff 01 0c 00 00 52 63 03                           |.....Rc.|+Sending: GET_POWER_MODE                1783113.342832512+         ff 00 68 1d 67                                    |..h.g|+Received:GET_POWER_MODE                1783113.344719334+         ff 01 68 00 00 00 a4 bf                           |..h.....|+Sending: GET_READER_OPTIONAL_PARAMS    1783113.344877962+         ff 02 6a 01 0e 2e 40                              |..j...@|+Received:GET_READER_OPTIONAL_PARAMS    1783113.347044658+         ff 03 6a 00 00 01 0e 00  30 44                    |..j.....0D|+Sending: GET_READER_OPTIONAL_PARAMS    1783113.354181389+         ff 02 6a 01 12 2e 5c                              |..j...\|+Received:GET_READER_OPTIONAL_PARAMS    1783113.356482817+         ff 04 6a 00 00 01 12 00  00 69 af                 |..j......i.|+Sending: GET_TAG_PROTOCOL              1783113.356679203+         ff 00 63 1d 6c                                    |..c.l|+Received:GET_TAG_PROTOCOL              1783113.358546212+         ff 02 63 00 00 00 05 21  46                       |..c....!F|+Sending: GET_ANTENNA_PORT              1783113.358712824+         ff 01 61 05 bd b8                                 |..a...|+Received:GET_ANTENNA_PORT              1783113.360832578+         ff 03 61 00 00 05 01 00  61 df                    |..a.....a.|+Sending: GET_READER_OPTIONAL_PARAMS    1783113.361047512+         ff 02 6a 01 0c 2e 42                              |..j...B|+Received:GET_READER_OPTIONAL_PARAMS    1783113.363254874+         ff 03 6a 00 00 01 0c 01  32 45                    |..j.....2E|+Sending: GET_READER_OPTIONAL_PARAMS    1783113.363464915+         ff 02 6a 01 0d 2e 43                              |..j...C|+Received:GET_READER_OPTIONAL_PARAMS    1783113.365915536+         ff 06 6a 00 00 01 0d 00  00 00 00 15 43           |..j.........C|+Sending: SET_REGION                    1783113.366099275+         ff 01 97 0d 4b b0                                 |....K.|+Received:SET_REGION                    1783113.367851295+         ff 00 97 00 00 77 9e                              |.....w.|+Sending: SET_READ_TX_POWER             1783113.368065458+         ff 02 92 08 98 49 c1                              |.....I.|+Received:SET_READ_TX_POWER             1783113.369971357+         ff 00 92 00 00 27 3b                              |.....';|+Sending: SET_WRITE_TX_POWER            1783113.370116064+         ff 02 94 08 98 29 07                              |.....).|+Received:SET_WRITE_TX_POWER            1783113.371990494+         ff 00 94 00 00 47 fd                              |.....G.|+Sending: SET_ANTENNA_PORT              1783113.372144979+         ff 02 91 01 01 70 3b                              |.....p;|+Received:SET_ANTENNA_PORT              1783113.374086488+         ff 00 91 00 00 17 58                              |......X|+Sending: SET_READER_OPTIONAL_PARAMS    1783113.374223675+         ff 03 9a 01 06 01 a9 5c                           |.......\|+Received:SET_READER_OPTIONAL_PARAMS    1783113.376213620+         ff 00 9a 00 00 a6 33                              |......3|+Sending: GET_READER_STATS              1783113.376365163+         ff 03 6c 01 9f 41 89 7b                           |..l..A.{|+Received:GET_READER_STATS              1783113.378504811+         ff 03 6c 00 00 01 9f 41  86 9c                    |..l....A..|+Sending: CLEAR_TAG_ID_BUFFER           1783113.378674249+         ff 00 2a 1d 25                                    |..*.%|+Received:CLEAR_TAG_ID_BUFFER           1783113.380379708+         ff 00 2a 00 00 01 e8                              |..*....|+Sending: SET_ANTENNA_PORT              1783113.380525173+         ff 03 91 02 01 01 42 c5                           |......B.|+Received:SET_ANTENNA_PORT              1783113.382539190+         ff 00 91 00 00 17 58                              |......X|+Sending: READ_TAG_ID_MULTIPLE          1783113.382687791+         ff 10 22 03 00 13 03 e8  00 00 00 00 00 00 00 00  |..".............|+         10 00 00 86 a3                                    |.....|+Received:READ_TAG_ID_MULTIPLE          1783114.389189850+         ff 07 22 00 00 03 00 13  00 00 00 01 65 8a        |..".........e.|+Sending: GET_TAG_ID_BUFFER             1783114.389440192+         ff 03 29 01 ff 00 1b 03                           |..).....|+Received:GET_TAG_ID_BUFFER             1783114.394987785+         ff 26 29 00 00 01 ff 00  01 1f d1 11 0e 13 e8 00  |.&).............|+         00 03 23 00 ae 05 00 00  00 00 80 30 00 e2 00 51  |..#........0...Q|+         86 01 07 01 87 07 70 c4  c1 ba 1e f3 0f           |......p......|+Sending: WRITE_TAG_ID                  1783114.395787548+         ff 1c 23 03 e8 01 00 00  00 00 60 e2 00 51 86 01  |..#.......`..Q..|+         07 01 87 07 70 c4 c1 01  23 45 67 89 ab cd ef 5b  |....p...#Eg....[|+         20                                                | |+Received:WRITE_TAG_ID                  1783114.473001670+         ff 00 23 00 00 90 c1                              |..#....|+Sending: GET_READER_STATS              1783114.473210471+         ff 03 6c 01 9f 41 89 7b                           |..l..A.{|+Received:GET_READER_STATS              1783114.475568734+         ff 03 6c 00 00 01 9f 41  86 9c                    |..l....A..|+Sending: CLEAR_TAG_ID_BUFFER           1783114.475730903+         ff 00 2a 1d 25                                    |..*.%|+Received:CLEAR_TAG_ID_BUFFER           1783114.477455041+         ff 00 2a 00 00 01 e8                              |..*....|+Sending: SET_ANTENNA_PORT              1783114.477668332+         ff 03 91 02 01 01 42 c5                           |......B.|+Received:SET_ANTENNA_PORT              1783114.479714545+         ff 00 91 00 00 17 58                              |......X|+Sending: READ_TAG_ID_MULTIPLE          1783114.479888386+         ff 11 22 00 00 17 03 e8  01 09 28 07 d0 00 03 00  |..".......(.....|+         00 00 00 20 49 70                                 |... Ip|+Received:READ_TAG_ID_MULTIPLE          1783115.497038299+         ff 4d 22 00 00 00 00 17  00 00 00 01 01 28 00 16  |.M"..........(..|+         00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|+         00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|+         00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|+         00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|+         00 00 e4 bf                                       |....|+Sending: GET_TAG_ID_BUFFER             1783115.498013194+         ff 03 29 01 ff 00 1b 03                           |..).....|+Received:GET_TAG_ID_BUFFER             1783115.508879879+         ff 62 29 00 00 01 ff 00  01 16 d3 11 0e 03 80 00  |.b).............|+         00 01 9d 00 ab 05 02 00  00 00 00 00 00 00 00 00  |................|+         00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|+         00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|+         00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|+         00 00 00 00 00 00 00 00  00 00 60 20 00 01 23 45  |..........` ..#E|+         67 89 ab cd ef 8e 9e 37  23                       |g......7#|+Sending: WRITE_TAG_ID                  1783115.510126246+         ff 1c 23 03 e8 01 00 00  00 00 40 01 23 45 67 89  |..#.......@.#Eg.|+         ab cd ef e2 00 51 86 01  07 01 87 07 70 c4 c1 72  |.....Q......p..r|+         c4                                                |.|+Received:WRITE_TAG_ID                  1783115.619815239+         ff 00 23 00 00 90 c1                              |..#....|