blob: 2a2ec7f5e02a708b9de49078760e779db35525a7 [file] [log] [blame]
Rohan Martinaf8cf682012-11-16 21:11:07 -07001/*
2 * ANT Stack
3 *
4 * Copyright 2011 Dynastream Innovations
5 *
6 * Licensed under the Apache License, Version 2.0 (the "License");
7 * you may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at
9 *
10 * http://www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
17 */
18/******************************************************************************\
19*
20* FILE NAME: ant_rx_chardev.c
21*
22* BRIEF:
23* This file implements the receive thread function which will loop reading
24* ANT messages until told to exit.
25*
26*
27\******************************************************************************/
28
29#include <errno.h>
Naveen Kumar09c39572015-08-20 19:49:28 +053030#include <string.h>
Rohan Martinaf8cf682012-11-16 21:11:07 -070031#include <poll.h>
32#include <pthread.h>
Khurshid4d09cf12013-10-01 16:45:34 -060033#include <stdint.h> /* for uint64_t */
Rohan Martinaf8cf682012-11-16 21:11:07 -070034
35#include "ant_types.h"
36#include "antradio_power.h"
37#include "ant_rx_chardev.h"
Khurshid4d09cf12013-10-01 16:45:34 -060038#include "ant_hci_defines.h"
Rohan Martinaf8cf682012-11-16 21:11:07 -070039#include "ant_log.h"
40#include "ant_native.h" // ANT_HCI_MAX_MSG_SIZE, ANT_MSG_ID_OFFSET, ANT_MSG_DATA_OFFSET,
41 // ant_radio_enabled_status()
42
43extern ANTStatus ant_tx_message_flowcontrol_none(ant_channel_type eTxPath, ANT_U8 ucMessageLength, ANT_U8 *pucTxMessage);
44
45#undef LOG_TAG
46#define LOG_TAG "antradio_rx"
47
48#define ANT_POLL_TIMEOUT ((int)30000)
James Bootsma105c80a2014-03-13 16:12:54 -060049#define KEEPALIVE_TIMEOUT ((int)5000)
Rohan Martinaf8cf682012-11-16 21:11:07 -070050
Jeremy Friesenbc436592013-05-07 14:44:01 -060051static ANT_U8 aucRxBuffer[NUM_ANT_CHANNELS][ANT_HCI_MAX_MSG_SIZE];
52
53#ifdef ANT_DEVICE_NAME // Single transport path
54 static int iRxBufferLength[NUM_ANT_CHANNELS] = {0};
55#else
56 static int iRxBufferLength[NUM_ANT_CHANNELS] = {0, 0};
57#endif //
58
Khurshide1e69662013-09-27 10:27:48 -060059// Defines for use with the poll() call
60#define EVENT_DATA_AVAILABLE (POLLIN|POLLRDNORM)
James Bootsma105c80a2014-03-13 16:12:54 -060061#define EVENT_CHIP_SHUTDOWN (POLLHUP)
Khurshide1e69662013-09-27 10:27:48 -060062#define EVENT_HARD_RESET (POLLERR|POLLPRI|POLLRDHUP)
63
James Bootsma105c80a2014-03-13 16:12:54 -060064#define EVENTS_TO_LISTEN_FOR (EVENT_DATA_AVAILABLE|EVENT_CHIP_SHUTDOWN|EVENT_HARD_RESET)
Khurshide1e69662013-09-27 10:27:48 -060065
Khurshid4d09cf12013-10-01 16:45:34 -060066// Plus one is for the eventfd shutdown signal.
67#define NUM_POLL_FDS (NUM_ANT_CHANNELS + 1)
68#define EVENTFD_IDX NUM_ANT_CHANNELS
69
James Bootsma105c80a2014-03-13 16:12:54 -060070static ANT_U8 KEEPALIVE_MESG[] = {0x01, 0x00, 0x00};
71static ANT_U8 KEEPALIVE_RESP[] = {0x03, 0x40, 0x00, 0x00, 0x28};
72
Khurshid4d09cf12013-10-01 16:45:34 -060073void doReset(ant_rx_thread_info_t *stRxThreadInfo);
Rohan Martinaf8cf682012-11-16 21:11:07 -070074int readChannelMsg(ant_channel_type eChannel, ant_channel_info_t *pstChnlInfo);
75
76/*
Khurshide1e69662013-09-27 10:27:48 -060077 * Function to check that all given flags are set in a particular value.
78 * Designed for use with the revents field of pollfds filled out by poll().
79 *
80 * Parameters:
81 * - value: The value that will be checked to contain all flags.
82 * - flags: Bitwise-or of the flags that value should be checked for.
83 *
84 * Returns:
85 * - true IFF all the bits that are set in 'flags' are also set in 'value'
86 */
87ANT_BOOL areAllFlagsSet(short value, short flags)
88{
89 value &= flags;
90 return (value == flags);
91}
92
93/*
James Bootsma105c80a2014-03-13 16:12:54 -060094 * This thread is run occasionally as a detached thread in order to send a keepalive message to the
95 * chip.
96 */
97void *fnKeepAliveThread(void *unused)
98{
99 ANT_DEBUG_V("Sending dummy keepalive message.");
100 ant_tx_message(sizeof(KEEPALIVE_MESG)/sizeof(ANT_U8), KEEPALIVE_MESG);
101 return NULL;
102}
103
104/*
Rohan Martinaf8cf682012-11-16 21:11:07 -0700105 * This thread waits for ANT messages from a VFS file.
106 */
107void *fnRxThread(void *ant_rx_thread_info)
108{
109 int iMutexLockResult;
110 int iPollRet;
111 ant_rx_thread_info_t *stRxThreadInfo;
Khurshid4d09cf12013-10-01 16:45:34 -0600112 struct pollfd astPollFd[NUM_POLL_FDS];
Rohan Martinaf8cf682012-11-16 21:11:07 -0700113 ant_channel_type eChannel;
114 ANT_FUNC_START();
115
116 stRxThreadInfo = (ant_rx_thread_info_t *)ant_rx_thread_info;
117 for (eChannel = 0; eChannel < NUM_ANT_CHANNELS; eChannel++) {
118 astPollFd[eChannel].fd = stRxThreadInfo->astChannels[eChannel].iFd;
Khurshide1e69662013-09-27 10:27:48 -0600119 astPollFd[eChannel].events = EVENTS_TO_LISTEN_FOR;
Rohan Martinaf8cf682012-11-16 21:11:07 -0700120 }
Khurshid4d09cf12013-10-01 16:45:34 -0600121 // Fill out poll request for the shutdown signaller.
122 astPollFd[EVENTFD_IDX].fd = stRxThreadInfo->iRxShutdownEventFd;
123 astPollFd[EVENTFD_IDX].events = POLL_IN;
Rohan Martinaf8cf682012-11-16 21:11:07 -0700124
James Bootsma105c80a2014-03-13 16:12:54 -0600125 // Reset the waiting for response, since we don't want a stale value if we were reset.
126 stRxThreadInfo->bWaitingForKeepaliveResponse = ANT_FALSE;
127
Rohan Martinaf8cf682012-11-16 21:11:07 -0700128 /* continue running as long as not terminated */
129 while (stRxThreadInfo->ucRunThread) {
James Bootsma105c80a2014-03-13 16:12:54 -0600130 /* Wait for data available on any file (transport path), shorter wait if we just timed out. */
131 int timeout = stRxThreadInfo->bWaitingForKeepaliveResponse ? KEEPALIVE_TIMEOUT : ANT_POLL_TIMEOUT;
132 iPollRet = poll(astPollFd, NUM_POLL_FDS, timeout);
Rohan Martinaf8cf682012-11-16 21:11:07 -0700133 if (!iPollRet) {
James Bootsma105c80a2014-03-13 16:12:54 -0600134 if(!stRxThreadInfo->bWaitingForKeepaliveResponse)
135 {
136 stRxThreadInfo->bWaitingForKeepaliveResponse = ANT_TRUE;
137 // Keep alive is done on a separate thread so that rxThread can handle flow control during
138 // the message.
139 pthread_t thread;
140 // Don't care if it failed as the consequence is just a missed keep-alive.
141 pthread_create(&thread, NULL, fnKeepAliveThread, NULL);
142 // Detach the thread so that we don't need to join it later.
143 pthread_detach(thread);
144 ANT_DEBUG_V("poll timed out, checking exit cond");
145 } else
146 {
147 ANT_DEBUG_E("No response to keepalive, attempting recovery.");
148 doReset(stRxThreadInfo);
149 goto out;
150 }
Rohan Martinaf8cf682012-11-16 21:11:07 -0700151 } else if (iPollRet < 0) {
Khurshid4d09cf12013-10-01 16:45:34 -0600152 ANT_ERROR("unhandled error: %s, attempting recovery.", strerror(errno));
153 doReset(stRxThreadInfo);
154 goto out;
Rohan Martinaf8cf682012-11-16 21:11:07 -0700155 } else {
156 for (eChannel = 0; eChannel < NUM_ANT_CHANNELS; eChannel++) {
Khurshide1e69662013-09-27 10:27:48 -0600157 if (areAllFlagsSet(astPollFd[eChannel].revents, EVENT_HARD_RESET)) {
Khurshid4d09cf12013-10-01 16:45:34 -0600158 ANT_ERROR("Hard reset indicated by %s. Attempting recovery.",
Rohan Martinaf8cf682012-11-16 21:11:07 -0700159 stRxThreadInfo->astChannels[eChannel].pcDevicePath);
Khurshid4d09cf12013-10-01 16:45:34 -0600160 doReset(stRxThreadInfo);
161 goto out;
James Bootsma105c80a2014-03-13 16:12:54 -0600162 } else if (areAllFlagsSet(astPollFd[eChannel].revents, EVENT_CHIP_SHUTDOWN)) {
163 /* chip reported it was unexpectedly disabled */
Khurshide1e69662013-09-27 10:27:48 -0600164 ANT_DEBUG_D(
165 "poll hang-up from %s. exiting rx thread", stRxThreadInfo->astChannels[eChannel].pcDevicePath);
166
James Bootsma105c80a2014-03-13 16:12:54 -0600167 doReset(stRxThreadInfo);
168 goto out;
Khurshide1e69662013-09-27 10:27:48 -0600169 } else if (areAllFlagsSet(astPollFd[eChannel].revents, EVENT_DATA_AVAILABLE)) {
Rohan Martinaf8cf682012-11-16 21:11:07 -0700170 ANT_DEBUG_D("data on %s. reading it",
171 stRxThreadInfo->astChannels[eChannel].pcDevicePath);
172
James Bootsma105c80a2014-03-13 16:12:54 -0600173 // Doesn't matter what data we received, we know the chip is alive.
174 stRxThreadInfo->bWaitingForKeepaliveResponse = ANT_FALSE;
175
Rohan Martinaf8cf682012-11-16 21:11:07 -0700176 if (readChannelMsg(eChannel, &stRxThreadInfo->astChannels[eChannel]) < 0) {
Khurshide1e69662013-09-27 10:27:48 -0600177 // set flag to exit out of Rx Loop
178 stRxThreadInfo->ucRunThread = 0;
Rohan Martinaf8cf682012-11-16 21:11:07 -0700179 }
Khurshid4d09cf12013-10-01 16:45:34 -0600180 } else if (areAllFlagsSet(astPollFd[eChannel].revents, POLLNVAL)) {
181 ANT_ERROR("poll was called on invalid file descriptor %s. Attempting recovery.",
182 stRxThreadInfo->astChannels[eChannel].pcDevicePath);
183 doReset(stRxThreadInfo);
184 goto out;
185 } else if (areAllFlagsSet(astPollFd[eChannel].revents, POLLERR)) {
186 ANT_ERROR("Unknown error from %s. Attempting recovery.",
187 stRxThreadInfo->astChannels[eChannel].pcDevicePath);
188 doReset(stRxThreadInfo);
189 goto out;
Rohan Martinaf8cf682012-11-16 21:11:07 -0700190 } else if (astPollFd[eChannel].revents) {
191 ANT_DEBUG_W("unhandled poll result %#x from %s",
192 astPollFd[eChannel].revents,
193 stRxThreadInfo->astChannels[eChannel].pcDevicePath);
194 }
195 }
Khurshid4d09cf12013-10-01 16:45:34 -0600196 // Now check for shutdown signal
197 if(areAllFlagsSet(astPollFd[EVENTFD_IDX].revents, POLLIN))
198 {
199 ANT_DEBUG_I("rx thread caught shutdown signal.");
200 // reset the counter by reading.
201 uint64_t counter;
202 read(stRxThreadInfo->iRxShutdownEventFd, &counter, sizeof(counter));
203 // don't care if read error, going to close the thread anyways.
204 stRxThreadInfo->ucRunThread = 0;
205 } else if (astPollFd[EVENTFD_IDX].revents != 0) {
206 ANT_ERROR("Shutdown event descriptor had unexpected event: %#x. exiting rx thread.",
207 astPollFd[EVENTFD_IDX].revents);
208 stRxThreadInfo->ucRunThread = 0;
209 }
Rohan Martinaf8cf682012-11-16 21:11:07 -0700210 }
211 }
212
Khurshide1e69662013-09-27 10:27:48 -0600213 /* disable ANT radio if not already disabling */
214 // Try to get stEnabledStatusLock.
215 // if you get it then no one is enabling or disabling
216 // if you can't get it assume something made you exit
Rohan Martinaf8cf682012-11-16 21:11:07 -0700217 ANT_DEBUG_V("try getting stEnabledStatusLock in %s", __FUNCTION__);
218 iMutexLockResult = pthread_mutex_trylock(stRxThreadInfo->pstEnabledStatusLock);
219 if (!iMutexLockResult) {
220 ANT_DEBUG_V("got stEnabledStatusLock in %s", __FUNCTION__);
221 ANT_WARN("rx thread has unexpectedly crashed, cleaning up");
Khurshide1e69662013-09-27 10:27:48 -0600222
223 // spoof our handle as closed so we don't try to join ourselves in disable
224 stRxThreadInfo->stRxThread = 0;
Rohan Martinaf8cf682012-11-16 21:11:07 -0700225
226 if (g_fnStateCallback) {
227 g_fnStateCallback(RADIO_STATUS_DISABLING);
228 }
229
230 ant_disable();
231
232 if (g_fnStateCallback) {
233 g_fnStateCallback(ant_radio_enabled_status());
234 }
235
236 ANT_DEBUG_V("releasing stEnabledStatusLock in %s", __FUNCTION__);
237 pthread_mutex_unlock(stRxThreadInfo->pstEnabledStatusLock);
238 ANT_DEBUG_V("released stEnabledStatusLock in %s", __FUNCTION__);
239 } else if (iMutexLockResult != EBUSY) {
240 ANT_ERROR("rx thread closing code, trylock on state lock failed: %s",
241 strerror(iMutexLockResult));
242 } else {
243 ANT_DEBUG_V("stEnabledStatusLock busy");
244 }
245
Khurshid4d09cf12013-10-01 16:45:34 -0600246 out:
Rohan Martinaf8cf682012-11-16 21:11:07 -0700247 ANT_FUNC_END();
248#ifdef ANDROID
249 return NULL;
250#endif
Khurshid4d09cf12013-10-01 16:45:34 -0600251}
Rohan Martinaf8cf682012-11-16 21:11:07 -0700252
Khurshid4d09cf12013-10-01 16:45:34 -0600253void doReset(ant_rx_thread_info_t *stRxThreadInfo)
254{
255 int iMutexLockResult;
256
257 ANT_FUNC_START();
258 /* Chip was reset or other error, only way to recover is to
259 * close and open ANT chardev */
260 stRxThreadInfo->ucChipResetting = 1;
261
262 if (g_fnStateCallback) {
263 g_fnStateCallback(RADIO_STATUS_RESETTING);
264 }
265
Rohan Martinaf8cf682012-11-16 21:11:07 -0700266 stRxThreadInfo->ucRunThread = 0;
267
268 ANT_DEBUG_V("getting stEnabledStatusLock in %s", __FUNCTION__);
269 iMutexLockResult = pthread_mutex_lock(stRxThreadInfo->pstEnabledStatusLock);
270 if (iMutexLockResult < 0) {
271 ANT_ERROR("chip was reset, getting state mutex failed: %s",
272 strerror(iMutexLockResult));
273 stRxThreadInfo->stRxThread = 0;
James Bootsma105c80a2014-03-13 16:12:54 -0600274 stRxThreadInfo->ucChipResetting = 0;
Rohan Martinaf8cf682012-11-16 21:11:07 -0700275 } else {
276 ANT_DEBUG_V("got stEnabledStatusLock in %s", __FUNCTION__);
277
278 stRxThreadInfo->stRxThread = 0; /* spoof our handle as closed so we don't
279 * try to join ourselves in disable */
280
281 ant_disable();
282
James Bootsma105c80a2014-03-13 16:12:54 -0600283 int enableResult = ant_enable();
284
285 stRxThreadInfo->ucChipResetting = 0;
286 if (enableResult) { /* failed */
Rohan Martinaf8cf682012-11-16 21:11:07 -0700287 if (g_fnStateCallback) {
288 g_fnStateCallback(RADIO_STATUS_DISABLED);
289 }
290 } else { /* success */
291 if (g_fnStateCallback) {
292 g_fnStateCallback(RADIO_STATUS_RESET);
293 }
294 }
295
296 ANT_DEBUG_V("releasing stEnabledStatusLock in %s", __FUNCTION__);
297 pthread_mutex_unlock(stRxThreadInfo->pstEnabledStatusLock);
298 ANT_DEBUG_V("released stEnabledStatusLock in %s", __FUNCTION__);
299 }
300
Rohan Martinaf8cf682012-11-16 21:11:07 -0700301 ANT_FUNC_END();
Rohan Martinaf8cf682012-11-16 21:11:07 -0700302}
303
304////////////////////////////////////////////////////////////////////
305// setFlowControl
306//
307// Sets the flow control "flag" to the value provided and signals the transmit
308// thread to check the value.
309//
310// Parameters:
311// pstChnlInfo the details of the channel being updated
312// ucFlowSetting the value to use
313//
314// Returns:
315// Success:
316// 0
317// Failure:
318// -1
319////////////////////////////////////////////////////////////////////
320int setFlowControl(ant_channel_info_t *pstChnlInfo, ANT_U8 ucFlowSetting)
321{
322 int iRet = -1;
323 int iMutexResult;
324 ANT_FUNC_START();
325
326 ANT_DEBUG_V("getting stFlowControlLock in %s", __FUNCTION__);
327 iMutexResult = pthread_mutex_lock(pstChnlInfo->pstFlowControlLock);
328 if (iMutexResult) {
329 ANT_ERROR("failed to lock flow control mutex during response: %s", strerror(iMutexResult));
330 } else {
331 ANT_DEBUG_V("got stFlowControlLock in %s", __FUNCTION__);
332
333 pstChnlInfo->ucFlowControlResp = ucFlowSetting;
334
335 ANT_DEBUG_V("releasing stFlowControlLock in %s", __FUNCTION__);
336 pthread_mutex_unlock(pstChnlInfo->pstFlowControlLock);
337 ANT_DEBUG_V("released stFlowControlLock in %s", __FUNCTION__);
338
339 pthread_cond_signal(pstChnlInfo->pstFlowControlCond);
340
341 iRet = 0;
342 }
343
344 ANT_FUNC_END();
345 return iRet;
346}
347
348int readChannelMsg(ant_channel_type eChannel, ant_channel_info_t *pstChnlInfo)
349{
350 int iRet = -1;
Rohan Martinaf8cf682012-11-16 21:11:07 -0700351 int iRxLenRead;
Jeremy Friesenf8b491f2013-04-05 15:58:20 -0600352 int iCurrentHciPacketOffset;
Jeremy Friesenddde26e2013-04-17 16:40:52 -0600353 int iHciDataSize;
Rohan Martinaf8cf682012-11-16 21:11:07 -0700354 ANT_FUNC_START();
355
356 // Keep trying to read while there is an error, and that error is EAGAIN
Jeremy Friesenbc436592013-05-07 14:44:01 -0600357 while (((iRxLenRead = read(pstChnlInfo->iFd, &aucRxBuffer[eChannel][iRxBufferLength[eChannel]], (sizeof(aucRxBuffer[eChannel]) - iRxBufferLength[eChannel]))) < 0)
Rohan Martinaf8cf682012-11-16 21:11:07 -0700358 && errno == EAGAIN)
359 ;
360
361 if (iRxLenRead < 0) {
362 if (errno == ENODEV) {
363 ANT_ERROR("%s not enabled, exiting rx thread",
364 pstChnlInfo->pcDevicePath);
365
366 goto out;
367 } else if (errno == ENXIO) {
368 ANT_ERROR("%s there is no physical ANT device connected",
369 pstChnlInfo->pcDevicePath);
370
371 goto out;
372 } else {
373 ANT_ERROR("%s read thread exiting, unhandled error: %s",
374 pstChnlInfo->pcDevicePath, strerror(errno));
375
376 goto out;
377 }
378 } else {
Jeremy Friesenbc436592013-05-07 14:44:01 -0600379 ANT_SERIAL(aucRxBuffer[eChannel], iRxLenRead, 'R');
Rohan Martinaf8cf682012-11-16 21:11:07 -0700380
Jeremy Friesenbc436592013-05-07 14:44:01 -0600381 iRxLenRead += iRxBufferLength[eChannel]; // add existing data on
Jeremy Friesenddde26e2013-04-17 16:40:52 -0600382
383 // if we didn't get a full packet, then just exit
Jeremy Friesenbc436592013-05-07 14:44:01 -0600384 if (iRxLenRead < (aucRxBuffer[eChannel][ANT_HCI_SIZE_OFFSET] + ANT_HCI_HEADER_SIZE + ANT_HCI_FOOTER_SIZE)) {
385 iRxBufferLength[eChannel] = iRxLenRead;
Jeremy Friesenddde26e2013-04-17 16:40:52 -0600386 iRet = 0;
387 goto out;
388 }
Jeremy Friesene6e7a812013-05-01 09:10:37 -0600389
Jeremy Friesenbc436592013-05-07 14:44:01 -0600390 iRxBufferLength[eChannel] = 0; // reset buffer length here since we should have a full packet
Jeremy Friesenddde26e2013-04-17 16:40:52 -0600391
Rohan Martinaf8cf682012-11-16 21:11:07 -0700392#if ANT_HCI_OPCODE_SIZE == 1 // Check the different message types by opcode
Jeremy Friesenbc436592013-05-07 14:44:01 -0600393 ANT_U8 opcode = aucRxBuffer[eChannel][ANT_HCI_OPCODE_OFFSET];
Rohan Martinaf8cf682012-11-16 21:11:07 -0700394
395 if(ANT_HCI_OPCODE_COMMAND_COMPLETE == opcode) {
396 // Command Complete, so signal a FLOW_GO
397 if(setFlowControl(pstChnlInfo, ANT_FLOW_GO)) {
398 goto out;
399 }
400 } else if(ANT_HCI_OPCODE_FLOW_ON == opcode) {
401 // FLow On, so resend the last Tx
402#ifdef ANT_FLOW_RESEND
403 // Check if there is a message to resend
404 if(pstChnlInfo->ucResendMessageLength > 0) {
405 ant_tx_message_flowcontrol_none(eChannel, pstChnlInfo->ucResendMessageLength, pstChnlInfo->pucResendMessage);
406 } else {
407 ANT_DEBUG_D("Resend requested by chip, but tx request cancelled");
408 }
409#endif // ANT_FLOW_RESEND
410 } else if(ANT_HCI_OPCODE_ANT_EVENT == opcode)
411 // ANT Event, send ANT packet to Rx Callback
412#endif // ANT_HCI_OPCODE_SIZE == 1
413 {
414 // Received an ANT packet
Jeremy Friesenf8b491f2013-04-05 15:58:20 -0600415 iCurrentHciPacketOffset = 0;
416
417 while(iCurrentHciPacketOffset < iRxLenRead) {
418
Jeremy Friesenddde26e2013-04-17 16:40:52 -0600419 // TODO Allow HCI Packet Size value to be larger than 1 byte
420 // This currently works as no size value is greater than 255, and little endian
Jeremy Friesenbc436592013-05-07 14:44:01 -0600421 iHciDataSize = aucRxBuffer[eChannel][iCurrentHciPacketOffset + ANT_HCI_SIZE_OFFSET];
Jeremy Friesenf8b491f2013-04-05 15:58:20 -0600422
Jeremy Friesen2d96a122013-05-01 09:29:08 -0600423 if ((iHciDataSize + ANT_HCI_HEADER_SIZE + ANT_HCI_FOOTER_SIZE + iCurrentHciPacketOffset) >
Jeremy Friesenddde26e2013-04-17 16:40:52 -0600424 iRxLenRead) {
425 // we don't have a whole packet
Jeremy Friesenbc436592013-05-07 14:44:01 -0600426 iRxBufferLength[eChannel] = iRxLenRead - iCurrentHciPacketOffset;
427 memcpy(aucRxBuffer[eChannel], &aucRxBuffer[eChannel][iCurrentHciPacketOffset], iRxBufferLength[eChannel]);
Jeremy Friesenddde26e2013-04-17 16:40:52 -0600428 // the increment at the end should push us out of the while loop
429 } else
Rohan Martinaf8cf682012-11-16 21:11:07 -0700430#ifdef ANT_MESG_FLOW_CONTROL
Jeremy Friesenbc436592013-05-07 14:44:01 -0600431 if (aucRxBuffer[eChannel][iCurrentHciPacketOffset + ANT_HCI_DATA_OFFSET + ANT_MSG_ID_OFFSET] ==
Jeremy Friesenf8b491f2013-04-05 15:58:20 -0600432 ANT_MESG_FLOW_CONTROL) {
433 // This is a flow control packet, not a standard ANT message
434 if(setFlowControl(pstChnlInfo, \
Jeremy Friesenbc436592013-05-07 14:44:01 -0600435 aucRxBuffer[eChannel][iCurrentHciPacketOffset + ANT_HCI_DATA_OFFSET + ANT_MSG_DATA_OFFSET])) {
Jeremy Friesenf8b491f2013-04-05 15:58:20 -0600436 goto out;
437 }
438 } else
Rohan Martinaf8cf682012-11-16 21:11:07 -0700439#endif // ANT_MESG_FLOW_CONTROL
Jeremy Friesenf8b491f2013-04-05 15:58:20 -0600440 {
James Bootsma105c80a2014-03-13 16:12:54 -0600441 ANT_U8 *msg = aucRxBuffer[eChannel] + iCurrentHciPacketOffset + ANT_HCI_DATA_OFFSET;
442 ANT_BOOL bIsKeepAliveResponse = memcmp(msg, KEEPALIVE_RESP, sizeof(KEEPALIVE_RESP)/sizeof(ANT_U8)) == 0;
443 if (bIsKeepAliveResponse) {
444 ANT_DEBUG_V("Filtered out keepalive response.");
445 } else if (pstChnlInfo->fnRxCallback != NULL) {
Jeremy Friesenf8b491f2013-04-05 15:58:20 -0600446
447 // Loop through read data until all HCI packets are written to callback
Jeremy Friesenddde26e2013-04-17 16:40:52 -0600448 pstChnlInfo->fnRxCallback(iHciDataSize, \
James Bootsma105c80a2014-03-13 16:12:54 -0600449 msg);
Jeremy Friesenf8b491f2013-04-05 15:58:20 -0600450 } else {
451 ANT_WARN("%s rx callback is null", pstChnlInfo->pcDevicePath);
Jeremy Friesene6e7a812013-05-01 09:10:37 -0600452 }
Rohan Martinaf8cf682012-11-16 21:11:07 -0700453 }
Jeremy Friesenf8b491f2013-04-05 15:58:20 -0600454
Jeremy Friesenddde26e2013-04-17 16:40:52 -0600455 iCurrentHciPacketOffset = iCurrentHciPacketOffset + ANT_HCI_HEADER_SIZE + ANT_HCI_FOOTER_SIZE + iHciDataSize;
Jeremy Friesenf8b491f2013-04-05 15:58:20 -0600456 }
Rohan Martinaf8cf682012-11-16 21:11:07 -0700457 }
458
459 iRet = 0;
460 }
461
462out:
463 ANT_FUNC_END();
464 return iRet;
465}