static jint nativeJAnt_TxMessage(JNIEnv *env, jobject obj, jbyteArray msg) { (void)obj; //unused warning ANT_FUNC_START(); if (msg == NULL) { if (jniThrowException(env, "java/lang/NullPointerException", NULL)) { ANT_ERROR("Unable to throw NullPointerException"); } return -1; } jbyte* msgBytes = env->GetByteArrayElements(msg, NULL); jint msgLength = env->GetArrayLength(msg); ANTStatus status = ant_tx_message((ANT_U8) msgLength, (ANT_U8 *)msgBytes); ANT_DEBUG_D("nativeJAnt_TxMessage: ant_tx_message() returned %d", (int)status); env->ReleaseByteArrayElements(msg, msgBytes, JNI_ABORT); ANT_FUNC_END(); return status; }
ANTStatus ant_deinit(void) { int mutexResult; ANTStatus result_status = ANT_STATUS_FAILED; ANT_FUNC_START(); mutexResult = pthread_mutex_destroy(&txLock); if (mutexResult) { ANT_ERROR("Tx Lock mutex destroy failed: %s", strerror(mutexResult)); } else { mutexResult = pthread_mutex_destroy(&enableLock); if (mutexResult) { ANT_ERROR("Enable Lock mutex destroy failed: %s", strerror(mutexResult)); } else { result_status = ANT_STATUS_SUCCESS; } } ANT_FUNC_END(); return result_status; }
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; }
ANTStatus ant_init(void) { ANTStatus status = ANT_STATUS_FAILED; ANT_FUNC_START(); stRxThreadInfo.stRxThread = 0; stRxThreadInfo.ucRunThread = 0; stRxThreadInfo.ucChipResetting = 0; stRxThreadInfo.pstEnabledStatusLock = &stEnabledStatusLock; g_fnStateCallback = 0; #ifdef ANT_DEVICE_NAME // Single transport path ant_channel_init(&stRxThreadInfo.astChannels[SINGLE_CHANNEL], ANT_DEVICE_NAME); #else // Separate data/command paths ant_channel_init(&stRxThreadInfo.astChannels[COMMAND_CHANNEL], ANT_COMMANDS_DEVICE_NAME); ant_channel_init(&stRxThreadInfo.astChannels[DATA_CHANNEL], ANT_DATA_DEVICE_NAME); #endif // Separate data/command paths // 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; }
//////////////////////////////////////////////////////////////////// // 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; }
ANTStatus ant_init(void) { int mutexResult; ANTStatus status = ANT_STATUS_FAILED; ANT_FUNC_START(); mutexResult = pthread_mutex_init(&txLock, NULL); //use default attr if (mutexResult) { ANT_ERROR("Tx Lock mutex initialization failed: %s", strerror(mutexResult)); } else { mutexResult = pthread_mutex_init(&enableLock, NULL); if (mutexResult) { ANT_ERROR("Enable Lock mutex init failed %s", strerror(mutexResult)); } else { status = ANT_STATUS_SUCCESS; } } ANT_FUNC_END(); return status; }
//////////////////////////////////////////////////////////////////// // setFlowControl // // Sets the flow control "flag" to the value provided and signals the transmit // thread to check the value. // // Parameters: // pstChnlInfo the details of the channel being updated // ucFlowSetting the value to use // // Returns: // Success: // 0 // Failure: // -1 //////////////////////////////////////////////////////////////////// int setFlowControl(ant_channel_info_t *pstChnlInfo, ANT_U8 ucFlowSetting) { int iRet = -1; int iMutexResult; ANT_FUNC_START(); ANT_DEBUG_V("getting stFlowControlLock in %s", __FUNCTION__); iMutexResult = pthread_mutex_lock(pstChnlInfo->pstFlowControlLock); if (iMutexResult) { ANT_ERROR("failed to lock flow control mutex during response: %s", strerror(iMutexResult)); } else { ANT_DEBUG_V("got stFlowControlLock in %s", __FUNCTION__); pstChnlInfo->ucFlowControlResp = ucFlowSetting; ANT_DEBUG_V("releasing stFlowControlLock in %s", __FUNCTION__); pthread_mutex_unlock(pstChnlInfo->pstFlowControlLock); ANT_DEBUG_V("released stFlowControlLock in %s", __FUNCTION__); pthread_cond_signal(pstChnlInfo->pstFlowControlCond); iRet = 0; } ANT_FUNC_END(); return iRet; }
ANTStatus ant_radio_hard_reset(void) { ANTStatus result_status = ANT_STATUS_NOT_SUPPORTED; ANT_FUNC_START(); ANT_FUNC_END(); return result_status; }
static jint nativeJAnt_Create(JNIEnv *env, jobject obj) { ANTStatus antStatus = ANT_STATUS_FAILED; (void)env; //unused warning (void)obj; //unused warning ANT_FUNC_START(); antStatus = ant_init(); if (antStatus) { ANT_DEBUG_D("failed to init ANT stack"); goto CLEANUP; } antStatus = set_ant_rx_callback(nativeJAnt_RxCallback); if (antStatus) { ANT_DEBUG_D("failed to set ANT rx callback"); goto CLEANUP; } antStatus = set_ant_state_callback(nativeJAnt_StateCallback); if (antStatus) { ANT_DEBUG_D("failed to set ANT state callback"); goto CLEANUP; } CLEANUP: ANT_FUNC_END(); return antStatus; }
ANTStatus ant_disable_radio(void) { int iLockResult; ANTStatus ret = ANT_STATUS_FAILED; ANT_FUNC_START(); ANT_DEBUG_V("getting stEnabledStatusLock in %s", __FUNCTION__); iLockResult = pthread_mutex_lock(&stEnabledStatusLock); if(iLockResult) { ANT_ERROR("disable failed to get state lock: %s", strerror(iLockResult)); goto out; } ANT_DEBUG_V("got stEnabledStatusLock in %s", __FUNCTION__); if (g_fnStateCallback) { g_fnStateCallback(RADIO_STATUS_DISABLING); } ant_disable(); if (g_fnStateCallback) { g_fnStateCallback(ant_radio_enabled_status()); } ret = ANT_STATUS_SUCCESS; ANT_DEBUG_V("releasing stEnabledStatusLock in %s", __FUNCTION__); pthread_mutex_unlock(&stEnabledStatusLock); ANT_DEBUG_V("released stEnabledStatusLock in %s", __FUNCTION__); out: ANT_FUNC_END(); return ret; }
ANTStatus set_ant_state_callback(ANTNativeANTStateCb state_callback_func) { ANTStatus status = ANT_STATUS_SUCCESS; ANT_FUNC_START(); g_fnStateCallback = state_callback_func; ANT_FUNC_END(); return status; }
ANTStatus set_ant_rx_callback(ANTNativeANTEventCb rx_callback_func) { ANTStatus status = ANT_STATUS_SUCCESS; ANT_FUNC_START(); RxParams.pfRxCallback = rx_callback_func; ANT_FUNC_END(); return status; }
static jint nativeJAnt_GetRadioEnabledStatus(JNIEnv *env, jobject obj) { (void)env; //unused warning (void)obj; //unused warning ANT_FUNC_START(); jint status = ant_radio_enabled_status(); ANT_FUNC_END(); return status; }
static jint nativeJAnt_HardReset(JNIEnv *env, jobject obj) { (void)env; //unused warning (void)obj; //unused warning ANT_FUNC_START(); ANTStatus status = ant_radio_hard_reset(); ANT_FUNC_END(); return status; }
static jint nativeJAnt_Disable(JNIEnv *env, jobject obj) { (void)env; //unused warning (void)obj; //unused warning ANT_FUNC_START(); ANTStatus status = ant_disable_radio(); ANT_FUNC_END(); return status; }
ANTRadioEnabledStatus ant_radio_enabled_status(void) { ANT_FUNC_START(); if ((RADIO_STATUS_ENABLING != radio_status) && (RADIO_STATUS_DISABLING != radio_status)) { get_and_set_radio_status(); } ANT_FUNC_END(); return radio_status; }
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__); iMutexLockResult = pthread_mutex_lock(stRxThreadInfo->pstEnabledStatusLock); if (iMutexLockResult < 0) { ANT_ERROR("chip was reset, getting state mutex failed: %s", strerror(iMutexLockResult)); stRxThreadInfo->stRxThread = 0; stRxThreadInfo->ucChipResetting = 0; } else { ANT_DEBUG_V("got stEnabledStatusLock in %s", __FUNCTION__); stRxThreadInfo->stRxThread = 0; /* spoof our handle as closed so we don't * try to join ourselves in disable */ ant_disable(); int enableResult = ant_enable(); stRxThreadInfo->ucChipResetting = 0; if (enableResult) { /* failed */ if (g_fnStateCallback) { g_fnStateCallback(RADIO_STATUS_DISABLED); } } else { /* success */ if (g_fnStateCallback) { g_fnStateCallback(RADIO_STATUS_RESET); } } ANT_DEBUG_V("releasing stEnabledStatusLock in %s", __FUNCTION__); pthread_mutex_unlock(stRxThreadInfo->pstEnabledStatusLock); ANT_DEBUG_V("released stEnabledStatusLock in %s", __FUNCTION__); } ANT_FUNC_END(); }
ANTStatus ant_radio_hard_reset(void) { ANTStatus result_status = ANT_STATUS_NOT_SUPPORTED; ANT_FUNC_START(); #ifdef ANT_IOCTL_RESET ant_channel_type eChannel; int iLockResult; result_status = ANT_STATUS_FAILED; ANT_DEBUG_V("getting stEnabledStatusLock in %s", __FUNCTION__); iLockResult = pthread_mutex_lock(&stEnabledStatusLock); if(iLockResult) { ANT_ERROR("enable failed to get state lock: %s", strerror(iLockResult)); goto out; } ANT_DEBUG_V("got stEnabledStatusLock in %s", __FUNCTION__); stRxThreadInfo.ucChipResetting = 1; if (g_fnStateCallback) g_fnStateCallback(RADIO_STATUS_RESETTING); #ifdef ANT_IOCTL_RESET_PARAMETER ioctl(stRxThreadInfo.astChannels[0].iFd, ANT_IOCTL_RESET, ANT_IOCTL_RESET_PARAMETER); #else ioctl(stRxThreadInfo.astChannels[0].iFd, ANT_IOCTL_RESET); #endif // ANT_IOCTL_RESET_PARAMETER ant_disable(); if (ant_enable()) { /* failed */ if (g_fnStateCallback) g_fnStateCallback(RADIO_STATUS_DISABLED); } else { /* success */ if (g_fnStateCallback) g_fnStateCallback(RADIO_STATUS_RESET); result_status = ANT_STATUS_SUCCESS; } stRxThreadInfo.ucChipResetting = 0; ANT_DEBUG_V("releasing stEnabledStatusLock in %s", __FUNCTION__); pthread_mutex_unlock(&stEnabledStatusLock); ANT_DEBUG_V("released stEnabledStatusLock in %s", __FUNCTION__); out: #endif // ANT_IOCTL_RESET ANT_FUNC_END(); return result_status; }
ANTStatus ant_deinit(void) { ANTStatus result_status = ANT_STATUS_FAILED; ANT_FUNC_START(); 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; }
ANTStatus set_ant_rx_callback(ANTNativeANTEventCb rx_callback_func) { ANTStatus status = ANT_STATUS_SUCCESS; ANT_FUNC_START(); #ifdef ANT_DEVICE_NAME // Single transport path stRxThreadInfo.astChannels[SINGLE_CHANNEL].fnRxCallback = rx_callback_func; #else // Separate data/command paths stRxThreadInfo.astChannels[COMMAND_CHANNEL].fnRxCallback = rx_callback_func; stRxThreadInfo.astChannels[DATA_CHANNEL].fnRxCallback = rx_callback_func; #endif // Separate data/command paths ANT_FUNC_END(); return status; }
int ant_enable(void) { int iRet = -1; 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++) { if (ant_enable_channel(&stRxThreadInfo.astChannels[eChannel]) < 0) { ANT_ERROR("failed to enable channel %s: %s", stRxThreadInfo.astChannels[eChannel].pcDevicePath, strerror(errno)); goto out; } } if (stRxThreadInfo.stRxThread == 0) { if (pthread_create(&stRxThreadInfo.stRxThread, NULL, fnRxThread, &stRxThreadInfo) < 0) { ANT_ERROR("failed to start rx thread: %s", strerror(errno)); goto out; } } else { ANT_DEBUG_D("rx thread is already running"); } if (!stRxThreadInfo.ucRunThread) { ANT_ERROR("rx thread crashed during init"); goto out; } iRet = 0; out: ANT_FUNC_END(); return iRet; }
void nativeJAnt_StateCallback(ANTRadioEnabledStatus uiNewState) { JNIEnv* env = NULL; jint jNewState = uiNewState; ANT_BOOL iShouldDetach = ANT_FALSE; ANT_FUNC_START(); g_jVM->GetEnv((void**) &env, JNI_VERSION_1_4); if (env == NULL) { ANT_DEBUG_D("nativeJAnt_StateCallback: called from rx thread, attaching to VM"); g_jVM->AttachCurrentThread((&env), NULL); if (env == NULL) { ANT_DEBUG_E("nativeJAnt_StateCallback: failed to attach rx thread to VM"); return; } iShouldDetach = ANT_TRUE; } else { ANT_DEBUG_D("nativeJAnt_StateCallback: called from java enable/disable" ", already attached, don't detach"); } ANT_DEBUG_V("nativeJAnt_StateCallback: Calling java state callback"); env->CallStaticVoidMethod(g_sJClazz, g_sMethodId_nativeCb_AntStateChange, jNewState); ANT_DEBUG_V("nativeJAnt_StateCallback: Called java state callback"); if (env->ExceptionOccurred()) { ANT_ERROR("nativeJAnt_StateCallback: Calling Java nativeCb_AntStateChange failed"); env->ExceptionDescribe(); env->ExceptionClear(); } if (iShouldDetach) { ANT_DEBUG_D("nativeJAnt_StateCallback: env was attached, detaching"); g_jVM->DetachCurrentThread(); } ANT_FUNC_END(); return; }
jint JNI_OnLoad(JavaVM* vm, void* reserved) { ANT_FUNC_START(); (void)reserved; //unused warning g_jVM = vm; if (g_jVM->GetEnv((void**) &g_jEnv, JNI_VERSION_1_4) != JNI_OK) { ANT_ERROR("GetEnv failed"); return -1; } if (NULL == g_jEnv) { ANT_ERROR("env is null"); return -1; } g_sJClazz = g_jEnv->FindClass("com/dsi/ant/core/JAntJava"); if (NULL == g_sJClazz) { ANT_ERROR("could not find class \"com/dsi/ant/core/JAntJava\""); return -1; } /* Save class information in global reference to prevent class unloading */ g_sJClazz = (jclass)g_jEnv->NewGlobalRef(g_sJClazz); if (g_jEnv->RegisterNatives(g_sJClazz, g_sMethods, NELEM(g_sMethods)) != JNI_OK) { ANT_ERROR("failed to register methods"); return -1; } g_sMethodId_nativeCb_AntRxMessage = g_jEnv->GetStaticMethodID(g_sJClazz, "nativeCb_AntRxMessage", "([B)V"); if (NULL == g_sMethodId_nativeCb_AntRxMessage) { ANT_ERROR("VerifyMethodId: Failed getting method id of \"void nativeCb_AntRxMessage(byte[])\""); return -1; } g_sMethodId_nativeCb_AntStateChange = g_jEnv->GetStaticMethodID(g_sJClazz, "nativeCb_AntStateChange", "(I)V"); if (NULL == g_sMethodId_nativeCb_AntStateChange) { ANT_ERROR("VerifyMethodId: Failed getting method id of \"void nativeCb_AntStateChange(int)\""); return -1; } ANT_FUNC_END(); return JNI_VERSION_1_4; }
ANTStatus ant_tx_message_flowcontrol_none(ant_channel_type eTxPath, ANT_U8 ucMessageLength, ANT_U8 *pucTxMessage) { int iResult; ANTStatus status = ANT_STATUS_FAILED;\ ANT_FUNC_START(); iResult = write(stRxThreadInfo.astChannels[eTxPath].iFd, pucTxMessage, ucMessageLength); if (iResult < 0) { ANT_ERROR("failed to write message to device: %s", strerror(errno)); } else if (iResult != ucMessageLength) { ANT_ERROR("bytes written and message size don't match up"); } else { status = ANT_STATUS_SUCCESS; } ANT_FUNC_END(); return status; }
ANTRadioEnabledStatus ant_radio_enabled_status(void) { ant_channel_type eChannel; int iOpenFiles = 0; int iOpenThread; ANTRadioEnabledStatus uiRet = RADIO_STATUS_UNKNOWN; ANT_FUNC_START(); if (stRxThreadInfo.ucChipResetting) { uiRet = RADIO_STATUS_RESETTING; goto out; } for (eChannel = 0; eChannel < NUM_ANT_CHANNELS; eChannel++) { if (stRxThreadInfo.astChannels[eChannel].iFd != -1) { iOpenFiles++; } } iOpenThread = (stRxThreadInfo.stRxThread) ? 1 : 0; if (!stRxThreadInfo.ucRunThread) { if (iOpenFiles || iOpenThread) { uiRet = RADIO_STATUS_DISABLING; } else { uiRet = RADIO_STATUS_DISABLED; } } else { if ((iOpenFiles == NUM_ANT_CHANNELS) && iOpenThread) { uiRet = RADIO_STATUS_ENABLED; } else if (!iOpenFiles && iOpenThread) { uiRet = RADIO_STATUS_UNKNOWN; } else { uiRet = RADIO_STATUS_ENABLING; } } out: ANT_DEBUG_D("get radio enabled status returned %d", uiRet); ANT_FUNC_END(); return uiRet; }
static void ant_disable_channel(ant_channel_info_t *pstChnlInfo) { ANT_FUNC_START(); if (!pstChnlInfo) { ANT_ERROR("null channel info passed to channel disable function"); goto out; } if (pstChnlInfo->iFd != -1) { // Use the new init_transport function instead of open() to get our fd. if (init_transport_bdroid(0) < 0) { ANT_ERROR("failed to close channel %s(%#x): %s", pstChnlInfo->pcDevicePath, pstChnlInfo->iFd, strerror(errno)); } pstChnlInfo->iFd = -1; //TODO can this overwrite a still valid fd? } else { ANT_DEBUG_D("%s file is already closed", pstChnlInfo->pcDevicePath); } out: ANT_FUNC_END(); }
static jint nativeJAnt_Destroy(JNIEnv *env, jobject obj) { (void)env; //unused warning (void)obj; //unused warning ANTStatus status; ANT_FUNC_START(); ANT_DEBUG_D("nativeJAnt_Destroy(): calling ant_deinit"); status = ant_deinit(); if (status) { ANT_DEBUG_D("failed to deinit ANT stack returned %d",(int)status); return status; } else { ANT_DEBUG_D("deinit ANT stack Success"); } ANT_FUNC_END(); return status; }
static void ant_channel_init(ant_channel_info_t *pstChnlInfo, const char *pcCharDevName) { ANT_FUNC_START(); // TODO Don't need to store, only accessed when trying to open: // Is however useful for logs. pstChnlInfo->pcDevicePath = pcCharDevName; // This is the only piece of info that needs to be stored per channel pstChnlInfo->iFd = -1; // TODO Only 1 of these (not per-channel) is actually ever used: pstChnlInfo->fnRxCallback = NULL; pstChnlInfo->ucFlowControlResp = ANT_FLOW_GO; #ifdef ANT_FLOW_RESEND pstChnlInfo->ucResendMessageLength = 0; pstChnlInfo->pucResendMessage = NULL; #endif // ANT_FLOW_RESEND // TODO Only used when Flow Control message received, so must only be Command path Rx thread pstChnlInfo->pstFlowControlCond = &stFlowControlCond; pstChnlInfo->pstFlowControlLock = &stFlowControlLock; ANT_FUNC_END(); }
static int ant_enable_channel(ant_channel_info_t *pstChnlInfo) { int iRet = -1; ANT_FUNC_START(); if (!pstChnlInfo) { ANT_ERROR("null channel info passed to channel enable function"); errno = EINVAL; goto out; } if (pstChnlInfo->iFd == -1) { // Use the init_transport function to release our fd instead of close() pstChnlInfo->iFd = init_transport_bdroid(1); if (pstChnlInfo->iFd < 0) { ANT_ERROR("failed to open dev %s: %s", pstChnlInfo->pcDevicePath, strerror(errno)); goto out; } } else { ANT_DEBUG_D("%s is already enabled", pstChnlInfo->pcDevicePath); } iRet = 0; out: ANT_FUNC_END(); return iRet; }
/* * This thread opens a Bluez HCI socket and waits for ANT messages. */ void *ANTHCIRxThread(void *pvHCIDevice) { int ret = ANT_STATUS_SUCCESS; int rxSocket; int len; unsigned char buf[HCI_MAX_EVENT_SIZE]; int result; struct hci_filter eventVendorFilter; ANT_FUNC_START(); (void)pvHCIDevice; //unused waring ANT_DEBUG_D("Entering ANTHCIRxThread"); rxSocket = create_hci_sock(); if (rxSocket < 0) { ANT_DEBUG_E("can't open HCI socket in rx thread: %s", strerror(errno)); ret = ANT_STATUS_FAILED; goto out; } eventVendorFilter.type_mask = TYPE_MASK_EVENT_PACKET; eventVendorFilter.event_mask[0] = 0; eventVendorFilter.event_mask[1] = EVENT_MASK_1_EVENT_VENDOR; eventVendorFilter.opcode = htobs(ANT_EVENT_VENDOR_CODE); if (setsockopt(rxSocket, SOL_HCI, HCI_FILTER, &eventVendorFilter, sizeof(eventVendorFilter)) < 0) { ANT_ERROR("failed to set socket options: %s", strerror(errno)); ret = ANT_STATUS_FAILED; goto close; } /* continue running as long as not terminated */ while (get_and_set_radio_status() == RADIO_STATUS_ENABLED) { struct pollfd p; int n; p.fd = rxSocket; p.events = POLLIN; ANT_DEBUG_V(" RX: Polling HCI for data..."); /* poll socket, wait for ANT messages */ while ((n = poll(&p, 1, 2500)) == -1) { if (errno == EAGAIN || errno == EINTR) continue; ANT_ERROR("failed to poll socket: %s", strerror(errno)); ret = ANT_STATUS_FAILED; goto close; } /* we timeout once in a while */ /* this let's us the chance to check if we were terminated */ if (0 == n) { ANT_DEBUG_V(" RX: Timeout"); continue; } ANT_DEBUG_D("New HCI data available, reading..."); /* read newly arrived data */ /* TBD: rethink assumption about single arrival */ while ((len = read(rxSocket, buf, sizeof(buf))) < 0) { if (errno == EAGAIN || errno == EINTR) continue; ANT_ERROR("failed to read socket: %s", strerror(errno)); ret = ANT_STATUS_FAILED; goto close; } hci_event_packet_t *event_packet = (hci_event_packet_t *)buf; int hci_payload_len = validate_hci_event_packet(event_packet, len); if (hci_payload_len == -1) { // part of the message is incorrect, ignore it. validate_event_packet will log error continue; } ANT_SERIAL(event_packet->hci_payload, hci_payload_len, 'R'); if(RxParams.pfRxCallback != NULL) { RxParams.pfRxCallback(hci_payload_len, event_packet->hci_payload); } else { ANT_ERROR("Can't send rx message - no callback registered"); } } close: result = pthread_mutex_trylock(&enableLock); ANT_DEBUG_D("rx thread close: trylock enableLock returned %d", result); if (result == 0) { ANT_DEBUG_W("rx thread socket has unexpectedly crashed"); #if USE_EXTERNAL_POWER_LIBRARY if (RxParams.pfStateCallback) RxParams.pfStateCallback(RADIO_STATUS_DISABLING); ant_disable(); get_and_set_radio_status(); #else radio_status = RADIO_STATUS_DISABLED; #endif RxParams.thread = 0; pthread_mutex_unlock(&enableLock); } else if (result == EBUSY) { ANT_DEBUG_V("rx thread socket was closed"); } else { ANT_ERROR("rx thread close: trylock failed: %s", strerror(result)); } if (-1 == close(rxSocket)) { ANT_ERROR("failed to close hci device (socket handle=%#x): %s", rxSocket, strerror(errno)); } else { ANT_DEBUG_D("closed hci device (socket handle=%#x)", rxSocket); } out: ANT_FUNC_END(); pthread_exit((void *)ret); #if defined(ANDROID) return 0; #endif }