tm_reader_async.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 #include "tm_config.h"
00030 #include "tm_reader.h"
00031 #include "serial_reader_imp.h"
00032 #include <stdio.h>
00033 #ifdef TMR_ENABLE_BACKGROUND_READS
00034 
00035 #include <stdlib.h>
00036 #include <pthread.h>
00037 #include <semaphore.h>
00038 #include <time.h>
00039 #include <stdio.h>
00040 
00041 #ifndef WIN32
00042 #include <sys/time.h>
00043 #endif
00044 
00045 #ifdef TMR_ENABLE_LLRP_READER
00046 #include "llrp_reader_imp.h"
00047 #endif
00048 #include "osdep.h"
00049 #include "tmr_utils.h"
00050 
00051 static void *do_background_reads(void *arg);
00052 static void *parse_tag_reads(void *arg);
00053 static void process_async_response(TMR_Reader *reader);
00054 bool IsDutyCycleEnabled(TMR_Reader *reader);
00055 bool isBufferOverFlow = false;
00056 #endif /* TMR_ENABLE_BACKGROUND_READS */
00057 
00058 TMR_Status
00059 TMR_startReading(struct TMR_Reader *reader)
00060 {
00061 #ifdef SINGLE_THREAD_ASYNC_READ
00062   TMR_Status ret;
00063   reader->continuousReading = true;
00064   ret = TMR_read(reader, 500, NULL);
00065   if(TMR_SUCCESS != ret)
00066      return ret;
00067 #else
00068 #ifdef TMR_ENABLE_BACKGROUND_READS
00069   int ret;
00070   bool createParser = true;
00071 
00072   if (TMR_READER_TYPE_SERIAL == reader->readerType)
00073   {
00074 #ifdef TMR_ENABLE_SERIAL_READER
00075 
00080     if (TMR_READ_PLAN_TYPE_MULTI == reader->readParams.readPlan->type)
00081     {
00082       uint8_t loop = 0;
00083       TMR_MultiReadPlan *multi;
00084 
00085       multi = &reader->readParams.readPlan->u.multi;
00086 
00087       for (loop = 0; loop < multi->planCount; loop++)
00088       {
00089         if (multi->plans[loop]->u.simple.stopOnCount.stopNTriggerStatus)
00090         {
00091           /* Not supporting stop N trigger */
00092           return TMR_ERROR_UNSUPPORTED; 
00093         }
00094       }
00095     }
00096     else if (TMR_READ_PLAN_TYPE_SIMPLE == reader->readParams.readPlan->type)
00097     {
00098       if (reader->readParams.readPlan->u.simple.stopOnCount.stopNTriggerStatus)
00099       {
00100         /* Not supporting stop N trigger */
00101         return TMR_ERROR_UNSUPPORTED;
00102       }
00103     }
00104     else
00105     {
00106       /* do nothing */
00107     }
00108 
00114     if (
00115         ((TMR_SR_MODEL_M6E == reader->u.serialReader.versionInfo.hardware[0])||
00116          (TMR_SR_MODEL_M6E_I == reader->u.serialReader.versionInfo.hardware[0]) ||
00117          (TMR_SR_MODEL_MICRO == reader->u.serialReader.versionInfo.hardware[0]) ||
00118          (TMR_SR_MODEL_M6E_NANO == reader->u.serialReader.versionInfo.hardware[0])) &&
00119         (reader->readParams.asyncOffTime == 0 || (reader->readParams.asyncOffTime != 0 && IsDutyCycleEnabled(reader)) ) &&
00120         ((TMR_READ_PLAN_TYPE_SIMPLE == reader->readParams.readPlan->type) || 
00121          ((TMR_READ_PLAN_TYPE_MULTI == reader->readParams.readPlan->type)  && 
00122           (compareAntennas(&reader->readParams.readPlan->u.multi))))
00123        )
00124     {
00125                 if (reader->readParams.asyncOffTime == 0)
00126                 {
00127                         reader->dutyCycle = false;
00128                 }
00129                 else
00130                 {
00131                         reader->dutyCycle = true;
00132                 }
00133     }
00134     else
00135     {
00136       createParser = false;
00137           reader->dutyCycle = false;
00138     }
00139 #else
00140     return TMR_ERROR_UNSUPPORTED;
00141 #endif/* TMR_ENABLE_SERIAL_READER */    
00142   }
00143 #ifdef TMR_ENABLE_LLRP_READER
00144   if (TMR_READER_TYPE_LLRP == reader->readerType)
00145   {
00150     TMR_LLRP_setBackgroundReceiverState(reader, false);
00156     reader->u.llrpReader.ka_start = tmr_gettime();
00157   }
00158 #endif
00159 
00163   pthread_mutex_lock(&reader->backgroundLock);
00164   reader->readState = TMR_READ_STATE_STARTING;
00165   pthread_cond_broadcast(&reader->readCond);
00166   pthread_mutex_unlock(&reader->backgroundLock);
00167 
00168   if (true == createParser)
00169   {
00176     pthread_mutex_lock(&reader->parserLock);
00177     
00178     if (false == reader->parserSetup)
00179     {
00180       ret = pthread_create(&reader->backgroundParser, NULL,
00181                        parse_tag_reads, reader);
00182       if (0 != ret)
00183       {
00184         pthread_mutex_unlock(&reader->parserLock);
00185         return TMR_ERROR_NO_THREADS;
00186       }
00187       pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL);
00188       pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
00189       pthread_detach(reader->backgroundParser);
00193       reader->queue_depth = 0;
00194       sem_init(&reader->queue_length, 0, 0);
00195       sem_init(&reader->queue_slots, 0, TMR_MAX_QUEUE_SLOTS);
00196       reader->parserSetup = true;
00197     }
00198 
00199     reader->parserEnabled = true;
00200 
00201 
00202     /* Enable streaming */
00203     reader->continuousReading = true;
00204     reader->finishedReading = false;
00205     pthread_cond_signal(&reader->parserCond);
00206     pthread_mutex_unlock(&reader->parserLock);
00207   }
00208 
00209   /* Background reader thread initialization */
00210   pthread_mutex_lock(&reader->backgroundLock);
00211 
00212   if (false == reader->backgroundSetup)
00213   {
00214     ret = pthread_create(&reader->backgroundReader, NULL,
00215                          do_background_reads, reader);
00216     if (0 != ret)
00217     {
00218       pthread_mutex_unlock(&reader->backgroundLock);
00219       return TMR_ERROR_NO_THREADS;
00220     }
00221     pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL);
00222     pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
00223     reader->backgroundSetup = true;
00224   }
00225 
00226   reader->backgroundEnabled = true;
00227   reader->searchStatus = true;
00228 
00229 #ifdef TMR_ENABLE_SERIAL_READER    
00230   if (TMR_READER_TYPE_SERIAL == reader->readerType)
00231   {
00232     reader->u.serialReader.tagopFailureCount = 0;
00233     reader->u.serialReader.tagopSuccessCount = 0;
00234   }
00235 #endif/* TMR_ENABLE_SERIAL_READER */    
00236   pthread_cond_signal(&reader->backgroundCond);
00237   pthread_mutex_unlock(&reader->backgroundLock);
00238 
00239   /* End of Background reader thread initialization */
00245   pthread_mutex_lock(&reader->backgroundLock);
00246   while (TMR_READ_STATE_STARTING == reader->readState)
00247   {
00248     pthread_cond_wait(&reader->readCond, &reader->backgroundLock);
00249   }
00250   pthread_mutex_unlock(&reader->backgroundLock);
00251 #endif /* TMR_ENABLE_BACKGROUND_READS */
00252 #endif
00253 
00254   return TMR_SUCCESS;
00255 }
00256 #ifdef TMR_ENABLE_BACKGROUND_READS
00257 bool IsDutyCycleEnabled(struct TMR_Reader *reader)
00258 {
00259         uint16_t i; 
00260         uint8_t *readerVersion = reader->u.serialReader.versionInfo.fwVersion ;
00261         uint8_t checkVersion[4];
00262         switch (reader->u.serialReader.versionInfo.hardware[0])
00263         {
00264                 case TMR_SR_MODEL_M6E:
00265                 case TMR_SR_MODEL_M6E_I:
00266                         checkVersion[0] = 0x01; checkVersion[1] = 0x21; checkVersion[2] = 0x01; checkVersion[3] = 0x07;
00267                         break;
00268                 case TMR_SR_MODEL_MICRO:
00269                         checkVersion[0] = 0x01; checkVersion[1] = 0x09; checkVersion[2] = 0x00; checkVersion[3] = 0x02;
00270                         break;
00271                 case TMR_SR_MODEL_M6E_NANO:
00272                         checkVersion[0] = 0x01; checkVersion[1] = 0x07; checkVersion[2] = 0x00; checkVersion[3] = 0x02;
00273                         break;
00274                 default:
00275                         checkVersion[0] = 0xFF; checkVersion[1] = 0xFF; checkVersion[2] = 0xFF; checkVersion[3] = 0xFF;
00276         }
00277         for (i = 0; i < 4; i++)
00278         {
00279                 if (readerVersion[i] < checkVersion[i])
00280                 {
00281                         return false;
00282                 }
00283         }
00284         return true;
00285 }
00286 
00287 #endif /* TMR_ENABLE_BACKGROUND_READS */
00288 
00289 void
00290 reset_continuous_reading(struct TMR_Reader *reader, bool dueToError)
00291 {
00292   if (true == reader->continuousReading)
00293   {
00294 #ifndef SINGLE_THREAD_ASYNC_READ
00295 #ifdef TMR_ENABLE_LLRP_READER
00296     if (TMR_READER_TYPE_LLRP == reader->readerType)
00297     {
00302       TMR_LLRP_setBackgroundReceiverState(reader, true);
00303     }
00304 #endif
00305 
00306 #ifdef TMR_ENABLE_SERIAL_READER      
00307     if ((false == dueToError) && (TMR_READER_TYPE_SERIAL == reader->readerType))
00308     {
00312       TMR_Status ret;
00313       bool value = reader->u.serialReader.enableReadFiltering;
00314           reader->hasContinuousReadStarted = false;
00315       ret = TMR_SR_cmdSetReaderConfiguration(reader, TMR_SR_CONFIGURATION_ENABLE_READ_FILTER, &value);
00316       if (TMR_SUCCESS != ret)
00317       {
00318 #ifndef BARE_METAL
00319         notify_exception_listeners(reader, ret);
00320 #endif
00321       }
00322     }
00323 #endif/* TMR_ENABLE_SERIAL_READER */      
00324 #endif /*SINGLE_THREAD_ASYNC_READ*/
00325     /* disable streaming */
00326     reader->continuousReading = false;
00327   }
00328 }
00329 
00330 TMR_Status
00331 TMR_stopReading(struct TMR_Reader *reader)
00332 {
00333   reader->hasContinuousReadStarted = false;
00334 #ifdef SINGLE_THREAD_ASYNC_READ
00335   reader->cmdStopReading(reader);
00336 #else
00337 #ifdef TMR_ENABLE_BACKGROUND_READS
00338 
00339   /* Check if background setup is active */
00340   pthread_mutex_lock(&reader->backgroundLock);
00341 
00342   if (false == reader->backgroundSetup)
00343   {
00344     pthread_mutex_unlock(&reader->backgroundLock);
00345     return TMR_SUCCESS;
00346   }
00347 
00348   if (false == reader->searchStatus)
00349   {
00354     pthread_mutex_unlock(&reader->backgroundLock);
00355     return TMR_SUCCESS;
00356   }
00361   reader->searchStatus = false;
00362   pthread_mutex_unlock(&reader->backgroundLock);
00363 
00367   pthread_mutex_lock(&reader->backgroundLock);
00368   while (TMR_READ_STATE_STARTING == reader->readState)
00369   {
00370     pthread_cond_wait(&reader->readCond, &reader->backgroundLock);
00371     }
00372   pthread_mutex_unlock(&reader->backgroundLock);
00373 
00374   if ((true == reader->continuousReading) && (true == reader->trueAsyncflag))
00375     {
00380     if(!isBufferOverFlow)
00381     {
00382       reader->cmdStopReading(reader);
00383     }
00384 
00389     pthread_mutex_lock(&reader->backgroundLock);
00390     while (TMR_READ_STATE_DONE != reader->readState)
00391     {
00392       pthread_cond_wait(&reader->readCond, &reader->backgroundLock);
00393     }
00394     pthread_mutex_unlock(&reader->backgroundLock);
00400   }
00401 
00407   pthread_mutex_lock(&reader->backgroundLock);
00408   reader->backgroundEnabled = false;
00409   while (true == reader->backgroundRunning)
00410   {
00411     pthread_cond_wait(&reader->backgroundCond, &reader->backgroundLock);
00412   }
00413   pthread_mutex_unlock(&reader->backgroundLock);
00414 
00420 #else
00421         reader->cmdStopReading(reader);
00422 #endif
00423   reset_continuous_reading(reader, false);
00424 #endif
00425   return TMR_SUCCESS;
00426 }
00427 
00428 void
00429 notify_read_listeners(TMR_Reader *reader, TMR_TagReadData *trd)
00430 {
00431   TMR_ReadListenerBlock *rlb;
00432 
00433   /* notify tag read to listener */
00434   if (NULL != reader)
00435   {
00436 #ifndef SINGLE_THREAD_ASYNC_READ
00437     pthread_mutex_lock(&reader->listenerLock);
00438 #endif
00439         rlb = reader->readListeners;
00440     while (rlb)
00441     {
00442       rlb->listener(reader, trd, rlb->cookie);
00443       rlb = rlb->next;
00444     }
00445 #ifndef SINGLE_THREAD_ASYNC_READ
00446     pthread_mutex_unlock(&reader->listenerLock);
00447 #endif
00448   }
00449 }
00450 
00451 void
00452 notify_stats_listeners(TMR_Reader *reader, TMR_Reader_StatsValues *stats)
00453 {
00454   TMR_StatsListenerBlock *slb;
00455 
00456   /* notify stats to the listener */
00457 #ifndef SINGLE_THREAD_ASYNC_READ
00458   pthread_mutex_lock(&reader->listenerLock);
00459 #endif
00460   slb = reader->statsListeners;
00461   while (slb)
00462   {
00463     slb->listener(reader, stats, slb->cookie);
00464     slb = slb->next;
00465   }
00466 #ifndef SINGLE_THREAD_ASYNC_READ
00467   pthread_mutex_unlock(&reader->listenerLock);
00468 #endif
00469 }
00470 
00471 #ifdef TMR_ENABLE_BACKGROUND_READS
00472 /* NOTE: There is only one auth object for all the authreq listeners, so whichever listener touches it last wins.
00473  * For now (2012 Jul 20) we only anticipate having a single authreq listener, but there may be future cases which 
00474  * require multiples.  Revise this design if necessary. */
00475 void
00476 notify_authreq_listeners(TMR_Reader *reader, TMR_TagReadData *trd, TMR_TagAuthentication *auth)
00477 {
00478   TMR_AuthReqListenerBlock *arlb;
00479 
00480   /* notify tag read to listener */
00481   pthread_mutex_lock(&reader->listenerLock);
00482   arlb = reader->authReqListeners;
00483   while (arlb)
00484   {
00485     arlb->listener(reader, trd, arlb->cookie, auth);
00486     arlb = arlb->next;
00487   }
00488   pthread_mutex_unlock(&reader->listenerLock);
00489 }
00490 #endif /* TMR_ENABLE_BACKGROUND_READS */
00491 
00492 TMR_Status
00493 TMR_addReadExceptionListener(TMR_Reader *reader,
00494                              TMR_ReadExceptionListenerBlock *b)
00495 {
00496 #ifndef SINGLE_THREAD_ASYNC_READ
00497   if (0 != pthread_mutex_lock(&reader->listenerLock))
00498     return TMR_ERROR_TRYAGAIN;
00499 #endif
00500   b->next = reader->readExceptionListeners;
00501   reader->readExceptionListeners = b;
00502 
00503 #ifndef SINGLE_THREAD_ASYNC_READ
00504   pthread_mutex_unlock(&reader->listenerLock);
00505 #endif
00506   return TMR_SUCCESS;
00507 }
00508 
00509 #ifdef TMR_ENABLE_BACKGROUND_READS
00510 TMR_Status
00511 TMR_removeReadExceptionListener(TMR_Reader *reader,
00512                                 TMR_ReadExceptionListenerBlock *b)
00513 {
00514   TMR_ReadExceptionListenerBlock *block, **prev;
00515 
00516   if (0 != pthread_mutex_lock(&reader->listenerLock))
00517     return TMR_ERROR_TRYAGAIN;
00518 
00519   prev = &reader->readExceptionListeners;
00520   block = reader->readExceptionListeners;
00521   while (NULL != block)
00522   {
00523     if (block == b)
00524     {
00525       *prev = block->next;
00526       break;
00527     }
00528     prev = &block->next;
00529     block = block->next;
00530   }
00531 
00532   pthread_mutex_unlock(&reader->listenerLock);
00533 
00534   if (block == NULL)
00535   {
00536     return TMR_ERROR_INVALID;
00537   }
00538 
00539   return TMR_SUCCESS;
00540 }
00541 #endif
00542 
00543 void
00544 notify_exception_listeners(TMR_Reader *reader, TMR_Status status)
00545 {
00546   TMR_ReadExceptionListenerBlock *relb;
00547 
00548   if (NULL != reader)
00549   {
00550 #ifndef SINGLE_THREAD_ASYNC_READ
00551     pthread_mutex_lock(&reader->listenerLock);
00552 #endif
00553     relb = reader->readExceptionListeners;
00554     while (relb)
00555     {
00556       relb->listener(reader, status, relb->cookie);
00557       relb = relb->next;
00558     }
00559 #ifndef SINGLE_THREAD_ASYNC_READ
00560     pthread_mutex_unlock(&reader->listenerLock);
00561 #endif
00562   }
00563 }
00564 
00565 #ifdef TMR_ENABLE_BACKGROUND_READS
00566 TMR_Queue_tagReads *
00567 dequeue(TMR_Reader *reader)
00568 {
00569   TMR_Queue_tagReads *tagRead = NULL;
00570   pthread_mutex_lock(&reader->queue_lock);
00571   if (NULL != reader->tagQueueHead)
00572   {
00573     /* Fetch the head always */
00574     tagRead = reader->tagQueueHead;
00575     reader->tagQueueHead = reader->tagQueueHead->next;
00576   }
00577   reader->queue_depth --;
00578   pthread_mutex_unlock(&reader->queue_lock);
00579   return(tagRead);
00580 }
00581 
00582 
00583 void enqueue(TMR_Reader *reader, TMR_Queue_tagReads *tagRead)
00584 {
00585   pthread_mutex_lock(&reader->queue_lock);
00586   if (NULL == reader->tagQueueHead)
00587   {
00588     /* first tag */
00589     reader->tagQueueHead = tagRead;
00590     reader->tagQueueHead->next = NULL;
00591     reader->tagQueueTail = reader->tagQueueHead;
00592   }
00593   else
00594   {
00595     reader->tagQueueTail->next = tagRead;
00596     reader->tagQueueTail = tagRead;
00597     tagRead->next = NULL;
00598   }
00599   reader->queue_depth ++;
00600   pthread_mutex_unlock(&reader->queue_lock);
00601 }
00602 
00603 static void *
00604 parse_tag_reads(void *arg)
00605 {
00606   TMR_Reader *reader;
00607   TMR_Queue_tagReads *tagRead;
00608   reader = arg;  
00609 
00610   while (1)
00611   {
00612     pthread_mutex_lock(&reader->parserLock);
00613     reader->parserRunning = false;
00614     pthread_cond_broadcast(&reader->parserCond);
00615     while (false == reader->parserEnabled)
00616     {
00617       pthread_cond_wait(&reader->parserCond, &reader->parserLock);
00618     }
00619 
00620     reader->parserRunning = true;
00621     pthread_mutex_unlock(&reader->parserLock);
00622 
00627     sem_wait(&reader->queue_length);
00628 
00629     if (NULL != reader->tagQueueHead)
00630     {
00635       tagRead = dequeue(reader);
00636       if (false == tagRead->isStatusResponse)
00637       {
00638         /* Tag Buffer stream response */
00639 
00640 #ifdef TMR_ENABLE_SERIAL_READER          
00641         if (TMR_READER_TYPE_SERIAL == reader->readerType)
00642         {
00647           notify_read_listeners(reader, &tagRead->trd);
00648         }
00649 #endif/* TMR_ENABLE_SERIAL_READER */           
00650 #ifdef TMR_ENABLE_LLRP_READER
00651         if (TMR_READER_TYPE_LLRP == reader->readerType)
00652         {
00653           /* Else it is LLRP message, parse it */
00654           LLRP_tSRO_ACCESS_REPORT *pReport;
00655           LLRP_tSTagReportData *pTagReportData;
00656 
00657           pReport = (LLRP_tSRO_ACCESS_REPORT *)tagRead->tagEntry.lMsg;
00658 
00659           for(pTagReportData = pReport->listTagReportData;
00660               NULL != pTagReportData;
00661               pTagReportData = (LLRP_tSTagReportData *)pTagReportData->hdr.pNextSubParameter)
00662           {
00663             TMR_TagReadData trd;
00664 
00665             TMR_TRD_init(&trd);
00666             TMR_LLRP_parseMetadataFromMessage(reader, &trd, pTagReportData);
00667           
00668             trd.reader = reader;
00669             notify_read_listeners(reader, &trd);
00670         }
00671         }
00672 #endif
00673         }
00674       else
00675       {
00676        /* A status stream response */
00677 
00678         if (TMR_READER_TYPE_SERIAL == reader->readerType)
00679         {
00680           TMR_Reader_StatsValues stats;
00681           uint8_t offset, i,j;
00682           uint16_t flags = 0;                 
00683 
00684           TMR_STATS_init(&stats);
00685           offset = tagRead->bufPointer;
00686 
00687           if (NULL != reader->statusListeners && NULL== reader->statsListeners)
00688           {
00689             /* A status stream response */
00690             TMR_StatusListenerBlock *slb;
00691             uint8_t index = 0, j;
00692             TMR_SR_StatusReport report[TMR_SR_STATUS_MAX];
00693 
00694 
00695             /* Get status content flags */
00696             flags = GETU16(tagRead->tagEntry.sMsg, offset);
00697 
00698             if (0 != (flags & TMR_SR_STATUS_FREQUENCY))
00699             {
00700               report[index].type = TMR_SR_STATUS_FREQUENCY;
00701               report[index].u.fsr.freq = (uint32_t)(GETU24(tagRead->tagEntry.sMsg, offset));
00702               index ++;
00703             }
00704             if (0 != (flags & TMR_SR_STATUS_TEMPERATURE))
00705             {
00706               report[index].type = TMR_SR_STATUS_TEMPERATURE;
00707               report[index].u.tsr.temp = GETU8(tagRead->tagEntry.sMsg, offset);
00708               index ++;
00709             }
00710             if (0 != (flags & TMR_SR_STATUS_ANTENNA))
00711             {
00712               uint8_t tx, rx;
00713               report[index].type = TMR_SR_STATUS_ANTENNA;
00714               tx = GETU8(tagRead->tagEntry.sMsg, offset);
00715               rx = GETU8(tagRead->tagEntry.sMsg, offset);
00716 
00717               for (j = 0; j < reader->u.serialReader.txRxMap->len; j++)
00718               {
00719                 if ((rx == reader->u.serialReader.txRxMap->list[j].rxPort) && (tx == reader->u.serialReader.txRxMap->list[j].txPort))
00720                 {
00721                   report[index].u.asr.ant = reader->u.serialReader.txRxMap->list[j].antenna;
00722                   break;
00723                 }
00724               }
00725               index ++;
00726             }
00727 
00728             report[index].type = TMR_SR_STATUS_NONE;
00729             /* notify status response to listener */
00730             pthread_mutex_lock(&reader->listenerLock);
00731             slb = reader->statusListeners;
00732             while (slb)
00733             {
00734               slb->listener(reader, report, slb->cookie);
00735               slb = slb->next;
00736             }
00737             pthread_mutex_unlock(&reader->listenerLock);
00738 
00739           }
00740           else if (NULL != reader->statsListeners && NULL== reader->statusListeners)
00741           {
00742             /* Get status content flags */
00743             if ((0x80) > reader->statsFlag)
00744             {
00745               offset += 1;
00746             }
00747             else
00748             {
00749               offset += 2;
00750             }
00751 
00756             for (i = 0; i < stats.perAntenna.max; i++)
00757             {
00758               stats.perAntenna.list[i].antenna = 0;
00759               stats.perAntenna.list[i].rfOnTime = 0;
00760               stats.perAntenna.list[i].noiseFloor = 0;
00761             }
00762 
00763             TMR_fillReaderStats(reader, &stats, flags, tagRead->tagEntry.sMsg, offset);
00764 
00770             for (i = 0; i < reader->u.serialReader.txRxMap->len; i++)
00771             {
00772               if (!stats.perAntenna.list[i].antenna)
00773               {
00774                 for (j = i + 1; j < reader->u.serialReader.txRxMap->len; j++)
00775                 {
00776                   if (stats.perAntenna.list[j].antenna)
00777                   {
00778                     stats.perAntenna.list[i].antenna = stats.perAntenna.list[j].antenna;
00779                     stats.perAntenna.list[i].rfOnTime = stats.perAntenna.list[j].rfOnTime;
00780                     stats.perAntenna.list[i].noiseFloor = stats.perAntenna.list[j].noiseFloor;
00781                     stats.perAntenna.list[j].antenna = 0;
00782                     stats.perAntenna.list[j].rfOnTime = 0;
00783                     stats.perAntenna.list[j].noiseFloor = 0;
00784 
00785                     stats.perAntenna.len++;
00786                     break;
00787                   }
00788                 }
00789               }
00790               else
00791               {
00792                 /* Increment the length */
00793                 stats.perAntenna.len++;
00794               }
00795             }
00796 
00797             /* store the requested flags for future use */
00798             stats.valid = reader->statsFlag;
00799 
00800             /* notify status response to listener */
00801             notify_stats_listeners(reader, &stats);
00802           }
00803           else
00804           {
00809             TMR_Status ret;
00810             ret = TMR_ERROR_UNSUPPORTED;
00811             notify_exception_listeners(reader, ret);
00812           }
00813         }
00814 #ifdef TMR_ENABLE_LLRP_READER
00815         else
00816         {
00821         }
00822 #endif
00823       }
00824 
00825       /* Free the memory */
00826       if (TMR_READER_TYPE_SERIAL == reader->readerType)
00827       {
00828         free(tagRead->tagEntry.sMsg);
00829       }
00830 #ifdef TMR_ENABLE_LLRP_READER
00831       else
00832       {
00833         TMR_LLRP_freeMessage(tagRead->tagEntry.lMsg);
00834       }
00835 #endif
00836       free(tagRead);
00837 
00838       /* Now, increment the queue_slots as we have removed one entry */
00839       sem_post(&reader->queue_slots);
00840     }
00841   }
00842   return NULL;
00843 }
00844 
00845 
00846 static void
00847 process_async_response(TMR_Reader *reader)
00848 {
00849   TMR_Queue_tagReads *tagRead;
00850   uint16_t flags = 0;
00851 
00852   /* Decrement Queue slots */
00853   sem_wait(&reader->queue_slots);
00854 
00855   tagRead = (TMR_Queue_tagReads *) malloc(sizeof(TMR_Queue_tagReads));
00856   if (TMR_READER_TYPE_SERIAL == reader->readerType)
00857   {
00858     tagRead->tagEntry.sMsg = (uint8_t *) malloc(TMR_SR_MAX_PACKET_SIZE); /* size of bufResponse */
00859     memcpy(tagRead->tagEntry.sMsg, reader->u.serialReader.bufResponse, TMR_SR_MAX_PACKET_SIZE);
00860     tagRead->bufPointer = reader->u.serialReader.bufPointer;
00861   }
00862 #ifdef TMR_ENABLE_LLRP_READER
00863   else
00864   {
00865     tagRead->tagEntry.lMsg = reader->u.llrpReader.bufResponse[0];
00866     reader->u.llrpReader.bufResponse[0] = NULL;
00867   }
00868 #endif
00869 
00870   tagRead->isStatusResponse = reader->isStatusResponse;
00875   if (TMR_READER_TYPE_SERIAL == reader->readerType)
00876   {
00877     if (false == tagRead->isStatusResponse)
00878     {
00879       TMR_TRD_init(&tagRead->trd);
00880       flags = GETU16AT(tagRead->tagEntry.sMsg, 8);
00881       TMR_SR_parseMetadataFromMessage(reader, &tagRead->trd, flags, &tagRead->bufPointer, tagRead->tagEntry.sMsg);
00882       TMR_SR_postprocessReaderSpecificMetadata(&tagRead->trd, &reader->u.serialReader);
00883       tagRead->trd.reader = reader;
00884     }
00885   }
00886 
00887   /* Enqueue the tagRead into Queue */
00888   enqueue(reader, tagRead);
00889   /* Increment queue_length */
00890   sem_post(&reader->queue_length);
00891 
00892   if ((false == reader->isStatusResponse) && (TMR_READER_TYPE_SERIAL == reader->readerType))
00893   {
00894     reader->u.serialReader.tagsRemainingInBuffer--;
00895   }
00896 }
00897 
00898 static void *
00899 do_background_reads(void *arg)
00900 {
00901   TMR_Status ret;
00902   TMR_Reader *reader;
00903   uint32_t onTime, offTime;
00904   int32_t sleepTime;
00905   uint64_t end, now, difftime;
00906 
00907   reader = arg;
00908   reader->trueAsyncflag = false;
00909 
00910   TMR_paramGet(reader, TMR_PARAM_READ_ASYNCOFFTIME, &offTime);
00911 
00912   while (1)
00913   {
00914     /* Wait for reads to be enabled */
00915     pthread_mutex_lock(&reader->backgroundLock);
00916     reader->backgroundRunning = false;
00917 
00918     pthread_cond_broadcast(&reader->backgroundCond);
00919     while (false == reader->backgroundEnabled)
00920     {
00921       reader->trueAsyncflag = false;
00922       pthread_cond_wait(&reader->backgroundCond, &reader->backgroundLock);
00923       if (true == reader->backgroundThreadCancel)
00924       {
00929         goto EXIT;
00930       }
00931     }
00932 
00933     TMR_paramGet(reader, TMR_PARAM_READ_ASYNCONTIME, &onTime);
00934 
00935     if (!reader->trueAsyncflag)
00936     {
00937       ret = TMR_read(reader, onTime, NULL);
00938       if (TMR_SUCCESS != ret)
00939       {
00940         if ((TMR_ERROR_TIMEOUT == ret) || (TMR_ERROR_CRC_ERROR == ret) ||
00941               (TMR_ERROR_SYSTEM_UNKNOWN_ERROR == ret) || (TMR_ERROR_TM_ASSERT_FAILED == ret))
00942         {
00943           if (TMR_READER_TYPE_SERIAL == reader->readerType)
00944           {
00945             reader->u.serialReader.transport.flush(&reader->u.serialReader.transport);
00946           }
00947           reader->backgroundEnabled = false;
00948         }
00949 
00956         if (((TMR_ERROR_HIGH_RETURN_LOSS == ret) || (TMR_ERROR_NO_ANTENNA == ret))
00957             &&
00958             ((TMR_SR_MODEL_M6E != reader->u.serialReader.versionInfo.hardware[0]) &&
00959              (TMR_SR_MODEL_MICRO != reader->u.serialReader.versionInfo.hardware[0]) &&
00960              (TMR_SR_MODEL_M6E_NANO != reader->u.serialReader.versionInfo.hardware[0]) &&
00961              (TMR_SR_MODEL_M6E_I != reader->u.serialReader.versionInfo.hardware[0])))
00962         {
00963           reader->backgroundEnabled = false;
00964           reader->readState = TMR_READ_STATE_DONE;
00965           pthread_mutex_unlock(&reader->backgroundLock);
00966           notify_exception_listeners(reader, ret);
00967           break;
00968         }
00969 
00970         notify_exception_listeners(reader, ret);
00971         if(false == reader->searchStatus)
00972         {
00979           reader->readState = TMR_READ_STATE_STARTED;
00980           pthread_cond_broadcast(&reader->readCond);
00981           reader->backgroundEnabled = false;
00982         }
00983         pthread_mutex_unlock(&reader->backgroundLock);
00984         continue;
00985       }
00986       if(reader->continuousReading)
00987       {
00992         reader->trueAsyncflag = true;
00993       }
00994 
00998       reader->readState = TMR_READ_STATE_ACTIVE;
00999       pthread_cond_broadcast(&reader->readCond);
01000     }
01001 
01002     reader->backgroundRunning = true;
01003     pthread_mutex_unlock(&reader->backgroundLock);
01004 
01005     if (true == reader->continuousReading)
01006     {
01011       /* Make the time stamp zero for serial reader */
01012       while (true)
01013       {
01014         if (TMR_READER_TYPE_SERIAL == reader->readerType)
01015         {
01016           if (false == reader->u.serialReader.isBasetimeUpdated)
01017           {
01018             /* Update the base time stamp */
01019             TMR_SR_updateBaseTimeStamp(reader);
01020             reader->u.serialReader.isBasetimeUpdated = true;
01021           }
01022         }
01023         ret = TMR_hasMoreTags(reader);
01024         if (TMR_SUCCESS == ret)
01025         {
01026           /* Got a valid message, before posting it to queue
01027            * check whether we have slots free in the queue or
01028            * not. Validate this only for Serial reader.
01029            */
01030           if (TMR_READER_TYPE_SERIAL == reader->readerType)
01031           {
01032             int slotsFree = 0;
01033             int semret;
01034             /* Get the semaphore value */
01035             semret = sem_getvalue(&reader->queue_slots, &slotsFree);
01036             if (0 == semret)
01037             {
01038               if (10 > slotsFree)
01039               {
01040                 tmr_sleep(20);
01041               }
01042               if (0 >= slotsFree)
01043               {
01044                 /* In a normal case we should not come here.
01045                  * we are here means there is no place to
01046                  * store the tags. May be the read listener
01047                  * is not fast enough.
01048                  * In this case stop the read and exit.
01049                  */
01050                 if (true == reader->searchStatus)
01051                 {
01052                   isBufferOverFlow = true;
01053                   ret = TMR_ERROR_BUFFER_OVERFLOW;
01054                   notify_exception_listeners(reader, ret);
01055                   ret = verifySearchStatus(reader);
01056                   /*isBufferOverFlow = false;
01057                   pthread_mutex_lock(&reader->backgroundLock);
01058                   reader->backgroundEnabled = false;
01059                   reader->readState = TMR_READ_STATE_DONE;
01060                   pthread_cond_broadcast(&reader->readCond);
01061                   pthread_mutex_unlock(&reader->backgroundLock);
01062                   reader->searchStatus = false;*/
01063                                   /* Waiting till all slots are free */
01064                                   while(slotsFree < TMR_MAX_QUEUE_SLOTS)
01065                                   {
01066                                           tmr_sleep(20);
01067                                           semret = sem_getvalue(&reader->queue_slots, &slotsFree);
01068                                   }
01069                                   reader->trueAsyncflag = false;
01070                   break;
01071                 }
01072               }
01073             }
01074           }
01075 
01076           /* There is place to store the response. Post it */
01077           process_async_response(reader);
01078         }
01079         else if (TMR_ERROR_CRC_ERROR == ret)
01080         {
01081           /* Currently, just drop the corrupted packet,
01082            * inform the user about the error and move on.
01083            *
01084            * TODO: Fix the error by tracing the exact reason of failour
01085            */
01086           notify_exception_listeners(reader, ret);
01087         }
01088         else if (TMR_ERROR_TAG_ID_BUFFER_FULL == ret)
01089         {
01090           /* In case of buffer full error, notify the exception */
01091           notify_exception_listeners(reader, ret);
01092 
01097           if (true == reader->searchStatus)
01098           {
01104             ret = TMR_hasMoreTags(reader);
01105             reader->trueAsyncflag = false;
01106             break;
01107           }
01108         }
01109         else
01110         {
01111           if ((TMR_ERROR_TIMEOUT == ret) || (TMR_ERROR_SYSTEM_UNKNOWN_ERROR == ret) || 
01112             (TMR_ERROR_TM_ASSERT_FAILED == ret) || (TMR_ERROR_LLRP_READER_CONNECTION_LOST == ret))
01113           {
01114             notify_exception_listeners(reader, ret);
01119             if (TMR_READER_TYPE_SERIAL == reader->readerType)
01120             {
01121               /* Handling this fix for serial reader now */
01122                           reader->u.serialReader.transport.flush(&reader->u.serialReader.transport);
01123             }
01124 
01129             if (!reader->finishedReading)
01130             {
01131               reader->cmdStopReading(reader);
01132             }
01133 
01134             pthread_mutex_lock(&reader->backgroundLock);
01135             reader->backgroundEnabled = false;
01136             reader->readState = TMR_READ_STATE_DONE;
01137             pthread_cond_broadcast(&reader->readCond);
01138             pthread_mutex_unlock(&reader->backgroundLock);
01139 
01140 
01147             reader->searchStatus = false;
01148             reset_continuous_reading(reader, true);
01149           }
01150           else if (TMR_ERROR_END_OF_READING == ret)
01151           {
01152             while(0 < reader->queue_depth)
01153             {
01160               tmr_sleep(5);
01161             }
01162 
01167             pthread_mutex_lock(&reader->backgroundLock);
01168             reader->backgroundEnabled = false;
01169             reader->readState = TMR_READ_STATE_DONE;
01170             pthread_cond_broadcast(&reader->readCond);
01171             pthread_mutex_unlock(&reader->backgroundLock);
01172             break;
01173           }
01174           else if ((TMR_ERROR_NO_TAGS_FOUND != ret) && (TMR_ERROR_NO_TAGS != ret) && (TMR_ERROR_TAG_ID_BUFFER_AUTH_REQUEST != ret) && (TMR_ERROR_TOO_BIG != ret))
01175           {
01176             /* Any exception other than 0x400 should be notified */
01177             notify_exception_listeners(reader, ret);
01178           }
01179           break;
01180         }
01181       }
01182     }
01183     else
01184     {
01192       end = tmr_gettime();
01193 
01194       while (TMR_SUCCESS == TMR_hasMoreTags(reader))
01195       {
01196         TMR_TagReadData trd;
01197         TMR_ReadListenerBlock *rlb;
01198 
01199         TMR_TRD_init(&trd);
01200 
01201         ret = TMR_getNextTag(reader, &trd);
01202         if (TMR_SUCCESS != ret)
01203         {
01204           pthread_mutex_lock(&reader->backgroundLock);
01205           reader->backgroundEnabled = false;
01206           pthread_mutex_unlock(&reader->backgroundLock);
01207           notify_exception_listeners(reader, ret);
01208           break;
01209         }
01210 
01211         pthread_mutex_lock(&reader->listenerLock);
01212         rlb = reader->readListeners;
01213         while (rlb)
01214         { 
01215           rlb->listener(reader, &trd, rlb->cookie);
01216           rlb = rlb->next;
01217         }
01218         pthread_mutex_unlock(&reader->listenerLock);
01219       }
01220 
01221       /* Wait for the asyncOffTime duration to pass */
01222       now = tmr_gettime();
01223       difftime = now - end;
01224 
01225       sleepTime = offTime - (uint32_t)difftime;
01226       if(sleepTime > 0)
01227       {
01228         tmr_sleep(sleepTime);
01229       }
01230     }
01231 EXIT:
01232     if (reader->backgroundThreadCancel)
01233     {
01237       pthread_exit(NULL);
01238     }
01239   }
01240   return NULL;
01241 }
01242 #endif /* TMR_ENABLE_BACKGROUND_READS */
01243 
01244 TMR_Status
01245 TMR_addReadListener(TMR_Reader *reader, TMR_ReadListenerBlock *b)
01246 {
01247 #ifndef SINGLE_THREAD_ASYNC_READ
01248   if (0 != pthread_mutex_lock(&reader->listenerLock))
01249     return TMR_ERROR_TRYAGAIN;
01250 #endif
01251   b->next = reader->readListeners;
01252   reader->readListeners = b;
01253 #ifndef SINGLE_THREAD_ASYNC_READ
01254   pthread_mutex_unlock(&reader->listenerLock);
01255 #endif
01256   return TMR_SUCCESS;
01257 }
01258 #ifdef TMR_ENABLE_BACKGROUND_READS
01259 
01260 TMR_Status
01261 TMR_removeReadListener(TMR_Reader *reader, TMR_ReadListenerBlock *b)
01262 {
01263   TMR_ReadListenerBlock *block, **prev;
01264 
01265   if (0 != pthread_mutex_lock(&reader->listenerLock))
01266     return TMR_ERROR_TRYAGAIN;
01267 
01268   prev = &reader->readListeners;
01269   block = reader->readListeners;
01270   while (NULL != block)
01271   {
01272     if (block == b)
01273     {
01274       *prev = block->next;
01275       break;
01276     }
01277     prev = &block->next;
01278     block = block->next;
01279   }
01280 
01281   pthread_mutex_unlock(&reader->listenerLock);
01282 
01283   if (block == NULL)
01284   {
01285     return TMR_ERROR_INVALID;
01286   }
01287 
01288   return TMR_SUCCESS;
01289 }
01290 
01291 
01292 TMR_Status
01293 TMR_addAuthReqListener(TMR_Reader *reader, TMR_AuthReqListenerBlock *b)
01294 {
01295 
01296   if (0 != pthread_mutex_lock(&reader->listenerLock))
01297     return TMR_ERROR_TRYAGAIN;
01298 
01299   b->next = reader->authReqListeners;
01300   reader->authReqListeners = b;
01301 
01302   pthread_mutex_unlock(&reader->listenerLock);
01303 
01304   return TMR_SUCCESS;
01305 }
01306 
01307 
01308 TMR_Status
01309 TMR_removeAuthReqListener(TMR_Reader *reader, TMR_AuthReqListenerBlock *b)
01310 {
01311   TMR_AuthReqListenerBlock *block, **prev;
01312 
01313   if (0 != pthread_mutex_lock(&reader->listenerLock))
01314     return TMR_ERROR_TRYAGAIN;
01315 
01316   prev = &reader->authReqListeners;
01317   block = reader->authReqListeners;
01318   while (NULL != block)
01319   {
01320     if (block == b)
01321     {
01322       *prev = block->next;
01323       break;
01324     }
01325     prev = &block->next;
01326     block = block->next;
01327   }
01328 
01329   pthread_mutex_unlock(&reader->listenerLock);
01330 
01331   if (block == NULL)
01332   {
01333     return TMR_ERROR_INVALID;
01334   }
01335 
01336   return TMR_SUCCESS;
01337 }
01338 
01339 TMR_Status
01340 TMR_addStatusListener(TMR_Reader *reader, TMR_StatusListenerBlock *b)
01341 {
01342 
01343   if (0 != pthread_mutex_lock(&reader->listenerLock))
01344     return TMR_ERROR_TRYAGAIN;
01345 
01346   b->next = reader->statusListeners;
01347   reader->statusListeners = b;
01348 
01349   /*reader->streamStats |= b->statusFlags & TMR_SR_STATUS_CONTENT_FLAGS_ALL;*/
01350 
01351   pthread_mutex_unlock(&reader->listenerLock);
01352 
01353   return TMR_SUCCESS;
01354 }
01355 #endif /* TMR_ENABLE_BACKGROUND_READS */
01356 
01357 TMR_Status
01358 TMR_addStatsListener(TMR_Reader *reader, TMR_StatsListenerBlock *b)
01359 {
01360 #ifndef SINGLE_THREAD_ASYNC_READ
01361   if (0 != pthread_mutex_lock(&reader->listenerLock))
01362     return TMR_ERROR_TRYAGAIN;
01363 #endif
01364   b->next = reader->statsListeners;
01365   reader->statsListeners = b;
01366 
01367   /*reader->streamStats |= b->statusFlags & TMR_SR_STATUS_CONTENT_FLAGS_ALL; */
01368 #ifndef SINGLE_THREAD_ASYNC_READ
01369   pthread_mutex_unlock(&reader->listenerLock);
01370 #endif
01371   return TMR_SUCCESS;
01372 }
01373 #ifdef TMR_ENABLE_BACKGROUND_READS
01374 
01375 TMR_Status
01376 TMR_removeStatsListener(TMR_Reader *reader, TMR_StatsListenerBlock *b)
01377 {
01378   TMR_StatsListenerBlock *block, **prev;
01379 
01380   if (0 != pthread_mutex_lock(&reader->listenerLock))
01381     return TMR_ERROR_TRYAGAIN;
01382 
01383   prev = &reader->statsListeners;
01384   block = reader->statsListeners;
01385   while (NULL != block)
01386   {
01387     if (block == b)
01388     {
01389       *prev = block->next;
01390       break;
01391     }
01392     prev = &block->next;
01393     block = block->next;
01394   }
01395 
01396   /* Remove the status flags requested by this listener and reframe */
01397   /*reader->streamStats = TMR_SR_STATUS_CONTENT_FLAG_NONE;
01398   {
01399     TMR_StatusListenerBlock *current;
01400     current = reader->statusListeners;
01401     while (NULL != current)
01402     {
01403       reader->streamStats |= current->statusFlags;
01404       current = current->next;
01405     }    
01406   }*/
01407   
01408   pthread_mutex_unlock(&reader->listenerLock);
01409 
01410   if (block == NULL)
01411   {
01412     return TMR_ERROR_INVALID;
01413   }
01414 
01415   return TMR_SUCCESS;
01416 }
01417 
01418 TMR_Status
01419 TMR_removeStatusListener(TMR_Reader *reader, TMR_StatusListenerBlock *b)
01420 {
01421   TMR_StatusListenerBlock *block, **prev;
01422 
01423   if (0 != pthread_mutex_lock(&reader->listenerLock))
01424     return TMR_ERROR_TRYAGAIN;
01425 
01426   prev = &reader->statusListeners;
01427   block = reader->statusListeners;
01428   while (NULL != block)
01429   {
01430     if (block == b)
01431     {
01432       *prev = block->next;
01433       break;
01434     }
01435     prev = &block->next;
01436     block = block->next;
01437   }
01438 
01439   /* Remove the status flags requested by this listener and reframe */
01440   /*reader->streamStats = TMR_SR_STATUS_CONTENT_FLAG_NONE;
01441     {
01442     TMR_StatusListenerBlock *current;
01443     current = reader->statusListeners;
01444     while (NULL != current)
01445     {
01446     reader->streamStats |= current->statusFlags;
01447     current = current->next;
01448     }
01449     }*/
01450 
01451   pthread_mutex_unlock(&reader->listenerLock);
01452 
01453   if (block == NULL)
01454   {
01455     return TMR_ERROR_INVALID;
01456   }
01457 
01458   return TMR_SUCCESS;
01459 }
01460 
01461 void cleanup_background_threads(TMR_Reader *reader)
01462 {
01463   if (NULL != reader)
01464   {
01465     pthread_mutex_lock(&reader->backgroundLock);
01466     pthread_mutex_lock(&reader->listenerLock);
01467     reader->readExceptionListeners = NULL;
01468     reader->statsListeners = NULL;
01469     if (true == reader->backgroundSetup)
01470     {
01475       reader->backgroundThreadCancel = true;
01476       pthread_cond_broadcast(&reader->backgroundCond);
01477     }
01478     pthread_mutex_unlock(&reader->listenerLock);
01479     pthread_mutex_unlock(&reader->backgroundLock);
01480 
01481     if (true == reader->backgroundSetup)
01482     {
01486       pthread_join(reader->backgroundReader, NULL);
01487     }
01488 
01489     pthread_mutex_lock(&reader->parserLock);
01490     pthread_mutex_lock(&reader->listenerLock);
01491     reader->readListeners = NULL;
01492     if (true == reader->parserSetup)
01493     {
01494       pthread_cancel(reader->backgroundParser);
01495     }
01496     pthread_mutex_unlock(&reader->listenerLock);
01497     pthread_mutex_unlock(&reader->parserLock);
01498   }
01499 }
01500 
01501 void*
01502 do_background_receiveAutonomousReading(void * arg)
01503 {
01504   TMR_Status ret;
01505   TMR_TagReadData trd;
01506   TMR_Reader *reader;
01507   TMR_Reader_StatsValues stats;  
01508 
01509   reader = arg;
01510   TMR_TRD_init(&trd);
01511 
01512   while (1)
01513   {
01514     ret = TMR_SR_receiveAutonomousReading(reader, &trd, &stats);
01515     if (TMR_SUCCESS == ret)
01516     {
01517       if (false == reader->isStatusResponse)
01518       {
01519         /* Notify the read listener */
01520         notify_read_listeners(reader, &trd);
01521       }
01522       else
01523       {
01524         notify_stats_listeners(reader, &stats);
01525       }
01526     }
01527   }
01528   return NULL;
01529 }
01530 #endif /* TMR_ENABLE_BACKGROUND_READS */
01531 


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