blob: a06ce5d3bf7e7d1674e802b0612959b9af36bbad [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/sys/__assert.h>
#include <zephyr/logging/log.h>
#include <testlib/scan.h>
LOG_MODULE_REGISTER(bt_testlib_scan, LOG_LEVEL_INF);
struct bt_scan_find_name_closure {
const char *wanted_name;
bt_addr_le_t *result;
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_scan_find_name_closure *g_ctx;
static bool bt_scan_find_name_cb_data_cb(struct bt_data *data, void *user_data)
{
const char **wanted = user_data;
if (data->type == BT_DATA_NAME_COMPLETE) {
if (data->data_len == strlen(*wanted) &&
!memcmp(*wanted, data->data, data->data_len)) {
*wanted = NULL;
/* Stop bt_data_parse. */
return false;
}
}
/* Continue with next ad data. */
return true;
}
static void bt_scan_find_name_cb(const bt_addr_le_t *addr, int8_t rssi, uint8_t adv_type,
struct net_buf_simple *buf)
{
const char *wanted;
k_mutex_lock(&g_ctx_lock, K_FOREVER);
__ASSERT_NO_MSG(g_ctx);
__ASSERT_NO_MSG(g_ctx->wanted_name);
wanted = g_ctx->wanted_name;
bt_data_parse(buf, bt_scan_find_name_cb_data_cb, &wanted);
if (!wanted) {
(void)bt_le_scan_stop();
*g_ctx->result = *addr;
k_condvar_signal(&g_ctx->done);
}
k_mutex_unlock(&g_ctx_lock);
}
int bt_testlib_scan_find_name(bt_addr_le_t *result, const char *name)
{
int api_err;
struct bt_scan_find_name_closure ctx = {
.wanted_name = name,
.result = result,
};
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_le_scan_start(BT_LE_SCAN_PASSIVE, bt_scan_find_name_cb);
if (!api_err) {
k_condvar_wait(&ctx.done, &g_ctx_lock, K_FOREVER);
}
g_ctx = NULL;
k_mutex_unlock(&g_ctx_lock);
k_sem_give(&g_ctx_free);
if (!api_err) {
char str[BT_ADDR_LE_STR_LEN];
(void)bt_addr_le_to_str(result, str, ARRAY_SIZE(str));
LOG_INF("Scan match: %s", str);
} else {
LOG_ERR("Scan error: %d", api_err);
}
return api_err;
}