/** * Wait for @a list to be non-empty. * * @param[in] list List that should not be empty. * @param[in] retries Number of times to retry if the @a timeout is * reached. * @param[in] timeout Timeout in microseconds to wait between retries. */ static bool CALEWaitForNonEmptyList(GList * const * list, int retries, uint64_t timeout) { bool success = false; ca_mutex_lock(g_context.lock); for (int i = 0; *list == NULL && i < retries; ++i) { if (ca_cond_wait_for(g_context.condition, g_context.lock, timeout) == CA_WAIT_SUCCESS) { /* Condition variable was signaled before the timeout was reached. */ success = true; } } ca_mutex_unlock(g_context.lock); return success; }
CAResult_t CAManagerStartAutoConnection(JNIEnv *env, jstring remote_le_address) { VERIFY_NON_NULL(env, TAG, "env is null"); VERIFY_NON_NULL(remote_le_address, TAG, "remote_le_address is null"); OIC_LOG(DEBUG, TAG, "IN - CAManagerStartAutoConnection"); ca_mutex_lock(g_connectRetryMutex); bool isAutoConnecting = false; if (CA_STATUS_OK != CAManagerGetAutoConnectingFlag(env, remote_le_address, &isAutoConnecting)) { OIC_LOG(DEBUG, TAG, "CAManagerIsAutoConnecting has failed"); ca_mutex_unlock(g_connectRetryMutex); return CA_STATUS_FAILED; } if (isAutoConnecting) { OIC_LOG(INFO, TAG, "connection has been already in progress or completed"); ca_mutex_unlock(g_connectRetryMutex); return CA_STATUS_FAILED; } for (size_t retry_cnt = 0 ; retry_cnt < MAX_RETRY_COUNT ; retry_cnt++) { // there is retry logic 5 times when connectGatt call has failed // because BT adapter might be not ready yet. if (NULL == CAManagerConnectGatt(env, remote_le_address)) { OIC_LOG_V(INFO, TAG, "retry will be started at least %d times after delay 1sec", MAX_RETRY_COUNT - retry_cnt - 1); if (ca_cond_wait_for(g_connectRetryCond, g_connectRetryMutex, TIMEOUT) == 0) { ca_mutex_unlock(g_connectRetryMutex); OIC_LOG(INFO, TAG, "request to connect gatt was canceled"); return CA_STATUS_OK; } // time out. retry connection } else { OIC_LOG(INFO, TAG, "ConnectGatt has called successfully"); break; } } ca_mutex_unlock(g_connectRetryMutex); OIC_LOG(DEBUG, TAG, "OUT - CAManagerStartAutoConnection"); return CA_STATUS_OK; }
CAResult_t CAManagerProcessRecovery(JNIEnv *env, uint16_t adapter_state) { VERIFY_NON_NULL(env, TAG, "env"); OIC_LOG(DEBUG, TAG, "IN - CAManagerProcessRecovery"); ca_mutex_lock(g_recoveryMutex); CAResult_t res = CA_STATUS_OK; switch(adapter_state) { case STATE_OFF: // adapter will be enabled automatically after WAITING_TIME. if (ca_cond_wait_for(g_recoveryCond, g_recoveryMutex, WAITING_TIME) == 0) { OIC_LOG(INFO, TAG, "BT recovery was canceled"); } else { // enabled if (!CAManagerControlAdapter(env, true)) { OIC_LOG(ERROR, TAG, "BT recovery(enable) failure"); res = CA_STATUS_FAILED; } } CAManagerSetBTRecovery(false); break; case START_RECOVERY: if (!CAManagerControlAdapter(env, false)) { OIC_LOG(ERROR, TAG, "BT recovery(disable) failure"); res = CA_STATUS_FAILED; } CAManagerSetBTRecovery(true); break; default: break; } ca_mutex_unlock(g_recoveryMutex); OIC_LOG(DEBUG, TAG, "OUT - CAManagerProcessRecovery"); return res; }
CAResult_t CAPeripheralStart(CALEContext * context) { /** * @todo Bluetooth adapters that are hot-plugged after the * peripheral has started will not be started! */ CAResult_t result = CA_STATUS_FAILED; // Only start if we were previously stopped. if (CAPeripheralCheckStarted()) { result = CA_SERVER_STARTED_ALREADY; return result; } if (!CAPeripheralAdaptersFound(context)) { // No Bluetooth adapters. Don't bother continuing. return result; } /* Spawn a thread to run the Glib event loop that will drive D-Bus signal handling. */ result = ca_thread_pool_add_task(context->server_thread_pool, CAPeripheralStartEventLoop, context); if (result != CA_STATUS_OK) { return result; } /* Wait until initialization completes before proceeding to service and advertisement registration. */ // Number of times to wait for initialization to complete. static int const max_retries = 2; static uint64_t const timeout = 2 * MICROSECS_PER_SEC; // Microseconds ca_mutex_lock(g_context.lock); for (int i = 0; g_context.gatt_services == NULL && i < max_retries; ++i) { if (ca_cond_wait_for(g_context.condition, g_context.lock, timeout) == CA_WAIT_SUCCESS) { result = CA_STATUS_OK; } } ca_mutex_unlock(g_context.lock); if (result != CA_STATUS_OK) { return result; } /** * First register the GATT services, then register the LE * advertisments with BlueZ to make sure the service we're * advertising actually exists. */ if (result == CA_STATUS_OK && !(CAPeripheralRegisterGattServices(&g_context) && CAPeripheralRegisterAdvertisements(&g_context))) { result = CA_STATUS_FAILED; } /* Make the local bluetooth adapters discoverable over LE by enabling LE, enabling advertising, and making the LE device connectable. */ result = CAPeripheralSetDiscoverability(context, CAPeripheralMakeDiscoverable); return result; }
void ca_cond_wait(ca_cond cond, ca_mutex mutex) { ca_cond_wait_for(cond, mutex, 0L); }