/**
 * 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;
}
示例#2
0
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;
}
示例#3
0
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;
}
示例#4
0
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);
}