Android_System_ANT-HAL_1-6-2
diff --git a/src/common/inc/ant_version.h b/src/common/inc/ant_version.h
index 0b8988b..21f3660 100644
--- a/src/common/inc/ant_version.h
+++ b/src/common/inc/ant_version.h
@@ -21,7 +21,7 @@
 

 #define LIBANT_STACK_MAJOR "1"

 #define LIBANT_STACK_MINOR "6"

-#define LIBANT_STACK_INCRE "1"

+#define LIBANT_STACK_INCRE "2"

 

 #endif // __ANT_VERSION_H

 

diff --git a/src/vfs/ant_native_chardev.c b/src/vfs/ant_native_chardev.c
index df209c2..2b49a8c 100644
--- a/src/vfs/ant_native_chardev.c
+++ b/src/vfs/ant_native_chardev.c
@@ -30,6 +30,9 @@
 #include <fcntl.h> /* for open() */
 #include <linux/ioctl.h> /* For hard reset */
 #include <pthread.h>
+#include <stdint.h> /* for uint64_t */
+#include <sys/eventfd.h> /* For eventfd() */
+#include <unistd.h> /* for read(), write(), and close() */
 
 #include "ant_types.h"
 #include "ant_native.h"
@@ -37,7 +40,7 @@
 
 #include "antradio_power.h"
 #include "ant_rx_chardev.h"
-#include "ant_driver_defines.h"
+#include "ant_hci_defines.h"
 #include "ant_log.h"
 
 #if ANT_HCI_SIZE_SIZE > 1
@@ -58,6 +61,8 @@
 static pthread_cond_t stFlowControlCond = PTHREAD_COND_INITIALIZER;
 ANTNativeANTStateCb g_fnStateCallback;
 
+static const uint64_t EVENT_FD_PLUS_ONE = 1L;
+
 static void ant_channel_init(ant_channel_info_t *pstChnlInfo, const char *pcCharDevName);
 
 ////////////////////////////////////////////////////////////////////
@@ -69,13 +74,14 @@
 //      -
 //
 //  Returns:
-//      ANT_STATUS_SUCCESS
+//      ANT_STATUS_SUCCESS if intialize completed, else ANT_STATUS_FAILED
 //
 //  Psuedocode:
 /*
 Set variables to defaults
 Initialise each supported path to chip
-RESULT = ANT_STATUS_SUCCESS
+Setup eventfd object.
+RESULT = ANT_STATUS_SUCCESS if no problems else ANT_STATUS_FAILED
 */
 ////////////////////////////////////////////////////////////////////
 ANTStatus ant_init(void)
@@ -96,7 +102,16 @@
    ant_channel_init(&stRxThreadInfo.astChannels[DATA_CHANNEL], ANT_DATA_DEVICE_NAME);
 #endif // Separate data/command paths
 
-   status = ANT_STATUS_SUCCESS;
+   // Make the eventfd. Want it non blocking so that we can easily reset it by reading.
+   stRxThreadInfo.iRxShutdownEventFd = eventfd(0, EFD_NONBLOCK);
+
+   // Check for error case
+   if(stRxThreadInfo.iRxShutdownEventFd == -1)
+   {
+      ANT_ERROR("ANT init failed. Could not create event fd. Reason: %s", strerror(errno));
+   } else {
+      status = ANT_STATUS_SUCCESS;
+   }
 
    ANT_FUNC_END();
    return status;
@@ -105,7 +120,7 @@
 ////////////////////////////////////////////////////////////////////
 //  ant_deinit
 //
-//  Doesn't actually do anything.
+//  clean up eventfd object
 //
 //  Parameters:
 //      -
@@ -123,7 +138,12 @@
    ANTStatus result_status = ANT_STATUS_FAILED;
    ANT_FUNC_START();
 
-   result_status = ANT_STATUS_SUCCESS;
+   if(close(stRxThreadInfo.iRxShutdownEventFd) < 0)
+   {
+      ANT_ERROR("Could not close eventfd in deinit. Reason: %s", strerror(errno));
+   } else {
+      result_status = ANT_STATUS_SUCCESS;
+   }
 
    ANT_FUNC_END();
    return result_status;
