llrp_reader.c
Go to the documentation of this file.
00001 
00008 /*
00009  * Copyright (c) 2011 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 "tm_reader.h"
00031 #ifdef TMR_ENABLE_LLRP_READER
00032 
00033 #include <stdlib.h>
00034 #include <stdio.h>
00035 #include <string.h>
00036 #include <sys/socket.h>
00037 #include <errno.h>
00038 #include <netinet/in.h>
00039 #include <netinet/tcp.h>
00040 #include <arpa/inet.h>
00041 #include <netdb.h>
00042 #include <unistd.h>
00043 
00044 #include "tmr_utils.h"
00045 #include "osdep.h"
00046 #include "tmr_llrp_reader.h"
00047 #include "llrp_reader_imp.h"
00048 
00049 extern uint8_t TMR_LLRP_gpiListSargas[];
00050 extern uint8_t TMR_LLRP_gpoListSargas[];
00051 extern uint8_t sizeGpiListSargas;
00052 extern uint8_t sizeGpoListSargas;
00053 extern uint8_t TMR_LLRP_gpiListM6Astra[];
00054 extern uint8_t TMR_LLRP_gpoListM6Astra[];
00055 extern uint8_t sizeGpiListM6Astra;
00056 extern uint8_t sizeGpoListM6Astra;
00057 
00058 static TMR_Status
00059 TMR_LLRP_initTxRxMapFromPorts(TMR_Reader *reader)
00060 {
00061   TMR_Status ret;
00062   TMR_LLRP_PortDetect ports[TMR_SR_MAX_ANTENNA_PORTS];
00063   uint8_t numPorts, i;
00064   TMR_LLRP_LlrpReader *lr;
00065 
00066   numPorts = numberof(ports);
00067   lr = &reader->u.llrpReader;
00068 
00069   /* Need number of ports to set up Tx-Rx map */
00070   ret = TMR_LLRP_cmdAntennaDetect(reader, &numPorts, ports);
00071   if (TMR_SUCCESS != ret)
00072   {
00073     return ret;
00074   }
00075 
00076   lr->portMask = 0;
00077   for (i = 0; i < numPorts; i ++)
00078   {
00079     lr->portMask |= 1 << (ports[i].port - 1);
00080     lr->staticTxRxMapData[i].antenna = ports[i].port;
00081     lr->staticTxRxMapData[i].txPort  = ports[i].port;
00082     lr->staticTxRxMapData[i].rxPort  = ports[i].port;
00083 
00084     if (0 == reader->tagOpParams.antenna && ports[i].connected)
00085     {
00086       reader->tagOpParams.antenna = ports[i].port;
00087     }
00088   }
00089 
00090   lr->staticTxRxMap.max = TMR_SR_MAX_ANTENNA_PORTS;
00091   lr->staticTxRxMap.len = numPorts;
00092   lr->staticTxRxMap.list = lr->staticTxRxMapData;
00093   lr->txRxMap = &lr->staticTxRxMap;
00094 
00095   return TMR_SUCCESS;
00096 }
00097 
00098 
00099 static TMR_Status
00100 TMR_LLRP_boot(TMR_Reader *reader)
00101 {
00102   TMR_Status ret;
00103   TMR_LLRP_LlrpReader *lr;
00104 
00105   int i;
00106 
00107   ret = TMR_SUCCESS;
00108   lr = &reader->u.llrpReader;
00109 
00110   if (TMR_LLRP_READER_DEFAULT_PORT == reader->u.llrpReader.portNum)
00111   {
00120     ret = TMR_LLRP_setHoldEventsAndReportsStatus(reader, 1);
00121     if (TMR_SUCCESS != ret)
00122     {
00126     }
00127 
00131     ret = TMR_LLRP_stopActiveROSpecs(reader);
00132     if (TMR_SUCCESS != ret)
00133     {
00134       return ret;
00135     }
00136   }
00137 
00141   ret = TMR_LLRP_cmdGetRegion(reader, &reader->u.llrpReader.regionId);
00142   if (TMR_SUCCESS != ret)
00143   {
00148     reader->u.llrpReader.regionId = TMR_REGION_NA;
00149   }
00150 
00154   ret = TMR_LLRP_cmdGetReaderCapabilities(reader, &reader->u.llrpReader.capabilities);
00155   if (TMR_SUCCESS != ret)
00156   {
00157     uint8_t length = strlen("NOT AVAILABLE");
00162     memcpy(reader->u.llrpReader.capabilities.softwareVersion, "NOT AVAILABLE", (size_t)length);
00163     reader->u.llrpReader.capabilities.softwareVersion[length + 1] = '\0';
00164     reader->u.llrpReader.capabilities.model = 0;
00165     reader->u.llrpReader.capabilities.powerTable.list = NULL;
00166     reader->u.llrpReader.capabilities.powerTable.len = 0;
00167     reader->u.llrpReader.capabilities.freqTable.list = NULL;
00168     reader->u.llrpReader.capabilities.freqTable.len = 0;
00169   }
00170 
00171   /* Initialize the paramPresent and paramConfirmed bits. */
00172   /* This block is expected to be collapsed by the compiler into a
00173    * small number of constant-value writes into the lr->paramPresent
00174    * array.
00175    */
00176   for (i = 0 ; i < TMR_PARAMWORDS; i++)
00177   {
00178     lr->paramPresent[i] = 0;
00179   }
00180 
00181   BITSET(lr->paramPresent, TMR_PARAM_REGION_ID);
00182   BITSET(lr->paramPresent, TMR_PARAM_ANTENNA_PORTLIST);
00183   BITSET(lr->paramPresent, TMR_PARAM_ANTENNA_CONNECTEDPORTLIST);
00184   BITSET(lr->paramPresent, TMR_PARAM_RADIO_POWERMAX);
00185   BITSET(lr->paramPresent, TMR_PARAM_RADIO_POWERMIN);
00186   BITSET(lr->paramPresent, TMR_PARAM_RADIO_PORTREADPOWERLIST);
00187   BITSET(lr->paramPresent, TMR_PARAM_RADIO_PORTWRITEPOWERLIST);
00188   BITSET(lr->paramPresent, TMR_PARAM_READ_PLAN);
00189   BITSET(lr->paramPresent, TMR_PARAM_URI);
00190   BITSET(lr->paramPresent, TMR_PARAM_TRANSPORTTIMEOUT);
00191   BITSET(lr->paramPresent, TMR_PARAM_COMMANDTIMEOUT);
00192   BITSET(lr->paramPresent, TMR_PARAM_GPIO_INPUTLIST);
00193   BITSET(lr->paramPresent, TMR_PARAM_GPIO_OUTPUTLIST);
00194   BITSET(lr->paramPresent, TMR_PARAM_GEN2_ACCESSPASSWORD);
00195   BITSET(lr->paramPresent, TMR_PARAM_VERSION_HARDWARE);
00196   BITSET(lr->paramPresent, TMR_PARAM_VERSION_MODEL);
00197   BITSET(lr->paramPresent, TMR_PARAM_VERSION_SERIAL);
00198   BITSET(lr->paramPresent, TMR_PARAM_VERSION_SOFTWARE);
00199   BITSET(lr->paramPresent, TMR_PARAM_TAGREADDATA_RECORDHIGHESTRSSI);
00200   BITSET(lr->paramPresent, TMR_PARAM_TAGREADDATA_UNIQUEBYANTENNA);
00201   BITSET(lr->paramPresent, TMR_PARAM_TAGREADDATA_UNIQUEBYDATA);
00202   BITSET(lr->paramPresent, TMR_PARAM_READER_DESCRIPTION);
00203   BITSET(lr->paramPresent, TMR_PARAM_READER_HOSTNAME);
00204   BITSET(lr->paramPresent, TMR_PARAM_CURRENTTIME);
00205   BITSET(lr->paramPresent, TMR_PARAM_RADIO_TEMPERATURE);
00206   BITSET(lr->paramPresent, TMR_PARAM_GEN2_BLF);
00207   BITSET(lr->paramPresent, TMR_PARAM_GEN2_TAGENCODING);
00208   BITSET(lr->paramPresent, TMR_PARAM_GEN2_TARI);
00209   BITSET(lr->paramPresent, TMR_PARAM_GEN2_Q);
00210   BITSET(lr->paramPresent, TMR_PARAM_RADIO_READPOWER);
00211   BITSET(lr->paramPresent, TMR_PARAM_RADIO_WRITEPOWER);
00212   BITSET(lr->paramPresent, TMR_PARAM_VERSION_SUPPORTEDPROTOCOLS);
00213   BITSET(lr->paramPresent, TMR_PARAM_ANTENNA_CHECKPORT);
00214   BITSET(lr->paramPresent, TMR_PARAM_GEN2_SESSION);
00215   BITSET(lr->paramPresent, TMR_PARAM_GEN2_TARGET);
00216   BITSET(lr->paramPresent, TMR_PARAM_LICENSE_KEY);
00217   BITSET(lr->paramPresent, TMR_PARAM_TAGOP_ANTENNA);
00218   BITSET(lr->paramPresent, TMR_PARAM_TAGOP_PROTOCOL);
00219   BITSET(lr->paramPresent, TMR_PARAM_ISO180006B_DELIMITER);
00220   BITSET(lr->paramPresent, TMR_PARAM_ISO180006B_MODULATION_DEPTH);
00221   BITSET(lr->paramPresent, TMR_PARAM_ISO180006B_BLF);
00222   BITSET(lr->paramPresent, TMR_PARAM_REGION_SUPPORTEDREGIONS);
00223   BITSET(lr->paramPresent, TMR_PARAM_READ_ASYNCOFFTIME);
00224   BITSET(lr->paramPresent, TMR_PARAM_LICENSED_FEATURES);
00225  
00226   for (i = 0; i < TMR_PARAMWORDS; i++)
00227   {
00228     lr->paramConfirmed[i] = lr->paramPresent[i];
00229   }
00230 
00236    TMR_TagProtocol protocol[5];
00237    TMR_TagProtocolList protocolList;
00238    protocolList.list = protocol;
00239    ret = TMR_LLRP_cmdGetTMDeviceProtocolCapabilities(reader, &protocolList);
00240    if (TMR_SUCCESS != ret)
00241    {
00246      lr->supportedProtocols = (1 << (TMR_TAG_PROTOCOL_GEN2 - 1));
00247    }
00248 
00252   ret = TMR_LLRP_initTxRxMapFromPorts(reader);
00253   if (TMR_SUCCESS != ret)
00254   {
00258   }
00259 
00260   if (TMR_LLRP_READER_DEFAULT_PORT == reader->u.llrpReader.portNum)
00261   {
00267     ret = TMR_LLRP_setKeepAlive(reader);
00268     if (TMR_SUCCESS != ret)
00269     {
00273     }
00274   }
00275 
00276   return ret;
00277 }
00278 
00279 static void
00280 TMR_LLRP_paramProbe(struct TMR_Reader *reader, TMR_Param key)
00281 {
00282   TMR_LLRP_LlrpReader *lr;
00283  /* buf is at least as large as the largest parameter, with all values 0
00284   * (NULL pointers and 0 lengths).
00285   */
00286   uint32_t buf[] = {0, 0, 0, 0, 0, 0, 0, 0};
00287   TMR_Status ret;
00288 
00289   lr = &reader->u.llrpReader;
00290 
00291   ret = TMR_paramGet(reader, key, &buf);
00292   if (TMR_SUCCESS == ret)
00293   {
00294     BITSET(lr->paramPresent, key);
00295   }
00296   BITSET(lr->paramConfirmed, key);
00297 }
00298 
00299 static TMR_Status
00300 TMR_LLRP_paramSet(struct TMR_Reader *reader, TMR_Param key, const void *value)
00301 {
00302   TMR_Status ret;
00303   TMR_LLRP_LlrpReader *lr;
00304 
00305   ret = TMR_SUCCESS;
00306   lr = &reader->u.llrpReader;
00307 
00308   if (0 == BITGET(lr->paramConfirmed, key))
00309   {
00310     TMR_LLRP_paramProbe(reader, key);
00311   }
00312 
00313   if (BITGET(lr->paramConfirmed, key) && (0 == BITGET(lr->paramPresent, key)))
00314   {
00315     return TMR_ERROR_NOT_FOUND;
00316   }
00317 
00318   switch (key)
00319   {
00320     case TMR_PARAM_REGION_ID:
00321     case TMR_PARAM_REGION_SUPPORTEDREGIONS:
00322       {
00323         ret = TMR_ERROR_READONLY;
00324         break;
00325       }
00326    
00327     case TMR_PARAM_ANTENNA_PORTLIST:
00328     case TMR_PARAM_URI:
00329     case TMR_PARAM_ANTENNA_CONNECTEDPORTLIST:
00330     case TMR_PARAM_RADIO_POWERMAX:
00331     case TMR_PARAM_RADIO_POWERMIN:
00332     case TMR_PARAM_GPIO_INPUTLIST:
00333     case TMR_PARAM_GPIO_OUTPUTLIST:
00334     case TMR_PARAM_VERSION_MODEL:
00335     case TMR_PARAM_VERSION_SERIAL:
00336     case TMR_PARAM_VERSION_SOFTWARE:
00337     case TMR_PARAM_VERSION_HARDWARE:
00338     case TMR_PARAM_CURRENTTIME:
00339     case TMR_PARAM_RADIO_TEMPERATURE:
00340     case TMR_PARAM_VERSION_SUPPORTEDPROTOCOLS:
00341       {
00342         ret = TMR_ERROR_READONLY;
00343         break;
00344       }
00345 
00346     case TMR_PARAM_RADIO_PORTREADPOWERLIST:
00347       {
00348         TMR_PortValueList *list = (TMR_PortValueList *)value;
00349 
00350         if (NULL == list)
00351         {
00352           ret = TMR_ERROR_ILLEGAL_VALUE;
00353           break;
00354         }
00355 
00356         if (0 >= list->len)
00357         {
00358           ret = TMR_ERROR_ILLEGAL_VALUE;
00359           break;
00360         }
00361 
00362         ret = TMR_LLRP_cmdSetReadTransmitPowerList(reader, list);
00363         break;
00364       }
00365 
00366     case TMR_PARAM_RADIO_PORTWRITEPOWERLIST:
00367       {
00368         TMR_PortValueList *list = (TMR_PortValueList *)value;
00369 
00370         if (NULL == list)
00371         {
00372           ret = TMR_ERROR_ILLEGAL_VALUE;
00373           break;
00374         }
00375 
00376         if (0 >= list->len)
00377         {
00378           ret = TMR_ERROR_ILLEGAL_VALUE;
00379           break;
00380         }
00381 
00382         ret = TMR_LLRP_cmdSetWriteTransmitPowerList(reader, list);
00383         break;
00384       }
00385 
00386     case TMR_PARAM_READ_PLAN:
00387       {
00388         const TMR_ReadPlan *plan;
00389         TMR_ReadPlan tmpPlan;
00390 
00391         plan = value;
00392         tmpPlan = *plan;
00393 
00394         ret = validateReadPlan(reader, &tmpPlan, 
00395                         lr->txRxMap, lr->supportedProtocols);
00396         if (TMR_SUCCESS != ret)
00397         {
00398           return ret;
00399         }
00400 
00401         *reader->readParams.readPlan = tmpPlan;
00402         break;
00403       }
00404 
00405     case TMR_PARAM_COMMANDTIMEOUT:
00406       {
00407         uint32_t val = *(uint32_t *)value;
00408         if ((1<<31) & val)
00409         {
00410           ret = TMR_ERROR_ILLEGAL_VALUE;
00411         }
00412         else
00413         {
00414           lr->commandTimeout = *(uint32_t *)value;
00415         }
00416         break;
00417       }
00418 
00419     case TMR_PARAM_TRANSPORTTIMEOUT:
00420       {
00421         uint32_t val = *(uint32_t *)value;
00422         if ((1<<31) & val)
00423         {
00424           ret = TMR_ERROR_ILLEGAL_VALUE;
00425         }
00426         else
00427         {
00428           lr->transportTimeout = *(uint32_t *)value;
00429         }
00430         break;
00431       }
00432 
00433     case TMR_PARAM_GEN2_ACCESSPASSWORD:
00434       {
00435         lr->gen2AccessPassword = *(TMR_GEN2_Password *)value;
00436         break;
00437       }
00438 
00439     case TMR_PARAM_TAGREADDATA_RECORDHIGHESTRSSI:
00440     case TMR_PARAM_TAGREADDATA_UNIQUEBYANTENNA:
00441     case TMR_PARAM_TAGREADDATA_UNIQUEBYDATA:
00442       {
00443         TMR_LLRP_TMDeDuplication duplication;
00444 
00445         if (NULL == value)
00446         {
00447           return TMR_ERROR_ILLEGAL_VALUE;
00448         }
00449 
00450         /* Get ThingMagic DeDuplication before setting it */
00451         ret = TMR_LLRP_cmdGetThingMagicDeDuplication(reader, &duplication);
00452 
00453         if(TMR_SUCCESS != ret)
00454         {
00455           break;
00456         }
00457 
00458         /* Set the parameter asked by the user */
00459         switch(key)
00460         {
00461           case TMR_PARAM_TAGREADDATA_RECORDHIGHESTRSSI:
00462             {
00463               duplication.highestRSSI = *(bool*)value;
00464               break;
00465             }
00466 
00467           case TMR_PARAM_TAGREADDATA_UNIQUEBYANTENNA:
00468             {
00469               duplication.uniquebyAntenna = *(bool*)value;
00470               break;
00471             }
00472 
00473           case TMR_PARAM_TAGREADDATA_UNIQUEBYDATA:
00474             {
00475               duplication.uniquebyData = *(bool*)value;
00476               break;
00477             }
00478 
00479           default:
00480             ret = TMR_ERROR_NOT_FOUND;
00481         }
00482         /* Set ThingMagic DeDuplication */
00483         ret = TMR_LLRP_cmdSetThingMagicDeDuplication(reader, &duplication);
00484 
00485         break;
00486       }
00487     case TMR_PARAM_READER_DESCRIPTION:
00488       {
00489         TMR_String *desc = (TMR_String *)value;
00490         TMR_LLRP_TMReaderConfiguration config;
00491 
00492         if (NULL == value)
00493         {
00494           ret = TMR_ERROR_INVALID;
00495           break;
00496         }
00497 
00498         if (NULL == desc->value)
00499         {
00500           ret = TMR_ERROR_INVALID;
00501           break;
00502         }
00503 
00504         /* Get Reader Configuration before setting it */
00505         ret = TMR_LLRP_cmdGetThingmagicReaderConfiguration(reader, &config);
00506         if (TMR_SUCCESS != ret)
00507         {
00508           break;
00509         }
00510 
00511         /* Set the description asked by user */
00512         LLRP_utf8v_clear(&config.description);
00513         config.description = LLRP_utf8v_construct(strlen(desc->value));
00514         strcpy((char *)config.description.pValue, desc->value);
00515         
00516         /* Set Reader Configuration */
00517         ret = TMR_LLRP_cmdSetThingmagicReaderConfiguration(reader, &config);
00518 
00519         TMR_LLRP_freeTMReaderConfiguration(&config);
00520         break;
00521       }
00522 
00523     case TMR_PARAM_READER_HOSTNAME:
00524       {
00525         TMR_String *hostname = (TMR_String *)value;
00526         TMR_LLRP_TMReaderConfiguration config;
00527 
00528         if (NULL == value)
00529         {
00530           ret = TMR_ERROR_INVALID;
00531           break;
00532         }
00533 
00534         if (NULL == hostname->value)
00535         {
00536           ret = TMR_ERROR_INVALID;
00537           break;
00538         }
00539 
00540         /* Get Reader Configuration before setting it */
00541         ret = TMR_LLRP_cmdGetThingmagicReaderConfiguration(reader, &config);
00542         if (TMR_SUCCESS != ret)
00543         {
00544           break;
00545         }
00546 
00547         /* Set the host name asked by user */
00548         LLRP_utf8v_clear(&config.hostName);
00549         config.hostName = LLRP_utf8v_construct(strlen(hostname->value));
00550         strcpy((char *)config.hostName.pValue, hostname->value);
00551 
00552         /* Set Reader Configuration */
00553         ret = TMR_LLRP_cmdSetThingmagicReaderConfiguration(reader, &config);
00554 
00555         TMR_LLRP_freeTMReaderConfiguration(&config);
00556         break;
00557       }
00558 
00559     case TMR_PARAM_GEN2_BLF:
00560       {
00561         TMR_LLRP_RFControl rfControl;
00562         TMR_GEN2_LinkFrequency setBlf, activeBlf;
00563         TMR_GEN2_TagEncoding activeM;
00564         
00565         ret = TMR_LLRP_cmdGetActiveRFControl(reader, &rfControl);
00566         if (TMR_SUCCESS != ret)
00567         {
00568           break;
00569         }
00570 
00571         setBlf = *(TMR_GEN2_LinkFrequency *)value;
00572         activeBlf = lr->capabilities.u.gen2Modes[rfControl.index].blf;
00573         activeM = lr->capabilities.u.gen2Modes[rfControl.index].m;
00574 
00575         /* Set only if the active BLF value is not same */
00576         if (setBlf != activeBlf)
00577         {
00578           uint8_t i;
00579 
00580           /* RFMode table index starts from 1*/
00581           for (i = 1; i < TMR_LLRP_MAX_RFMODE_ENTRIES; i++)
00582           {
00583             TMR_LLRP_C1G2RFModeTable *entry = &lr->capabilities.u.gen2Modes[i];
00584 
00585             /* Find a suitable mode with the setM and active BLF */
00586             if ((setBlf == entry->blf) && (activeM == entry->m))
00587             {
00588               /* Set mode index */
00589               rfControl.index = i;
00590 
00591               /* Set this as active RFControl */
00592               ret = TMR_LLRP_cmdSetActiveRFControl(reader, &rfControl);
00593               return ret;
00594             }
00595           }
00596 
00604           return TMR_ERROR_LLRP_INVALID_RFMODE;
00605         }
00606  
00607         break;
00608       }
00609 
00610     case TMR_PARAM_GEN2_TAGENCODING:
00611       {
00612         TMR_LLRP_RFControl rfControl;
00613         TMR_GEN2_TagEncoding setM, activeM;
00614         TMR_GEN2_LinkFrequency activeBlf;
00615 
00616         ret = TMR_LLRP_cmdGetActiveRFControl(reader, &rfControl);
00617         if (TMR_SUCCESS != ret)
00618         {
00619           break;
00620         }
00621 
00622         setM = *(TMR_GEN2_TagEncoding *)value;
00623         activeBlf = lr->capabilities.u.gen2Modes[rfControl.index].blf;
00624         activeM = lr->capabilities.u.gen2Modes[rfControl.index].m;
00625 
00626         /* Set only if the active m value is not same */
00627         if (setM != activeM)
00628         {
00629           uint8_t i;
00630 
00631           /* RFMode table index starts from 1*/
00632           for (i = 1; i < TMR_LLRP_MAX_RFMODE_ENTRIES; i++)
00633           {
00634             TMR_LLRP_C1G2RFModeTable *entry = &lr->capabilities.u.gen2Modes[i];
00635 
00636             /* Find a suitable mode with the setM and active BLF */
00637             if ((setM == entry->m) && (activeBlf == entry->blf))
00638             {
00639               /* Set mode index */
00640               rfControl.index = i;
00641 
00642               /* Set this as active RFControl */
00643               ret = TMR_LLRP_cmdSetActiveRFControl(reader, &rfControl);
00644               return ret;
00645             }
00646           }
00647 
00655           return TMR_ERROR_LLRP_INVALID_RFMODE;
00656         }
00657         break;
00658       }
00659 
00660     case TMR_PARAM_GEN2_TARI:
00661       {
00662         TMR_LLRP_RFControl rfControl;
00663         TMR_GEN2_Tari tari = *(TMR_GEN2_Tari *)value;
00664 
00665         /* Get active RFControl */
00666         ret = TMR_LLRP_cmdGetActiveRFControl(reader, &rfControl);
00667         if (TMR_SUCCESS != ret)
00668         {
00669           break;
00670         }
00671         if((tari < lr->capabilities.u.gen2Modes[rfControl.index].minTari) || (tari > lr->capabilities.u.gen2Modes[rfControl.index].maxTari))
00672         {
00673           return TMR_ERROR_ILLEGAL_VALUE;  
00674         }
00675 
00676         /* Set only if the active tari value is not same */
00677         if (tari != rfControl.tari)
00678         {
00679           rfControl.tari = tari;
00680           ret = TMR_LLRP_cmdSetActiveRFControl(reader, &rfControl);
00681         }
00682 
00683         break;
00684       }
00685 
00686     case TMR_PARAM_GEN2_Q:
00687       {
00688         TMR_GEN2_Q *q = (TMR_GEN2_Q *)value;
00689 
00690         /* Error check for q value, in case of static type */
00691         if (TMR_SR_GEN2_Q_STATIC == q->type)
00692         {
00693           int qval = (int) q->u.staticQ.initialQ;
00694           if ((qval < 0) || (qval > 15))
00695           {
00696             return TMR_ERROR_ILLEGAL_VALUE;
00697           }
00698         }
00699 
00700         ret = TMR_LLRP_cmdSetGen2Q(reader, q);
00701         break;
00702       }
00703 
00704     case TMR_PARAM_GEN2_TARGET:
00705       {
00706         TMR_GEN2_Target target = *(TMR_GEN2_Target *)value;
00707 
00708         if (NULL == value)
00709         {
00710           ret = TMR_ERROR_INVALID;
00711           break;
00712         }
00713         ret = TMR_LLRP_cmdSetGen2Target(reader, &target);
00714         break;
00715       }
00716 
00717     case TMR_PARAM_GEN2_SESSION:
00718       {
00719         TMR_GEN2_Session session = *(TMR_GEN2_Session *)value;
00720 
00721         if (NULL == value)
00722         {
00723           ret = TMR_ERROR_INVALID;
00724           break;
00725         }
00726         ret = TMR_LLRP_cmdSetGen2Session(reader, &session);
00727         break;
00728       }
00729             
00730     case TMR_PARAM_RADIO_READPOWER:
00731     case TMR_PARAM_RADIO_WRITEPOWER:
00732       {
00733         TMR_PortValueList powerList;
00734         TMR_PortValue list[TMR_SR_MAX_ANTENNA_PORTS];
00735         int32_t power = *(int32_t *)value;
00736         uint8_t i;
00737 
00738         powerList.max = TMR_SR_MAX_ANTENNA_PORTS;
00739         powerList.list = list;
00740         powerList.len = 0;
00741 
00742         /* Set all antennas to same power */
00743         for (i = 0; i < lr->txRxMap->len; i ++)
00744         {
00745           powerList.list[i].port  = lr->txRxMap->list[i].antenna;
00746           powerList.list[i].value = power;
00747           powerList.len ++;
00748         }
00749 
00750         if (TMR_PARAM_RADIO_READPOWER == key)
00751         {
00752           /* Set read power */
00753           ret = TMR_LLRP_cmdSetReadTransmitPowerList(reader, &powerList);
00754         }
00755         else
00756         {
00757           /* Set write power */
00758           ret = TMR_LLRP_cmdSetWriteTransmitPowerList(reader, &powerList);
00759         }
00760      
00761         break;
00762       }
00763     case TMR_PARAM_ANTENNA_CHECKPORT:
00764       {
00765         if (NULL == value)
00766         {
00767           ret = TMR_ERROR_INVALID;
00768           break;
00769         }
00770         ret = TMR_LLRP_cmdSetThingMagicAntennaDetection(reader, (bool*)value);
00771         break;
00772       }
00773 
00774     case TMR_PARAM_LICENSE_KEY:
00775       {
00776         if (NULL == value)
00777         {
00778           ret = TMR_ERROR_INVALID;
00779           break;
00780         }
00781         ret = TMR_LLRP_cmdSetTMLicenseKey(reader, (TMR_uint8List *)value);
00782         break;
00783       }
00784 
00785     case TMR_PARAM_TAGOP_ANTENNA:
00786       {
00787         uint16_t i;
00788         TMR_AntennaMapList *map;
00789         uint8_t antenna, txPort, rxPort;
00790 
00791         map = lr->txRxMap;
00792         antenna = *(uint8_t *)value;
00793 
00794         txPort = rxPort = 0;
00795         for (i = 0; i < map->len && i < map->max; i++)
00796         {
00797           if (map->list[i].antenna == antenna)
00798           {
00799             txPort = map->list[i].txPort;
00800             rxPort = map->list[i].rxPort;
00801             reader->tagOpParams.antenna = antenna;
00802             break;
00803           }
00804         }
00805         if (txPort == 0)
00806         {
00807           ret = TMR_ERROR_NO_ANTENNA;
00808         }
00809         break;
00810       }
00811 
00812     case TMR_PARAM_TAGOP_PROTOCOL:
00813       {
00818         if (0 == ((1 << (*(TMR_TagProtocol *)value - 1)) &
00819                                 lr->supportedProtocols))
00820         {
00821           /* If not present, return unsupported error */
00822           ret = TMR_ERROR_UNSUPPORTED;
00823         }
00824         else
00825         {
00826           reader->tagOpParams.protocol = *(TMR_TagProtocol *)value;
00827           reader->u.llrpReader.currentProtocol = reader->tagOpParams.protocol;
00828         }
00829         break;
00830       }
00831 
00832     case TMR_PARAM_READ_ASYNCOFFTIME:
00833       {
00834         uint32_t offtime = *(uint32_t *)value;
00835         ret = TMR_LLRP_cmdSetTMAsyncOffTime(reader, offtime);
00836         break;
00837       }
00838 
00839     case TMR_PARAM_LICENSED_FEATURES:
00840       {
00841         ret = TMR_ERROR_UNSUPPORTED;
00842         break;
00843       }
00844 #ifdef TMR_ENABLE_ISO180006B
00845     case TMR_PARAM_ISO180006B_DELIMITER:
00846       {
00847         TMR_ISO180006B_Delimiter delimiter = *(TMR_ISO180006B_Delimiter *)value;
00848 
00849         if (NULL == value)
00850         {
00851           ret = TMR_ERROR_INVALID;
00852           break;
00853         }
00854         ret = TMR_LLRP_cmdSetISO18K6BDelimiter(reader, &delimiter);
00855         break;
00856       }
00857 
00858     case TMR_PARAM_ISO180006B_MODULATION_DEPTH:
00859       {
00860         TMR_ISO180006B_ModulationDepth modDepth = *(TMR_ISO180006B_ModulationDepth *)value;
00861 
00862         if (NULL == value)
00863         {
00864           ret = TMR_ERROR_INVALID;
00865           break;
00866         }
00867         ret = TMR_LLRP_cmdSetISO18K6BModDepth(reader, &modDepth);
00868         break;
00869       }
00870 
00871     case TMR_PARAM_ISO180006B_BLF:
00872       {
00873         TMR_ISO180006B_LinkFrequency linkFreq = *(TMR_ISO180006B_LinkFrequency *)value;
00874 
00875         if (NULL == value)
00876         {
00877           ret = TMR_ERROR_INVALID;
00878           break;
00879         }
00880         ret = TMR_LLRP_cmdSetISO18K6BLinkFrequency(reader, &linkFreq);
00881         break;
00882       }
00883 #endif /* TMR_ENABLE_ISO180006B */
00884 
00885     default:
00886       ret = TMR_ERROR_NOT_FOUND;
00887   }
00888 
00889   return ret;
00890 }
00891 
00892 
00893 static TMR_Status
00894 TMR_LLRP_paramGet(struct TMR_Reader *reader, TMR_Param key, void *value)
00895 {
00896   TMR_Status ret;
00897   TMR_LLRP_LlrpReader *lr;
00898 
00899   ret = TMR_SUCCESS;
00900   lr = &reader->u.llrpReader;
00901 
00902   if (NULL == value)
00903   {
00904     return TMR_ERROR_ILLEGAL_VALUE;
00905   }
00906 
00907   if (BITGET(lr->paramConfirmed, key) && (0 == BITGET(lr->paramPresent, key)))
00908   {
00909     return TMR_ERROR_NOT_FOUND;
00910   }
00911 
00912   switch (key)
00913   {
00914     case TMR_PARAM_REGION_ID:
00915       {
00916         *(TMR_Region *)value = lr->regionId;
00917         break;
00918       }
00919 
00920     case TMR_PARAM_REGION_SUPPORTEDREGIONS:
00921       {
00926         TMR_RegionList *regions = (TMR_RegionList *)value;
00927         regions->len = 0;
00928         regions->list[regions->len++] = lr->regionId;
00929         break;
00930       }
00931 
00932     case TMR_PARAM_URI:
00933       {
00934         TMR_stringCopy((TMR_String *) value, reader->uri, (int)strlen(reader->uri));
00935         break;
00936       }
00937 
00938     case TMR_PARAM_ANTENNA_PORTLIST:
00939       {
00940         uint8_t i;
00941         TMR_uint8List *u8List;
00942 
00943         u8List = value;
00944         u8List->len = 0;
00945 
00946         for (i = 0; i < reader->u.llrpReader.txRxMap->len; i++)
00947         {
00948           LISTAPPEND(u8List, reader->u.llrpReader.txRxMap->list[i].antenna);
00949         }
00950         break;
00951       }
00952 
00953     case TMR_PARAM_ANTENNA_CONNECTEDPORTLIST:
00954       {
00955         TMR_LLRP_PortDetect ports[TMR_SR_MAX_ANTENNA_PORTS];
00956         uint8_t numPorts, i;
00957         TMR_uint8List *u8List;
00958 
00959         u8List = (TMR_uint8List *)value;
00960         u8List->len = 0;
00961 
00962         numPorts = numberof(ports);
00963         ret = TMR_LLRP_cmdAntennaDetect(reader, &numPorts, ports);
00964         if (TMR_SUCCESS != ret)
00965         {
00966           break;
00967         }
00968 
00969         if (u8List->max < numPorts)
00970         {
00971           numPorts = u8List->max;
00972         }
00973 
00974         for (i = 0; i < numPorts; i++)
00975         {
00976           if (ports[i].connected)
00977           {
00978             LISTAPPEND(u8List, ports[i].port);
00979           }
00980         }
00981         break;
00982       }
00983 
00984     case TMR_PARAM_GPIO_INPUTLIST:
00985       {
00986         if (TMR_LLRP_MODEL_M6 == lr->capabilities.model ||
00987                         TMR_LLRP_MODEL_ASTRA_EX == lr->capabilities.model ||
00988                         TMR_LLRP_MODEL_SARGAS == lr->capabilities.model)
00989         {
00990           TMR_uint8List *u8List;
00991           uint8_t i, numPins;
00992 
00993           u8List = (TMR_uint8List *)value;
00994 
00995           u8List->len = 0;
00996           if (TMR_LLRP_MODEL_SARGAS == lr->capabilities.model)
00997           {
00998                   numPins = sizeGpiListSargas;
00999           }
01000           else
01001           {
01002                   numPins = sizeGpiListM6Astra;
01003           }
01004           if (u8List->max < numPins)
01005           {
01006             numPins = u8List->max;
01007           }
01008 
01009           for(i = 0; i < numPins; i++)
01010           {
01011                   if (TMR_LLRP_MODEL_SARGAS == lr->capabilities.model)
01012                   {
01013                     LISTAPPEND(u8List, TMR_LLRP_gpiListSargas[i]);
01014                   }
01015                   else
01016                   {
01017                     LISTAPPEND(u8List, TMR_LLRP_gpiListM6Astra[i]);
01018                   }
01019           }
01020         }
01021         break;
01022 
01023       }
01024     case TMR_PARAM_GPIO_OUTPUTLIST:
01025       {
01026         if (TMR_LLRP_MODEL_M6 == lr->capabilities.model ||
01027                         TMR_LLRP_MODEL_ASTRA_EX == lr->capabilities.model ||
01028                         TMR_LLRP_MODEL_SARGAS == lr->capabilities.model)
01029         {
01030           TMR_uint8List *u8List;
01031           uint8_t i, numPins;
01032 
01033           u8List = (TMR_uint8List *)value;
01034 
01035           u8List->len = 0;
01036           if (TMR_LLRP_MODEL_SARGAS == lr->capabilities.model)
01037           {
01038                   numPins = sizeGpoListSargas;
01039           }
01040           else
01041           {
01042                   numPins = sizeGpoListM6Astra;
01043           }
01044           if (u8List->max < numPins)
01045           {
01046             numPins = u8List->max;
01047           }
01048           for(i = 0; i < numPins; i++)
01049           {
01050                   if (TMR_LLRP_MODEL_SARGAS == lr->capabilities.model)
01051                   {
01052                     LISTAPPEND(u8List, TMR_LLRP_gpoListSargas[i]);
01053                   }
01054                   else
01055                   {
01056                     LISTAPPEND(u8List, TMR_LLRP_gpoListM6Astra[i]);
01057                   }
01058           }
01059         }
01060         break;
01061       }
01062     case TMR_PARAM_RADIO_POWERMAX:
01063       {
01064         TMR_uint16List *table;
01065         int16_t i, max;
01066 
01067         table = &lr->capabilities.powerTable;
01068 
01069         if (0 == table->len)
01070         {
01071           ret = TMR_ERROR_INVALID;
01072           break;
01073         }
01074 
01076         max = table->list[1];
01077         for(i = 1; i <= table->len; i ++)
01078         {
01079           if(table->list[i] > max)
01080           {
01081             max = table->list[i];
01082           }
01083         }
01084 
01085         *(int16_t*)value = max;
01086         break;
01087       }
01088 
01089     case TMR_PARAM_RADIO_POWERMIN:
01090       {
01091         TMR_uint16List *table;
01092         int16_t i, min;
01093 
01094         table = &lr->capabilities.powerTable;
01095 
01096         if (0 == table->len)
01097         {
01098           ret = TMR_ERROR_INVALID;
01099           break;
01100         }
01101 
01103         min = table->list[1];
01104         for(i = 1; i <= table->len; i ++)
01105         {
01106           if(table->list[i] < min)
01107           {
01108             min = table->list[i];
01109           }
01110         }
01111 
01112         *(int16_t*)value = min;
01113         break;
01114       }
01115 
01116     case TMR_PARAM_RADIO_PORTREADPOWERLIST:
01117       {
01118         TMR_PortValueList *list = (TMR_PortValueList *)value;
01119 
01120         if (NULL == list)
01121         {
01122           ret = TMR_ERROR_ILLEGAL_VALUE;
01123           break;
01124         }
01125 
01126         if (0 >= list->max)
01127         {
01128           ret = TMR_ERROR_ILLEGAL_VALUE;
01129           break;
01130         }
01131 
01132         ret = TMR_LLRP_cmdGetReadTransmitPowerList(reader, (TMR_PortValueList *)list);
01133         break;
01134       }
01135 
01136     case TMR_PARAM_RADIO_PORTWRITEPOWERLIST:
01137       {
01138         TMR_PortValueList *list = (TMR_PortValueList *)value;
01139 
01140         if (NULL == list)
01141         {
01142           ret = TMR_ERROR_ILLEGAL_VALUE;
01143           break;
01144         }
01145 
01146         if (0 >= list->max)
01147         {
01148           ret = TMR_ERROR_ILLEGAL_VALUE;
01149           break;
01150         }
01151 
01152         ret = TMR_LLRP_cmdGetWriteTransmitPowerList(reader, (TMR_PortValueList *)list);
01153         break;
01154       }
01155 
01156     case TMR_PARAM_VERSION_MODEL:
01157       {
01158         const char *model;
01159 
01160         switch (lr->capabilities.model)
01161         {
01162           case TMR_LLRP_MODEL_M6:
01163             model = "Mercury6";
01164             break;
01165           case TMR_LLRP_MODEL_ASTRA_EX:
01166             model = "Astra-EX" ;
01167             break;
01168 
01169           case TMR_LLRP_MODEL_SARGAS:
01170             model = "Sargas" ;
01171             break;
01172 
01173           default:
01174             model = "Unknown";
01175         }
01176 
01177         TMR_stringCopy(value, model, (int)strlen(model));
01178         break;
01179       }
01180     case TMR_PARAM_VERSION_SERIAL:
01181       {
01182         //TMR_String *val = (TMR_String *) value;
01183         //ret = TMR_LLRP_cmdGetVersionSerial (reader, (TMR_String *)val);
01184         //break;
01185         TMR_String *val = (TMR_String *)value;
01186         ret = TMR_LLRP_cmdGetTMDeviceInformationCapabilities (reader, TMR_PARAM_VERSION_SERIAL, (TMR_String *)val);
01187         break;
01188 
01189       }
01190 
01191     case TMR_PARAM_VERSION_SOFTWARE:
01192       {
01193         char *software = lr->capabilities.softwareVersion;
01194         TMR_stringCopy(value, software, (int)strlen(software));
01195         break;
01196       }
01197       
01198     case TMR_PARAM_VERSION_HARDWARE:
01199       {
01200         TMR_String *val = (TMR_String *)value;
01201         ret = TMR_LLRP_cmdGetTMDeviceInformationCapabilities (reader, TMR_PARAM_VERSION_HARDWARE, (TMR_String *)val);
01202 
01203         break;
01204       }
01205 
01206     case TMR_PARAM_COMMANDTIMEOUT:
01207       {
01208         *(uint32_t *)value = lr->commandTimeout;
01209         break;
01210       }
01211 
01212     case TMR_PARAM_TRANSPORTTIMEOUT:
01213       {
01214         *(uint32_t *)value = lr->transportTimeout;
01215         break;
01216       }
01217 
01218     case TMR_PARAM_GEN2_ACCESSPASSWORD:
01219       {
01220         *(TMR_GEN2_Password *)value = lr->gen2AccessPassword;
01221         break;
01222       }
01223 
01224     case TMR_PARAM_TAGREADDATA_RECORDHIGHESTRSSI:
01225     case TMR_PARAM_TAGREADDATA_UNIQUEBYANTENNA:
01226     case TMR_PARAM_TAGREADDATA_UNIQUEBYDATA:
01227       {
01228         TMR_LLRP_TMDeDuplication duplication;
01229         ret = TMR_LLRP_cmdGetThingMagicDeDuplication(reader, &duplication);
01230         if (TMR_SUCCESS != ret)
01231         {
01232           break;
01233         }
01234 
01235         switch(key)
01236         {
01237           case TMR_PARAM_TAGREADDATA_RECORDHIGHESTRSSI:
01238             {
01239               *(bool*)value = (bool)duplication.highestRSSI;
01240               break;
01241             }
01242           case TMR_PARAM_TAGREADDATA_UNIQUEBYANTENNA:
01243             {
01244               *(bool*)value = (bool)duplication.uniquebyAntenna;
01245               break;
01246             }
01247           case TMR_PARAM_TAGREADDATA_UNIQUEBYDATA:
01248             {
01249               *(bool*)value = (bool)duplication.uniquebyData;
01250               break;
01251             }
01252           default:
01253             ret = TMR_ERROR_NOT_FOUND;
01254         }
01255 
01256         break;
01257       }
01258 
01259     case TMR_PARAM_READER_DESCRIPTION:
01260       {
01261         TMR_String *desc = (TMR_String *)value;
01262         TMR_LLRP_TMReaderConfiguration config;
01263 
01264         if (NULL != desc->value)
01265         {
01266           ret = TMR_LLRP_cmdGetThingmagicReaderConfiguration(reader, &config);
01267           if (TMR_SUCCESS == ret)
01268           {
01269             TMR_stringCopy(desc, (char *)config.description.pValue, config.description.nValue);
01270             TMR_LLRP_freeTMReaderConfiguration(&config);
01271           }
01272         }
01273         else
01274         {
01275           ret = TMR_ERROR_ILLEGAL_VALUE;
01276         }
01277 
01278         break;
01279       }
01280 
01281     case TMR_PARAM_READER_HOSTNAME:
01282       {
01283         TMR_String *hostname = (TMR_String *)value;
01284         TMR_LLRP_TMReaderConfiguration config;
01285         hostname->max = 25;
01286 
01287         if (NULL != hostname->value)
01288         {
01289           ret = TMR_LLRP_cmdGetThingmagicReaderConfiguration(reader, &config);
01290           if (TMR_SUCCESS == ret)
01291           {
01292             TMR_stringCopy(hostname, (char *)config.hostName.pValue, config.hostName.nValue);
01293             TMR_LLRP_freeTMReaderConfiguration(&config);
01294           }
01295         }
01296         else
01297         {
01298           ret = TMR_ERROR_ILLEGAL_VALUE;
01299         }
01300 
01301         break;
01302       }
01303 
01304     case TMR_PARAM_CURRENTTIME:
01305       {
01306         ret = TMR_LLRP_cmdGetThingMagicCurrentTime(reader, (struct tm *)value);
01307         break;
01308       }
01309 
01310     case TMR_PARAM_RADIO_TEMPERATURE:
01311     {
01312       ret = TMR_LLRP_cmdGetThingMagicReaderModuleTemperature(reader, (uint8_t *)value);
01313       break;
01314     }
01315     case TMR_PARAM_ANTENNA_CHECKPORT:
01316     {
01317       ret = TMR_LLRP_cmdGetThingMagicAntennaDetection(reader, (bool *)value);
01318       break;
01319     }
01320 
01321     case TMR_PARAM_VERSION_SUPPORTEDPROTOCOLS:
01322     {
01323       TMR_TagProtocolList *protocol = (TMR_TagProtocolList *)value;
01324       if (NULL == protocol->list)
01325       {
01326         ret = TMR_ERROR_ILLEGAL_VALUE;
01327         break;
01328       }
01329 
01330       ret = TMR_LLRP_cmdGetTMDeviceProtocolCapabilities(reader, (TMR_TagProtocolList *)protocol);
01331       break;
01332     }
01333 
01334     case TMR_PARAM_GEN2_BLF:
01335       {
01336         TMR_LLRP_RFControl rfControl;
01337         TMR_GEN2_LinkFrequency *blf = (TMR_GEN2_LinkFrequency *)value;
01338 
01339         ret = TMR_LLRP_cmdGetActiveRFControl(reader, &rfControl);
01340         if (TMR_SUCCESS != ret)
01341         {
01342           break;
01343         }
01344 
01345         *blf = lr->capabilities.u.gen2Modes[rfControl.index].blf;
01346         break;
01347       }
01348 
01349     case TMR_PARAM_GEN2_TAGENCODING:
01350       {
01351         TMR_LLRP_RFControl rfControl;
01352         TMR_GEN2_TagEncoding *m = (TMR_GEN2_TagEncoding *)value;
01353 
01354         ret = TMR_LLRP_cmdGetActiveRFControl(reader, &rfControl);
01355         if (TMR_SUCCESS != ret)
01356         {
01357           break;
01358         }
01359 
01360         *m = lr->capabilities.u.gen2Modes[rfControl.index].m;
01361         break;
01362       }
01363 
01364     case TMR_PARAM_GEN2_TARI:
01365       {
01366         TMR_LLRP_RFControl rfControl;
01367         TMR_GEN2_Tari *tari = (TMR_GEN2_Tari *)value;
01368 
01369         ret = TMR_LLRP_cmdGetActiveRFControl(reader, &rfControl);
01370         if (TMR_SUCCESS != ret)
01371         {
01372           break;
01373         }
01374 
01375         *tari = rfControl.tari;
01376         break;
01377       }
01378 
01379     case TMR_PARAM_GEN2_Q:
01380       {
01381         TMR_GEN2_Q *q = (TMR_GEN2_Q *)value;
01382 
01383         ret = TMR_LLRP_cmdGetGen2Q(reader, q);
01384         break;
01385       }
01386 
01387     case TMR_PARAM_GEN2_TARGET:
01388       {
01389         TMR_GEN2_Target *target = (TMR_GEN2_Target *)value;
01390 
01391         ret = TMR_LLRP_cmdGetGen2Target(reader, target);
01392         break;
01393       }
01394 
01395     case TMR_PARAM_LICENSE_KEY:
01396       {
01397         ret = TMR_ERROR_UNSUPPORTED;
01398         break;
01399       }
01400   
01401     case TMR_PARAM_GEN2_SESSION:
01402       {
01403         TMR_GEN2_Session *session = (TMR_GEN2_Session *)value;
01404 
01405         ret = TMR_LLRP_cmdGetGen2Session(reader, session);
01406         break;
01407       }
01408 
01409     case TMR_PARAM_RADIO_READPOWER:
01410     case TMR_PARAM_RADIO_WRITEPOWER:
01411       {
01412         TMR_PortValueList powerList;
01413         TMR_PortValue list[TMR_SR_MAX_ANTENNA_PORTS];
01414         uint8_t i;
01415         int32_t power;
01416 
01417 
01418         powerList.max  = TMR_SR_MAX_ANTENNA_PORTS;
01419         powerList.list = list;
01420         powerList.len  = 0;
01421 
01422         if (TMR_PARAM_RADIO_READPOWER == key)
01423         {
01424           /* Get per port read power list */
01425           ret = TMR_LLRP_cmdGetReadTransmitPowerList(reader, &powerList);
01426         }
01427         else
01428         {
01429           /* Get per port write power list */
01430           ret = TMR_LLRP_cmdGetWriteTransmitPowerList(reader, &powerList);
01431         }
01432         if (TMR_SUCCESS != ret)
01433         {
01434           break;
01435         }
01436        
01437         power = powerList.list[0].value;
01438         for (i = 1; i < powerList.len; i ++)
01439         {
01440           if (power != powerList.list[i].value)
01441           {
01442             return TMR_ERROR_LLRP_UNDEFINED_VALUE;
01443           }
01444         }
01445 
01450         *(int32_t *)value = (int32_t)power;
01451         
01452         break;
01453       }
01454 
01455     case TMR_PARAM_TAGOP_ANTENNA:
01456       {
01457         *(uint8_t *)value = reader->tagOpParams.antenna;
01458         break;
01459       }
01460 
01461     case TMR_PARAM_TAGOP_PROTOCOL:
01462       {
01463         *(TMR_TagProtocol *)value = reader->tagOpParams.protocol;
01464         break;
01465       }
01466     case TMR_PARAM_READ_ASYNCOFFTIME:
01467       {
01468         uint32_t offtime;
01469         ret = TMR_LLRP_cmdGetTMAsyncOffTime(reader, &offtime);
01470         if (TMR_SUCCESS != ret)
01471         {
01472           break;
01473         }
01474         *(uint32_t *)value = offtime;
01475         break;
01476       }
01477 
01478     case TMR_PARAM_LICENSED_FEATURES:
01479       {
01480         if(TMR_LLRP_MODEL_SARGAS == lr->capabilities.model)
01481         {
01482           TMR_uint8List *val = (TMR_uint8List *)value;
01483           ret = TMR_LLRP_cmdGetLicensedFeatures(reader, (TMR_uint8List *)val);
01484           if (TMR_SUCCESS != ret)
01485           {
01486             break;
01487           }
01488         }
01489         else
01490         {
01491           ret = TMR_ERROR_UNSUPPORTED;
01492         }
01493         break;
01494       }
01495 #ifdef TMR_ENABLE_ISO180006B
01496     case TMR_PARAM_ISO180006B_DELIMITER:
01497       {
01498         TMR_ISO180006B_Delimiter *delimiter = (TMR_ISO180006B_Delimiter *)value;
01499 
01500         ret = TMR_LLRP_cmdGetISO18K6BDelimiter(reader, delimiter);
01501         break;
01502       }
01503 
01504     case TMR_PARAM_ISO180006B_MODULATION_DEPTH:
01505       {
01506         TMR_ISO180006B_ModulationDepth *modDepth = (TMR_ISO180006B_ModulationDepth *)value;
01507 
01508         ret = TMR_LLRP_cmdGetISO18K6BModDepth(reader, modDepth);
01509         break;
01510       }
01511 
01512     case TMR_PARAM_ISO180006B_BLF:
01513       {
01514         TMR_ISO180006B_LinkFrequency *linkFreq = (TMR_ISO180006B_LinkFrequency *)value;
01515         
01516         ret = TMR_LLRP_cmdGetISO18K6BLinkFrequency(reader, linkFreq);
01517         break;
01518       }
01519 #endif /* TMR_ENABLE_ISO180006B */
01520 
01521     default:
01522       ret = TMR_ERROR_NOT_FOUND;
01523   }
01524 
01525   if (0 == BITGET(lr->paramConfirmed, key))
01526   {
01527     if (TMR_SUCCESS == ret)
01528     {
01529       BITSET(lr->paramPresent, key);
01530     }
01531     BITSET(lr->paramConfirmed, key);
01532   }
01533 
01534   return ret;
01535 }
01536 
01537 TMR_Status
01538 TMR_LLRP_LlrpReader_init(TMR_Reader *reader)
01539 {
01540   reader->readerType = TMR_READER_TYPE_LLRP;
01541   
01542   /*
01543    * Allocate the type registry. This is needed
01544    * by the connection to decode.
01545    */
01546   reader->u.llrpReader.pTypeRegistry = LLRP_getTheTypeRegistry();
01547   if(NULL == reader->u.llrpReader.pTypeRegistry)
01548   {
01549     return TMR_ERROR_LLRP_GETTYPEREGISTRY;
01550   }
01554   LLRP_enrollTmTypesIntoRegistry(reader->u.llrpReader.pTypeRegistry);
01555 
01556 
01560   reader->connect     = TMR_LLRP_connect;
01561   reader->destroy     = TMR_LLRP_destroy;
01562   reader->paramSet    = TMR_LLRP_paramSet;
01563   reader->paramGet    = TMR_LLRP_paramGet;
01564   reader->read        = TMR_LLRP_read;
01565   reader->hasMoreTags = TMR_LLRP_hasMoreTags;
01566   reader->getNextTag  = TMR_LLRP_getNextTag;
01567   reader->executeTagOp = TMR_LLRP_executeTagOp;
01568   reader->gpiGet = TMR_LLRP_gpiGet;
01569   reader->gpoSet = TMR_LLRP_gpoSet;
01570   reader->readTagMemBytes = TMR_LLRP_readTagMemBytes;
01571   reader->readTagMemWords = TMR_LLRP_readTagMemWords;
01572   reader->writeTagMemBytes = TMR_LLRP_writeTagMemBytes;
01573   reader->writeTagMemWords = TMR_LLRP_writeTagMemWords;
01574   reader->firmwareLoad = TMR_LLRP_firmwareLoad;
01575   reader->reboot = TMR_LLRP_reboot;
01576   reader->writeTag = TMR_LLRP_writeTag;
01577   reader->killTag = TMR_LLRP_killTag;
01578   reader->lockTag = TMR_LLRP_lockTag;
01579 #ifdef TMR_ENABLE_BACKGROUND_READS
01580   reader->cmdStopReading = TMR_LLRP_cmdStopReading;
01581 #endif
01582   
01586   reader->u.llrpReader.msgId = 1;
01587   reader->u.llrpReader.roSpecId = 0;
01588   reader->u.llrpReader.opSpecId = 0;
01589   reader->u.llrpReader.accessSpecId = 0;
01590   reader->u.llrpReader.gen2AccessPassword = 0;
01591   memset(reader->u.llrpReader.paramConfirmed,0,
01592          sizeof(reader->u.llrpReader.paramConfirmed));
01593   memset(reader->u.llrpReader.paramPresent,0,
01594          sizeof(reader->u.llrpReader.paramPresent));
01595   
01596   reader->u.llrpReader.transportTimeout = 5000;
01597   reader->u.llrpReader.commandTimeout = 1000;
01598   reader->u.llrpReader.currentProtocol = TMR_TAG_PROTOCOL_NONE;
01599   reader->u.llrpReader.supportedProtocols = 0;
01600   reader->u.llrpReader.regionId = TMR_REGION_NONE;
01601   reader->u.llrpReader.tagsRemaining = 0;
01602   reader->continuousReading = false;
01603   reader->u.llrpReader.capabilities.model = 0;
01604 
01605   /* Initialize tagOpParams */
01606   reader->tagOpParams.antenna = 1;
01607   reader->tagOpParams.protocol = TMR_TAG_PROTOCOL_GEN2;
01608 
01609   /* Initialize llrp receiver thread params */
01610   pthread_mutex_init(&reader->u.llrpReader.receiverLock, NULL);
01611   pthread_cond_init(&reader->u.llrpReader.receiverCond, NULL);
01612   reader->u.llrpReader.receiverSetup = false;
01613   reader->u.llrpReader.receiverRunning = false;
01614   reader->u.llrpReader.receiverEnabled = false;
01615   reader->u.llrpReader.numOfROSpecEvents = 0;
01616   reader->u.llrpReader.bufResponse = NULL;
01617 
01618   /* Initialize keep alive params */
01619   reader->u.llrpReader.ka_start = 0;
01620   reader->u.llrpReader.ka_now   = 0;
01621   reader->u.llrpReader.get_report = false;
01622   reader->u.llrpReader.reportReceived = false;
01623   reader->u.llrpReader.isResponsePending = false;
01624   reader->u.llrpReader.threadCancel = false;
01625   return TMR_reader_init_internal(reader);
01626 }
01627 
01628 static TMR_Status
01629 TMR_LLRP_openConnectionToReader(TMR_Reader *reader, LLRP_tSConnection *pConn)
01630 {
01631   int sock;
01632   static const struct addrinfo addrInfoMask =
01633   {    
01634     0,   
01635     AF_INET,
01636     SOCK_STREAM,
01637     0,                                                                                                                                                             
01638     0,   
01639     NULL,
01640     NULL,
01641     NULL 
01642   };   
01643   struct addrinfo *           hostAddress;
01644   int                         flag;
01645   struct sockaddr_in          sin; 
01646   int                         rc;
01647 
01648   if (NULL == pConn)
01649   {
01650     return TMR_ERROR_LLRP_CONNECTIONFAILED;
01651   }
01652 
01653   /*
01654    * Clear the connect error string
01655    */
01656   pConn->pConnectErrorStr = NULL;
01657 
01658   /*
01659    * Make sure there isn't already a connection.
01660    */
01661   if(0 <= pConn->fd)
01662   {
01663     pConn->pConnectErrorStr = "already connected";
01664     return TMR_ERROR_LLRP_ALREADY_CONNECTED;
01665   }
01666 
01667   /*
01668    * Look up host using getaddrinfo().
01669    * Gethostbyname() could be configured a lot of
01670    * different ways. There is /etc/hosts, DNS, NIS, etc, etc.
01671    * Suffice to say it is big, bulky, and susceptible to stall.
01672    */
01673   if(0 != getaddrinfo(reader->uri, NULL, &addrInfoMask, &hostAddress))
01674   {
01675     pConn->pConnectErrorStr = "host lookup failed";
01676     return -1;
01677   }
01678 
01679   /*
01680    * Convert the address to sockaddr_in format
01681    */
01682   memset(&sin, 0, sizeof sin);
01683   sin.sin_family = AF_INET;
01684   sin.sin_addr = ((struct sockaddr_in *)(hostAddress->ai_addr))->sin_addr;
01685   sin.sin_port = htons(reader->u.llrpReader.portNum);
01686 
01687   /*
01688    * Done withe the host addrinfo
01689    */
01690   freeaddrinfo(hostAddress);
01691 
01692   /*
01693    * Create the socket.
01694    */
01695   sock = socket(AF_INET, SOCK_STREAM, 0);
01696   if(0 > sock)
01697   {
01698     pConn->pConnectErrorStr = "socket() failed";
01699     return TMR_ERROR_LLRP_CONNECTIONFAILED;
01700   }
01701 
01702   /*
01703    * Connect the socket to reader. This can stall.
01704    */
01705   rc = connect(sock, (struct sockaddr *)&sin, sizeof sin);
01706   if(0 > rc)
01707   {
01708     /* Connect failed */
01709     /* check for the error no */
01710     if (ECONNREFUSED ==  errno)
01711     {
01716       tmr_sleep(1000);
01717     }
01718     pConn->pConnectErrorStr = "connect() failed";
01719     close(sock);
01720     return TMR_ERROR_LLRP_CONNECTIONFAILED;
01721   }
01722 
01723   /*
01724    * Best effort to set no delay. If this doesn't work
01725    * (no reason it shouldn't) we do not declare defeat.
01726    */
01727   flag = 1;
01728   setsockopt(sock, IPPROTO_TCP, TCP_NODELAY, (void*)&flag, sizeof flag);
01729 
01730   /*
01731    * Record the socket in the connection instance
01732    */
01733   pConn->fd = sock;
01734 
01735   return TMR_SUCCESS;
01736 }
01737 
01738 TMR_Status
01739 TMR_LLRP_connect(TMR_Reader *reader)
01740 {
01741   TMR_Status ret;
01742   LLRP_tSMessage *pMsg = NULL;
01743   LLRP_tSREADER_EVENT_NOTIFICATION *pNtf;
01744   LLRP_tSReaderEventNotificationData *pNtfData;
01745   LLRP_tSConnectionAttemptEvent *pEvent;
01746   LLRP_tSConnection *pConn;
01747 
01748   ret = TMR_SUCCESS;
01749   /*
01750    * Construct a connection (LLRP_tSConnection).
01751    * Using a 32kb max frame size for send/recv.
01752    * The connection object is ready for business
01753    * but not actually connected to the reader yet.
01754    */
01755   reader->u.llrpReader.pConn = LLRP_Conn_construct(reader->u.llrpReader.pTypeRegistry, 32u*1024u);
01756   if(NULL == reader->u.llrpReader.pConn)
01757   {
01758     sprintf(reader->u.llrpReader.errMsg, "Error: Connection initialization failed");
01759     return TMR_ERROR_LLRP_CONNECTIONFAILED;
01760   }
01761 
01762   /*
01763    * Open the connection to the reader
01764    */
01765   pConn = reader->u.llrpReader.pConn;
01766   ret = TMR_LLRP_openConnectionToReader(reader, pConn);
01767   if(TMR_SUCCESS != ret)
01768   {
01769     LLRP_Conn_destruct(pConn);
01770     reader->u.llrpReader.pConn = NULL;
01771     sprintf(reader->u.llrpReader.errMsg,
01772             "Error: Connect - %s", pConn->pConnectErrorStr);
01773     return TMR_ERROR_LLRP_CONNECTIONFAILED;
01774   }
01775 
01776   /* Receive READER_EVENT_NOTIFICATION.ConnectionAttemptEvent */
01777   ret = TMR_LLRP_receiveMessage(reader, &pMsg, reader->u.llrpReader.commandTimeout);
01778   if (TMR_SUCCESS != ret)
01779   {
01780     goto fail;
01781   }
01782 
01783   /*
01784    * Check to make sure the message is of the right type.
01785    * The type label (pointer) in the message should be
01786    * the type descriptor for READER_EVENT_NOTIFICATION.
01787    */
01788   if (&LLRP_tdREADER_EVENT_NOTIFICATION != pMsg->elementHdr.pType)
01789   {
01790     goto fail;
01791   }
01792 
01793   /*
01794    * Now that we are sure it is a READER_EVENT_NOTIFICATION,
01795    * traverse to the ReaderEventNotificationData parameter.
01796    */
01797   pNtf = (LLRP_tSREADER_EVENT_NOTIFICATION *) pMsg;
01798   pNtfData = pNtf->pReaderEventNotificationData;
01799   if(NULL == pNtfData)
01800   {
01801     goto fail;
01802   }
01803 
01804   /*
01805    * The ConnectionAttemptEvent parameter must be present.
01806    */
01807   pEvent = pNtfData->pConnectionAttemptEvent;
01808   if(NULL == pEvent)
01809   {
01810     goto fail;
01811   }
01812 
01813   /*
01814    * The status in the ConnectionAttemptEvent parameter
01815    * must indicate connection success.
01816    */
01817   if(LLRP_ConnectionAttemptStatusType_Success != pEvent->eStatus)
01818   {
01819     goto fail;
01820   }
01821 
01822   /*
01823    * At this point, We are sure that the connection is success
01824    * Free the message
01825    */
01826   TMR_LLRP_freeMessage(pMsg);
01827   reader->connected = true;
01828   ret = TMR_LLRP_boot(reader);
01829   
01830   return ret;
01831 
01832 fail:
01833   /*
01834    * Connection attempt is not successful, Return Error
01835    */
01836   TMR_LLRP_freeMessage(pMsg);
01837   sprintf(reader->u.llrpReader.errMsg,
01838       "Error: Connection attempt failed");
01839   return TMR_ERROR_LLRP_CONNECTIONFAILED;
01840 }
01841 
01842 TMR_Status
01843 TMR_LLRP_destroy(TMR_Reader *reader)
01844 {
01845   LLRP_tSCLOSE_CONNECTION CloseConn = {
01846     .hdr.elementHdr.pType = &LLRP_tdCLOSE_CONNECTION,
01847     .hdr.MessageID        = reader->u.llrpReader.msgId ++,
01848   };
01849 
01850   LLRP_tSMessage *pRspMsg = NULL;
01851   uint8_t i;
01852 
01858   reader->u.llrpReader.threadCancel = true;
01859 
01861   pthread_join(reader->u.llrpReader.llrpReceiver, NULL);
01862   reader->u.llrpReader.threadCancel = false;
01863 
01864   pthread_mutex_lock(&reader->u.llrpReader.receiverLock);
01865   if (true == reader->u.llrpReader.receiverSetup)
01866   {
01867     usleep(10);
01868     reader->u.llrpReader.receiverSetup = false;
01869   }
01870   pthread_mutex_unlock(&reader->u.llrpReader.receiverLock);
01871 
01872 #ifdef TMR_ENABLE_BACKGROUND_READS
01873   /* Cleanup background threads */
01874   cleanup_background_threads(reader);
01875 #endif
01876 
01878   if (NULL != reader->u.llrpReader.bufResponse)
01879   {
01880     /* free this before leaking the memory */
01881     for (i = 0; i < reader->u.llrpReader.bufPointer; i++)
01882     {
01883       TMR_LLRP_freeMessage(reader->u.llrpReader.bufResponse[i]);
01884     }
01885     free(reader->u.llrpReader.bufResponse);
01886     reader->u.llrpReader.bufResponse=NULL;
01887   }
01888 
01889   if (true == reader->connected)
01890   {
01894     TMR_LLRP_send(reader, &CloseConn.hdr, &pRspMsg);
01901     if (NULL != pRspMsg)
01902     {
01903       TMR_LLRP_checkLLRPStatus(((LLRP_tSCLOSE_CONNECTION_RESPONSE *) pRspMsg)->pLLRPStatus);
01904 
01905       /* Free the response */
01906       TMR_LLRP_freeMessage(pRspMsg);
01907     }
01908     /*
01909      * Close the connection and release its resources
01910      */
01911   }
01912   if (NULL != reader->u.llrpReader.pConn)
01913   {
01914     LLRP_Conn_destruct(reader->u.llrpReader.pConn);
01915     reader->u.llrpReader.pConn=NULL;
01916   }
01917   if (NULL != reader->u.llrpReader.pTypeRegistry)
01918   {
01919     LLRP_TypeRegistry_destruct(reader->u.llrpReader.pTypeRegistry);
01920     reader->u.llrpReader.pTypeRegistry=NULL;
01921   }
01922   reader->connected = false;
01923   
01924   return TMR_SUCCESS;
01925 }
01926 
01927 static TMR_Status
01928 TMR_LLRP_read_internal(TMR_Reader *reader,
01929                         uint32_t timeoutMs,
01930                         TMR_ReadPlan *rp)
01931 {
01932   TMR_Status ret;
01933   TMR_LLRP_LlrpReader *lr;
01934   TMR_uint8List *antennaList = NULL;
01935 
01936   ret = TMR_SUCCESS;
01937   lr  = &reader->u.llrpReader;
01938   lr->searchTimeoutMs = timeoutMs;
01939   
01940   if (TMR_READ_PLAN_TYPE_SIMPLE == rp->type)
01941   {
01942     antennaList = &rp->u.simple.antennas;
01943     reader->fastSearch = rp->u.simple.useFastSearch;
01944   }
01945   else if (TMR_READ_PLAN_TYPE_MULTI == rp->type)
01946   {
01950     uint32_t subTimeout;
01951     int i;
01952 
01953     subTimeout = 0;
01954 
01959     reader->u.llrpReader.numOfROSpecEvents = rp->u.multi.planCount;
01964     if (0 == rp->u.multi.totalWeight)
01965     {
01966       subTimeout = timeoutMs / rp->u.multi.planCount;
01967     }
01968 
01969     for (i = 0; i < rp->u.multi.planCount; i ++)
01970     {
01971       if (rp->u.multi.totalWeight)
01972       {
01973         subTimeout = (rp->u.multi.plans[i]->weight * timeoutMs) 
01974                                   / rp->u.multi.totalWeight;
01975       }
01976 
01977       /* Iterate each simple read plan */
01978       ret = TMR_LLRP_read_internal(reader, subTimeout, rp->u.multi.plans[i]);
01979       if (TMR_SUCCESS != ret && TMR_ERROR_NO_TAGS_FOUND != ret)
01980       {
01981         return ret;
01982       }
01983     }
01984     return ret;
01985   }
01986   else
01987   {
01988     return TMR_ERROR_INVALID;
01989   }
01990 
01991   /* At this point we are guaranteed to have simple read plan */
01992   
01996   if (NULL == rp->u.simple.tagop)
01997   {
02001     lr->roSpecId++;
02002     if (TMR_LLRP_SYNC_MAX_ROSPECS <= lr->roSpecId)
02003     {
02004       lr->roSpecId = 1;
02005     }
02006     lr->readPlanProtocol[lr->roSpecId].rospecProtocol = rp->u.simple.protocol;
02007     lr->readPlanProtocol[lr->roSpecId].rospecID = lr->roSpecId;
02008     ret = TMR_LLRP_cmdPrepareROSpec(reader, (uint16_t)timeoutMs, antennaList, 
02009                                   rp->u.simple.filter, rp->u.simple.protocol);
02010   }
02011 
02015   else
02016   {
02022     lr->roSpecId ++;
02023     if (TMR_LLRP_SYNC_MAX_ROSPECS <= lr->roSpecId)
02024     {
02025       lr->roSpecId = 1;
02026     }
02027     lr->readPlanProtocol[lr->roSpecId].rospecProtocol = rp->u.simple.protocol;
02028     lr->readPlanProtocol[lr->roSpecId].rospecID = lr->roSpecId;
02029     ret = TMR_LLRP_cmdPrepareROSpec(reader, (uint16_t)timeoutMs, antennaList,
02030                                 rp->u.simple.filter, rp->u.simple.protocol);
02031     if (TMR_SUCCESS != ret)
02032     {
02033       return ret;
02034   }
02035 
02041     lr->accessSpecId ++;
02042     ret = TMR_LLRP_cmdAddAccessSpec(reader, rp->u.simple.protocol,
02043                                   NULL, lr->roSpecId, rp->u.simple.tagop, false);
02044     if (TMR_SUCCESS != ret)
02045   {
02046       return ret;
02047   }
02048 
02053     ret = TMR_LLRP_cmdEnableAccessSpec(reader, lr->accessSpecId);
02054     if (TMR_SUCCESS != ret)
02055   {
02056       return ret;
02057   }
02058  }
02059 
02060   if ((true == reader->continuousReading) &&
02061       (TMR_READ_PLAN_TYPE_MULTI == reader->readParams.readPlan->type))
02062   {
02067   return ret;
02068   }
02069   else
02070   {
02074     return TMR_LLRP_cmdStartROSpec(reader, lr->roSpecId);
02075   }
02076 }
02077 
02078 TMR_Status
02079 TMR_LLRP_read(TMR_Reader *reader, uint32_t timeoutMs, int32_t *tagCount)
02080 {
02081   TMR_Status ret;
02082   TMR_ReadPlan *rp;
02083   uint8_t i;
02084 
02085   rp = reader->readParams.readPlan;
02086   ret = TMR_SUCCESS;
02087 
02088   if (tagCount)
02089   {
02090     *tagCount = 0;
02091   }
02092 
02097   if (NULL != reader->u.llrpReader.bufResponse)
02098   {
02099     /* free this before leaking the memory */
02100     for (i = 0; i < reader->u.llrpReader.bufPointer; i++)
02101     {
02102       TMR_LLRP_freeMessage(reader->u.llrpReader.bufResponse[i]);
02103     }
02104     free(reader->u.llrpReader.bufResponse);
02105     reader->u.llrpReader.bufResponse=NULL;
02106   }
02107 
02108   reader->u.llrpReader.tagsRemaining = 0;
02109   reader->u.llrpReader.bufPointer = 0;
02110   reader->u.llrpReader.bufIndex = 0;
02111  
02112   reader->u.llrpReader.bufResponse = (LLRP_tSMessage **) malloc( 1 * sizeof(LLRP_tSMessage *));
02113   reader->u.llrpReader.pTagReportData = NULL;
02114    
02120   ret = TMR_LLRP_enableEventsAndReports(reader);
02121   if (TMR_SUCCESS != ret)
02122   {
02123     return ret;
02124   }
02125 
02131   ret = TMR_LLRP_cmdDeleteAllROSpecs(reader, true);
02132   /*FIXME:
02133    * If there are no rospecs on reader, it will throw an exception
02134    * Do we really need to care about the error here?
02135   if (TMR_SUCCESS != ret)
02136   {
02137     return ret;
02138   }*/
02144   ret = TMR_LLRP_cmdDeleteAllAccessSpecs(reader);
02149   if (!reader->continuousReading)
02150   {
02155     /* Enable Reader Event Notifications */
02156     ret = TMR_LLRP_cmdSetEventNotificationSpec(reader, true);
02157     if (TMR_SUCCESS != ret)
02158     {
02159       return ret;
02160     }
02161   }
02162 
02166   reader->u.llrpReader.numOfROSpecEvents = 1;
02167 
02168   ret = TMR_LLRP_read_internal(reader, timeoutMs, rp);
02169   if (TMR_SUCCESS != ret)
02170   {
02171     return ret;
02172   }
02173 
02174   if (!reader->continuousReading)
02175   {
02180     ret = TMR_LLRP_verifyReadOperation(reader, tagCount);
02181     if (TMR_SUCCESS != ret)
02182     {
02183 #ifdef TMR_ENABLE_BACKGROUND_READS      
02184       notify_exception_listeners(reader, ret);
02185 #endif
02186       return ret;
02187     }
02188 
02193     /* Disable Reader Event Notifications */
02194     ret = TMR_LLRP_cmdSetEventNotificationSpec(reader, false);
02195     if (TMR_SUCCESS != ret)
02196     {
02197       return ret;
02198     }
02199   }
02200 
02201   return ret;
02202 }
02203 
02204 TMR_Status
02205 TMR_LLRP_hasMoreTags(TMR_Reader *reader)
02206 {
02207   TMR_LLRP_LlrpReader *lr;
02208   TMR_Status ret;
02209 
02210   lr = &reader->u.llrpReader;
02211   ret = TMR_SUCCESS;
02212 
02213 #ifdef TMR_ENABLE_BACKGROUND_READS
02214   if (reader->continuousReading)
02215   {
02216     const LLRP_tSTypeDescriptor   *pType;
02217     int timeout;
02218 
02219     timeout = lr->searchTimeoutMs;
02220 
02221     if (true == reader->u.llrpReader.get_report)
02222     {
02226       ret = TMR_LLRP_cmdGetReport(reader);
02227       if (TMR_SUCCESS == ret)
02228       {
02229         reader->u.llrpReader.get_report = false;
02230       }
02231     }
02232 
02237     ret = TMR_LLRP_receiveMessage(reader, &lr->bufResponse[0], timeout);
02238     if (TMR_SUCCESS != ret)
02239     {
02240       TMR_LLRP_freeMessage(lr->bufResponse[0]);
02241       
02242       if (TMR_ERROR_LLRP_RECEIVEIO_ERROR == ret)
02243       {
02244         uint64_t diffTime;
02245 
02246         reader->u.llrpReader.ka_now = tmr_gettime();
02247         diffTime = reader->u.llrpReader.ka_now - reader->u.llrpReader.ka_start;
02248         if ((TMR_LLRP_KEEP_ALIVE_TIMEOUT * 4) < diffTime)
02249         {
02256           return TMR_ERROR_LLRP_READER_CONNECTION_LOST;
02257         }
02258       }
02259       return ret;
02260     }
02261 
02262     if (NULL != lr->bufResponse[0])
02263     {
02264       pType = lr->bufResponse[0]->elementHdr.pType;
02265 
02269       if (&LLRP_tdRO_ACCESS_REPORT == pType)
02270       {
02271         reader->isStatusResponse = false;
02272         reader->u.llrpReader.reportReceived = true;
02273         return TMR_SUCCESS;
02274       }
02278       else if(&LLRP_tdRFSurveyReportData == pType)
02279       {
02280         reader->isStatusResponse = true;
02281         /* TODO: yet to be implemented */
02282         return TMR_ERROR_UNIMPLEMENTED_FEATURE;
02283       }
02288       else if(&LLRP_tdREADER_EVENT_NOTIFICATION == pType)
02289       {
02299         TMR_LLRP_handleReaderEvents(reader, lr->bufResponse[0]);
02300 
02305         return TMR_ERROR_NO_TAGS;
02306       }
02310       else if (&LLRP_tdKEEPALIVE == pType)
02311       {
02316         reader->u.llrpReader.ka_start = tmr_gettime();
02317 
02318         /* handle keepalive messages. */
02319         TMR_LLRP_handleKeepAlive(reader, lr->bufResponse[0]);
02320 
02326         if (false == reader->u.llrpReader.reportReceived)
02327         {
02328           reader->u.llrpReader.get_report = true;
02329         }
02330         reader->u.llrpReader.reportReceived = false;
02331 
02332         return TMR_ERROR_NO_TAGS;
02333       }
02338       else if ((&LLRP_tdSTOP_ROSPEC_RESPONSE == pType) ||
02339                (&LLRP_tdDELETE_ROSPEC_RESPONSE == pType))
02340       {
02341         reader->finishedReading = true;
02342         TMR_LLRP_freeMessage(lr->bufResponse[0]);
02343         free(lr->bufResponse);
02344         lr->bufResponse = NULL;
02345         return TMR_ERROR_END_OF_READING;
02346       }
02347       else
02348       {
02353         reader->u.llrpReader.unhandledAsyncResponse.lMsg = reader->u.llrpReader.bufResponse[0];
02354         reader->u.llrpReader.isResponsePending = true;
02355 
02356         return TMR_ERROR_NO_TAGS;
02357       }
02358     }
02359   }
02360   else
02361 #endif
02362   {
02367     ret = (lr->tagsRemaining > 0) ? TMR_SUCCESS : TMR_ERROR_NO_TAGS;
02368 
02369     if (TMR_SUCCESS == ret)
02370     {
02371       /* If TagReportData is not null, loop through the list */
02372       if (NULL != lr->pTagReportData)
02373       {
02374         lr->pTagReportData = (LLRP_tSTagReportData *)lr->pTagReportData->hdr.pNextSubParameter;
02375       }
02376 
02382       if (NULL == lr->pTagReportData)
02383       {
02389         LLRP_tSRO_ACCESS_REPORT *pReport;
02390     
02391         pReport = (LLRP_tSRO_ACCESS_REPORT *)lr->bufResponse[lr->bufIndex];
02392         lr->pTagReportData = pReport->listTagReportData;
02393           lr->bufIndex ++;
02394         }
02395     }
02396     else
02397     {
02402       uint8_t i;
02403 
02404       for (i = 0; i < lr->bufIndex; i ++)
02405       {
02406         TMR_LLRP_freeMessage(lr->bufResponse[i]);
02407       }
02408       
02413       free(lr->bufResponse);
02414       lr->bufResponse = NULL;
02415     }
02416   }
02417     return ret;
02418 }
02419 
02420 TMR_Status
02421 TMR_LLRP_getNextTag(TMR_Reader *reader, TMR_TagReadData *data)
02422 {
02423   TMR_LLRP_LlrpReader *lr;
02424   TMR_Status ret;
02425   LLRP_tSMessage *pMsg;
02426 
02427   lr = &reader->u.llrpReader;
02428   ret = TMR_SUCCESS;
02429 
02430   pMsg = lr->bufResponse[lr->bufIndex];
02431 
02432   if (0 == lr->tagsRemaining)
02433   {
02434     return TMR_ERROR_NO_TAGS;
02435   }
02436 
02437   if (reader->continuousReading)
02438   {
02439     ret = TMR_LLRP_hasMoreTags(reader);
02440     if (TMR_SUCCESS != ret)
02441     {
02442       return ret;
02443     }
02444   }
02445   
02449   TMR_TRD_init(data);
02450 
02451   /* Parse the response message */
02452   ret = TMR_LLRP_parseMetadataFromMessage(reader, data, lr->pTagReportData);
02453   if (TMR_SUCCESS != ret)
02454   {
02455     TMR_LLRP_freeMessage(pMsg);
02456     return ret;
02457   }
02458 
02459   if (reader->continuousReading)
02460   {
02465     TMR_LLRP_freeMessage(pMsg);
02466   }
02467   else
02468   {
02469     lr->tagsRemaining --;
02470   }
02471 
02472   data->reader = reader;
02473   return ret;
02474 }
02475 
02492 TMR_Status
02493 TMR_LLRP_executeTagOp(TMR_Reader *reader, TMR_TagOp *tagop, 
02494                 TMR_TagFilter *filter, TMR_uint8List *data)
02495 {
02496   TMR_Status ret;
02497   TMR_LLRP_LlrpReader *lr;
02498   TMR_TagProtocol protocol;
02499   int timeout;
02500   uint64_t start, end, difftime;
02501 
02502   lr = &reader->u.llrpReader;
02503   ret = TMR_SUCCESS;
02504  
02505   reader->u.llrpReader.bufPointer = 0;
02510   if (NULL != reader->u.llrpReader.bufResponse)
02511   {
02512     /* free this before leaking the memory */
02513     free(reader->u.llrpReader.bufResponse);
02514     reader->u.llrpReader.bufResponse=NULL;
02515   }
02516   reader->u.llrpReader.bufResponse = (LLRP_tSMessage **) malloc(1 * sizeof(LLRP_tSMessage *));
02517 
02518 
02538   TMR_LLRP_cmdDeleteAllROSpecs(reader, true);
02539   TMR_LLRP_cmdDeleteAllAccessSpecs(reader);
02540 
02546   {
02547     uint8_t antenna[1];
02548     TMR_uint8List antennaList;
02549 
02555     antenna[0] = reader->tagOpParams.antenna;
02556     antennaList.len = 1;
02557     antennaList.max = 1;
02558     antennaList.list = antenna;
02559 
02563     if ((TMR_TAGOP_ISO180006B_READDATA == tagop->type) || (TMR_TAGOP_ISO180006B_WRITEDATA == tagop->type)
02564                                           ||(TMR_TAGOP_ISO180006B_LOCK == tagop->type))
02565     {
02566       protocol = TMR_TAG_PROTOCOL_ISO180006B;
02567     }
02568     else
02569     {
02570       protocol = reader->tagOpParams.protocol;
02571     }
02572 
02576     lr->roSpecId ++;
02577     /* timeout = 0, as it has no significance in this case */
02578     ret = TMR_LLRP_cmdPrepareROSpec(reader, 0, &antennaList, filter, protocol);
02579     if (TMR_SUCCESS != ret)
02580     {
02581       return ret;
02582     }
02583   }
02584 
02588   lr->accessSpecId ++;
02595   ret = TMR_LLRP_cmdAddAccessSpec(reader, protocol, NULL,
02596                                 lr->roSpecId, tagop, true);
02597   if (TMR_SUCCESS != ret)
02598   {
02599     return ret;
02600   }
02601 
02605   ret = TMR_LLRP_cmdEnableAccessSpec(reader, lr->accessSpecId);
02606   if (TMR_SUCCESS != ret)
02607   {
02608     return ret;
02609   }
02610 
02614   ret = TMR_LLRP_cmdStartROSpec(reader, lr->roSpecId);
02615   if (TMR_SUCCESS != ret)
02616   {
02617     return ret;
02618   }
02619 
02625   timeout = lr->commandTimeout + lr->transportTimeout;
02626   start = tmr_gettime();
02627   while (true)
02628   {
02634     if (lr->bufPointer)
02635     {
02636       break;
02637     }
02638     end = tmr_gettime();
02639     difftime = end - start;
02640     if (difftime > timeout)
02641     {
02647       return TMR_ERROR_TIMEOUT;
02648     }
02649   }
02650 
02654   {
02655     LLRP_tSRO_ACCESS_REPORT *pReport;
02656     LLRP_tSTagReportData *pTagReportData;
02657 
02658     pReport = (LLRP_tSRO_ACCESS_REPORT *)lr->bufResponse[0];
02659     pTagReportData = pReport->listTagReportData;
02660 
02661     if (NULL != pTagReportData)
02662     {
02663       LLRP_tSParameter *pOpSpec;
02664 
02669       pOpSpec = pTagReportData->listAccessCommandOpSpecResult;
02670       /* Verify the OpSpecResult status */
02671       ret = TMR_LLRP_verifyOpSpecResultStatus(reader, pOpSpec);
02672       if (TMR_SUCCESS != ret)
02673       {
02678         return ret;
02679       }
02683       if (NULL != data)
02684       {
02685         TMR_LLRP_parseTagOpSpecData(pOpSpec, data);
02686       }
02687     }
02688 
02692     {
02693       uint8_t i;
02694 
02695       for (i = 0; i < lr->bufPointer; i ++)
02696       {
02697         TMR_LLRP_freeMessage(lr->bufResponse[i]);
02698       }
02699       free(lr->bufResponse);
02700       lr->bufResponse = NULL;
02701     }
02702   }
02703   return ret;
02704 }
02705 
02706 TMR_Status
02707 TMR_LLRP_gpiGet(struct TMR_Reader *reader, uint8_t *count,
02708                          TMR_GpioPin state[])
02709 {
02710   TMR_Status ret;
02711   ret = TMR_LLRP_cmdGetGPIState(reader, count, state);
02712   return ret;
02713 }
02714 
02715 TMR_Status
02716 TMR_LLRP_gpoSet(struct TMR_Reader *reader, uint8_t count,
02717                       const TMR_GpioPin state[])
02718 {
02719   TMR_Status ret;
02720   ret = TMR_LLRP_cmdSetGPOState(reader, count, state);
02721   return ret;
02722 }
02723 
02724 TMR_Status
02725 TMR_LLRP_readTagMemBytes(struct TMR_Reader *reader, const TMR_TagFilter *filter,
02726                          uint32_t bank, uint32_t address,
02727                          uint16_t count,uint8_t data[])
02728 {
02729   TMR_Status ret;
02730   /*
02731    * currently in fixed reader this feature is
02732    * not supported
02733    */
02734   ret = TMR_ERROR_UNSUPPORTED;
02735   return ret;
02736 }
02737 
02738 TMR_Status
02739 TMR_LLRP_readTagMemWords(struct TMR_Reader *reader, const TMR_TagFilter *filter,
02740                          uint32_t bank, uint32_t address,
02741                          uint16_t count, uint16_t *data)
02742 {
02743   TMR_Status ret;
02744   /*
02745    * currently in fixed reader this feature is
02746    * not supported
02747    */
02748   ret = TMR_ERROR_UNSUPPORTED;
02749   return ret;
02750 }
02751 
02752 TMR_Status
02753 TMR_LLRP_writeTagMemBytes(struct TMR_Reader *reader, const TMR_TagFilter *filter,
02754                          uint32_t bank, uint32_t address,
02755                          uint16_t count,const uint8_t data[])
02756 {
02757   TMR_Status ret;
02758   /*
02759    * currently in fixed reader this feature is
02760    * not supported
02761    */
02762   ret = TMR_ERROR_UNSUPPORTED;
02763   return ret;
02764 }
02765 
02766 TMR_Status
02767 TMR_LLRP_writeTagMemWords(struct TMR_Reader *reader, const TMR_TagFilter *filter,
02768                          uint32_t bank, uint32_t address,
02769                          uint16_t count, const uint16_t *data)
02770 {
02771   TMR_Status ret;
02772   /*
02773    * currently in fixed reader this feature is
02774    * not supported
02775    */
02776   ret = TMR_ERROR_UNSUPPORTED;
02777   return ret;
02778 }
02779 
02780 TMR_Status
02781 TMR_LLRP_firmwareLoad( TMR_Reader *reader, void *cookie,
02782                       TMR_FirmwareDataProvider provider)
02783 {
02784   TMR_Status ret;
02785   /*
02786    * currently in fixed reader this feature is
02787    * not supported
02788    */
02789   ret = TMR_ERROR_UNSUPPORTED;
02790   return ret;
02791 }
02792 
02793 TMR_Status
02794 TMR_LLRP_reboot(TMR_Reader *reader)
02795 {
02796   TMR_Status ret;
02797 
02798   ret = TMR_LLRP_cmdrebootReader(reader);
02799 
02800   return ret;
02801 }
02802 
02803 TMR_Status
02804 TMR_LLRP_writeTag( TMR_Reader *reader, const TMR_TagFilter *filter,
02805                   const TMR_TagData *data)
02806 {
02807   TMR_Status ret;
02808   TMR_TagOp tagop;
02809   ret = TMR_TagOp_init_GEN2_WriteTag(&tagop, (TMR_TagData *)data);
02810   ret = TMR_executeTagOp(reader, &tagop, (TMR_TagFilter *)filter, NULL);
02811   if (TMR_SUCCESS != ret)
02812   {
02817     return ret;
02818   }
02819   return ret;
02820 }
02821 
02822 TMR_Status
02823 TMR_LLRP_killTag(struct TMR_Reader *reader, const TMR_TagFilter *filter,
02824                  const TMR_TagAuthentication *auth)
02825 {
02826   TMR_Status ret;
02827   TMR_TagOp tagop;
02828   TMR_TagOp_init_GEN2_Kill(&tagop, auth->u.gen2Password);
02829   ret= TMR_executeTagOp(reader,&tagop, (TMR_TagFilter *)filter, NULL);
02830   if (TMR_SUCCESS != ret)
02831   {
02836     return ret;
02837   }
02838   return ret;
02839 
02840 }
02841 
02842 TMR_Status
02843 TMR_LLRP_lockTag(struct TMR_Reader *reader,const TMR_TagFilter *filter,
02844                  TMR_TagLockAction *action)
02845 {
02846   TMR_Status ret;
02847   TMR_TagOp tagop;
02848   TMR_TagOp_init_GEN2_Lock(&tagop, action->u.gen2LockAction.mask, action->u.gen2LockAction.action, 
02849       reader->u.llrpReader.gen2AccessPassword);
02850   ret= TMR_executeTagOp(reader,&tagop, (TMR_TagFilter *)filter, NULL);
02851   if (TMR_SUCCESS != ret)
02852   {
02857     return ret;
02858   }
02859   return ret;
02860 }
02861 #endif /* TMR_ENABLE_LLRP_TRANSPORT  */
02862 


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