blob: e8f5a90224ee053276b6098bc6607118b1103db6 [file] [log] [blame]
/* Copyright (c) 2023 Nordic Semiconductor ASA
* SPDX-License-Identifier: Apache-2.0
*/
#include <stdint.h>
#include <zephyr/bluetooth/gatt.h>
#include <zephyr/kernel.h>
#include <zephyr/logging/log.h>
#include <testlib/conn.h>
LOG_MODULE_REGISTER(bt_testlib_connect, LOG_LEVEL_INF);
struct bt_testlib_connect_closure {
uint8_t conn_err;
struct bt_conn **conn;
struct k_mutex lock;
struct k_condvar done;
};
/* Context pool (with capacity of one). */
static K_SEM_DEFINE(g_ctx_free, 1, 1);
static K_MUTEX_DEFINE(g_ctx_lock);
static struct bt_testlib_connect_closure *g_ctx;
static void connected_cb(struct bt_conn *conn, uint8_t conn_err)
{
/* Loop over each (allocated) item in pool. */
k_mutex_lock(&g_ctx_lock, K_FOREVER);
if (g_ctx && conn == *g_ctx->conn) {
g_ctx->conn_err = conn_err;
k_condvar_signal(&g_ctx->done);
}
k_mutex_unlock(&g_ctx_lock);
}
BT_CONN_CB_DEFINE(conn_callbacks) = {
.connected = connected_cb,
};
int bt_testlib_connect(const bt_addr_le_t *peer, struct bt_conn **conn)
{
int api_err;
struct bt_testlib_connect_closure ctx = {
.conn = conn,
};
__ASSERT_NO_MSG(conn);
__ASSERT_NO_MSG(*conn == NULL);
k_condvar_init(&ctx.done);
k_sem_take(&g_ctx_free, K_FOREVER);
k_mutex_lock(&g_ctx_lock, K_FOREVER);
g_ctx = &ctx;
api_err = bt_conn_le_create(peer, BT_CONN_LE_CREATE_CONN, BT_LE_CONN_PARAM_DEFAULT, conn);
if (!api_err) {
LOG_INF("Connecting.. conn %u", bt_conn_index(*conn));
k_condvar_wait(&ctx.done, &g_ctx_lock, K_FOREVER);
LOG_INF("Connect complete");
}
g_ctx = NULL;
k_mutex_unlock(&g_ctx_lock);
k_sem_give(&g_ctx_free);
if (api_err) {
LOG_ERR("bt_conn_le_create err %d", api_err);
__ASSERT_NO_MSG(api_err < 0);
return api_err;
}
if (ctx.conn_err) {
LOG_ERR("Connect HCI err %d", ctx.conn_err);
__ASSERT_NO_MSG(ctx.conn_err >= 0);
return ctx.conn_err;
}
return 0;
}