@@ -838,6 +858,16 @@
    ant_channel_type eChannel;
    ANT_FUNC_START();
 
+   // Reset the shutdown signal.
+   uint64_t counter;
+   ssize_t result = read(stRxThreadInfo.iRxShutdownEventFd, &counter, sizeof(counter));
+   // EAGAIN result indicates that the counter was already 0 in non-blocking mode.
+   if(result < 0 && errno != EAGAIN)
+   {
+      ANT_ERROR("Could not clear shutdown signal in enable. Reason: %s", strerror(errno));
+      goto out;
+   }
+
    stRxThreadInfo.ucRunThread = 1;
 
    for (eChannel = 0; eChannel < NUM_ANT_CHANNELS; eChannel++) {
@@ -878,11 +908,14 @@
 
    stRxThreadInfo.ucRunThread = 0;
 
-   for (eChannel = 0; eChannel < NUM_ANT_CHANNELS; eChannel++) {
-      ant_disable_channel(&stRxThreadInfo.astChannels[eChannel]);
-   }
-
    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;
@@ -891,6 +924,10 @@
       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:
diff --git a/src/vfs/ant_rx_chardev.c b/src/vfs/ant_rx_chardev.c
index b38757f..aa51825 100644
--- a/src/vfs/ant_rx_chardev.c
+++ b/src/vfs/ant_rx_chardev.c
@@ -29,11 +29,12 @@
 #include <errno.h>
 #include <poll.h>
 #include <pthread.h>
+#include <stdint.h> /* for uint64_t */
 
 #include "ant_types.h"
 #include "antradio_power.h"
 #include "ant_rx_chardev.h"
-#include "ant_driver_defines.h"
+#include "ant_hci_defines.h"
 #include "ant_log.h"
 #include "ant_native.h"  // ANT_HCI_MAX_MSG_SIZE, ANT_MSG_ID_OFFSET, ANT_MSG_DATA_OFFSET,
                          // ant_radio_enabled_status()
@@ -60,6 +61,11 @@
 
 #define EVENTS_TO_LISTEN_FOR (EVENT_DATA_AVAILABLE|EVENT_DISABLE|EVENT_HARD_RESET)
 
+// Plus one is for the eventfd shutdown signal.
+#define NUM_POLL_FDS (NUM_ANT_CHANNELS + 1)
+#define EVENTFD_IDX NUM_ANT_CHANNELS
+
+void doReset(ant_rx_thread_info_t *stRxThreadInfo);
 int readChannelMsg(ant_channel_type eChannel, ant_channel_info_t *pstChnlInfo);
 
 /*
@@ -87,7 +93,7 @@
    int iMutexLockResult;
    int iPollRet;
    ant_rx_thread_info_t *stRxThreadInfo;
-   struct pollfd astPollFd[NUM_ANT_CHANNELS];
+   struct pollfd astPollFd[NUM_POLL_FDS];
    ant_channel_type eChannel;
    ANT_FUNC_START();
 
@@ -96,29 +102,27 @@
       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;
 
    /* continue running as long as not terminated */
    while (stRxThreadInfo->ucRunThread) {
       /* Wait for data available on any file (transport path) */
-      iPollRet = poll(astPollFd, NUM_ANT_CHANNELS, ANT_POLL_TIMEOUT);
+      iPollRet = poll(astPollFd, NUM_POLL_FDS, ANT_POLL_TIMEOUT);
       if (!iPollRet) {
          ANT_DEBUG_V("poll timed out, checking exit cond");
       } else if (iPollRet < 0) {
-         ANT_ERROR("read thread exiting, unhandled error: %s", strerror(errno));
+         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("poll error from %s. exiting rx thread",
+               ANT_ERROR("Hard reset indicated by %s. Attempting recovery.",
                             stRxThreadInfo->astChannels[eChannel].pcDevicePath);
-               /* Chip was reset or other error, only way to recover is to
-                * close and open ANT chardev */
-               stRxThreadInfo->ucChipResetting = 1;
-
-               if (g_fnStateCallback) {
-                  g_fnStateCallback(RADIO_STATUS_RESETTING);
-               }
-
-               goto reset;
+               doReset(stRxThreadInfo);
+               goto out;
             } else if (areAllFlagsSet(astPollFd[eChannel].revents, EVENT_DISABLE)) {
                /* chip reported it was disabled, either unexpectedly or due to us closing the file */
                ANT_DEBUG_D(
@@ -135,12 +139,36 @@
                   // 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;
+         }
       }
    }
 
@@ -177,15 +205,26 @@
       ANT_DEBUG_V("stEnabledStatusLock busy");
    }
 
-   // FIXME This is not the end of the function
-   // Probably because goto:reset is a bad implementation; can have a reset function.
-   // Will only end here on Android.
+   out:
    ANT_FUNC_END();
 #ifdef ANDROID
    return NULL;
 #endif
+}
 
