aboutsummaryrefslogtreecommitdiffstats
path: root/src/vfs/ant_rx_chardev.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/vfs/ant_rx_chardev.c')
-rw-r--r--src/vfs/ant_rx_chardev.c78
1 files changed, 57 insertions, 21 deletions
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 @@ static ANT_U8 aucRxBuffer[NUM_ANT_CHANNELS][ANT_HCI_MAX_MSG_SIZE];
#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 @@ void *fnRxThread(void *ant_rx_thread_info)
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 @@ void *fnRxThread(void *ant_rx_thread_info)
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 @@ void *fnRxThread(void *ant_rx_thread_info)
// 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 @@ void *fnRxThread(void *ant_rx_thread_info)
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
+}
+
+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);
+ }
-reset:
stRxThreadInfo->ucRunThread = 0;
ANT_DEBUG_V("getting stEnabledStatusLock in %s", __FUNCTION__);
@@ -220,9 +259,6 @@ reset:
stRxThreadInfo->ucChipResetting = 0;
ANT_FUNC_END();
-#ifdef ANDROID
- return NULL;
-#endif
}
////////////////////////////////////////////////////////////////////