1 /* Copyright (c) 2023 Nordic Semiconductor ASA
2 * SPDX-License-Identifier: Apache-2.0
3 */
4
5 #include <stddef.h>
6 #include <stdint.h>
7 #include <string.h>
8 #include <zephyr/bluetooth/bluetooth.h>
9 #include <zephyr/bluetooth/conn.h>
10 #include <zephyr/bluetooth/gap.h>
11 #include <zephyr/bluetooth/gatt.h>
12 #include <zephyr/bluetooth/l2cap.h>
13 #include <zephyr/bluetooth/uuid.h>
14 #include <zephyr/kernel.h>
15 #include <zephyr/sys/__assert.h>
16
17 struct bt_testlib_adv_ctx {
18 struct bt_conn **result;
19 struct k_condvar done;
20 };
21
22 /* Context pool (with capacity of one). */
23 static K_SEM_DEFINE(g_ctx_free, 1, 1);
24 static K_MUTEX_DEFINE(g_ctx_lock);
25 static struct bt_testlib_adv_ctx *g_ctx;
26
connected_cb(struct bt_le_ext_adv * adv,struct bt_le_ext_adv_connected_info * info)27 static void connected_cb(struct bt_le_ext_adv *adv, struct bt_le_ext_adv_connected_info *info)
28 {
29 k_mutex_lock(&g_ctx_lock, K_FOREVER);
30
31 if (g_ctx->result) {
32 *g_ctx->result = bt_conn_ref(info->conn);
33 }
34 k_condvar_signal(&g_ctx->done);
35
36 k_mutex_unlock(&g_ctx_lock);
37 }
38
bt_testlib_adv_conn(struct bt_conn ** conn,int id,const char * name)39 int bt_testlib_adv_conn(struct bt_conn **conn, int id, const char *name)
40 {
41 int api_err;
42 struct bt_le_ext_adv *adv = NULL;
43 struct bt_le_adv_param param = {};
44 struct bt_testlib_adv_ctx ctx = {
45 .result = conn,
46 };
47 static const struct bt_le_ext_adv_cb cb = {
48 .connected = connected_cb,
49 };
50
51 param.id = id;
52 param.interval_min = BT_GAP_ADV_FAST_INT_MIN_1;
53 param.interval_max = BT_GAP_ADV_FAST_INT_MAX_1;
54 param.options |= BT_LE_ADV_OPT_CONN;
55
56 k_condvar_init(&ctx.done);
57
58 k_sem_take(&g_ctx_free, K_FOREVER);
59 k_mutex_lock(&g_ctx_lock, K_FOREVER);
60 g_ctx = &ctx;
61
62 api_err = bt_le_ext_adv_create(¶m, &cb, &adv);
63 if (!api_err && name != NULL) {
64 struct bt_data ad;
65
66 ad.type = BT_DATA_NAME_COMPLETE;
67 ad.data_len = strlen(name);
68 ad.data = (const uint8_t *)name;
69
70 api_err = bt_le_ext_adv_set_data(adv, &ad, 1, NULL, 0);
71 }
72
73 if (!api_err) {
74 api_err = bt_le_ext_adv_start(adv, BT_LE_EXT_ADV_START_DEFAULT);
75 }
76
77 if (!api_err) {
78 k_condvar_wait(&ctx.done, &g_ctx_lock, K_FOREVER);
79 }
80
81 /* Delete adv before giving semaphore so that it's potentially available
82 * for the next taker of the semaphore.
83 */
84 if (adv) {
85 bt_le_ext_adv_delete(adv);
86 }
87
88 g_ctx = NULL;
89 k_mutex_unlock(&g_ctx_lock);
90 k_sem_give(&g_ctx_free);
91
92 return api_err;
93 }
94