blob: 560b20183bf6906600a481ed1aaaf3f2614c9f4f [file] [log] [blame]
/*
* Copyright (c) 2023 Nordic Semiconductor ASA
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <zephyr/kernel.h>
#include "bs_types.h"
#include "bs_tracing.h"
#include "time_machine.h"
#include "bstests.h"
#include <zephyr/types.h>
#include <zephyr/sys/printk.h>
#include <zephyr/bluetooth/bluetooth.h>
#include "common.h"
extern enum bst_result_t bst_result;
static struct bt_conn *g_conn;
CREATE_FLAG(flag_connected);
CREATE_FLAG(flag_bonded);
static void connected(struct bt_conn *conn, uint8_t err)
{
char addr[BT_ADDR_LE_STR_LEN];
bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr));
if (err != BT_HCI_ERR_SUCCESS) {
FAIL("Failed to connect to %s: %u\n", addr, err);
return;
}
printk("Connected to %s\n", addr);
g_conn = bt_conn_ref(conn);
SET_FLAG(flag_connected);
}
static void disconnected(struct bt_conn *conn, uint8_t reason)
{
char addr[BT_ADDR_LE_STR_LEN];
bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr));
printk("Disconnected: %s (reason %u)\n", addr, reason);
bt_conn_unref(g_conn);
g_conn = NULL;
}
static struct bt_conn_cb conn_cbs = {
.connected = connected,
.disconnected = disconnected,
};
static void pairing_complete_cb(struct bt_conn *conn, bool bonded)
{
if (conn == g_conn && bonded) {
SET_FLAG(flag_bonded);
}
}
static struct bt_conn_auth_info_cb auto_info_cbs = {
.pairing_complete = pairing_complete_cb,
};
static void common_init(void)
{
int err;
err = bt_enable(NULL);
if (err) {
FAIL("Bluetooth init failed: %d\n", err);
return;
}
printk("Bluetooth initialized\n");
bt_conn_cb_register(&conn_cbs);
bt_conn_auth_info_cb_register(&auto_info_cbs);
}
static void create_per_adv_set(struct bt_le_ext_adv **adv)
{
int err;
printk("Creating extended advertising set...");
err = bt_le_ext_adv_create(BT_LE_EXT_ADV_NCONN, NULL, adv);
if (err) {
printk("Failed to create advertising set: %d\n", err);
return;
}
printk("done.\n");
printk("Setting periodic advertising parameters...");
err = bt_le_per_adv_set_param(*adv, BT_LE_PER_ADV_DEFAULT);
if (err) {
printk("Failed to set periodic advertising parameters: %d\n",
err);
return;
}
printk("done.\n");
}
static void create_conn_adv_set(struct bt_le_ext_adv **adv)
{
int err;
printk("Creating connectable extended advertising set...");
err = bt_le_ext_adv_create(BT_LE_EXT_ADV_CONN, NULL, adv);
if (err) {
printk("Failed to create advertising set: %d\n", err);
return;
}
printk("done.\n");
}
static void start_ext_adv_set(struct bt_le_ext_adv *adv)
{
int err;
printk("Starting Extended Advertising...");
err = bt_le_ext_adv_start(adv, BT_LE_EXT_ADV_START_DEFAULT);
if (err) {
printk("Failed to start extended advertising: %d\n", err);
return;
}
printk("done.\n");
}
static void start_per_adv_set(struct bt_le_ext_adv *adv)
{
int err;
printk("Starting periodic advertising...");
err = bt_le_per_adv_start(adv);
if (err) {
printk("Failed to start periodic advertising: %d\n", err);
return;
}
printk("done.\n");
}
#if defined(CONFIG_BT_PER_ADV)
static void set_per_adv_data(struct bt_le_ext_adv *adv)
{
int err;
const struct bt_data ad[] = {
BT_DATA(BT_DATA_MANUFACTURER_DATA, mfg_data, ARRAY_SIZE(mfg_data)),
BT_DATA(BT_DATA_MANUFACTURER_DATA, mfg_data, ARRAY_SIZE(mfg_data))};
printk("Setting Periodic Advertising Data...");
err = bt_le_per_adv_set_data(adv, ad, ARRAY_SIZE(ad));
if (err) {
printk("Failed to set periodic advertising data: %d\n",
err);
return;
}
printk("done.\n");
}
#endif
static void stop_ext_adv_set(struct bt_le_ext_adv *adv)
{
int err;
printk("Stopping Extended Advertising...");
err = bt_le_ext_adv_stop(adv);
if (err) {
printk("Failed to stop extended advertising: %d\n",
err);
return;
}
printk("done.\n");
}
static void stop_per_adv_set(struct bt_le_ext_adv *adv)
{
int err;
printk("Stopping Periodic Advertising...");
err = bt_le_per_adv_stop(adv);
if (err) {
printk("Failed to stop periodic advertising: %d\n",
err);
return;
}
printk("done.\n");
}
static void delete_adv_set(struct bt_le_ext_adv *adv)
{
int err;
printk("Delete extended advertising set...");
err = bt_le_ext_adv_delete(adv);
if (err) {
printk("Failed Delete extended advertising set: %d\n", err);
return;
}
printk("done.\n");
}
static void main_per_adv_advertiser(void)
{
struct bt_le_ext_adv *per_adv;
common_init();
create_per_adv_set(&per_adv);
start_per_adv_set(per_adv);
start_ext_adv_set(per_adv);
/* Advertise for a bit */
k_sleep(K_SECONDS(10));
stop_per_adv_set(per_adv);
stop_ext_adv_set(per_adv);
delete_adv_set(per_adv);
per_adv = NULL;
PASS("Periodic advertiser passed\n");
}
static void main_per_adv_conn_advertiser(void)
{
struct bt_le_ext_adv *conn_adv;
struct bt_le_ext_adv *per_adv;
common_init();
create_per_adv_set(&per_adv);
create_conn_adv_set(&conn_adv);
start_per_adv_set(per_adv);
start_ext_adv_set(per_adv);
start_ext_adv_set(conn_adv);
WAIT_FOR_FLAG(flag_connected);
/* Advertise for a bit */
k_sleep(K_SECONDS(10));
stop_per_adv_set(per_adv);
stop_ext_adv_set(per_adv);
stop_ext_adv_set(conn_adv);
delete_adv_set(per_adv);
per_adv = NULL;
delete_adv_set(conn_adv);
conn_adv = NULL;
PASS("Periodic advertiser passed\n");
}
static void main_per_adv_conn_privacy_advertiser(void)
{
struct bt_le_ext_adv *conn_adv;
struct bt_le_ext_adv *per_adv;
common_init();
create_conn_adv_set(&conn_adv);
start_ext_adv_set(conn_adv);
WAIT_FOR_FLAG(flag_connected);
WAIT_FOR_FLAG(flag_bonded);
/* Start periodic advertising after bonding so that the scanner gets
* the resolved address
*/
create_per_adv_set(&per_adv);
start_per_adv_set(per_adv);
start_ext_adv_set(per_adv);
/* Advertise for a bit */
k_sleep(K_SECONDS(10));
stop_per_adv_set(per_adv);
stop_ext_adv_set(per_adv);
stop_ext_adv_set(conn_adv);
delete_adv_set(per_adv);
per_adv = NULL;
delete_adv_set(conn_adv);
conn_adv = NULL;
PASS("Periodic advertiser passed\n");
}
static void main_per_adv_long_data_advertiser(void)
{
#if defined(CONFIG_BT_PER_ADV)
struct bt_le_ext_adv *per_adv;
common_init();
create_per_adv_set(&per_adv);
set_per_adv_data(per_adv);
start_per_adv_set(per_adv);
start_ext_adv_set(per_adv);
/* Advertise for a bit */
k_sleep(K_SECONDS(10));
stop_per_adv_set(per_adv);
stop_ext_adv_set(per_adv);
delete_adv_set(per_adv);
per_adv = NULL;
#endif
PASS("Periodic long data advertiser passed\n");
}
static const struct bst_test_instance per_adv_advertiser[] = {
{
.test_id = "per_adv_advertiser",
.test_descr = "Basic periodic advertising test. "
"Will just start periodic advertising.",
.test_post_init_f = test_init,
.test_tick_f = test_tick,
.test_main_f = main_per_adv_advertiser
},
{
.test_id = "per_adv_conn_advertiser",
.test_descr = "Periodic advertising test with concurrent ACL "
"and PA sync.",
.test_post_init_f = test_init,
.test_tick_f = test_tick,
.test_main_f = main_per_adv_conn_advertiser
},
{
.test_id = "per_adv_conn_privacy_advertiser",
.test_descr = "Periodic advertising test with concurrent ACL "
"with bonding and PA sync.",
.test_post_init_f = test_init,
.test_tick_f = test_tick,
.test_main_f = main_per_adv_conn_privacy_advertiser
},
{
.test_id = "per_adv_long_data_advertiser",
.test_descr = "Periodic advertising test with a longer data length. "
"To test the syncers reassembly of large data packets",
.test_post_init_f = test_init,
.test_tick_f = test_tick,
.test_main_f = main_per_adv_long_data_advertiser
},
BSTEST_END_MARKER
};
struct bst_test_list *test_per_adv_advertiser(struct bst_test_list *tests)
{
return bst_add_tests(tests, per_adv_advertiser);
}