tmr_loadsave_configuration.c
Go to the documentation of this file.
00001 
00008 /*
00009  * Copyright (c) 2009 ThingMagic, Inc.
00010  *
00011  * Permission is hereby granted, free of charge, to any person obtaining a copy
00012  * of this software and associated documentation files (the "Software"), to deal
00013  * in the Software without restriction, including without limitation the rights
00014  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
00015  * copies of the Software, and to permit persons to whom the Software is
00016  * furnished to do so, subject to the following conditions:
00017  *
00018  * The above copyright notice and this permission notice shall be included in
00019  * all copies or substantial portions of the Software.
00020  * 
00021  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
00022  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
00023  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
00024  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
00025  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
00026  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
00027  * THE SOFTWARE.
00028  */
00029 
00030 #include <string.h>
00031 #include <stdio.h>
00032 #include <inttypes.h>
00033 #include <ctype.h>
00034 #include <stdlib.h>
00035 #ifndef WIN32
00036 #include <libgen.h>
00037 #endif
00038 
00039 #include "tm_reader.h"
00040 #include "tmr_utils.h"
00041 #include "serial_reader_imp.h"
00042 
00043 #ifdef WIN32
00044 #define strncasecmp _strnicmp
00045 #endif /* WIN32 */
00046 
00047 #define CONFIG_MAX_BUFFER_LEN 1500
00048 #define CONFIG_MAX_PARAMETERS_LEN 100
00049 
00050 typedef struct properties
00051 {
00052   char keyConfig[CONFIG_MAX_BUFFER_LEN];
00053   char valueConfig[CONFIG_MAX_BUFFER_LEN];
00054 }properties;
00055 
00056 typedef enum paramOption
00057 {
00058   PARAM_OPTION_GET = 0x00,
00059   PARAM_OPTION_SET = 0x01,
00060 }paramOption;
00061 
00062 /* Private: Should not be used by user level application. */
00063 static const char *hexChars = "0123456789abcdefABCDEF";
00064 static const char *selectOptionNames[] = {"EQ", "NE", "GT", "LT"};
00065 static const char *regions[] = {"UNSPEC", "NA", "EU", "KR", "IN", "JP", "PRC",
00066                                 "EU2", "EU3", "KR2", "PRC2", "AU", "NZ", "NA2", "NA3", "IS"};
00067 static const char *powerModes[] = {"FULL", "MINSAVE", "MEDSAVE", "MAXSAVE", "SLEEP"};
00068 static const char *tagEncodingNames[] = {"FM0", "M2", "M4", "M8"};
00069 static const char *sessionNames[] = {"S0", "S1", "S2", "S3"};
00070 static const char *targetNames[] = {"A", "B", "AB", "BA"};
00071 static const char *tariNames[] = {"TARI_25US", "TARI_12_5US", "TARI_6_25US"};
00072 static const char *gen2LinkFrequencyNames[] = {"LINK250KHZ", "LINK300KHZ", "LINK320KHZ", "LINK40KHZ", "LINK640KHZ"};
00073 static const char *gen2ProtocolExtensionNames[] = {"TMR_GEN2_PROTOCOLEXTENSION_LICENSE_NONE", "TMR_GEN2_PROTOCOLEXTENSION_LICENSE_IAV_DENATRAN"};
00074 static const char *protocolNames[] = {NULL, NULL, NULL, "ISO180006B",
00075                                       NULL, "GEN2", "ISO180006B_UCODE", "IPX64", "IPX256"};
00076 static const char *bankNames[] = {"Reserved", "EPC", "TID", "User"};
00077 static const char *tagopNames[] = {NULL, "ReadData"};
00078 static TMR_Status readLine(FILE *fp, char *buffer);
00079 static TMR_Status isParamWritable(TMR_Param key);
00080 static void logErrorMessage(struct TMR_Reader *reader, char *errorString);
00081 static int parseEpc(const char *arg, TMR_TagData *tag, int *nchars);
00082 static int parseTagop(const char *arg, TMR_TagOp **tagopp, int *nchars);
00083 static int parseFilter(const char *arg, TMR_TagFilter **filterp, int *nchars);
00084 static int parseU32List(const char *arg, TMR_uint32List *list, int *nchars);
00085 static int parseU8List(const char *arg, TMR_uint8List *list, int *nchars);
00086 static int parsePortValueList(const char *arg, TMR_PortValueList *list, int *nchars);
00087 static int parseReadPlan(const char *arg, TMR_ReadPlan *plan, int *nchars);
00088 static void printU8List(TMR_String *string, TMR_uint8List *list);
00089 static void printU32List(TMR_String *string, TMR_uint32List *list);
00090 static void printPortValueList(TMR_String *string, TMR_PortValueList *list);
00091 static void printReadPlan(const char *string, TMR_ReadPlan *plan, int *nchars);
00092 static void printFilter(TMR_String *string, TMR_TagFilter *filter);
00093 static void printTagop(TMR_String *string, TMR_TagOp *tagop);
00094 static const char *regionName(TMR_Region region);
00095 static TMR_Region regionID(const char *name);
00096 static bool strcasecmpcount(const char *a, const char *b, int *matches);
00097 const char *listname(const char *list[], int listlen, unsigned int id);
00098 static int listid(const char *list[], int listlen, const char *name);
00099 static TMR_Status getSetOneParam(struct TMR_Reader *reader, const char *paramName, TMR_String *string, paramOption option);
00100 static TMR_Status loadConfiguration(struct TMR_Reader *reader, char *filePath, properties *dict, uint8_t noOfEntries, bool isRollBack);
00101 static TMR_Status rollBackConfigData(struct TMR_Reader *reader, char *filePath);
00102 
00103 static void
00104 logErrorMessage(struct TMR_Reader *reader, char *errorString)
00105 {
00106   if(TMR_READER_TYPE_SERIAL == reader->readerType)
00107   {
00108     sprintf(reader->u.serialReader.errMsg, "%s", errorString);
00109   }
00110 #ifdef TMR_ENABLE_LLRP_READER
00111   else
00112   {
00113     sprintf(reader->u.llrpReader.errMsg,  "%s", errorString);
00114   }
00115 #endif
00116 }
00117 
00118 static bool
00119 strcasecmpcount(const char *a, const char *b, int *matches)
00120 {
00121   int i = 0;
00122 
00123   while (*a && *b && 
00124     (tolower((unsigned char)*a) == tolower((unsigned char)*b)))
00125   {
00126     i++;
00127     a++;
00128     b++;
00129   }
00130   if (matches)
00131   {
00132     *matches = i;
00133   }
00134   return (*a == *b);
00135 }
00136 
00137 static 
00138 int listid(const char *list[], int listlen, const char *name)
00139 {
00140   int i, len, match, bestmatch, bestmatchindex;
00141 
00142   bestmatch = 0;
00143   bestmatchindex = -1;
00144   len = (int)strlen(name);
00145   for (i = 0; i < listlen; i++)
00146   {
00147     if (NULL != list[i])
00148     {
00149       if (strcasecmpcount(name, list[i], &match))
00150       {
00151         return i; /* Exact match - return immediately */
00152       }
00153       if (match == len)
00154       {
00155         if (bestmatch == 0)
00156         {
00157           /* Prefix match - return if nothing else conflicts */
00158           bestmatch = match;
00159           bestmatchindex = i;
00160         }
00161         else
00162         {
00163           /* More than one prefix match of the same length - ambiguous */
00164           bestmatchindex = -1;
00165         }
00166       }
00167     }
00168   }
00169   return bestmatchindex;
00170 }
00171 
00172 const char *listname(const char *list[], int listlen, unsigned int id)
00173 {
00174   if ((id < (unsigned)listlen) && list[id] != NULL)
00175   {
00176     return (list[id]);
00177   }
00178   return ("Unknown");
00179 }
00180 
00181 static const char *regionName(TMR_Region region)
00182 {
00183   if (region == TMR_REGION_OPEN)
00184   {
00185     return "OPEN";
00186   }
00187   return listname(regions, numberof(regions), region);
00188 }
00189 
00190 static TMR_Region regionID(const char *name)
00191 {
00192 
00193   if (0 == strcasecmp(name, "OPEN"))
00194   {
00195     return TMR_REGION_OPEN;
00196   }
00197 
00198   return listid(regions, numberof(regions), name);
00199 }
00200 
00201 /* Helper function to read a new line from the file */
00202 static TMR_Status 
00203 readLine(FILE *fp, char *buffer)
00204 {
00205   int c;
00206   TMR_Status ret = TMR_SUCCESS;  
00207   int i = 0x00;
00208 
00209   do
00210   {
00211     c = fgetc(fp);
00212     if (feof(fp))
00213     {
00214       /* encountered EOF */
00215       buffer[i] = (char)c;
00216       ret = TMR_ERROR_TRYAGAIN;
00217       break;
00218     }
00219     else
00220     {
00221       if ('\n' != c)
00222       {
00223         if (32 != c)
00224         {
00225           /* remove spaces if any and then copy */
00226           buffer[i] = (char) c;
00227           i++;
00228         }
00229         else
00230         {
00231           continue;
00232         }
00233       }
00234       else
00235       {
00236         /* one line read */
00237         ret = TMR_SUCCESS;
00238         break;
00239       }
00240     }
00241   }while(i < CONFIG_MAX_BUFFER_LEN);
00242 
00243   /* check for buffer over flow */
00244   if (CONFIG_MAX_BUFFER_LEN == i)
00245   {
00246     ret = TMR_ERROR_OUT_OF_MEMORY;
00247   }
00248 return ret;
00249 }
00250 
00251 static TMR_Status
00252 isParamWritable(TMR_Param key)
00253 {
00254   TMR_Status ret;
00255 
00256   ret = TMR_SUCCESS;
00257 
00258   switch(key)
00259   {
00260   case TMR_PARAM_URI:
00261   case TMR_PARAM_PRODUCT_GROUP_ID:
00262   case TMR_PARAM_PRODUCT_GROUP:
00263   case TMR_PARAM_PRODUCT_ID:
00264   case TMR_PARAM_TAGREADATA_TAGOPSUCCESSCOUNT:
00265   case TMR_PARAM_TAGREADATA_TAGOPFAILURECOUNT:
00266   case TMR_PARAM_RADIO_POWERMAX:
00267   case TMR_PARAM_RADIO_POWERMIN:
00268   case TMR_PARAM_REGION_SUPPORTEDREGIONS:
00269   case TMR_PARAM_ANTENNA_PORTLIST:
00270   case TMR_PARAM_ANTENNA_CONNECTEDPORTLIST:
00271   case TMR_PARAM_VERSION_SUPPORTEDPROTOCOLS:
00272   case TMR_PARAM_RADIO_TEMPERATURE:
00273   case TMR_PARAM_VERSION_HARDWARE:
00274   case TMR_PARAM_VERSION_MODEL:
00275   case TMR_PARAM_VERSION_SOFTWARE:
00276   case TMR_PARAM_VERSION_SERIAL:
00277   case TMR_PARAM_ANTENNA_RETURNLOSS:
00278   case TMR_PARAM_CURRENTTIME:
00279     /* Following parameters are not read only in Mercury API, but we decided
00280      * not to support them as part for LoadSaveConfiguration. Hence adding them as
00281      * read only parameters. */
00282   case TMR_PARAM_LICENSE_KEY:
00283   case TMR_PARAM_READER_STATS:
00284   case TMR_PARAM_USER_CONFIG:
00285   case TMR_PARAM_READER_STATISTICS:
00286   case TMR_PARAM_REGION_LBT_ENABLE:
00287   case TMR_PARAM_RADIO_ENABLEPOWERSAVE:
00288   case TMR_PARAM_GEN2_BAP:
00289   case TMR_PARAM_ISO180006B_MODULATION_DEPTH:
00290   case TMR_PARAM_ISO180006B_DELIMITER:
00291   case TMR_PARAM_ISO180006B_BLF:
00292   case TMR_PARAM_RADIO_ENABLESJC:
00293   case TMR_PARAM_USERMODE:
00294   case TMR_PARAM_GEN2_WRITEMODE:
00295   case TMR_PARAM_READER_WRITE_EARLY_EXIT:
00296   case TMR_PARAM_READER_WRITE_REPLY_TIMEOUT:
00297   case TMR_PARAM_READER_DESCRIPTION:
00298   case TMR_PARAM_READER_HOSTNAME:
00299   case TMR_PARAM_EXTENDEDEPC:
00300   case TMR_PARAM_TAGOP_ANTENNA:
00301     {
00302       ret = TMR_ERROR_READONLY;
00303       break;
00304     }
00305   default:
00306     ret = TMR_SUCCESS;
00307   }
00308   return ret;
00309 }
00310 
00311 /*
00312  * Tag operations (for embedding)
00313  *  Read:   gen2.read:EPC,2,2 (word address and count)
00314  */
00315 static int
00316 parseTagop(const char *arg, TMR_TagOp **tagopp, int *nchars)
00317 {
00318   TMR_TagOp *tagop;
00319   const char *orig;
00320   int id;
00321   char buf[100];
00322   int charcount;
00323 
00324   if (0 == strncasecmp(arg, "NULL", 4))
00325   {
00326     *tagopp = NULL;
00327     if (nchars)
00328     {
00329       *nchars = 4;
00330     }
00331     return 0;
00332   }
00333 
00334   orig = arg;
00335   if (1 != sscanf(arg, "%[^]:]%n", buf, &charcount))
00336   {
00337     return -1;
00338   }
00339 
00340   tagop = malloc(sizeof(*tagop));
00341   id = listid(tagopNames, numberof(tagopNames), buf);
00342   if (-1 == id)
00343   {
00344     goto error;
00345   }
00346 
00347   arg += charcount;
00348   tagop->type = id;
00349   switch (tagop->type)
00350   {
00351   case TMR_TAGOP_GEN2_READDATA:
00352   {
00353     TMR_GEN2_Bank bank;
00354     int address,  wordLen;
00355 
00356     bank = 0x00;
00357     address = 0x00;
00358     wordLen = 0x00;
00359 
00360     arg++;
00361     while (']' != *arg)
00362     {
00363       arg++;
00364       if (1 != sscanf(arg, "%[^]=]%n", buf, &charcount))
00365       {
00366         return -1;
00367       }
00368       if (0x00 == strcmp("Bank", buf))
00369       {
00370         arg += charcount;
00371         arg++;
00372         if (1 != sscanf(arg, "%[^],]%n", buf, &charcount))
00373         {
00374           return -1;
00375         }
00376         arg += charcount;
00377         id = listid(bankNames, numberof(bankNames), buf);
00378         if (-1 == id)
00379         {
00380           goto error;
00381         }
00382         bank = id;
00383       }
00384       else if (0x00 == strcmp("WordAddress", buf))
00385       {
00386         arg += charcount;
00387         arg++;
00388         if (1 != sscanf(arg, "%[^],]%n", buf, &charcount))
00389         {
00390           return -1;
00391         }
00392         arg += charcount;
00393         address = atol(buf);
00394       }
00395       else if (0x00 == strcmp("Len", buf))
00396       {
00397         arg += charcount;
00398         arg++;
00399         if (1 != sscanf(arg, "%[^]]%n", buf, &charcount))
00400         {
00401           return -1;
00402         }
00403         arg += charcount;
00404         wordLen = atol(buf);
00405       }
00406     }
00407 
00408     TMR_TagOp_init_GEN2_ReadData(tagop, bank, address, wordLen);
00409     break;
00410   }
00411   default:
00412     /* Currently supporting only Gen2 Read Data */
00413     goto error;
00414   }
00415 
00416   if (NULL != nchars)
00417     *nchars = (int)(arg - orig);
00418 
00419   *tagopp = tagop;
00420   return 0;
00421 
00422 error:
00423   free(tagop);
00424   return -1;
00425 }
00426 
00427 /* Parse strings of the form [1,2,3,4] into a TMR_uint32List */
00428 static int
00429 parseU32List(const char *arg, TMR_uint32List *list, int *nchars)
00430 {
00431   int value;
00432   int chars;
00433   const char *origarg;
00434 
00435   origarg = arg;
00436   if ('[' != arg[0])
00437   {
00438     return -1;
00439   }
00440 
00441   arg++;
00442   list->len = 0;
00443   list->max = 4;
00444   list->list = malloc(sizeof(list->list[0]) * list->max);
00445 
00446   while (1 == sscanf(arg, "%i%n", &value, &chars))
00447   {
00448     if (list->len+1 > list->max)
00449     {
00450       list->list = realloc(list->list, 2 * list->max * sizeof(list->list[0]));
00451       list->max = 2 * list->max;
00452     }
00453     list->list[list->len] = value;
00454     list->len++;
00455     arg += chars;
00456     if (',' == *arg)
00457     {
00458       arg++;
00459     }
00460   }
00461 
00462   if (']' == *arg)
00463   {
00464     arg++;
00465   }
00466   else
00467   {
00468     free(list->list);
00469     return -1;
00470   }
00471 
00472   if (nchars)
00473   {
00474     *nchars = (int)(arg - origarg);
00475   }
00476   return 0;
00477 }
00478 
00479 static int 
00480 parseEpc(const char *arg, TMR_TagData *tag, int *nchars)
00481 {
00482   static const char epcPrefix[] = "EPC=";
00483   static int epcPrefixLen = sizeof(epcPrefix) - 1;
00484   TMR_Status ret;
00485   int len;
00486 
00487   if (0 != strncasecmp(arg, "TagData:", 8))
00488   {
00489     return -1;
00490   }
00491 
00492   arg += 9;
00493   if (0 != strncasecmp(arg, epcPrefix, epcPrefixLen))
00494   {
00495     return -1;
00496   }
00497 
00498   arg += epcPrefixLen;
00499   len = (int)strspn(arg, hexChars) / 2;
00500   ret = TMR_hexToBytes(arg, tag->epc, len, NULL);
00501   if (TMR_SUCCESS != ret)
00502   {
00503     return -1;
00504   }
00505   tag->protocol = TMR_TAG_PROTOCOL_NONE;
00506   tag->epcByteCount = len;
00507 
00508   if (nchars)
00509   {
00510     *nchars = epcPrefixLen + 2 * len;
00511   }
00512 
00513   return 0;
00514 }
00515 
00516 /*
00517  * Tag filters:
00518  *  Tag ID:      EPC:000011112222333344445555
00519  *  Gen2 Select: Gen2.Select:~EPC,16,32,DEADBEEF
00520  *  ISO 18k6B:   Iso18k6b.Select:~EQ,1,ff,001122334455667788
00521  *               (EQ,NE,GT,LT),address,bytemask,data
00522  */
00523 static int
00524 parseFilter(const char *arg, TMR_TagFilter **filterp, int *nchars)
00525 {
00526   TMR_Status ret;
00527   TMR_TagFilter *filter;
00528   static const char gen2Prefix[] = "Gen2.Select:";
00529   static int gen2PrefixLen = sizeof(gen2Prefix) - 1;
00530   static const char iso18k6bPrefix[] = "Iso18k6b.Select:";
00531   static int iso18k6bPrefixLen = sizeof(iso18k6bPrefix) - 1;
00532 
00533   int len = 0x00;
00534 
00535   if (0 == strncasecmp(arg, "NULL", 4))
00536   {
00537     *filterp = NULL;
00538     if (nchars)
00539     {
00540       *nchars = 4;
00541     }
00542     return 0;
00543   }
00544 
00545   filter = malloc(sizeof(*filter));
00546 
00547   if (0 == parseEpc(arg, &filter->u.tagData, nchars))
00548   {
00549     filter->type = TMR_FILTER_TYPE_TAG_DATA;
00550   }
00551   else if (0 == strncasecmp(arg, gen2Prefix, gen2PrefixLen))
00552   {
00553     bool invert = false;
00554     int bank = 0x00, pointer = 0x00, bitlen = 0x00;
00555     uint8_t *mask = NULL;
00556     char numbuf[100];
00557     const char *orig;
00558     int charcount = 0x00;
00559 
00560     orig = arg;
00561     arg += (gen2PrefixLen);
00562     
00563     while(']' != *arg)
00564     {
00565       arg++;
00566       if (1 != sscanf(arg, "%[^]=]%n", numbuf, &charcount))
00567       {
00568         return -1;
00569       }
00570       if (0x00 == strcmp(numbuf, "Invert"))
00571       {
00572         arg += charcount;
00573         arg++;
00574         if (1 != sscanf(arg, "%[^],]%n", numbuf, &charcount))
00575         {
00576           return -1;
00577         }
00578         arg += charcount;
00579         invert = (0 == strcmp(numbuf, "true")) ? true : false;
00580       }
00581       else if (0x00 == strcmp(numbuf, "Bank"))
00582       {
00583         arg += charcount;
00584         arg++;
00585         if (1 != sscanf(arg, "%[^],]%n", numbuf, &charcount))
00586         {
00587           return -1;
00588         }
00589         arg += charcount;
00590         bank = listid(bankNames, numberof(bankNames), numbuf);
00591         if (-1 == bank)
00592         {
00593           goto error;
00594         }
00595       }
00596       else if (0x00 == strcmp(numbuf, "BitPointer"))
00597       {
00598         arg += charcount;
00599         arg++;
00600         if (1 != sscanf(arg, "%[^],]%n", numbuf, &charcount))
00601         {
00602           return -1;
00603         }
00604         arg += charcount;
00605         pointer = atol(numbuf);
00606       }
00607       else if (0x00 == strcmp(numbuf, "BitLength"))
00608       {
00609         arg += charcount;
00610         arg++;
00611         if (1 != sscanf(arg, "%[^],]%n", numbuf, &charcount))
00612         {
00613           return -1;
00614         }
00615         arg += charcount;
00616         bitlen = atol(numbuf);
00617       }
00618       else if (0x00 == strcmp(numbuf, "Mask"))
00619       {
00620         arg += charcount;
00621         arg++;
00622         if (1 != sscanf(arg, "%[^]]%n", numbuf, &charcount))
00623         {
00624           return -1;
00625         }
00626         arg += charcount;
00627         len = (int)(strspn(numbuf, hexChars) / 2);
00628         mask = malloc(len);
00629         ret = TMR_hexToBytes(numbuf, mask, len, NULL);
00630         if (TMR_SUCCESS != ret)
00631         {
00632           free(mask);
00633           goto error;
00634         }
00635       }
00636     }
00637     TMR_TF_init_gen2_select(filter, invert, bank, pointer, bitlen, mask);
00638     if (nchars)
00639     {
00640       *nchars = (int)((arg + 2 * len) - orig);
00641     }
00642   }
00643   else if (0 == strncasecmp(arg, iso18k6bPrefix, iso18k6bPrefixLen))
00644   {
00645     bool invert;
00646     int selectOp, address, mask;
00647     uint8_t bytes[8];
00648     char buf[16];
00649     const char *orig;
00650     char *next;
00651 
00652     orig = arg;
00653     arg += iso18k6bPrefixLen;
00654 
00655     if ('~' == *arg)
00656     {
00657       invert = true;
00658       arg++;
00659     }
00660   else
00661   {
00662       invert = false;
00663     }
00664 
00665     /* Parse group select option */
00666     next = strchr(arg, ',');
00667     if (NULL == next)
00668     {
00669     goto error;
00670   }
00671     strncpy(buf, arg, next-arg);
00672     buf[next-arg] = '\0';
00673     selectOp = listid(selectOptionNames, numberof(selectOptionNames), buf);
00674     if (-1 == selectOp)
00675     {
00676       goto error;
00677     }
00678     arg = next + 1;
00679 
00680     /* Parse byte address */
00681     next = strchr(arg, ',');
00682     if (NULL == next || next - arg > 16)
00683     {
00684       goto error;
00685     }
00686     strncpy(buf, arg, next-arg);
00687     buf[next-arg] = '\0';
00688     address = strtol(buf, NULL, 16);
00689     arg = next + 1;
00690 
00691     /* Parse byte mask */
00692     next = strchr(arg, ',');
00693     if (NULL == next || next - arg > 16)
00694     {
00695       goto error;
00696     }
00697     strncpy(buf, arg, next-arg);
00698     buf[next-arg] = '\0';
00699     mask = strtol(buf, NULL, 16);
00700     arg = next + 1;
00701 
00702     len = (int)strspn(arg, hexChars) / 2;
00703     if (8 != len)
00704     {
00705       goto error;
00706     }
00707     ret = TMR_hexToBytes(arg, bytes, len, NULL);
00708     if (TMR_SUCCESS != ret)
00709     {
00710       goto error;
00711     }
00712 #ifdef TMR_ENABLE_ISO180006B    
00713 
00714     TMR_TF_init_ISO180006B_select(filter, invert, selectOp, address, mask,
00715                                   bytes);
00716 #endif /* TMR_ENABLE_ISO180006B */
00717 
00718     if (nchars)
00719     {
00720       *nchars = (int)((arg + 2 * len) - orig);
00721     }
00722   }
00723   else
00724   {
00725     goto error;
00726   }
00727 
00728   *filterp = filter;
00729   return 0;
00730 
00731 error:
00732   free(filter);
00733   return -1;
00734 }
00735 
00736 /* Parse strings of the form [1,2,3,4] into a TMR_uint8List */
00737 static int
00738 parseU8List(const char *arg, TMR_uint8List *list, int *nchars)
00739 {
00740   TMR_uint32List u32list;
00741   int i, ret;
00742 
00743   ret = 0;
00744 
00745   if (-1 == parseU32List(arg, &u32list, nchars))
00746   {
00747     return -1;
00748   }
00749 
00750   list->len = u32list.len;
00751   list->max = u32list.len;
00752   list->list = malloc(sizeof(list->list[0]) * list->max);
00753   for (i = 0; i < list->len; i++)
00754   {
00755     if (u32list.list[i] > UINT8_MAX)
00756     {
00757       ret = -1;
00758       goto out;
00759     }
00760     list->list[i] = (uint8_t)u32list.list[i];
00761   }
00762 
00763 out:
00764   free(u32list.list);
00765   return ret;
00766 }
00767 
00768 /* Parse strings of the form [[1,100],[2,200]] into a
00769  * TMR_PortValueList structure.
00770  */
00771 static int
00772 parsePortValueList(const char *arg, TMR_PortValueList *list, int *nchars)
00773 {
00774   int port, value;
00775   int chars;
00776   const char *origarg = arg;
00777 
00778   if ('[' != arg[0]
00779       || ']' != arg[strlen(arg)-1])
00780   {
00781     return -1;
00782   }
00783 
00784   arg++;
00785 
00786   list->len = 0;
00787   list->max = 4;
00788   list->list = malloc(sizeof(list->list[0]) * list->max);
00789 
00790   while (2 == sscanf(arg, "[%i,%i]%*[],]%n", &port, &value, &chars))
00791   {
00792     if (list->len+1 > list->max)
00793     {
00794       list->list = realloc(list->list, 2 * list->max * sizeof(list->list[0]));
00795       list->max = 2 * list->max;
00796     }
00797     if (port > UINT8_MAX || value > UINT16_MAX)
00798     {
00799       return -1;
00800     }
00801     list->list[list->len].port = port;
00802     list->list[list->len].value = value;
00803     list->len++;
00804     arg += chars;
00805   }
00806 
00807   if (nchars)
00808   {
00809     *nchars = (int)(arg - origarg);
00810   }
00811 
00812   return 0;
00813 }
00814 
00815 static void
00816 printU8List(TMR_String *string, TMR_uint8List *list)
00817 {
00818   int i;
00819   char *end;
00820 
00821   end = string->value;
00822   end += sprintf(string->value, "%c", '[');
00823   for (i = 0; i < list->len && i < list->max; i++)
00824   {
00825     end += sprintf(end, "%u%s", list->list[i], ((i + 1) == list->len) ? "" : ",");
00826   }
00827   if (list->len > list->max)
00828   {
00829     end += sprintf(end, "%s", "...");
00830   }
00831   end += sprintf(end, "%c", ']');
00832 }
00833 
00834 static void
00835 printU32List(TMR_String *string, TMR_uint32List *list)
00836 {
00837   int i;
00838   char *end;
00839 
00840   end = string->value;
00841   end += sprintf(string->value, "%c", '[');
00842   for (i = 0; i < list->len && i < list->max; i++)
00843   {
00844     end += sprintf(end, "%"PRIu32"%s", list->list[i], ((i + 1) == list->len) ? "" : ",");
00845   }
00846   if (list->len > list->max)
00847   {
00848     end += sprintf(end, "%s", "...");
00849   }
00850   end += sprintf(end, "%c", ']');
00851 }
00852 
00853 static void 
00854 printPortValueList(TMR_String *string, TMR_PortValueList *list)
00855 {
00856   int i;
00857   char *end;
00858 
00859   end = string->value;
00860   end += sprintf(string->value, "%c", '[');
00861   for (i = 0; i < list->len && i < list->max; i++)
00862   {
00863     end += sprintf(end, "[%u,%u]%s", list->list[i].port, list->list[i].value,
00864       ((i + 1) == list->len) ? "" : ",");
00865   }
00866   if (list->len > list->max)
00867   {
00868     end += sprintf(end, "%s", "...");
00869   }
00870   end += sprintf(end, "%c", ']');
00871 }
00872 
00873 static void 
00874 printFilter(TMR_String *string, TMR_TagFilter *filter)
00875 {
00876   char tmpStr[128];
00877   char *end;
00878 
00879   end = string->value;
00880   if (NULL == filter)
00881   {
00882     end += sprintf(end, "%s", ",Filter=null");
00883   }
00884   else if (TMR_FILTER_TYPE_TAG_DATA == filter->type)
00885   {
00886     TMR_bytesToHex(filter->u.tagData.epc, filter->u.tagData.epcByteCount, tmpStr);
00887     end += sprintf(end, ",Filter=TagData:[EPC=%s]", tmpStr);
00888   }
00889   else if (TMR_FILTER_TYPE_GEN2_SELECT == filter->type)
00890   {
00891     TMR_bytesToHex(filter->u.gen2Select.mask, (filter->u.gen2Select.maskBitLength + 7) / 8, tmpStr);
00892     end += sprintf(end, ",Filter=Gen2.Select:[Invert=%s,Bank=%s,BitPointer=%"PRIu32",BitLength=%d,Mask=%s]", 
00893       filter->u.gen2Select.invert ? "true" : "false",
00894       listname(bankNames, numberof(bankNames), filter->u.gen2Select.bank),
00895       filter->u.gen2Select.bitPointer,
00896       filter->u.gen2Select.maskBitLength,
00897       tmpStr);
00898   }
00899   else
00900   {
00901     end += sprintf(end, "%s", "Unknown");
00902   }
00903 }
00904 
00905 static void 
00906 printTagop(TMR_String *string, TMR_TagOp *tagop)
00907 {
00908   char *end;
00909 
00910   end = string->value;
00911   if (NULL == tagop)
00912   {
00913     end += sprintf(end, "%s", ",Op=null");
00914   }
00915   else
00916   {
00917     if (TMR_TAGOP_GEN2_READDATA == tagop->type)
00918     {
00919       end += sprintf(end, ",Op=ReadData:[Bank=%s,WordAddress=%d,Len=%d]",
00920         listname(bankNames, numberof(bankNames),tagop->u.gen2.u.readData.bank),
00921         tagop->u.gen2.u.readData.wordAddress,
00922         tagop->u.gen2.u.readData.len);
00923     }
00924     else
00925     {
00926       /* Currently supporting only read data tag op */
00927       end += sprintf(end, "%s", ",Op=null");
00928     }
00929   }
00930 }
00931 
00932 static int
00933 parseStats(char *string, TMR_Reader_StatsFlag *stats)
00934 {
00935   char *arg = NULL;
00936   
00937   *stats = TMR_READER_STATS_FLAG_NONE;
00938   arg = string;
00939 
00940   if (']' == *(arg + 1))
00941   {
00942     /* Empty string, return */
00943     return 0;
00944   }
00945 
00946   while(']' != *arg)
00947   {
00948     /* skip the leading '[' */
00949     arg++;
00950     if (0 == strncmp(arg, "NONE", 0x04))
00951     {
00952       *stats |= TMR_READER_STATS_FLAG_NONE;
00953       arg += 0x04;
00954     }
00955     else if(0 == strncmp(arg, "ALL", 0x03))
00956     {
00957       *stats |= TMR_READER_STATS_FLAG_ALL;
00958       arg += 0x03;
00959     }
00960     else if(0 == strncmp(arg, "RFONTIME", 0x08))
00961     {
00962       *stats |= TMR_READER_STATS_FLAG_RF_ON_TIME;
00963       arg += 0x08;
00964     }
00965     else if(0 == strncmp(arg, "NOISEFLOOR", 0x0A))
00966     {
00967       *stats |= TMR_READER_STATS_FLAG_NOISE_FLOOR_SEARCH_RX_TX_WITH_TX_ON;
00968       arg += 0x0A;
00969     }
00970     else if(0 == strncmp(arg, "FREQUENCY", 0x09))
00971     {
00972       *stats |= TMR_READER_STATS_FLAG_FREQUENCY;
00973       arg += 0x09;
00974     }
00975     else if(0 == strncmp(arg, "TEMPERATURE", 0x0B))
00976     {
00977       *stats |= TMR_READER_STATS_FLAG_TEMPERATURE;
00978       arg += 0x0B;
00979     }
00980     else if(0 == strncmp(arg, "ANTENNA", 0x07))
00981     {
00982       *stats |= TMR_READER_STATS_FLAG_ANTENNA_PORTS;
00983       arg += 0x07;
00984     }
00985     else if(0 == strncmp(arg, "PROTOCOL", 0x08))
00986     {
00987       *stats |= TMR_READER_STATS_FLAG_PROTOCOL;
00988       arg += 0x08;
00989     }
00990     else if(0 == strncmp(arg, "CONNECTEDANTENNAPORTS", 0x15))
00991     {
00992       *stats |= TMR_READER_STATS_FLAG_CONNECTED_ANTENNAS;
00993       arg += 0x15;
00994     }
00995     else
00996     {
00997       return -1;
00998     }
00999   }
01000   return 0; 
01001 }
01002 
01003 static int
01004 parseReadPlan(const char *arg, TMR_ReadPlan *plan, int *nchars)
01005 {
01006   TMR_Status ret;
01007   int charcount;
01008 
01009   if ((0 != strncmp(arg, "MultiReadPlan:", 0x0E)) &&
01010     (0 != strncmp(arg, "SimpleReadPlan:", 0x0F)))
01011   {
01012     return -1;
01013   }
01014 
01015   ret = TMR_SUCCESS;
01016   plan->weight = 1; /* Default value */
01017 
01018   if (0 == strncmp(arg, "MultiReadPlan:", 0x0E))
01019   {
01020     /* MultiReadPlan */
01021     const char *subString = NULL;
01022     TMR_ReadPlan *plans;
01023     int i, nplans;
01024     TMR_ReadPlan **planlist;
01025 
01026     subString = (arg + 0x0F);
01027     nplans = 2;
01028     plans = malloc(nplans * sizeof(plans[0]));
01029     i = 0x00;
01030     while (0 == strncmp(subString, "SimpleReadPlan:", 0x0F))
01031     {
01032       if (i == nplans)
01033       {
01034         nplans *= 2;
01035         plans = realloc(plans, nplans * sizeof(plans[0]));        
01036       }
01037       ret = parseReadPlan(subString, &plans[i], &charcount);
01038       subString++;
01039       if (ret == -1 || (',' != *(subString + charcount) && ']' != *(subString + charcount)))
01040       {
01041         free(plans);
01042         return -1;
01043       }
01044       subString += charcount;      
01045       subString++;
01046       i++;
01047     }
01048     nplans = i;
01049     planlist = malloc(nplans * sizeof(planlist[0]));
01050     for (i = 0; i < nplans ; i++)
01051     {
01052       planlist[i] = &plans[i];;
01053     }
01054     subString--;
01055     plan->type = TMR_READ_PLAN_TYPE_MULTI;
01056     plan->u.multi.planCount = nplans;
01057     plan->u.multi.plans = planlist;
01058   }
01059   else
01060   {
01061     /* SimpleReadPlan */
01062     const char *srpSubString = NULL;
01063     char protocolName[100];
01064     int tmp;   
01065 
01066     srpSubString = arg + 0x0F;
01067     plan->type = TMR_READ_PLAN_TYPE_SIMPLE;
01068 
01069     /* Initialize the simple read plan with default read pln */
01070     TMR_RP_init_simple(plan, 0, NULL,  TMR_TAG_PROTOCOL_GEN2, 1);
01071 
01072     /* skip the leading '[' */
01073     while (']' != *srpSubString)
01074     {
01075       srpSubString++;
01076       if (1 != sscanf(srpSubString, "%[^]=]%n", protocolName, &charcount))
01077       {
01078         return -1;
01079       }
01080 
01081       if (0x00 == strcmp("Antennas", protocolName))
01082       {
01083         srpSubString += charcount;
01084         /* skip the '=' symbol */
01085         srpSubString++;
01086         if (1 != sscanf(srpSubString, "%[^]]]%n", protocolName, &charcount))
01087         {
01088           /* there is no antenna value */
01089         }
01090         srpSubString += charcount;
01091         strcat(protocolName, "]");
01092         if (-1 == parseU8List(protocolName, &plan->u.simple.antennas, &charcount))
01093         {
01094           return -1;
01095         }
01096       }
01097       else if(0x00 == strcmp("Protocol", protocolName))
01098       {
01099         srpSubString += charcount;
01100         /* skip the '=' symbol */
01101         srpSubString++;
01102         if (1 != sscanf(srpSubString, "%[^],]%n", protocolName, &charcount))
01103         {
01104           return -1;
01105         }
01106         tmp = listid(protocolNames, numberof(protocolNames), protocolName);
01107         if (-1 == tmp)
01108         {
01109           return -1;
01110         }
01111         plan->u.simple.protocol = tmp;
01112         srpSubString += charcount;
01113       }
01114       else if (0x00 == strcmp("Filter", protocolName))
01115       {
01116         srpSubString += charcount;
01117         //*nchars += charcount;
01118         /* skip the '=' symbol */
01119         srpSubString++;
01120         if (1 != sscanf(srpSubString, "%[^]]]%n", protocolName, &charcount))
01121         {
01122           return -1;
01123         }
01124 
01125         if (0 != strncasecmp(srpSubString, "NULL", 4))
01126         {
01127           srpSubString += charcount;
01128         }
01129         strcat(protocolName, "]");
01130         if (-1 == parseFilter(protocolName, &plan->u.simple.filter, &charcount))
01131         {
01132           return -1;
01133         }
01134       }
01135       else if (0x00 == strcmp("Op", protocolName))
01136       {
01137         srpSubString += charcount;
01138         /* skip the '=' symbol */
01139         srpSubString++;
01140         if (1 != sscanf(srpSubString, "%[^]]]%n", protocolName, &charcount))
01141         {
01142           return -1;
01143         }
01144 
01145         if (0 != strncasecmp(srpSubString, "NULL", 4))
01146         {
01147           srpSubString += charcount;
01148         }
01149         strcat(protocolName, "]");
01150         if (-1 == parseTagop(protocolName, &plan->u.simple.tagop, &charcount))
01151         {
01152           return -1;
01153         }
01154       }
01155       else if (0x00 == strcmp("UseFastSearch", protocolName))
01156       {
01157         srpSubString += charcount;
01158         /* skip the '=' symbol */
01159         srpSubString++;
01160         if (1 != sscanf(srpSubString, "%[^],]%n", protocolName, &charcount))
01161         {
01162           return -1;
01163         }
01164         srpSubString += charcount;
01165         if (0 == strcmp(protocolName, "true"))
01166         {
01167           plan->u.simple.useFastSearch = true;
01168         }
01169         else
01170         {
01171           plan->u.simple.useFastSearch = false;
01172         }
01173       }
01174       else if(0x00 == strcmp("Weight", protocolName))
01175       {
01176         srpSubString += charcount;
01177         /* skip the '=' symbol */
01178         srpSubString++;
01179         if (1 != sscanf(srpSubString, "%[^]]%n", protocolName, &charcount))
01180         {
01181           return -1;
01182         }
01183         srpSubString += charcount;
01184         sscanf(protocolName, "%"SCNi32"%n", &plan->weight, &charcount);
01185       }
01186     }
01187     if (nchars)
01188     {
01189       *nchars = (int)(srpSubString - arg);
01190     }    
01191   }
01192  
01193   return 0;
01194 }
01195 
01196 static void
01197 printReadPlan(const char *string, TMR_ReadPlan *plan, int *nchars)
01198 {
01199   TMR_String temp;
01200   char str[100];
01201   char *end;
01202   int charRead;
01203 
01204   end = (char *)string;
01205   temp.max = numberof(str);
01206   temp.value = str;
01207   if (TMR_READ_PLAN_TYPE_MULTI == plan->type)
01208   {
01209     int i;
01210     end += sprintf(end, "%s", "MultiReadPlan:[");
01211     for (i = 0 ; i < plan->u.multi.planCount; i++)
01212     {
01213       printReadPlan(end, plan->u.multi.plans[i], &charRead);
01214       end += charRead;
01215       if (i + 1 !=  plan->u.multi.planCount)
01216       {
01217         end += sprintf(end, "%c", ',');
01218       }
01219     }
01220     end += sprintf(end, "%c", ']');
01221   }
01222   else
01223   {
01224     end += sprintf(end, "%s", "SimpleReadPlan:[");
01225     end += sprintf(end, "%s", "Antennas=");
01226     printU8List(&temp, &plan->u.simple.antennas);
01227     end += sprintf(end, "%s", temp.value);
01228     end += sprintf(end, "%s%s", ",Protocol=", listname(protocolNames, numberof(protocolNames), plan->u.simple.protocol));
01229     printFilter(&temp, plan->u.simple.filter);
01230     end += sprintf(end, "%s", temp.value);
01231     printTagop(&temp, plan->u.simple.tagop);
01232     end += sprintf(end, "%s", temp.value);
01233     end += sprintf(end, "%s%s", ",UseFastSearch=", plan->u.simple.useFastSearch ? "true" : "false");
01234     end += sprintf(end, "%s%"PRIu32"]", ",Weight=", plan->weight);
01235     if (nchars)
01236     {
01237       *nchars = (int)(end - string);
01238     }
01239   }
01240 }
01241 
01242 static void
01243 printReaderStats(const char *string, TMR_Reader_StatsFlag *stats)
01244 {
01245   char *end;
01246 
01247   end = (char *)string;
01248 
01249   end += sprintf(end, "%s", "[");
01250   switch (*stats)
01251   {
01252   case TMR_READER_STATS_FLAG_NONE:
01253     end += sprintf(end, "%s", "NONE,");
01254     break;
01255   
01256   case TMR_READER_STATS_FLAG_ALL:
01257     end += sprintf(end, "%s", "ALL,");
01258     break;
01259   
01260   default:
01261     {
01262       if (TMR_READER_STATS_FLAG_ANTENNA_PORTS & (*stats))
01263       {
01264         end += sprintf(end, "%s", "ANTENNA,");
01265       }
01266       if(TMR_READER_STATS_FLAG_CONNECTED_ANTENNAS & (*stats))
01267       {
01268         end += sprintf(end, "%s", "CONNECTEDANTENNAPORTS,");
01269       }
01270       if(TMR_READER_STATS_FLAG_FREQUENCY & (*stats))
01271       {
01272         end += sprintf(end, "%s", "FREQUENCY,");
01273       }
01274       if(TMR_READER_STATS_FLAG_NOISE_FLOOR_SEARCH_RX_TX_WITH_TX_ON & (*stats))
01275       {
01276         end += sprintf(end, "%s", "NOISEFLOOR,");
01277       }
01278       if(TMR_READER_STATS_FLAG_PROTOCOL & (*stats))
01279       {
01280         end += sprintf(end, "%s", "PROTOCOL,");
01281       }
01282       if(TMR_READER_STATS_FLAG_RF_ON_TIME & (*stats))
01283       {
01284         end += sprintf(end, "%s", "RFONTIME,");
01285       }
01286       if(TMR_READER_STATS_FLAG_TEMPERATURE & (*stats))
01287       {
01288         end += sprintf(end, "%s", "TEMPERATURE,");
01289       }
01290       break;
01291     }
01292   }
01293   end += sprintf((end -1), "%s", "]");
01294 }
01295 
01296 static TMR_Status
01297 getSetOneParam(struct TMR_Reader *reader, const char *paramName, TMR_String *string, paramOption option)
01298 {
01299   TMR_Status ret;
01300   TMR_Param param;
01301   TMR_String temp;
01302   char str[CONFIG_MAX_BUFFER_LEN];
01303   char *end;
01304 
01305   ret = TMR_SUCCESS;
01306   end = string->value;
01307   temp.max = CONFIG_MAX_BUFFER_LEN;
01308   temp.value = str;
01309 
01310   param = TMR_paramID(paramName);
01311   if (PARAM_OPTION_GET == option)
01312   {
01313     end += sprintf(end, "%s", paramName);
01314     end += sprintf(end, "%c", '=');
01315   }
01316   switch(param)
01317   {
01318   case TMR_PARAM_ANTENNA_PORTSWITCHGPOS:
01319   case TMR_PARAM_GPIO_INPUTLIST:
01320   case TMR_PARAM_GPIO_OUTPUTLIST:
01321   case TMR_PARAM_TRIGGER_READ_GPI:
01322     {
01323       if (PARAM_OPTION_GET == option)
01324       {
01325         /* The param get */
01326         TMR_uint8List value;
01327         uint8_t valueList[64];
01328 
01329         value.max = numberof(valueList);
01330         value.list = valueList;
01331 
01332         ret = TMR_paramGet(reader, param, &value);
01333         if (TMR_SUCCESS == ret)
01334         {
01335           printU8List(&temp, &value);
01336           end += sprintf(end, "%s", temp.value);
01337         }
01338       }
01339       else
01340       {
01341         /* The param set */
01342         TMR_uint8List value;
01343 
01344         if (-1 == parseU8List(end, &value, NULL))
01345         {
01346           char errMsg[256];
01347           sprintf(errMsg, "Can't parse '%s' as list of 8-bit values", end);
01348           logErrorMessage(reader, errMsg);
01349           notify_exception_listeners(reader, TMR_ERROR_LOADSAVE_CONFIG);
01350           return TMR_ERROR_INVALID;
01351         }
01352         ret = TMR_paramSet(reader, param, &value);
01353         free(value.list);
01354       }
01355       break;
01356     }
01357   case TMR_PARAM_BAUDRATE:
01358   case TMR_PARAM_COMMANDTIMEOUT:
01359   case TMR_PARAM_TRANSPORTTIMEOUT:
01360   case TMR_PARAM_READ_ASYNCOFFTIME:
01361   case TMR_PARAM_READ_ASYNCONTIME:
01362   case TMR_PARAM_REGION_HOPTIME:
01363     {
01364       if (PARAM_OPTION_GET == option)
01365       {
01366         /* The param get */
01367         uint32_t value;
01368         ret = TMR_paramGet(reader, param, &value);
01369         if (TMR_SUCCESS == ret)
01370         {
01371           end += sprintf(end, "%u", value);
01372         }
01373       }
01374       else
01375       {
01376         /* The param set */
01377         uint32_t value;
01378         int scans;
01379         scans = sscanf(end, "%"SCNi32, &value);
01380         if (1 != scans)
01381         {
01382           char errMsg[256];
01383           sprintf(errMsg, "Can't parse '%s' as a 32-bit hex value", end);
01384           logErrorMessage(reader, errMsg);
01385           notify_exception_listeners(reader, TMR_ERROR_LOADSAVE_CONFIG);
01386           return TMR_ERROR_INVALID;
01387         }
01388         ret = TMR_paramSet(reader, param, &value);
01389       }
01390       break;
01391     }
01392   case TMR_PARAM_ANTENNA_CHECKPORT:
01393   case TMR_PARAM_TAGREADDATA_RECORDHIGHESTRSSI:
01394   case TMR_PARAM_TAGREADDATA_UNIQUEBYANTENNA:
01395   case TMR_PARAM_TAGREADDATA_UNIQUEBYDATA:
01396   case TMR_PARAM_TAGREADDATA_REPORTRSSIINDBM:
01397   case TMR_PARAM_STATUS_ENABLE_ANTENNAREPORT:
01398   case TMR_PARAM_STATUS_ENABLE_FREQUENCYREPORT:
01399   case TMR_PARAM_STATUS_ENABLE_TEMPERATUREREPORT:
01400   case TMR_PARAM_TAGREADDATA_UNIQUEBYPROTOCOL:
01401   case TMR_PARAM_TAGREADDATA_ENABLEREADFILTER:
01402     {
01403       if (PARAM_OPTION_GET == option)
01404       {
01405         /* The param get */
01406         bool value;
01407         ret = TMR_paramGet(reader, param, &value);
01408         if (TMR_SUCCESS == ret)
01409         {
01410           end += sprintf(end, "%s", value ? "true" : "false");
01411         }
01412       }
01413       else
01414       {
01415         /* The param set */
01416         bool value;
01417         if (0 == strcasecmp(end, "true"))
01418         {
01419           value = true;
01420         }
01421         else if (0 == strcasecmp(end, "false"))
01422         {
01423           value = false;
01424         }
01425         else
01426         {
01427           char errMsg[256];
01428           sprintf(errMsg, "Can't parse '%s' as boolean value", end);
01429           logErrorMessage(reader, errMsg);
01430           notify_exception_listeners(reader, TMR_ERROR_LOADSAVE_CONFIG);
01431           return TMR_ERROR_INVALID;
01432         }
01433         ret = TMR_paramSet(reader, param, &value);
01434       }
01435       break;
01436     }
01437   case TMR_PARAM_GEN2_ACCESSPASSWORD:
01438     {
01439       if (PARAM_OPTION_GET == option)
01440       {
01441         /* The param get */
01442         TMR_GEN2_Password value;
01443         ret = TMR_paramGet(reader, param, &value);
01444         if (TMR_SUCCESS == ret)
01445         {
01446           end += sprintf(end, "%x", value);
01447         }        
01448       }
01449       else
01450       {
01451         /* The param set */
01452         TMR_GEN2_Password value;
01453         int scans;
01454 
01455         scans = sscanf(end, "%"SCNx32, &value);
01456         if (1 != scans)
01457         {
01458           char errMsg[256];
01459           sprintf(errMsg, "Can't parse '%s' as a 32-bit hex value", end);
01460           logErrorMessage(reader, errMsg);
01461           notify_exception_listeners(reader, TMR_ERROR_LOADSAVE_CONFIG);
01462           return TMR_ERROR_INVALID;
01463         }
01464         ret = TMR_paramSet(reader, param, &value);
01465       }
01466       break;
01467     }
01468   case TMR_PARAM_GEN2_TARI:
01469     {
01470       if (PARAM_OPTION_GET == option)
01471       {
01472         /* The param get */
01473         TMR_GEN2_Tari value;
01474         
01475         ret = TMR_paramGet(reader, param, &value);
01476         if (TMR_SUCCESS == ret)
01477         {
01478           end += sprintf(end, "%s", listname(tariNames, numberof(tariNames), value));
01479         }
01480       }
01481       else
01482       {
01483         TMR_GEN2_Tari value;
01484         int i;
01485 
01486         i = listid(tariNames, numberof(tariNames), end);
01487         if (i == -1)
01488         {
01489           char errMsg[256];
01490           sprintf(errMsg, "Can't parse '%s' as a Gen2 Tari value", end);
01491           logErrorMessage(reader, errMsg);
01492           notify_exception_listeners(reader, TMR_ERROR_LOADSAVE_CONFIG);
01493           return TMR_ERROR_INVALID;
01494         }
01495         value = i;
01496         ret = TMR_paramSet(reader, param, &value);
01497       }
01498       break;
01499     }
01500   case TMR_PARAM_GEN2_PROTOCOLEXTENSION:
01501     {
01502       if (PARAM_OPTION_GET == option)
01503       {
01504         /* The param get */
01505         TMR_GEN2_ProtocolExtension value;
01506         
01507         ret = TMR_paramGet(reader, param, &value);
01508         if (TMR_SUCCESS == ret)
01509         {
01510           end += sprintf(end, "%s", listname(gen2ProtocolExtensionNames, numberof(gen2ProtocolExtensionNames), value));
01511         }
01512       }
01513       else
01514       {
01515         TMR_GEN2_ProtocolExtension value;
01516         int i;
01517 
01518         i = listid(gen2ProtocolExtensionNames, numberof(gen2ProtocolExtensionNames), end);
01519         if (i == -1)
01520         {
01521           char errMsg[256];
01522           sprintf(errMsg, "Can't parse '%s' as a Gen2 Protocol Extension value", end);
01523           logErrorMessage(reader, errMsg);
01524           notify_exception_listeners(reader, TMR_ERROR_LOADSAVE_CONFIG);
01525           return TMR_ERROR_INVALID;
01526         }
01527         value = i;
01528         ret = TMR_paramSet(reader, param, &value);
01529       }
01530       break;
01531     }
01532   case TMR_PARAM_GEN2_TAGENCODING:
01533     {
01534       if (PARAM_OPTION_GET == option)
01535       {
01536         /* The param get */
01537         TMR_GEN2_TagEncoding value;
01538 
01539         ret = TMR_paramGet(reader, param, &value);
01540         if (TMR_SUCCESS == ret)
01541         {
01542           end += sprintf(end, "%s", listname(tagEncodingNames, numberof(tagEncodingNames), value));
01543         }
01544       }
01545       else
01546       {
01547         /* The param set */
01548         TMR_GEN2_TagEncoding value;
01549         int i;
01550 
01551         i = listid(tagEncodingNames, numberof(tagEncodingNames), end);
01552         if (i == -1)
01553         {
01554           char errMsg[256];
01555           sprintf(errMsg, "Can't parse '%s' as a Gen2 Miller M value", end);
01556           logErrorMessage(reader, errMsg);
01557           notify_exception_listeners(reader, TMR_ERROR_LOADSAVE_CONFIG);
01558           return TMR_ERROR_INVALID;
01559         }
01560         value = i;
01561         ret = TMR_paramSet(reader, param, &value);
01562       }
01563       break;
01564     }
01565   case TMR_PARAM_GEN2_SESSION:
01566     {
01567       if (PARAM_OPTION_GET == option)
01568       {
01569         /* The param get */
01570         TMR_GEN2_Session value;
01571 
01572         ret = TMR_paramGet(reader, param, &value);
01573         if (TMR_SUCCESS == ret)
01574         {
01575           end += sprintf(end, "%s", listname(sessionNames, numberof(sessionNames), value));
01576         }
01577       }
01578       else
01579       {
01580         /* The param set */
01581         TMR_GEN2_Session value;
01582         int i;
01583 
01584         i = listid(sessionNames, numberof(sessionNames), end);
01585         if (i == -1)
01586         {
01587           char errMsg[256];
01588           sprintf(errMsg, "Can't parse '%s' as a Gen2 session name", end);
01589           logErrorMessage(reader, errMsg);
01590           notify_exception_listeners(reader, TMR_ERROR_LOADSAVE_CONFIG);
01591           return TMR_ERROR_INVALID;
01592         }
01593         value = i;
01594         ret = TMR_paramSet(reader, param, &value);
01595       }
01596       break;
01597     }
01598   case TMR_PARAM_GEN2_TARGET:
01599     {
01600       if (PARAM_OPTION_GET == option)
01601       {
01602         /* The param get */
01603         TMR_GEN2_Target value;
01604 
01605         ret = TMR_paramGet(reader, param, &value);
01606         if (TMR_SUCCESS == ret)
01607         {
01608           end += sprintf(end, "%s", listname(targetNames, numberof(targetNames), value));
01609         }
01610       }
01611       else
01612       {
01613         /* The param set */
01614         TMR_GEN2_Target value;
01615         int i;
01616 
01617         i = listid(targetNames, numberof(targetNames), end);
01618         if (i == -1)
01619         {
01620           char errMsg[256];
01621           sprintf(errMsg, "Can't parse '%s' as a Gen2 target name", end);
01622           logErrorMessage(reader, errMsg);
01623           notify_exception_listeners(reader, TMR_ERROR_LOADSAVE_CONFIG);
01624           return TMR_ERROR_INVALID;
01625         }
01626         value = i;
01627         ret = TMR_paramSet(reader, param, &value);
01628       }
01629       break;
01630     }
01631   case TMR_PARAM_GEN2_Q:
01632     {
01633       if (PARAM_OPTION_GET == option)
01634       {
01635         /* The param get */
01636         TMR_SR_GEN2_Q value;
01637 
01638         ret = TMR_paramGet(reader, param, &value);
01639         if (TMR_SUCCESS == ret)
01640         {
01641           if (value.type == TMR_SR_GEN2_Q_DYNAMIC)
01642           {
01643             end += sprintf(end, "%s", "DynamicQ");
01644           }
01645           else if (value.type == TMR_SR_GEN2_Q_STATIC)
01646           {
01647             end += sprintf(end, "StaticQ(%d)", value.u.staticQ.initialQ);
01648           }
01649         }
01650       }
01651       else
01652       {
01653         /* The param set */
01654         TMR_SR_GEN2_Q value;
01655         int initialQ;
01656 
01657         if (0 == strcasecmp("DynamicQ", end))
01658         {
01659           value.type = TMR_SR_GEN2_Q_DYNAMIC;
01660         }
01661         else if (0 == strncasecmp("StaticQ(", end, 8) 
01662           && 1 == sscanf(end+8, "%i", &initialQ)
01663           && initialQ >= 0
01664           && initialQ <= UINT8_MAX)
01665         {
01666           value.type = TMR_SR_GEN2_Q_STATIC;
01667           value.u.staticQ.initialQ = initialQ;
01668         }
01669         else  
01670         {
01671           char errMsg[256];
01672           sprintf(errMsg, "Can't parse '%s' as a Q algorithm", end);
01673           logErrorMessage(reader, errMsg);
01674           notify_exception_listeners(reader, TMR_ERROR_LOADSAVE_CONFIG);
01675           return TMR_ERROR_INVALID;
01676         }
01677         ret = TMR_paramSet(reader, param, &value);
01678       }
01679       break;
01680     }
01681   case TMR_PARAM_GEN2_BLF:
01682     {
01683       if (PARAM_OPTION_GET == option)
01684       {
01685         /* The param get */
01686         TMR_GEN2_LinkFrequency value;
01687 
01688         ret = TMR_paramGet(reader, param, &value);
01689         if (TMR_SUCCESS == ret)
01690         {
01691           int temp = value;
01692           switch(temp)
01693           {
01694             case 250:
01695               value = 0;
01696               break;
01697             case 640:
01698               value = 4;
01699               break;
01700             case 320:
01701               value = 2;
01702               break;
01703             default:;
01704           }
01705           end += sprintf(end, "%s", listname(gen2LinkFrequencyNames, numberof(gen2LinkFrequencyNames), value));
01706         }
01707       }
01708       else
01709       {
01710         /* The param set */
01711         TMR_GEN2_LinkFrequency lf;
01712         TMR_String model;
01713         char str[64];
01714         model.value = str;
01715         model.max = 64;
01716 
01717         lf = listid(gen2LinkFrequencyNames, 
01718           numberof(gen2LinkFrequencyNames),
01719           end);
01720         TMR_paramGet(reader, TMR_PARAM_VERSION_MODEL, &model);
01721         {
01722           int temp = lf;
01723           switch (temp)
01724           {
01725           case 0: lf = 250;
01726             break;
01727           case 2: lf = 320;
01728             break;
01729           case 4: lf = 640;
01730             break;
01731           default:;
01732           }
01733         }
01734 
01735         if (lf == -1)
01736         {
01737           char errMsg[256];
01738           sprintf(errMsg, "Can't parse '%s' as a Gen2 link frequency", end);
01739           logErrorMessage(reader, errMsg);
01740           notify_exception_listeners(reader, TMR_ERROR_LOADSAVE_CONFIG);
01741           return TMR_ERROR_INVALID;
01742         }
01743         ret = TMR_paramSet(reader, param, &lf);
01744       }
01745       break;
01746     }
01747   case TMR_PARAM_RADIO_READPOWER:
01748   case TMR_PARAM_RADIO_WRITEPOWER:
01749   case TMR_PARAM_TAGREADDATA_READFILTERTIMEOUT:
01750     {
01751       if (PARAM_OPTION_GET == option)
01752       {
01753         /* The param get */
01754         int32_t value;
01755         ret = TMR_paramGet(reader, param, &value);
01756         if (TMR_SUCCESS == ret)
01757         {
01758           end += sprintf(end, "%d", value);
01759         }        
01760       }
01761       else
01762       {
01763         /* The param set */
01764         int32_t value;
01765         int scans;
01766 
01767         scans = sscanf(end, "%"SCNi32, &value);
01768         if (1 != scans)
01769         {
01770           char errMsg[256];
01771           sprintf(errMsg, "Can't parse '%s' as a 32bit-bit signed integer value", end);
01772           logErrorMessage(reader, errMsg);
01773           notify_exception_listeners(reader, TMR_ERROR_LOADSAVE_CONFIG);
01774           return TMR_ERROR_INVALID;
01775         }
01776         ret = TMR_paramSet(reader, param, &value);
01777       }
01778       break;
01779     }
01780   case TMR_PARAM_PROBEBAUDRATES:
01781     {
01782       if (PARAM_OPTION_GET == option)
01783       {
01784         /* The param get */
01785         TMR_uint32List value;
01786         uint32_t valueList[64];
01787 
01788         value.max = numberof(valueList);
01789         value.list = valueList;
01790 
01791         ret = TMR_paramGet(reader, param, &value);
01792         if (TMR_SUCCESS == ret)
01793         {
01794           printU32List(&temp, &value);
01795           end += sprintf(end, "%s", temp.value);
01796         }
01797       }
01798       else
01799       {
01800         /* The param set */
01801         TMR_uint32List value;
01802 
01803         if (-1 == parseU32List(end, &value, NULL))
01804         {
01805           char errMsg[256];
01806           sprintf(errMsg, "Can't parse '%s' as list of 32-bit values", end);
01807           logErrorMessage(reader, errMsg);
01808           notify_exception_listeners(reader, TMR_ERROR_LOADSAVE_CONFIG);
01809           return TMR_ERROR_INVALID;
01810         }
01811         ret = TMR_paramSet(reader, param, &value);
01812         free(value.list);
01813       }
01814       break;
01815     }
01816   case TMR_PARAM_REGION_HOPTABLE:
01817     {
01818       if (PARAM_OPTION_GET == option)
01819       {
01820         /* The param get */
01821         TMR_uint32List value;
01822         uint32_t valueList[64];
01823 
01824         value.max = numberof(valueList);
01825         value.list = valueList;
01826 
01827         ret = TMR_paramGet(reader, param, &value);
01828         if (TMR_SUCCESS == ret)
01829         {
01830           printU32List(&temp, &value);
01831           end += sprintf(end, "%s", temp.value);
01832         }
01833       }
01834       else
01835       {
01836         /* The param set */
01837         TMR_uint32List value;
01838 
01839         if (-1 == parseU32List(end, &value, NULL))
01840         {
01841           char errMsg[256];
01842           sprintf(errMsg, "Can't parse '%s' as list of 32-bit values", end);
01843           logErrorMessage(reader, errMsg);
01844           notify_exception_listeners(reader, TMR_ERROR_LOADSAVE_CONFIG);
01845           return TMR_ERROR_INVALID;
01846         }
01847         ret = TMR_paramSet(reader, param, &value);
01848         free(value.list);
01849       }
01850       break;
01851     }
01852   case TMR_PARAM_ANTENNA_TXRXMAP:
01853     {
01854       if (PARAM_OPTION_GET == option)
01855       {
01856         /* The param get */
01857         TMR_AntennaMapList value;
01858         TMR_AntennaMap valueList[64];
01859         int i;
01860 
01861         value.max = numberof(valueList);
01862         value.list = valueList;
01863 
01864         ret = TMR_paramGet(reader, param, &value);
01865         if (TMR_SUCCESS == ret)
01866         {
01867           end += sprintf(end, "%c", '[');
01868           for (i = 0; i < value.len && i < value.max; i++)
01869           {
01870             end += sprintf(end, "[%d,%d,%d]%s", value.list[i].antenna, value.list[i].txPort,
01871               value.list[i].rxPort,((i + 1) == value.len) ? "" : ",");
01872           }
01873           if (value.len > value.max)
01874           {
01875             end += sprintf(end, "%s", "...");
01876           }
01877           end += sprintf(end, "%c", ']');
01878         }
01879       }
01880       else
01881       {
01882         /* The param set */
01883         TMR_AntennaMapList list;
01884         char *arg;
01885         int chars, v1, v2, v3;
01886 
01887         arg = end;
01888         if ('[' != arg[0]
01889         || ']' != arg[strlen(arg)-1])
01890         {
01891           char errMsg[256];
01892           sprintf(errMsg, "Can't parse '%s' as list of antenna map entries", end);
01893           logErrorMessage(reader, errMsg);
01894           notify_exception_listeners(reader, TMR_ERROR_LOADSAVE_CONFIG);
01895           return TMR_ERROR_INVALID;
01896         }
01897         arg++;
01898         list.len = 0;
01899         list.max = 4;
01900         list.list = malloc(sizeof(list.list[0]) * list.max);
01901 
01902         while (3 == sscanf(arg, "[%i,%i,%i]%*[],]%n", &v1, &v2, &v3,
01903           &chars))
01904         {
01905           if (list.len + 1 > list.max)
01906           {
01907             list.list = realloc(list.list, 2 * list.max * sizeof(list.list[0]));
01908             list.max = 2 * list.max;
01909           }
01910           list.list[list.len].antenna = v1;
01911           list.list[list.len].txPort = v2;
01912           list.list[list.len].rxPort = v3;
01913 
01914           list.len++;
01915           arg += chars;
01916         }
01917 
01918         ret = TMR_paramSet(reader, param, &list);
01919         free(list.list);
01920       }
01921       break;
01922     }
01923   case TMR_PARAM_ANTENNA_SETTLINGTIMELIST:
01924   case TMR_PARAM_RADIO_PORTREADPOWERLIST:
01925   case TMR_PARAM_RADIO_PORTWRITEPOWERLIST:
01926     {
01927       if (PARAM_OPTION_GET == option)
01928       {
01929         /* The param get */
01930         TMR_PortValueList value;
01931         TMR_PortValue valueList[64];
01932 
01933         value.max = numberof(valueList);
01934         value.list = valueList;
01935 
01936         ret = TMR_paramGet(reader, param, &value);
01937         if (TMR_SUCCESS == ret)
01938         {
01939           printPortValueList(&temp, &value);
01940           end += sprintf(end, "%s", temp.value);
01941         }
01942       }
01943       else
01944       {
01945         /* The param set */
01946         TMR_PortValueList value;
01947 
01948         if (-1 == parsePortValueList(end, &value, NULL))
01949         {
01950           char errMsg[256];
01951           sprintf(errMsg, "Can't parse '%s' as a list of ports and values", end);
01952           logErrorMessage(reader, errMsg);
01953           notify_exception_listeners(reader, TMR_ERROR_LOADSAVE_CONFIG);
01954           return TMR_ERROR_INVALID;
01955         }
01956         ret = TMR_paramSet(reader, param, &value);
01957         free(value.list);
01958       }
01959       break;
01960     }
01961   case TMR_PARAM_REGION_ID:
01962     {
01963       if (PARAM_OPTION_GET == option)
01964       {
01965         /* The param get */
01966         TMR_Region region;
01967 
01968         ret = TMR_paramGet(reader, param, &region);
01969         if (TMR_SUCCESS == ret)
01970         {
01971           end += sprintf(end, "%s", regionName(region));
01972         }
01973       }
01974       else
01975       {
01976         /* The param set */
01977         TMR_Region region;
01978 
01979         region = regionID(end);
01980         if (TMR_REGION_NONE == region)
01981         {
01982           char errMsg[256];
01983           sprintf(errMsg, "Can't parse '%s' as a region name", end);
01984           logErrorMessage(reader, errMsg);
01985           notify_exception_listeners(reader, TMR_ERROR_LOADSAVE_CONFIG);
01986           return TMR_ERROR_INVALID;
01987         }
01988         ret = TMR_paramSet(reader, param, &region);
01989       }
01990       break;
01991     }
01992   case TMR_PARAM_POWERMODE:
01993     {
01994       if (PARAM_OPTION_GET == option)
01995       {
01996         /* The param get */
01997         TMR_SR_PowerMode mode;
01998 
01999         ret = TMR_paramGet(reader, param, &mode);
02000         if (TMR_SUCCESS == ret)
02001         {
02002           end += sprintf(end, "%s", listname(powerModes, numberof(powerModes), mode));
02003         }        
02004       }
02005       else
02006       {
02007         /* The param set */
02008         TMR_SR_PowerMode mode;
02009         int i;
02010 
02011         i = listid(powerModes, numberof(powerModes), end);
02012         if (i == -1)
02013         {
02014           char errMsg[256];
02015           sprintf(errMsg, "Can't parse '%s' as a power mode", end);
02016           logErrorMessage(reader, errMsg);
02017           notify_exception_listeners(reader, TMR_ERROR_LOADSAVE_CONFIG);
02018           return TMR_ERROR_INVALID;
02019         }
02020         mode = i;
02021         ret = TMR_paramSet(reader, param, &mode);
02022       }
02023       break;
02024     }
02025   case TMR_PARAM_TAGOP_PROTOCOL:
02026     {
02027       if (PARAM_OPTION_GET == option)
02028       {
02029         /* The param get */
02030         TMR_TagProtocol value;
02031         ret = TMR_paramGet(reader, param, &value);
02032         if (TMR_SUCCESS == ret)
02033         {
02034           end += sprintf(end, "%s", listname(protocolNames, numberof(protocolNames), value));
02035         }
02036       }
02037       else
02038       {
02039         /* The param set */
02040         TMR_TagProtocol value;
02041         int i;
02042 
02043         i = listid(protocolNames, numberof(protocolNames), end);
02044         if (i == -1)
02045         {
02046           char errMsg[256];
02047           sprintf(errMsg, "Can't parse '%s' as a protocol name", end);
02048           logErrorMessage(reader, errMsg);
02049           notify_exception_listeners(reader, TMR_ERROR_LOADSAVE_CONFIG);
02050           return TMR_ERROR_INVALID;
02051         }
02052         value = i;
02053         ret = TMR_paramSet(reader, param, &value);
02054       }
02055       break;
02056     }
02057   case TMR_PARAM_READ_PLAN:
02058     {
02059       if (PARAM_OPTION_GET == option)
02060       {        
02061         /* The param get */
02062         TMR_ReadPlan value;
02063         ret = TMR_paramGet(reader, param, &value);
02064         if (TMR_SUCCESS == ret)
02065         {
02066           printReadPlan(temp.value, &value, NULL);
02067           end += sprintf(end, "%s", temp.value);
02068         }
02069       }
02070       else
02071       {
02072         /* The param set */
02073         TMR_ReadPlan value;
02074 
02075         if (-1 == parseReadPlan(end, &value, NULL))
02076         {
02077           char errMsg[256];
02078           sprintf(errMsg, "Can't parse '%s' as a read plan", end);
02079           logErrorMessage(reader, errMsg);
02080           notify_exception_listeners(reader, TMR_ERROR_LOADSAVE_CONFIG);
02081           return TMR_ERROR_INVALID;
02082         }
02083         ret = TMR_paramSet(reader, param, &value);
02084       }
02085       break;
02086     }
02087   case TMR_PARAM_READER_STATS_ENABLE:
02088     {
02089       if (PARAM_OPTION_GET == option)
02090       {
02091         /* The param get */
02092         TMR_Reader_StatsFlag value;
02093         ret = TMR_paramGet(reader, param, &value);
02094         if (TMR_SUCCESS == ret)
02095         {
02096           printReaderStats(temp.value, &value);
02097           end += sprintf(end, "%s", temp.value);
02098         }
02099       }
02100       else
02101       {
02102         /* The param set */
02103         TMR_Reader_StatsFlag value;
02104         if (-1 == parseStats(end, &value))
02105         {
02106           char errMsg[256];
02107           sprintf(errMsg, "Can't parse '%s' as stats flag", end);
02108           logErrorMessage(reader, errMsg);
02109           notify_exception_listeners(reader, TMR_ERROR_LOADSAVE_CONFIG);
02110           return TMR_ERROR_INVALID;
02111         }
02112         ret = TMR_paramSet(reader, param, &value);
02113       }
02114       break;
02115     }
02116 
02117   default:
02118     break;
02119   }  
02120   return ret;
02121 }
02122 
02123 static TMR_Status
02124 rollBackConfigData(struct TMR_Reader *reader, char *filePath)
02125 {
02126   TMR_Status ret;
02127   FILE* fp = NULL;
02128   char temp[CONFIG_MAX_BUFFER_LEN];
02129   properties dict[CONFIG_MAX_PARAMETERS_LEN];
02130   uint8_t noOfEntries = 0x00;
02131 
02132   ret = TMR_SUCCESS;
02133   if (NULL == filePath)
02134   {
02135     sprintf(reader->u.serialReader.errMsg, "File path is Empty");
02136     return TMR_ERROR_TRYAGAIN;
02137   }
02138 
02139   fp = fopen(filePath, "r");
02140   if (NULL == fp)
02141   {
02142     sprintf(reader->u.serialReader.errMsg, "Error: Unable to open the configuration properties file");
02143     return TMR_ERROR_TRYAGAIN;
02144   }
02145   
02146   /* read the config parameters from the file and store in key value pair */
02147   do
02148   {
02149     memset(temp, 0, sizeof(temp)/sizeof(temp[0]));
02150     ret = readLine(fp, temp);
02151     if (TMR_SUCCESS == ret)
02152     {
02153       if (
02154         (0x00 != strlen(temp)) && (';' != temp[0]) && ('#' != temp[0]) && ('*' != temp[0])
02155         && (('/' == temp[0]) && ('/' != temp[1]))
02156         )
02157       {
02158         char *token;
02159         token = strtok(temp, "=");
02160         if (NULL != token)
02161         {
02162           /* copy the key field */
02163           strcpy(dict[noOfEntries].keyConfig, token);
02164           /* copy the value field */
02165           token = strtok(NULL, "=");
02166           while (NULL != token)
02167           {
02168             /* walk through other tokens */
02169             strcat(dict[noOfEntries].valueConfig, token);
02170             token = strtok(NULL, "=");
02171             if (token)
02172             {
02173               strcat(dict[noOfEntries].valueConfig, "=");
02174             }
02175           }          
02176           noOfEntries++;
02177         }
02178         else
02179         {
02180           /* there is no '=' in the line, skip it and move on to next line */
02181           continue;
02182         }
02183       }
02184     }
02185   }while((TMR_SUCCESS == ret) && (CONFIG_MAX_PARAMETERS_LEN > noOfEntries));
02186 
02187   if (!noOfEntries)
02188   {
02189     sprintf(reader->u.serialReader.errMsg, "No valid parameter line found");
02190     ret = TMR_ERROR_INVALID;
02191   }
02192   else if(CONFIG_MAX_PARAMETERS_LEN == noOfEntries)
02193   {
02194     sprintf(reader->u.serialReader.errMsg, "No having sufficent memory to hold all the parameters");
02195     ret = TMR_ERROR_OUT_OF_MEMORY;
02196   }
02197   else
02198   {
02199     /* at least we have some parameters to process, process them now */
02200     ret = TMR_SUCCESS;
02201   }
02202 
02203   if (TMR_SUCCESS == ret)
02204   {
02205     /* Load the configurations to the module */
02206     ret = loadConfiguration(reader, filePath, dict, noOfEntries, false);
02207   }
02208   return ret;
02209 }
02210 
02211 
02212 static TMR_Status 
02213 loadConfiguration(struct TMR_Reader *reader, char *filePath, properties *dict, uint8_t noOfEntries, bool isRollBack)
02214 {
02215   TMR_Status ret;
02216   FILE *fp = NULL;
02217   char tempFilePath[200];
02218   char timeStr[100];
02219   char *end;
02220   TMR_TimeStructure time;
02221   int i;
02222 
02223   ret = TMR_SUCCESS;
02224 
02225   /* Currently creating the back up config file in the current directory for windows */
02226 #ifndef WIN32
02227   {
02228     char *dirc = NULL, *dname = NULL;
02229 
02230     dirc = strdup(filePath);
02231     dname = dirname(dirc);
02232     if (NULL != dname)
02233     {
02234       strcat(dname, "/DeviceConfig");
02235       strcpy(tempFilePath, dname);
02236     }
02237   }
02238 #else
02239   strcpy(tempFilePath, "DeviceConfig.");
02240 #endif
02241   end = timeStr;
02242   time = tmr_gettimestructure();
02243   end += sprintf(end, "%d%d%d", time.tm_year, time.tm_mon, time.tm_mday);
02244   end += sprintf(end, "_%d%d%d", time.tm_hour, time.tm_min, time.tm_sec);
02245   strcat(tempFilePath, timeStr);
02246 
02247   fp = fopen(tempFilePath, "w");
02248   if (NULL == fp)
02249   {
02250     logErrorMessage(reader, "Unable to open the back up file");
02251     notify_exception_listeners(reader, TMR_ERROR_LOADSAVE_CONFIG);
02252     return TMR_ERROR_TRYAGAIN;
02253   }
02254   else
02255   {
02256     /* file is created */
02257     fclose(fp);
02258   }
02259 
02260   /* Save the reader current configuration for back up */
02261   ret = TMR_saveConfig(reader, tempFilePath);
02262   if (TMR_SUCCESS != ret)
02263   {
02264     logErrorMessage(reader, "Unable to take back up of parameters");
02265     notify_exception_listeners(reader, TMR_ERROR_LOADSAVE_CONFIG);
02266     return TMR_ERROR_TRYAGAIN;
02267   }
02268 
02269   for (i = 0; i < noOfEntries; i++)
02270   {
02271     /* load each parameter to module */
02272     if (0 != strncmp(dict[i].keyConfig, "/reader", 0x07))
02273     {
02274       /* Application specific parameter, skip them */
02275       continue;
02276     }
02277     else    
02278     {
02279       TMR_String temp;
02280 
02281       /* reader parameter, load it */
02282       temp.max = CONFIG_MAX_BUFFER_LEN;
02283       temp.value = dict[i].valueConfig;
02284       ret = getSetOneParam(reader, dict[i].keyConfig, &temp, PARAM_OPTION_SET);
02285       if (TMR_SUCCESS != ret)
02286       {
02287         if ((TMR_ERROR_READONLY == ret) || (TMR_ERROR_NOT_FOUND == ret) || 
02288           (TMR_ERROR_UNIMPLEMENTED_FEATURE == ret) || (TMR_ERROR_UNSUPPORTED == ret))
02289         {
02290           char errMsg[256];
02291           sprintf(errMsg, "either '%s'is read only or not supported by reader. Skipping this param", dict[i].keyConfig);
02292           logErrorMessage(reader, errMsg);
02293           notify_exception_listeners(reader, TMR_ERROR_LOADSAVE_CONFIG);
02294           ret = TMR_SUCCESS;
02295           continue;
02296         }
02297         else
02298         {
02299           char errMsg[256];
02300           sprintf(errMsg, "Rolling back the configurations");
02301           logErrorMessage(reader, errMsg);
02302           notify_exception_listeners(reader, TMR_ERROR_LOADSAVE_CONFIG);
02303           if (isRollBack)
02304           {
02305             ret = rollBackConfigData(reader, tempFilePath);
02306             if (TMR_SUCCESS != ret)
02307             {
02308               /* Unable to rollback the parameter, skip that */
02309               continue;
02310             }
02311             break;
02312           }
02313         }
02314       }
02315     }
02316 
02317   }
02318 /* remove the generated file */
02319 remove(tempFilePath);  
02320 return ret;
02321 }
02322 
02323 TMR_Status
02324 TMR_saveConfig(struct TMR_Reader *reader, char *filePath)
02325 {
02326   TMR_Status ret;
02327   TMR_Param keys[TMR_PARAM_MAX];
02328   TMR_String paramString;
02329   char str[CONFIG_MAX_BUFFER_LEN];
02330   uint32_t i, len;
02331   FILE* fp = NULL;
02332 
02333   ret = TMR_SUCCESS;
02334   paramString.max = CONFIG_MAX_BUFFER_LEN;
02335   paramString.value = str;
02336   len = numberof(keys);
02337 
02338   /* Open the file requested by user in write mode */
02339   fp = fopen(filePath, "w");
02340   if (NULL == fp)
02341   {
02342     logErrorMessage(reader, "SaveConfig:Can not open the file");
02343     notify_exception_listeners(reader, TMR_ERROR_LOADSAVE_CONFIG);
02344     return TMR_ERROR_INVALID;
02345   }
02346 
02347   /* Get the list of supported parameters by the connected module */
02348   TMR_paramList(reader, keys, &len);
02349   for (i = 0; i < len ; i++)
02350   {
02351     /* Save the parameters those are writeable */
02352     if (TMR_SUCCESS == isParamWritable(keys[i]))
02353     {
02354       /* Get the current value of the parameter */
02355       ret = getSetOneParam(reader, TMR_paramName(keys[i]), &paramString, PARAM_OPTION_GET);
02356       if (TMR_SUCCESS == ret)
02357       {
02358         /* Store the data into the file */
02359         fprintf(fp, "%s\n", paramString.value);
02360       }
02361       else
02362       {
02363         /* Ignore any error while saving the configuration */
02364         ret = TMR_SUCCESS;
02365       }
02366     }
02367     else
02368     {
02369        /* Parameter is read only, skip it */
02370       continue;
02371     }
02372   }
02373   fclose(fp);
02374   return ret;
02375 }
02376 
02377 TMR_Status
02378 TMR_loadConfig(struct TMR_Reader *reader, char *filePath)
02379 {
02380   TMR_Status ret = TMR_SUCCESS;
02381   FILE* fp = NULL;
02382   char temp[CONFIG_MAX_BUFFER_LEN];
02383   properties dict[CONFIG_MAX_PARAMETERS_LEN];
02384   uint8_t noOfEntries = 0x00;
02385 
02386   if (NULL == filePath)
02387   {
02388     logErrorMessage(reader, "File path is Empty");
02389     notify_exception_listeners(reader, TMR_ERROR_LOADSAVE_CONFIG);
02390     return TMR_ERROR_TRYAGAIN;
02391   }
02392 
02393   fp = fopen(filePath, "r");
02394   if (NULL == fp)
02395   {
02396     logErrorMessage(reader, "Error: Unable to open the configuration properties file");
02397     notify_exception_listeners(reader, TMR_ERROR_LOADSAVE_CONFIG);
02398     return TMR_ERROR_TRYAGAIN;
02399   }
02400   
02401   /* read the config parameters from the file and store in key value pair */
02402   do
02403   {
02404     memset(temp, 0, sizeof(temp)/sizeof(temp[0]));
02405     ret = readLine(fp, temp);
02406     if (TMR_SUCCESS == ret)
02407     {
02408       if (
02409         (0x00 != strlen(temp)) && (';' != temp[0]) && ('#' != temp[0]) && ('*' != temp[0])
02410         && (('/' == temp[0]) && ('/' != temp[1]))
02411         )
02412       {
02413         char *token;
02414 
02415         token = strtok(temp, "=");
02416         if (NULL != token)
02417         {
02418           /* copy the key field */
02419           strcpy(dict[noOfEntries].keyConfig, token);
02420           /* copy the value field */
02421           token = strtok(NULL, "=");
02422           while (NULL != token)
02423           {
02424             /* walk through other tokens */
02425             strcat(dict[noOfEntries].valueConfig, token);
02426             token = strtok(NULL, "=");
02427             if (token)
02428             {
02429               strcat(dict[noOfEntries].valueConfig, "=");
02430             }
02431           }
02432           noOfEntries++;
02433         }
02434         else
02435         {
02436           /* there is no '=' in the line, skip it and move on to next line */
02437           continue;
02438         }
02439       }
02440     }
02441   }while((TMR_SUCCESS == ret) && (CONFIG_MAX_PARAMETERS_LEN > noOfEntries));
02442 
02443   if (!noOfEntries)
02444   {
02445     logErrorMessage(reader, "No valid parameter line found");
02446     notify_exception_listeners(reader, TMR_ERROR_LOADSAVE_CONFIG);
02447     ret = TMR_ERROR_INVALID;
02448   }
02449   else if(CONFIG_MAX_PARAMETERS_LEN == noOfEntries)
02450   {
02451     logErrorMessage(reader, "No having sufficent memory to hold all the parameters");
02452     notify_exception_listeners(reader, TMR_ERROR_LOADSAVE_CONFIG);
02453     ret = TMR_ERROR_OUT_OF_MEMORY;
02454   }
02455   else
02456   {
02457     /* at least we have some parameters to process, process them now */
02458     ret = TMR_SUCCESS;
02459   }
02460 
02461   if (TMR_SUCCESS == ret)
02462   {
02463     /* Load the configurations to the module */
02464     ret = loadConfiguration(reader, filePath, dict, noOfEntries, true);
02465   }
02466   return ret;
02467 }


thingmagic_rfid
Author(s): Brian Bingham
autogenerated on Thu May 16 2019 03:01:24