diff options
Diffstat (limited to 'src/vfs/ant_rx_chardev.c')
-rw-r--r-- | src/vfs/ant_rx_chardev.c | 78 |
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 } //////////////////////////////////////////////////////////////////// |