-reset:
+void doReset(ant_rx_thread_info_t *stRxThreadInfo)
+{
+   int iMutexLockResult;
+
+   ANT_FUNC_START();
+   /* Chip was reset or other error, only way to recover is to
+    * close and open ANT chardev */
+   stRxThreadInfo->ucChipResetting = 1;
+
+   if (g_fnStateCallback) {
+      g_fnStateCallback(RADIO_STATUS_RESETTING);
+   }
+
    stRxThreadInfo->ucRunThread = 0;
 
    ANT_DEBUG_V("getting stEnabledStatusLock in %s", __FUNCTION__);
@@ -220,9 +259,6 @@
    stRxThreadInfo->ucChipResetting = 0;
 
    ANT_FUNC_END();
-#ifdef ANDROID
-   return NULL;
-#endif
 }
 
 ////////////////////////////////////////////////////////////////////
diff --git a/src/vfs/inc/ant_hci_defines.h b/src/vfs/inc/ant_hci_defines.h
new file mode 100644
index 0000000..3ffe672
--- /dev/null
+++ b/src/vfs/inc/ant_hci_defines.h
@@ -0,0 +1,53 @@
+/*
+ * ANT Stack
+ *
+ * Copyright 2013 Dynastream Innovations
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+/*******************************************************************************\
+*
+*   FILE NAME:    ant_hci_defines.h
+*
+*   BRIEF:
+*      This file defines ANT specific HCI values used by the ANT chip that are
+*      not specific to the underlying chip. These should not need to be modified,
+*      but should be verified they are correct.
+*
+\*******************************************************************************/
+
+#ifndef __VFS_INDEPENDENT_H
+#define __VFS_INDEPENDENT_H
+
+// ANT HCI Packet Structure
+// -----------------------------------------
+// |         Header       | Data |  Footer  |
+// |----------------------|-----------------|
+// |Optional| Data | Opt. | ...  | Optional |
+// | Opcode | Size | Sync |      | Checksum |
+// Data may include any number of ANT packets, with no sync byte or checksum.
+// A read from the driver may return any number of ANT HCI packets.
+
+#include "ant_driver_defines.h"
+
+#define ANT_HCI_HEADER_SIZE                  ((ANT_HCI_OPCODE_SIZE) + (ANT_HCI_SIZE_SIZE) + (ANT_HCI_SYNC_SIZE))
+#define ANT_HCI_FOOTER_SIZE                  (ANT_HCI_CHECKSUM_SIZE)
+
+#define ANT_HCI_OPCODE_OFFSET                0
+#define ANT_HCI_SIZE_OFFSET                  ((ANT_HCI_OPCODE_OFFSET) + (ANT_HCI_OPCODE_SIZE))
+#define ANT_HCI_SYNC_OFFSET                  ((ANT_HCI_SIZE_OFFSET) + (ANT_HCI_SIZE_SIZE))
+#define ANT_HCI_DATA_OFFSET                  (ANT_HCI_HEADER_SIZE)
+
+#define ANT_FLOW_GO_WAIT_TIMEOUT_SEC         10
+
+#endif /* ifndef __VFS_INDEPENDENT_H */
diff --git a/src/vfs/inc/ant_rx_chardev.h b/src/vfs/inc/ant_rx_chardev.h
index 526070c..1024dac 100644
--- a/src/vfs/inc/ant_rx_chardev.h
+++ b/src/vfs/inc/ant_rx_chardev.h
@@ -32,7 +32,7 @@
 #define __ANT_RX_NATIVE_H
 
 #include "ant_native.h"
