1 /* Copyright (c) 2023 Nordic Semiconductor ASA
2 * SPDX-License-Identifier: Apache-2.0
3 */
4
5 #include <stdint.h>
6 #include <zephyr/bluetooth/gatt.h>
7 #include <zephyr/kernel.h>
8 #include <zephyr/sys/__assert.h>
9 #include <zephyr/logging/log.h>
10
11 #include <testlib/scan.h>
12
13 LOG_MODULE_REGISTER(bt_testlib_scan, LOG_LEVEL_INF);
14
15 struct bt_scan_find_name_closure {
16 const char *wanted_name;
17 bt_addr_le_t *result;
18 struct k_condvar done;
19 };
20
21 /* Context pool (with capacity of one). */
22 static K_SEM_DEFINE(g_ctx_free, 1, 1);
23 static K_MUTEX_DEFINE(g_ctx_lock);
24 static struct bt_scan_find_name_closure *g_ctx;
25
bt_scan_find_name_cb_data_cb(struct bt_data * data,void * user_data)26 static bool bt_scan_find_name_cb_data_cb(struct bt_data *data, void *user_data)
27 {
28 const char **wanted = user_data;
29
30 if (data->type == BT_DATA_NAME_COMPLETE) {
31 if (data->data_len == strlen(*wanted) &&
32 !memcmp(*wanted, data->data, data->data_len)) {
33 *wanted = NULL;
34 /* Stop bt_data_parse. */
35 return false;
36 }
37 }
38
39 /* Continue with next ad data. */
40 return true;
41 }
42
bt_scan_find_name_cb(const bt_addr_le_t * addr,int8_t rssi,uint8_t adv_type,struct net_buf_simple * buf)43 static void bt_scan_find_name_cb(const bt_addr_le_t *addr, int8_t rssi, uint8_t adv_type,
44 struct net_buf_simple *buf)
45 {
46 const char *wanted;
47
48 k_mutex_lock(&g_ctx_lock, K_FOREVER);
49
50 __ASSERT_NO_MSG(g_ctx);
51 __ASSERT_NO_MSG(g_ctx->wanted_name);
52
53 wanted = g_ctx->wanted_name;
54
55 bt_data_parse(buf, bt_scan_find_name_cb_data_cb, &wanted);
56
57 if (!wanted) {
58 (void)bt_le_scan_stop();
59 *g_ctx->result = *addr;
60 k_condvar_signal(&g_ctx->done);
61 }
62
63 k_mutex_unlock(&g_ctx_lock);
64 }
65
bt_testlib_scan_find_name(bt_addr_le_t * result,const char * name)66 int bt_testlib_scan_find_name(bt_addr_le_t *result, const char *name)
67 {
68 int api_err;
69 struct bt_scan_find_name_closure ctx = {
70 .wanted_name = name,
71 .result = result,
72 };
73
74 k_condvar_init(&ctx.done);
75
76 k_sem_take(&g_ctx_free, K_FOREVER);
77 k_mutex_lock(&g_ctx_lock, K_FOREVER);
78 g_ctx = &ctx;
79
80 api_err = bt_le_scan_start(BT_LE_SCAN_PASSIVE, bt_scan_find_name_cb);
81 if (!api_err) {
82 k_condvar_wait(&ctx.done, &g_ctx_lock, K_FOREVER);
83 }
84
85 g_ctx = NULL;
86 k_mutex_unlock(&g_ctx_lock);
87 k_sem_give(&g_ctx_free);
88
89 if (!api_err) {
90 char str[BT_ADDR_LE_STR_LEN];
91 (void)bt_addr_le_to_str(result, str, ARRAY_SIZE(str));
92 LOG_INF("Scan match: %s", str);
93 } else {
94 LOG_ERR("Scan error: %d", api_err);
95 }
96
97 return api_err;
98 }
99