int ant_disable(void)
{
   int iRet = -1;
   ant_channel_type eChannel;
   ANT_FUNC_START();

   stRxThreadInfo.ucRunThread = 0;

   if (stRxThreadInfo.stRxThread != 0) {
      ANT_DEBUG_I("Sending shutdown signal to rx thread.");
      if(write(stRxThreadInfo.iRxShutdownEventFd, &EVENT_FD_PLUS_ONE, sizeof(EVENT_FD_PLUS_ONE)) < 0)
      {
         ANT_ERROR("failed to signal rx thread with eventfd. Reason: %s", strerror(errno));
         goto out;
      }
      ANT_DEBUG_I("Waiting for rx thread to finish.");
      if (pthread_join(stRxThreadInfo.stRxThread, NULL) < 0) {
         ANT_ERROR("failed to join rx thread: %s", strerror(errno));
         goto out;
      }
   } else {
      ANT_DEBUG_D("rx thread is not running");
   }

   for (eChannel = 0; eChannel < NUM_ANT_CHANNELS; eChannel++) {
      ant_disable_channel(&stRxThreadInfo.astChannels[eChannel]);
   }

   iRet = 0;

out:
   stRxThreadInfo.stRxThread = 0;
   ANT_FUNC_END();
   return iRet;
}
////////////////////////////////////////////////////////////////////
//  get_and_set_radio_status
//
//  Returns if the chip/transport is disabled/enabled/unknown This function WILL
//  overwrite what it thinks the state is with what the BlueZ core (kernel)
//  thinks it is. It will overwrite enabling or disabling states, and might
//  change internal state from enabled, disabled, or unknown to any of these
//  three on errors.
//
//  Parameters:
//      -
//
//  Returns:
//      The current radio status (ANTRadioEnabledStatus)
//
////////////////////////////////////////////////////////////////////
ANTRadioEnabledStatus get_and_set_radio_status(void)
{
    ANT_FUNC_START();
#if USE_EXTERNAL_POWER_LIBRARY
    ANTRadioEnabledStatus orig_status = radio_status;
    switch (ant_is_enabled())
    {
    case 0:
        radio_status = RADIO_STATUS_DISABLED;
        break;
    case 1:
        radio_status = RADIO_STATUS_ENABLED;
        break;
    default:
        ANT_ERROR("getting chip state returned an error");
        radio_status = RADIO_STATUS_UNKNOWN;
        break;
    }
    if (orig_status != radio_status)
    {
        ANT_DEBUG_I("radio_status (%d -> %d)", orig_status, radio_status);

        if (RxParams.pfStateCallback)
            RxParams.pfStateCallback(radio_status);
    }
#endif
    ANT_FUNC_END();
    return radio_status;
}
/*
 * This thread waits for ANT messages from a VFS file.
 */