-#include "ant_driver_defines.h"
+#include "ant_hci_defines.h"
 
 /* same as HCI_MAX_EVENT_SIZE from hci.h, but hci.h is not included for vfs */
 #define ANT_HCI_MAX_MSG_SIZE 260
@@ -84,6 +84,8 @@
    pthread_mutex_t *pstEnabledStatusLock;
    /* ANT channels */
    ant_channel_info_t astChannels[NUM_ANT_CHANNELS];
+   /* Event file descriptor used to interrupt the poll() loop in the rx thread. */
+   int iRxShutdownEventFd;
 } ant_rx_thread_info_t;
 
 extern ANTNativeANTStateCb g_fnStateCallback;  // TODO State callback should be inside ant_rx_thread_info_t.
diff --git a/src/vfs/prerelease/ant_driver_defines.h b/src/vfs/prerelease/ant_driver_defines.h
index f2e843b..692de0d 100644
--- a/src/vfs/prerelease/ant_driver_defines.h
+++ b/src/vfs/prerelease/ant_driver_defines.h
@@ -82,17 +82,4 @@
 //     That signals Flow Stop:
 #define ANT_FLOW_STOP                        ((ANT_U8)0x80)
 
-// ---------------------- NOT CHIP SPECIFIC
-// These should not need to be modified, but should be verified they are correct
-
-#define ANT_HCI_HEADER_SIZE                  ((ANT_HCI_OPCODE_SIZE) + (ANT_HCI_SIZE_SIZE) + (ANT_HCI_SYNC_SIZE))
-#define ANT_HCI_FOOTER_SIZE                  (ANT_HCI_CHECKSUM_SIZE)
-
-#define ANT_HCI_OPCODE_OFFSET                0
-#define ANT_HCI_SIZE_OFFSET                  ((ANT_HCI_OPCODE_OFFSET) + (ANT_HCI_OPCODE_SIZE))
-#define ANT_HCI_SYNC_OFFSET                  ((ANT_HCI_SIZE_OFFSET) + (ANT_HCI_SIZE_SIZE))
-#define ANT_HCI_DATA_OFFSET                  (ANT_HCI_HEADER_SIZE)
-
-#define ANT_FLOW_GO_WAIT_TIMEOUT_SEC         10
-
 #endif /* ifndef __VFS_PRERELEASE_H */
diff --git a/src/vfs/ste/cg29xx/ant_driver_defines.h b/src/vfs/ste/cg29xx/ant_driver_defines.h
index aa75ffa..c47415d 100644
--- a/src/vfs/ste/cg29xx/ant_driver_defines.h
+++ b/src/vfs/ste/cg29xx/ant_driver_defines.h
@@ -79,17 +79,4 @@
 //     That signals Flow Stop:
 #define ANT_FLOW_STOP                        ((ANT_U8)0x80)
 
-
-// ---------------------- NOT CHIP SPECIFIC
-// These should not need to be modified, but should be verified they are correct
-
-#define ANT_HCI_HEADER_SIZE                  ((ANT_HCI_OPCODE_SIZE) + (ANT_HCI_SIZE_SIZE) + (ANT_HCI_SYNC_SIZE))
-
-#define ANT_HCI_OPCODE_OFFSET                0
-#define ANT_HCI_SIZE_OFFSET                  ((ANT_HCI_OPCODE_OFFSET) + (ANT_HCI_OPCODE_SIZE))
-#define ANT_HCI_SYNC_OFFSET                  ((ANT_HCI_SIZE_OFFSET) + (ANT_HCI_SIZE_SIZE))
-#define ANT_HCI_DATA_OFFSET                  (ANT_HCI_HEADER_SIZE)
-
-#define ANT_FLOW_GO_WAIT_TIMEOUT_SEC         10
-
 #endif /* ifndef __VFS_PRERELEASE_H */