void *fnRxThread(void *ant_rx_thread_info)
{
   int iMutexLockResult;
   int iPollRet;
   ant_rx_thread_info_t *stRxThreadInfo;
   struct pollfd astPollFd[NUM_POLL_FDS];
   ant_channel_type eChannel;
   ANT_FUNC_START();

   stRxThreadInfo = (ant_rx_thread_info_t *)ant_rx_thread_info;
   for (eChannel = 0; eChannel < NUM_ANT_CHANNELS; eChannel++) {
      astPollFd[eChannel].fd = stRxThreadInfo->astChannels[eChannel].iFd;
      astPollFd[eChannel].events = EVENTS_TO_LISTEN_FOR;
   }
   // Fill out poll request for the shutdown signaller.
   astPollFd[EVENTFD_IDX].fd = stRxThreadInfo->iRxShutdownEventFd;
   astPollFd[EVENTFD_IDX].events = POLL_IN;

   // Reset the waiting for response, since we don't want a stale value if we were reset.
   stRxThreadInfo->bWaitingForKeepaliveResponse = ANT_FALSE;

   /* continue running as long as not terminated */
   while (stRxThreadInfo->ucRunThread) {
      /* Wait for data available on any file (transport path), shorter wait if we just timed out. */
      int timeout = stRxThreadInfo->bWaitingForKeepaliveResponse ? KEEPALIVE_TIMEOUT : ANT_POLL_TIMEOUT;
      iPollRet = poll(astPollFd, NUM_POLL_FDS, timeout);
      if (!iPollRet) {
         if(!stRxThreadInfo->bWaitingForKeepaliveResponse)
         {
            stRxThreadInfo->bWaitingForKeepaliveResponse = ANT_TRUE;
            // Keep alive is done on a separate thread so that rxThread can handle flow control during
            // the message.
            pthread_t thread;
            // Don't care if it failed as the consequence is just a missed keep-alive.
            pthread_create(&thread, NULL, fnKeepAliveThread, NULL);
            // Detach the thread so that we don't need to join it later.
            pthread_detach(thread);
            ANT_DEBUG_V("poll timed out, checking exit cond");
         } else
         {
            ANT_DEBUG_E("No response to keepalive, attempting recovery.");
            doReset(stRxThreadInfo);
            goto out;
         }
      } else if (iPollRet < 0) {
         ANT_ERROR("unhandled error: %s, attempting recovery.", strerror(errno));
         doReset(stRxThreadInfo);
         goto out;
      } else {
         for (eChannel = 0; eChannel < NUM_ANT_CHANNELS; eChannel++) {
            if (areAllFlagsSet(astPollFd[eChannel].revents, EVENT_HARD_RESET)) {
               ANT_ERROR("Hard reset indicated by %s. Attempting recovery.",
                            stRxThreadInfo->astChannels[eChannel].pcDevicePath);
               doReset(stRxThreadInfo);
               goto out;
            } else if (areAllFlagsSet(astPollFd[eChannel].revents, EVENT_CHIP_SHUTDOWN)) {
               /* chip reported it was unexpectedly disabled */
               ANT_DEBUG_D(
                     "poll hang-up from %s. exiting rx thread", stRxThreadInfo->astChannels[eChannel].pcDevicePath);

               doReset(stRxThreadInfo);
               goto out;
            } else if (areAllFlagsSet(astPollFd[eChannel].revents, EVENT_DATA_AVAILABLE)) {
               ANT_DEBUG_D("data on %s. reading it",
                            stRxThreadInfo->astChannels[eChannel].pcDevicePath);

               // Doesn't matter what data we received, we know the chip is alive.
               stRxThreadInfo->bWaitingForKeepaliveResponse = ANT_FALSE;

               if (readChannelMsg(eChannel, &stRxThreadInfo->astChannels[eChannel]) < 0) {
                  // set flag to exit out of Rx Loop
                  stRxThreadInfo->ucRunThread = 0;
               }
            } else if (areAllFlagsSet(astPollFd[eChannel].revents, POLLNVAL)) {
               ANT_ERROR("poll was called on invalid file descriptor %s. Attempting recovery.",
                     stRxThreadInfo->astChannels[eChannel].pcDevicePath);
               doReset(stRxThreadInfo);
               goto out;
            } else if (areAllFlagsSet(astPollFd[eChannel].revents, POLLERR)) {
               ANT_ERROR("Unknown error from %s. Attempting recovery.",
                     stRxThreadInfo->astChannels[eChannel].pcDevicePath);
               doReset(stRxThreadInfo);
               goto out;
            } else if (astPollFd[eChannel].revents) {
               ANT_DEBUG_W("unhandled poll result %#x from %s",
                            astPollFd[eChannel].revents,
                            stRxThreadInfo->astChannels[eChannel].pcDevicePath);
            }
         }
         // Now check for shutdown signal
         if(areAllFlagsSet(astPollFd[EVENTFD_IDX].revents, POLLIN))
         {
            ANT_DEBUG_I("rx thread caught shutdown signal.");
            // reset the counter by reading.
            uint64_t counter;
            read(stRxThreadInfo->iRxShutdownEventFd, &counter, sizeof(counter));
            // don't care if read error, going to close the thread anyways.
            stRxThreadInfo->ucRunThread = 0;
         } else if (astPollFd[EVENTFD_IDX].revents != 0) {
            ANT_ERROR("Shutdown event descriptor had unexpected event: %#x. exiting rx thread.",
                  astPollFd[EVENTFD_IDX].revents);
            stRxThreadInfo->ucRunThread = 0;
         }
      }
   }

   /* disable ANT radio if not already disabling */
   // Try to get stEnabledStatusLock.
   // if you get it then no one is enabling or disabling
   // if you can't get it assume something made you exit
   ANT_DEBUG_V("try getting stEnabledStatusLock in %s", __FUNCTION__);
   iMutexLockResult = pthread_mutex_trylock(stRxThreadInfo->pstEnabledStatusLock);
   if (!iMutexLockResult) {
      ANT_DEBUG_V("got stEnabledStatusLock in %s", __FUNCTION__);
      ANT_WARN("rx thread has unexpectedly crashed, cleaning up");

      // spoof our handle as closed so we don't try to join ourselves in disable
      stRxThreadInfo->stRxThread = 0;

      if (g_fnStateCallback) {
         g_fnStateCallback(RADIO_STATUS_DISABLING);
      }

      ant_disable();

      if (g_fnStateCallback) {
         g_fnStateCallback(ant_radio_enabled_status());
      }

      ANT_DEBUG_V("releasing stEnabledStatusLock in %s", __FUNCTION__);
      pthread_mutex_unlock(stRxThreadInfo->pstEnabledStatusLock);
      ANT_DEBUG_V("released stEnabledStatusLock in %s", __FUNCTION__);
   } else if (iMutexLockResult != EBUSY) {
      ANT_ERROR("rx thread closing code, trylock on state lock failed: %s",
            strerror(iMutexLockResult));
   } else {
      ANT_DEBUG_V("stEnabledStatusLock busy");
   }

   out:
   ANT_FUNC_END();
#ifdef ANDROID
   return NULL;
#endif
}
ANTStatus ant_disable_radio(void)
{
    int result;
    int lockResult;
    ANTStatus ret = ANT_STATUS_FAILED;
    ANT_FUNC_START();

    ANT_DEBUG_V("getting enableLock in %s", __FUNCTION__);
    lockResult = pthread_mutex_lock(&enableLock);
    if(lockResult)
    {
        ANT_ERROR("Disable failed to get enableLock mutex: %s", strerror(lockResult));
        return ANT_STATUS_FAILED;
    }
    ANT_DEBUG_V("got enableLock in %s", __FUNCTION__);

    ANT_DEBUG_V("getting txLock in %s", __FUNCTION__);
    lockResult = pthread_mutex_lock(&txLock);
    if (lockResult)
    {
        ANT_ERROR("Disable txLock failed: %s", strerror(lockResult));
        pthread_mutex_unlock(&enableLock);
        return ANT_STATUS_FAILED;
    }
    ANT_DEBUG_V("got txLock in %s", __FUNCTION__);

#if USE_EXTERNAL_POWER_LIBRARY
    if (get_and_set_radio_status() != RADIO_STATUS_DISABLED)
    {
        ANT_DEBUG_I("radio_status (%d -> %d)", radio_status, RADIO_STATUS_DISABLING);
        radio_status = RADIO_STATUS_DISABLING;

        if (RxParams.pfStateCallback)
            RxParams.pfStateCallback(radio_status);
    }

    result = ant_disable();

    ANT_DEBUG_D("ant_disable() result is %d", result);
#else
    radio_status = RADIO_STATUS_DISABLED;
#endif

    // If rx thread exists ( != 0)
    if (RxParams.thread)
    {
        ANT_DEBUG_V("quit rx thread, joining");
        pthread_join(RxParams.thread, NULL);
        RxParams.thread = 0;
        ANT_DEBUG_V("joined by rx thread");
    }
    else
    {
        ANT_DEBUG_W("rx thread is 0 (not created?)");
    }

    switch (get_and_set_radio_status())
    {
    case RADIO_STATUS_DISABLED:
        ret = ANT_STATUS_SUCCESS;
        break;
    case RADIO_STATUS_ENABLED:
        ANT_ERROR("SERIOUS: ANT was disabled, rx thread quit, but ANT is enabled");
        ret = ANT_STATUS_FAILED;
        break;
    default:
        ret = ANT_STATUS_NOT_DE_INITIALIZED;
        break;
    }

    ANT_DEBUG_V("releasing txLock in %s", __FUNCTION__);
    pthread_mutex_unlock(&txLock);
    ANT_DEBUG_V("released txLock in %s", __FUNCTION__);

    ANT_DEBUG_V("releasing enableLock in %s", __FUNCTION__);
    pthread_mutex_unlock(&enableLock);
    ANT_DEBUG_V("released enableLock in %s", __FUNCTION__);

    ANT_FUNC_END();
    return ret;
}
ANTStatus ant_enable_radio(void)
{
    int result;
    int lockResult;
    ANTStatus result_status = ANT_STATUS_FAILED;
    ANT_FUNC_START();

    ANT_DEBUG_V("getting enableLock in %s", __FUNCTION__);
    lockResult = pthread_mutex_lock(&enableLock);
    if(lockResult)
    {
        ANT_ERROR("Enable failed to get enableLock mutex: %s", strerror(lockResult));
        return ANT_STATUS_FAILED;
    }
    ANT_DEBUG_V("got enableLock in %s", __FUNCTION__);

    if(RADIO_STATUS_DISABLED == radio_status)
    {
        radio_status = RADIO_STATUS_ENABLING;
    }

    ANT_DEBUG_V("getting txLock in %s", __FUNCTION__);
    lockResult = pthread_mutex_lock(&txLock);
    if (lockResult)
    {
        ANT_ERROR("Enable txLock failed: %s", strerror(lockResult));
        pthread_mutex_unlock(&enableLock);
        return ANT_STATUS_FAILED;
    }
    ANT_DEBUG_V("got txLock in %s", __FUNCTION__);

    if (get_and_set_radio_status() != RADIO_STATUS_ENABLED)
    {
        if (RxParams.thread)
        {
            ANT_WARN("in enable call: rx thread still exists but radio crashed. trying to recover");
            ANT_DEBUG_V("radio crashed, letting rx thread join");
            pthread_join(RxParams.thread, NULL);
            RxParams.thread = 0;
            ANT_DEBUG_V("recovered. joined by rx thread");
        }

        ANT_DEBUG_I("radio_status (%d -> %d)", radio_status, RADIO_STATUS_ENABLING);
        radio_status = RADIO_STATUS_ENABLING;

#if USE_EXTERNAL_POWER_LIBRARY
        if (RxParams.pfStateCallback)
            RxParams.pfStateCallback(radio_status);
#endif
    }

#if USE_EXTERNAL_POWER_LIBRARY
    result = ant_enable();

    ANT_DEBUG_D("ant_enable() result is %d", result);
#else
    result = 0;
#endif
    if (result == 0)
    {
        if (RxParams.thread)
        {
            result_status = ANT_STATUS_SUCCESS;
            radio_status = RADIO_STATUS_ENABLED; // sanity assign, cant be enabling
            ANT_DEBUG_D("ANT radio re-enabled");
        }
        else
        {
            result = pthread_create(&RxParams.thread, NULL, ANTHCIRxThread, NULL);
            if (result)
            {
                ANT_ERROR("Thread initialization failed: %s", strerror(result));
                result_status = ANT_STATUS_FAILED;
            }
            else
            {
                result_status = ANT_STATUS_SUCCESS;
#if USE_EXTERNAL_POWER_LIBRARY
                if (radio_status == RADIO_STATUS_ENABLING)
                {
                    ANT_DEBUG_I("radio_status (%d -> %d)", radio_status, RADIO_STATUS_ENABLED);
                    radio_status = RADIO_STATUS_ENABLED;

                    if (RxParams.pfStateCallback)
                        RxParams.pfStateCallback(radio_status);
                }
                else
                {
                    ANT_WARN("radio was already enabled but rx thread was not running");
                }
#else
                radio_status = RADIO_STATUS_ENABLED;
#endif
            }
        }
    }
    else
    {
        result_status = ANT_STATUS_TRANSPORT_INIT_ERR;
    }

    if (result_status != ANT_STATUS_SUCCESS) // ant_enable() or rx thread creating failed
    {
#if USE_EXTERNAL_POWER_LIBRARY
        ant_disable();
#endif

        switch (get_and_set_radio_status())
        {
        case RADIO_STATUS_ENABLED:
            ANT_ERROR("SERIOUS: enable failed, but ANT is enabled without a rx thread");
            break;
        default:
            ANT_DEBUG_D("Enable failed, after cleanup chip is not enabled");
            break;
        }
    }

    ANT_DEBUG_V("releasing txLock in %s", __FUNCTION__);
    pthread_mutex_unlock(&txLock);
    ANT_DEBUG_V("released txLock in %s", __FUNCTION__);

    ANT_DEBUG_V("releasing enableLock in %s", __FUNCTION__);
    pthread_mutex_unlock(&enableLock);
    ANT_DEBUG_V("released enableLock in %s", __FUNCTION__);

    ANT_FUNC_END();
    return result_status;
}
int readChannelMsg(ant_channel_type eChannel, ant_channel_info_t *pstChnlInfo)
{
   int iRet = -1;
   int iRxLenRead;
   int iCurrentHciPacketOffset;
   int iHciDataSize;
/*1++++++++++++++++++*/
   int i = 0;
   int temp_offset = 0;
   int RxLength = 0;
/*1++++++++++++++++++*/

   ANT_FUNC_START();

// Keep trying to read while there is an error, and that error is EAGAIN
/*1-------------------------------------------------------------*/
//   while (((iRxLenRead = read(pstChnlInfo->iFd, &aucRxBuffer[eChannel][iRxBufferLength[eChannel]], (sizeof(aucRxBuffer[eChannel]) - iRxBufferLength[eChannel]))) < 0)
//                   && errno == EAGAIN)
//      ;
/*1-------------------------------------------------------------*/

/*2++++++++++++++++++++++++++++++++++++++++++++++*/
   while (((RxLength = read(pstChnlInfo->iFd, &auRxBuffer, ANT_HCI_MAX_MSG_SIZE)) < 0)
                  && errno == EAGAIN);
/*2++++++++++++++++++++++++++++++++++++++++++++++*/

   if (RxLength < 0) {
      if (errno == ENODEV) {
         ANT_ERROR("%s not enabled, exiting rx thread",
               pstChnlInfo->pcDevicePath);

         goto out;
      } else if (errno == ENXIO) {
         ANT_ERROR("%s there is no physical ANT device connected",
               pstChnlInfo->pcDevicePath);

         goto out;
      } else {
         ANT_ERROR("%s read thread exiting, unhandled error: %s",
               pstChnlInfo->pcDevicePath, strerror(errno));

         goto out;
      }
   } else {
/*3++++++++++++++++++++++++++++++++++++++++++++++*/
	   memcpy((&auRxTempBuff[partial_len]) , &auRxBuffer, RxLength);
	   RxLength += partial_len;
	   ANT_SERIAL(auRxBuffer, RxLength, 'A');
	   /*check header byte */
	   for(temp_offset = 0; temp_offset < RxLength; temp_offset++){
		  if((auRxTempBuff[temp_offset] == COMMAND_HEDAER) || (auRxTempBuff[temp_offset] == HEADER_TYPE)){
			if((auRxTempBuff[temp_offset + 1] + temp_offset + 2) <= RxLength){
				RxLength--;
				for(i = 0; i < (RxLength - temp_offset); i++)
					auRxTempBuff[temp_offset + i] = auRxTempBuff[temp_offset + i + 1];
				temp_offset += auRxTempBuff[temp_offset];
			}else{
				partial_len = RxLength - temp_offset;
				RxLength = temp_offset;
			}
		  }
	   }
	   if (RxLength) {
		   ANT_SERIAL(auRxTempBuff, RxLength, 'B');
		   ANT_DEBUG_I("rx_len: %d !",RxLength);
		   memcpy(&aucRxBuffer[eChannel][iRxBufferLength[eChannel]], &auRxTempBuff,RxLength);
		   if(partial_len){
		   		ANT_DEBUG_I("partial pkt: %d !",partial_len);
			 	for(i = 0; i < partial_len; i++)
					auRxTempBuff[i] = auRxTempBuff[RxLength + i];
		   	}
		   iRxLenRead = RxLength;
	   	} else {
	   		ANT_DEBUG_I("less than 1 pkt! rxd_len: %d !",partial_len);
	   	    iRet = 0;
         	goto out;
	   	}
/*3++++++++++++++++++++++++++++++++++++++++++++++*/

      ANT_SERIAL(aucRxBuffer[eChannel], iRxLenRead, 'R');

      iRxLenRead += iRxBufferLength[eChannel];   // add existing data on
      
      // if we didn't get a full packet, then just exit
      if (iRxLenRead < (aucRxBuffer[eChannel][ANT_HCI_SIZE_OFFSET] + ANT_HCI_HEADER_SIZE + ANT_HCI_FOOTER_SIZE)) {
         iRxBufferLength[eChannel] = iRxLenRead;
         iRet = 0;
         goto out;
      }

      iRxBufferLength[eChannel] = 0;    // reset buffer length here since we should have a full packet
      
#if ANT_HCI_OPCODE_SIZE == 1  // Check the different message types by opcode
      ANT_U8 opcode = aucRxBuffer[eChannel][ANT_HCI_OPCODE_OFFSET];

      if(ANT_HCI_OPCODE_COMMAND_COMPLETE == opcode) {
         // Command Complete, so signal a FLOW_GO
         if(setFlowControl(pstChnlInfo, ANT_FLOW_GO)) {
            goto out;
         }
      } else if(ANT_HCI_OPCODE_FLOW_ON == opcode) {
         // FLow On, so resend the last Tx
#ifdef ANT_FLOW_RESEND
         // Check if there is a message to resend
         if(pstChnlInfo->ucResendMessageLength > 0) {
            ant_tx_message_flowcontrol_none(eChannel, pstChnlInfo->ucResendMessageLength, pstChnlInfo->pucResendMessage);
         } else {
            ANT_DEBUG_D("Resend requested by chip, but tx request cancelled");
         }
#endif // ANT_FLOW_RESEND
      } else if(ANT_HCI_OPCODE_ANT_EVENT == opcode)
         // ANT Event, send ANT packet to Rx Callback
#endif // ANT_HCI_OPCODE_SIZE == 1
      {
      // Received an ANT packet
         iCurrentHciPacketOffset = 0;

         while(iCurrentHciPacketOffset < iRxLenRead) {

            // TODO Allow HCI Packet Size value to be larger than 1 byte
            // This currently works as no size value is greater than 255, and little endian
            iHciDataSize = aucRxBuffer[eChannel][iCurrentHciPacketOffset + ANT_HCI_SIZE_OFFSET];

            if ((iHciDataSize + ANT_HCI_HEADER_SIZE + ANT_HCI_FOOTER_SIZE + iCurrentHciPacketOffset) > 
                  iRxLenRead) {
               // we don't have a whole packet
               iRxBufferLength[eChannel] = iRxLenRead - iCurrentHciPacketOffset;
               memcpy(aucRxBuffer[eChannel], &aucRxBuffer[eChannel][iCurrentHciPacketOffset], iRxBufferLength[eChannel]);
               // the increment at the end should push us out of the while loop
            } else
#ifdef ANT_MESG_FLOW_CONTROL
            if (aucRxBuffer[eChannel][iCurrentHciPacketOffset + ANT_HCI_DATA_OFFSET + ANT_MSG_ID_OFFSET] == 
                  ANT_MESG_FLOW_CONTROL) {
               // This is a flow control packet, not a standard ANT message
               if(setFlowControl(pstChnlInfo, \
                     aucRxBuffer[eChannel][iCurrentHciPacketOffset + ANT_HCI_DATA_OFFSET + ANT_MSG_DATA_OFFSET])) {
                  goto out;
               }
            } else
#endif // ANT_MESG_FLOW_CONTROL
            {
               ANT_U8 *msg = aucRxBuffer[eChannel] + iCurrentHciPacketOffset + ANT_HCI_DATA_OFFSET;
               ANT_BOOL bIsKeepAliveResponse = memcmp(msg, KEEPALIVE_RESP, sizeof(KEEPALIVE_RESP)/sizeof(ANT_U8)) == 0;
               if (bIsKeepAliveResponse) {
                  ANT_DEBUG_V("Filtered out keepalive response.");
               } else if (pstChnlInfo->fnRxCallback != NULL) {

                  // Loop through read data until all HCI packets are written to callback
                     pstChnlInfo->fnRxCallback(iHciDataSize, \
                           msg);
               } else {
                  ANT_WARN("%s rx callback is null", pstChnlInfo->pcDevicePath);
               }
            }
            
            iCurrentHciPacketOffset = iCurrentHciPacketOffset + ANT_HCI_HEADER_SIZE + ANT_HCI_FOOTER_SIZE + iHciDataSize;               
         }         
      }

      iRet = 0;
   }

out:
   ANT_FUNC_END();
   return iRet;
}