blob: b16a03d442d56e2acd9d1c4aa8a187142f7c3b38 [file] [log] [blame]
/* main.c - Application main entry point */
/*
* Copyright (c) 2015-2016 Intel Corporation
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <stddef.h>
#include <zephyr/types.h>
#include <zephyr/sys/printk.h>
#include <zephyr/sys/util.h>
#include <zephyr/bluetooth/bluetooth.h>
#include <zephyr/bluetooth/hci.h>
#include "ll.h"
#include "bs_types.h"
#include "bs_tracing.h"
#include "time_machine.h"
#include "bstests.h"
#define HANDLE 0x0000
#define EVT_PROP_SCAN BIT(1)
#define EVT_PROP_ANON BIT(5)
#define EVT_PROP_TXP BIT(6)
#define ADV_INTERVAL 0x20 /* 20 ms advertising interval */
#define ADV_WAIT_MS 10 /* 10 ms wait loop */
#define OWN_ADDR_TYPE BT_ADDR_LE_RANDOM_ID
#define PEER_ADDR_TYPE BT_ADDR_LE_RANDOM_ID
#define PEER_ADDR peer_addr
#define ADV_CHAN_MAP 0x07
#define FILTER_POLICY 0x00
#define ADV_TX_PWR NULL
#define ADV_SEC_SKIP 0
#define ADV_PHY_1M BIT(0)
#define ADV_PHY_2M BIT(1)
#define ADV_PHY_CODED BIT(2)
#define ADV_SID 0x0a
#define SCAN_REQ_NOT 0
#define AD_OP 0x03
#define AD_FRAG_PREF 0x00
#define ADV_INTERVAL_PERIODIC 0x30
#define SCAN_INTERVAL 0x04
#define SCAN_WINDOW 0x04
#define FAIL(...) \
do { \
bst_result = Failed; \
bs_trace_error_time_line(__VA_ARGS__); \
} while (0)
#define PASS(...) \
do { \
bst_result = Passed; \
bs_trace_info_time(1, __VA_ARGS__); \
} while (0)
extern enum bst_result_t bst_result;
static uint8_t const own_addr_reenable[] = {0xE0, 0xE1, 0xE2, 0xE3, 0xE4, 0xE5};
static uint8_t const own_addr[] = {0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5};
static uint8_t const peer_addr[] = {0xc6, 0xc7, 0xc8, 0xc9, 0xc1, 0xcb};
static const struct bt_data ad[] = {
BT_DATA_BYTES(BT_DATA_FLAGS, BT_LE_AD_NO_BREDR),
};
static uint8_t adv_data[] = {
2, BT_DATA_FLAGS, BT_LE_AD_NO_BREDR,
};
static uint8_t adv_data1[] = {
2, BT_DATA_FLAGS, (BT_LE_AD_GENERAL | BT_LE_AD_NO_BREDR),
7, BT_DATA_NAME_COMPLETE, 'Z', 'e', 'p', 'h', 'y', 'r',
};
static uint8_t adv_data2[] = {
2, BT_DATA_FLAGS, (BT_LE_AD_GENERAL | BT_LE_AD_NO_BREDR),
};
static uint8_t sr_data[] = {
7, BT_DATA_NAME_COMPLETE, 'Z', 'e', 'p', 'h', 'y', 'r',
};
static uint8_t per_adv_data1[] = {
7, BT_DATA_NAME_COMPLETE, 'Z', 'e', 'p', 'h', 'y', 'r',
};
static uint8_t per_adv_data2[] = {
8, BT_DATA_NAME_COMPLETE, 'Z', 'e', 'p', 'h', 'y', 'r', '1',
};
static uint8_t per_adv_data3[] = {
0xFF, 0xFE, 0xFD, 0xFB, 0xF7, 0xEF, 0xDF, 0xBF,
};
static uint8_t chan_map[] = { 0x1F, 0XF1, 0x1F, 0xF1, 0x1F };
static bool volatile is_scanned, is_connected, is_disconnected;
static bool volatile connection_to_test;
static uint8_t adv_data_expected_len;
static uint8_t *adv_data_expected;
static void connected(struct bt_conn *conn, uint8_t conn_err)
{
int err;
printk("Connected.\n");
is_connected = true;
err = bt_conn_disconnect(conn, BT_HCI_ERR_REMOTE_USER_TERM_CONN);
if (err) {
printk("Disconnection failed (err %d).\n", err);
}
}
static void disconnected(struct bt_conn *conn, uint8_t reason)
{
printk("Disconnected.\n");
is_disconnected = true;
}
BT_CONN_CB_DEFINE(conn_callbacks) = {
.connected = connected,
.disconnected = disconnected,
};
static bool volatile is_sent;
static uint8_t volatile num_sent_actual;
void sent_cb(struct bt_le_ext_adv *adv, struct bt_le_ext_adv_sent_info *info)
{
printk("%s: num_sent = %u\n", __func__, info->num_sent);
is_sent = true;
num_sent_actual = info->num_sent;
}
void connected_cb(struct bt_le_ext_adv *adv,
struct bt_le_ext_adv_connected_info *info)
{
printk("%s\n", __func__);
}
void scanned_cb(struct bt_le_ext_adv *adv,
struct bt_le_ext_adv_scanned_info *info)
{
printk("%s\n", __func__);
}
struct bt_le_ext_adv_cb adv_callbacks = {
.sent = sent_cb,
.connected = connected_cb,
.scanned = scanned_cb,
};
static void test_advx_main(void)
{
struct bt_le_ext_adv_start_param ext_adv_param;
struct bt_le_ext_adv *adv;
uint8_t num_sent_expected;
uint16_t evt_prop;
uint8_t adv_type;
uint16_t handle;
uint8_t phy_p;
uint8_t phy_s;
int err;
printk("\n*Extended Advertising test*\n");
printk("Bluetooth initializing...");
err = bt_enable(NULL);
if (err) {
goto exit;
}
printk("success.\n");
printk("Connectable advertising...");
err = bt_le_adv_start(BT_LE_ADV_CONN_NAME, ad, ARRAY_SIZE(ad), NULL, 0);
if (err) {
printk("Advertising failed to start (err %d)\n", err);
return;
}
printk("success.\n");
printk("Waiting for connection...");
while (!is_connected) {
k_sleep(K_MSEC(100));
}
printk("success.\n");
printk("Waiting for disconnect...");
while (!is_disconnected) {
k_sleep(K_MSEC(100));
}
printk("success.\n");
printk("Stop advertising...");
err = bt_le_adv_stop();
if (err) {
goto exit;
}
printk("success.\n");
printk("AD Data set...");
handle = 0U;
err = ll_adv_data_set(handle, sizeof(adv_data), adv_data);
if (err) {
goto exit;
}
printk("success.\n");
printk("Directed advertising, parameter set...");
err = ll_adv_params_set(handle, 0, 0, BT_HCI_ADV_DIRECT_IND,
OWN_ADDR_TYPE, PEER_ADDR_TYPE, PEER_ADDR,
ADV_CHAN_MAP, FILTER_POLICY,
0, 0, 0, 0, 0, 0);
if (err) {
goto exit;
}
printk("success.\n");
printk("Connectable advertising, parameter set...");
err = ll_adv_params_set(handle, 0, ADV_INTERVAL, BT_HCI_ADV_NONCONN_IND,
OWN_ADDR_TYPE, PEER_ADDR_TYPE, PEER_ADDR,
ADV_CHAN_MAP, FILTER_POLICY,
0, 0, 0, 0, 0, 0);
if (err) {
goto exit;
}
printk("success.\n");
printk("Enabling...");
err = ll_adv_enable(handle, 1, 0, 0);
if (err) {
goto exit;
}
printk("success.\n");
k_sleep(K_MSEC(100));
printk("Disabling...");
err = ll_adv_enable(handle, 0, 0, 0);
if (err) {
goto exit;
}
printk("success.\n");
printk("Directed advertising, parameter set...");
err = ll_adv_params_set(handle, 0, 0, BT_HCI_ADV_DIRECT_IND,
OWN_ADDR_TYPE, PEER_ADDR_TYPE, PEER_ADDR,
ADV_CHAN_MAP, FILTER_POLICY,
0, 0, 0, 0, 0, 0);
if (err) {
goto exit;
}
printk("success.\n");
printk("AD Data set...");
handle = 0U;
err = ll_adv_data_set(handle, sizeof(adv_data1), adv_data1);
if (err) {
goto exit;
}
printk("success.\n");
printk("Connectable advertising, parameter set...");
err = ll_adv_params_set(handle, 0, ADV_INTERVAL, BT_HCI_ADV_NONCONN_IND,
OWN_ADDR_TYPE, PEER_ADDR_TYPE, PEER_ADDR,
ADV_CHAN_MAP, FILTER_POLICY,
0, 0, 0, 0, 0, 0);
if (err) {
goto exit;
}
printk("success.\n");
printk("Enabling...");
err = ll_adv_enable(handle, 1, 0, 0);
if (err) {
goto exit;
}
printk("success.\n");
k_sleep(K_MSEC(100));
printk("Disabling...");
err = ll_adv_enable(handle, 0, 0, 0);
if (err) {
goto exit;
}
printk("success.\n");
printk("Create scannable extended advertising set...");
err = bt_le_ext_adv_create(BT_LE_EXT_ADV_SCAN_NAME, &adv_callbacks,
&adv);
if (err) {
goto exit;
}
printk("success.\n");
printk("Start scannable advertising...");
ext_adv_param.timeout = 0;
ext_adv_param.num_events = 0;
err = bt_le_ext_adv_start(adv, &ext_adv_param);
if (err) {
goto exit;
}
printk("success.\n");
k_sleep(K_MSEC(500));
printk("Stopping scannable advertising...");
err = bt_le_ext_adv_stop(adv);
if (err) {
goto exit;
}
printk("success.\n");
printk("Removing scannable adv set...");
err = bt_le_ext_adv_delete(adv);
if (err) {
goto exit;
}
printk("success.\n");
printk("Create connectable extended advertising set...");
is_connected = false;
is_disconnected = false;
err = bt_le_ext_adv_create(BT_LE_EXT_ADV_CONN_NAME, &adv_callbacks, &adv);
if (err) {
goto exit;
}
printk("success.\n");
printk("Start advertising...");
ext_adv_param.timeout = 0;
ext_adv_param.num_events = 0;
err = bt_le_ext_adv_start(adv, &ext_adv_param);
if (err) {
goto exit;
}
printk("success.\n");
printk("Waiting for connection...");
while (!is_connected) {
k_sleep(K_MSEC(100));
}
printk("success.\n");
printk("Waiting for disconnect...");
while (!is_disconnected) {
k_sleep(K_MSEC(100));
}
printk("success.\n");
printk("Removing connectable adv aux set...");
err = bt_le_ext_adv_delete(adv);
if (err) {
goto exit;
}
printk("success.\n");
k_sleep(K_MSEC(1000));
printk("Starting non-connectable advertising...");
err = bt_le_adv_start(BT_LE_ADV_NCONN, ad, ARRAY_SIZE(ad), NULL, 0);
if (err) {
goto exit;
}
printk("success.\n");
k_sleep(K_MSEC(400));
printk("Stopping advertising...");
err = bt_le_adv_stop();
if (err) {
goto exit;
}
printk("success.\n");
k_sleep(K_MSEC(1000));
printk("Create connectable advertising set...");
err = bt_le_ext_adv_create(BT_LE_ADV_CONN_NAME, &adv_callbacks, &adv);
if (err) {
goto exit;
}
printk("success.\n");
printk("Start advertising using extended commands (max_events)...");
is_sent = false;
num_sent_actual = 0;
num_sent_expected = 3;
ext_adv_param.timeout = 0;
ext_adv_param.num_events = 3;
err = bt_le_ext_adv_start(adv, &ext_adv_param);
if (err) {
goto exit;
}
printk("success.\n");
printk("Waiting...");
while (!is_sent) {
k_sleep(K_MSEC(100));
}
printk("done.\n");
if (num_sent_actual != num_sent_expected) {
FAIL("Num sent actual = %u, expected = %u\n", num_sent_actual,
num_sent_expected);
}
k_sleep(K_MSEC(1000));
printk("Start advertising using extended commands (duration)...");
is_sent = false;
num_sent_actual = 0;
num_sent_expected = 4;
ext_adv_param.timeout = 50;
ext_adv_param.num_events = 0;
err = bt_le_ext_adv_start(adv, &ext_adv_param);
if (err) {
goto exit;
}
printk("success.\n");
printk("Waiting...");
while (!is_sent) {
k_sleep(K_MSEC(100));
}
printk("done.\n");
if (num_sent_actual != num_sent_expected) {
FAIL("Num sent actual = %u, expected = %u\n", num_sent_actual,
num_sent_expected);
}
k_sleep(K_MSEC(1000));
printk("Re-enable advertising using extended commands (max_events)...");
is_sent = false;
num_sent_actual = 0;
num_sent_expected = 3;
ext_adv_param.timeout = 0;
ext_adv_param.num_events = 3;
err = bt_le_ext_adv_start(adv, &ext_adv_param);
if (err) {
goto exit;
}
printk("success.\n");
k_sleep(K_MSEC(100));
printk("Setting advertising random address before re-enabling...");
handle = 0x0000;
err = ll_adv_aux_random_addr_set(handle, own_addr_reenable);
if (err) {
goto exit;
}
printk("success.\n");
printk("Re-enabling...");
handle = 0x0000;
err = ll_adv_enable(handle, 1,
ext_adv_param.timeout,
ext_adv_param.num_events);
if (err) {
goto exit;
}
printk("success.\n");
printk("Waiting...");
while (!is_sent) {
k_sleep(K_MSEC(100));
}
printk("done.\n");
if (num_sent_actual != num_sent_expected) {
FAIL("Num sent actual = %u, expected = %u\n", num_sent_actual,
num_sent_expected);
}
k_sleep(K_MSEC(1000));
printk("Re-enable advertising using extended commands (duration)...");
is_sent = false;
num_sent_actual = 0;
num_sent_expected = 4; /* 4 advertising events of (100 ms +
* random_delay of upto 10 ms) transmit in
* the range of 400 to 440 ms
*/
ext_adv_param.timeout = 50; /* Check there is atmost 4 advertising
* events in a timeout of 500 ms
*/
ext_adv_param.num_events = 0;
err = bt_le_ext_adv_start(adv, &ext_adv_param);
if (err) {
goto exit;
}
printk("success.\n");
/* Delay 100 ms, and the test should verify that re-enabling still
* results in correct num of events.
*/
k_sleep(K_MSEC(100));
printk("Re-enabling...");
handle = 0x0000;
err = ll_adv_enable(handle, 1,
ext_adv_param.timeout,
ext_adv_param.num_events);
if (err) {
goto exit;
}
printk("success.\n");
printk("Waiting...");
while (!is_sent) {
k_sleep(K_MSEC(100));
}
printk("done.\n");
if (num_sent_actual != num_sent_expected) {
FAIL("Num sent actual = %u, expected = %u\n", num_sent_actual,
num_sent_expected);
}
k_sleep(K_MSEC(1000));
printk("Start advertising using extended commands (disable)...");
ext_adv_param.timeout = 0;
ext_adv_param.num_events = 5;
err = bt_le_ext_adv_start(adv, &ext_adv_param);
if (err) {
goto exit;
}
printk("success.\n");
k_sleep(K_MSEC(400));
printk("Stopping advertising using extended commands...");
err = bt_le_ext_adv_stop(adv);
if (err) {
goto exit;
}
printk("success.\n");
k_sleep(K_MSEC(1000));
printk("Setting advertising random address...");
handle = 0x0000;
err = ll_adv_aux_random_addr_set(handle, own_addr);
if (err) {
goto exit;
}
printk("success.\n");
printk("Starting non-conn non-scan without aux 1M advertising...");
evt_prop = EVT_PROP_TXP;
adv_type = 0x07; /* Adv. Ext. */
phy_p = ADV_PHY_1M;
phy_s = ADV_PHY_2M;
err = ll_adv_params_set(handle, evt_prop, ADV_INTERVAL, adv_type,
OWN_ADDR_TYPE, PEER_ADDR_TYPE, PEER_ADDR,
ADV_CHAN_MAP, FILTER_POLICY, ADV_TX_PWR,
phy_p, ADV_SEC_SKIP, phy_s, ADV_SID,
SCAN_REQ_NOT);
if (err) {
goto exit;
}
printk("enabling...");
err = ll_adv_enable(handle, 1, 0, 0);
if (err) {
goto exit;
}
printk("success.\n");
k_sleep(K_MSEC(400));
printk("Disabling...");
err = ll_adv_enable(handle, 0, 0, 0);
if (err) {
goto exit;
}
printk("success.\n");
k_sleep(K_MSEC(1000));
printk("Enabling non-conn non-scan without aux 1M advertising...");
err = ll_adv_enable(handle, 1, 0, 0);
if (err) {
goto exit;
}
printk("success.\n");
k_sleep(K_MSEC(400));
printk("Adding data, so non-conn non-scan with aux 1M advertising...");
err = ll_adv_aux_ad_data_set(handle, AD_OP, AD_FRAG_PREF,
sizeof(adv_data), (void *)adv_data);
if (err) {
goto exit;
}
printk("success.\n");
k_sleep(K_MSEC(400));
printk("Update advertising data 1...");
err = ll_adv_aux_ad_data_set(handle, AD_OP, AD_FRAG_PREF,
sizeof(adv_data1), (void *)adv_data1);
if (err) {
goto exit;
}
printk("success.\n");
k_sleep(K_MSEC(400));
printk("Update advertising data 2...");
err = ll_adv_aux_ad_data_set(handle, AD_OP, AD_FRAG_PREF,
sizeof(adv_data2), (void *)adv_data2);
if (err) {
goto exit;
}
printk("success.\n");
k_sleep(K_MSEC(400));
printk("Starting directed advertising...");
const bt_addr_le_t direct_addr = {
.type = BT_ADDR_LE_RANDOM,
.a = {
.val = {0x11, 0x22, 0x33, 0x44, 0x55, 0xC6}
}
};
const struct bt_le_adv_param adv_param = {
.options = BT_LE_ADV_OPT_CONNECTABLE,
.peer = &direct_addr,
};
err = bt_le_adv_start(&adv_param, NULL, 0, NULL, 0);
if (err) {
goto exit;
}
printk("success.\n");
k_sleep(K_MSEC(2000));
printk("Disabling...");
err = ll_adv_enable(handle, 0, 0, 0);
if (err) {
goto exit;
}
printk("success.\n");
k_sleep(K_MSEC(1000));
printk("Add to resolving list...");
bt_addr_le_t peer_id_addr = {
.type = BT_ADDR_LE_RANDOM,
.a = {
.val = {0xc6, 0xc7, 0xc8, 0xc9, 0xc1, 0xcb}
}
};
uint8_t pirk[16] = {0x00, };
uint8_t lirk[16] = {0x01, };
err = ll_rl_add(&peer_id_addr, pirk, lirk);
if (err) {
goto exit;
}
printk("success.\n");
printk("Enable resolving list...");
err = ll_rl_enable(BT_HCI_ADDR_RES_ENABLE);
if (err) {
goto exit;
}
printk("success.\n");
printk("Enabling extended...");
err = ll_adv_enable(handle, 1, 0, 0);
if (err) {
goto exit;
}
printk("success.\n");
k_sleep(K_MSEC(400));
printk("Starting periodic 1M advertising...");
err = ll_adv_sync_param_set(handle, ADV_INTERVAL_PERIODIC, 0);
if (err) {
goto exit;
}
printk("enabling periodic...");
err = ll_adv_sync_enable(handle, BT_HCI_LE_SET_PER_ADV_ENABLE_ENABLE);
if (err) {
goto exit;
}
printk("success.\n");
k_sleep(K_MSEC(400));
printk("Update advertising data 1...");
err = ll_adv_aux_ad_data_set(handle, AD_OP, AD_FRAG_PREF,
sizeof(adv_data1), (void *)adv_data1);
if (err) {
goto exit;
}
printk("success.\n");
k_sleep(K_MSEC(400));
printk("Update advertising data 2...");
err = ll_adv_aux_ad_data_set(handle, AD_OP, AD_FRAG_PREF,
sizeof(adv_data2), (void *)adv_data2);
if (err) {
goto exit;
}
printk("success.\n");
k_sleep(K_MSEC(400));
printk("Update periodic advertising data 1...");
err = ll_adv_sync_ad_data_set(handle, AD_OP, sizeof(per_adv_data1),
(void *)per_adv_data1);
if (err) {
goto exit;
}
printk("success.\n");
k_sleep(K_MSEC(400));
printk("Update periodic advertising data 2...");
err = ll_adv_sync_ad_data_set(handle, AD_OP, sizeof(per_adv_data2),
(void *)per_adv_data2);
if (err) {
goto exit;
}
printk("success.\n");
k_sleep(K_MSEC(400));
printk("Update periodic advertising data 3...");
err = ll_adv_sync_ad_data_set(handle, AD_OP, sizeof(per_adv_data3),
(void *)per_adv_data3);
if (err) {
goto exit;
}
printk("success.\n");
k_sleep(K_MSEC(400));
printk("Update periodic advertising back to data 2...");
err = ll_adv_sync_ad_data_set(handle, AD_OP, sizeof(per_adv_data2),
(void *)per_adv_data2);
if (err) {
goto exit;
}
printk("success.\n");
k_sleep(K_MSEC(400));
printk("Disabling...");
err = ll_adv_enable(handle, 0, 0, 0);
if (err) {
goto exit;
}
printk("success.\n");
printk("Periodic Advertising Channel Map Indication...");
err = ll_chm_update(chan_map);
if (err) {
goto exit;
}
printk("success.\n");
k_sleep(K_MSEC(400));
printk("Disabling periodic...");
err = ll_adv_sync_enable(handle, 0);
if (err) {
goto exit;
}
printk("success.\n");
k_sleep(K_MSEC(1000));
printk("enabling periodic...");
err = ll_adv_sync_enable(handle,
(BT_HCI_LE_SET_PER_ADV_ENABLE_ENABLE |
BT_HCI_LE_SET_PER_ADV_ENABLE_ADI));
if (err) {
goto exit;
}
printk("success.\n");
printk("Enabling extended...");
err = ll_adv_enable(handle, 1, 0, 0);
if (err) {
goto exit;
}
printk("success.\n");
k_sleep(K_MSEC(400));
printk("Update periodic advertising data (duplicate filter)...");
err = ll_adv_sync_ad_data_set(handle, AD_OP, sizeof(per_adv_data3),
(void *)per_adv_data3);
if (err) {
goto exit;
}
printk("success.\n");
k_sleep(K_MSEC(1000));
printk("Disabling periodic...");
err = ll_adv_sync_enable(handle, 0);
if (err) {
goto exit;
}
printk("success.\n");
k_sleep(K_MSEC(400));
printk("Disabling...");
err = ll_adv_enable(handle, 0, 0, 0);
if (err) {
goto exit;
}
printk("success.\n");
k_sleep(K_MSEC(1000));
printk("Adding scan response data on non-scannable set...");
err = ll_adv_aux_sr_data_set(handle, AD_OP, AD_FRAG_PREF,
sizeof(sr_data), (void *)sr_data);
if (err != BT_HCI_ERR_INVALID_PARAM) {
goto exit;
}
printk("success.\n");
printk("Removing adv aux set that's created and disabled ...");
err = ll_adv_aux_set_remove(handle);
if (err) {
goto exit;
}
printk("success.\n");
printk("Creating new adv set (scannable)...");
err = ll_adv_params_set(handle, EVT_PROP_SCAN, ADV_INTERVAL, adv_type,
OWN_ADDR_TYPE, PEER_ADDR_TYPE, PEER_ADDR,
ADV_CHAN_MAP, FILTER_POLICY, ADV_TX_PWR,
phy_p, ADV_SEC_SKIP, phy_s, ADV_SID,
SCAN_REQ_NOT);
if (err) {
goto exit;
}
printk("success.\n");
printk("Adding scan response data...");
err = ll_adv_aux_sr_data_set(handle, AD_OP, AD_FRAG_PREF,
sizeof(sr_data), (void *)sr_data);
if (err) {
goto exit;
}
printk("success.\n");
printk("Enabling non-conn scan with scan response data...");
err = ll_adv_enable(handle, 1, 0, 0);
if (err) {
goto exit;
}
printk("success.\n");
k_sleep(K_MSEC(400));
printk("Disabling...");
err = ll_adv_enable(handle, 0, 0, 0);
if (err) {
goto exit;
}
printk("success.\n");
k_sleep(K_MSEC(1000));
printk("Removing adv aux set that's created and disabled ...");
err = ll_adv_aux_set_remove(handle);
if (err) {
goto exit;
}
printk("success.\n");
printk("Removing adv aux set that's not created ...");
err = ll_adv_aux_set_remove(handle);
if (err != BT_HCI_ERR_UNKNOWN_ADV_IDENTIFIER) {
goto exit;
}
printk("success.\n");
printk("Creating new adv set...");
err = ll_adv_params_set(handle, evt_prop, ADV_INTERVAL, adv_type,
OWN_ADDR_TYPE, PEER_ADDR_TYPE, PEER_ADDR,
ADV_CHAN_MAP, FILTER_POLICY, ADV_TX_PWR,
phy_p, ADV_SEC_SKIP, phy_s, ADV_SID,
SCAN_REQ_NOT);
if (err) {
goto exit;
}
printk("success.\n");
printk("Update advertising data 2...");
err = ll_adv_aux_ad_data_set(handle, AD_OP, AD_FRAG_PREF,
sizeof(adv_data2), (void *)adv_data2);
if (err) {
goto exit;
}
printk("success.\n");
printk("Enabling adv set...");
err = ll_adv_enable(handle, 1, 0, 0);
if (err) {
goto exit;
}
printk("success.\n");
k_sleep(K_MSEC(400));
printk("Removing adv aux set that's created and enabled ...");
err = ll_adv_aux_set_remove(handle);
if (err != BT_HCI_ERR_CMD_DISALLOWED) {
goto exit;
}
printk("success.\n");
printk("Disabling adv set...");
err = ll_adv_enable(handle, 0, 0, 0);
if (err) {
goto exit;
}
printk("success.\n");
printk("Removing adv aux set that's created and disabled ...");
err = ll_adv_aux_set_remove(handle);
if (err) {
goto exit;
}
printk("success.\n");
printk("Creating new adv set...");
err = ll_adv_params_set(handle, evt_prop, ADV_INTERVAL, adv_type,
OWN_ADDR_TYPE, PEER_ADDR_TYPE, PEER_ADDR,
ADV_CHAN_MAP, FILTER_POLICY, ADV_TX_PWR,
phy_p, ADV_SEC_SKIP, phy_s, ADV_SID,
SCAN_REQ_NOT);
if (err) {
goto exit;
}
printk("success.\n");
printk("Starting periodic 1M advertising...");
err = ll_adv_sync_param_set(handle, ADV_INTERVAL_PERIODIC, 0);
if (err) {
goto exit;
}
printk("success.\n");
printk("enabling periodic...");
err = ll_adv_sync_enable(handle, BT_HCI_LE_SET_PER_ADV_ENABLE_ENABLE);
if (err) {
goto exit;
}
printk("success.\n");
printk("Trying to remove an adv set with sync enabled ...");
err = ll_adv_aux_set_remove(handle);
if (err != BT_HCI_ERR_CMD_DISALLOWED) {
goto exit;
}
printk("success.\n");
printk("Disabling periodic...");
err = ll_adv_sync_enable(handle, 0);
if (err) {
goto exit;
}
printk("success.\n");
printk("Trying to remove an adv set after sync disabled ...");
err = ll_adv_aux_set_remove(handle);
if (err) {
goto exit;
}
printk("success.\n");
uint8_t num_adv_sets;
num_adv_sets = ll_adv_aux_set_count_get();
printk("Creating every other adv set ...");
for (handle = 0; handle < num_adv_sets; handle += 2) {
err = ll_adv_params_set(handle, evt_prop, ADV_INTERVAL, adv_type,
OWN_ADDR_TYPE, PEER_ADDR_TYPE, PEER_ADDR,
ADV_CHAN_MAP, FILTER_POLICY, ADV_TX_PWR,
phy_p, ADV_SEC_SKIP, phy_s, ADV_SID,
SCAN_REQ_NOT);
if (err) {
goto exit;
}
}
printk("success.\n");
printk("Clearing all adv sets...");
err = ll_adv_aux_set_clear();
if (err) {
goto exit;
}
printk("success.\n");
printk("Trying to remove adv sets ...");
for (handle = 0; handle < num_adv_sets; ++handle) {
err = ll_adv_aux_set_remove(handle);
if (err != BT_HCI_ERR_UNKNOWN_ADV_IDENTIFIER) {
goto exit;
}
}
printk("success.\n");
printk("Creating one adv set ...");
handle = 0;
err = ll_adv_params_set(handle, evt_prop, ADV_INTERVAL, adv_type,
OWN_ADDR_TYPE, PEER_ADDR_TYPE, PEER_ADDR,
ADV_CHAN_MAP, FILTER_POLICY, ADV_TX_PWR,
phy_p, ADV_SEC_SKIP, phy_s, ADV_SID,
SCAN_REQ_NOT);
if (err) {
goto exit;
}
printk("success.\n");
printk("Enabling adv set...");
err = ll_adv_enable(handle, 1, 0, 0);
if (err) {
goto exit;
}
printk("success.\n");
printk("Clearing all adv sets...");
err = ll_adv_aux_set_clear();
if (err != BT_HCI_ERR_CMD_DISALLOWED) {
goto exit;
}
printk("success.\n");
PASS("AdvX tests Passed\n");
bs_trace_silent_exit(0);
return;
exit:
printk("failed (%d)\n", err);
bst_result = Failed;
bs_trace_silent_exit(0);
}
static bool is_reenable_addr;
static void scan_cb(const bt_addr_le_t *addr, int8_t rssi, uint8_t adv_type,
struct net_buf_simple *buf)
{
char le_addr[BT_ADDR_LE_STR_LEN];
bt_addr_le_to_str(addr, le_addr, sizeof(le_addr));
printk("%s: type = 0x%x, addr = %s\n", __func__, adv_type, le_addr);
if (!is_reenable_addr &&
!memcmp(own_addr_reenable, addr->a.val,
sizeof(own_addr_reenable))) {
is_reenable_addr = true;
}
if (connection_to_test) {
struct bt_conn *conn;
int err;
connection_to_test = false;
err = bt_le_scan_stop();
if (err) {
printk("Stop LE scan failed (err %d)\n", err);
return;
}
err = bt_conn_le_create(addr, BT_CONN_LE_CREATE_CONN,
BT_LE_CONN_PARAM_DEFAULT,
&conn);
if (err) {
printk("Create conn failed (err %d)\n", err);
} else {
bt_conn_unref(conn);
}
} else if (!is_scanned) {
char addr_str[BT_ADDR_LE_STR_LEN];
bt_addr_le_to_str(addr, addr_str, sizeof(addr_str));
printk("Device found: %s, type: %u, AD len: %u, RSSI %d\n",
addr_str, adv_type, buf->len, rssi);
if ((buf->len == adv_data_expected_len) &&
!memcmp(buf->data, adv_data_expected,
adv_data_expected_len)) {
is_scanned = true;
}
}
}
static const char *phy2str(uint8_t phy)
{
switch (phy) {
case 0: return "No packets";
case BT_GAP_LE_PHY_1M: return "LE 1M";
case BT_GAP_LE_PHY_2M: return "LE 2M";
case BT_GAP_LE_PHY_CODED: return "LE Coded";
default: return "Unknown";
}
}
#define NAME_LEN 30
static bool data_cb(struct bt_data *data, void *user_data)
{
char *name = user_data;
switch (data->type) {
case BT_DATA_NAME_SHORTENED:
case BT_DATA_NAME_COMPLETE:
memcpy(name, data->data, MIN(data->data_len, NAME_LEN - 1));
return false;
default:
return true;
}
}
static bool is_scannable;
static bool is_scan_rsp;
static bool is_periodic;
static uint8_t per_sid;
static bt_addr_le_t per_addr;
static uint8_t per_adv_evt_cnt_actual;
static void scan_recv(const struct bt_le_scan_recv_info *info,
struct net_buf_simple *buf)
{
char le_addr[BT_ADDR_LE_STR_LEN];
char name[NAME_LEN];
(void)memset(name, 0, sizeof(name));
bt_data_parse(buf, data_cb, name);
bt_addr_le_to_str(info->addr, le_addr, sizeof(le_addr));
printk("[DEVICE]: %s, AD evt type %u, Tx Pwr: %i, RSSI %i %s "
"C:%u S:%u D:%u SR:%u E:%u Prim: %s, Secn: %s, "
"Interval: 0x%04x (%u ms), SID: %u\n",
le_addr, info->adv_type, info->tx_power, info->rssi, name,
(info->adv_props & BT_GAP_ADV_PROP_CONNECTABLE) != 0,
(info->adv_props & BT_GAP_ADV_PROP_SCANNABLE) != 0,
(info->adv_props & BT_GAP_ADV_PROP_DIRECTED) != 0,
(info->adv_props & BT_GAP_ADV_PROP_SCAN_RESPONSE) != 0,
(info->adv_props & BT_GAP_ADV_PROP_EXT_ADV) != 0,
phy2str(info->primary_phy), phy2str(info->secondary_phy),
info->interval, info->interval * 5 / 4, info->sid);
if (!is_scannable &&
((info->adv_props & BT_GAP_ADV_PROP_SCANNABLE) != 0)) {
is_scannable = true;
}
if (!is_scan_rsp &&
((info->adv_props & BT_GAP_ADV_PROP_SCANNABLE) != 0) &&
((info->adv_props & BT_GAP_ADV_PROP_SCAN_RESPONSE) != 0) &&
(strlen(name) == strlen(CONFIG_BT_DEVICE_NAME)) &&
(!strcmp(name, CONFIG_BT_DEVICE_NAME))) {
is_scan_rsp = true;
}
if (info->interval) {
if (!is_periodic) {
is_periodic = true;
per_sid = info->sid;
bt_addr_le_copy(&per_addr, info->addr);
} else {
if ((per_sid == info->sid) &&
!bt_addr_le_cmp(&per_addr, info->addr)) {
per_adv_evt_cnt_actual++;
printk("per_adv_evt_cnt_actual %u\n",
per_adv_evt_cnt_actual);
}
}
}
}
static bool is_scan_timeout;
static void scan_timeout(void)
{
is_scan_timeout = true;
}
static struct bt_le_scan_cb scan_callbacks = {
.recv = scan_recv,
.timeout = scan_timeout,
};
static bool volatile is_sync;
static bool volatile is_sync_report;
static bool volatile is_sync_lost;
static uint8_t volatile sync_report_len;
static uint8_t sync_report_data[251];
static void
per_adv_sync_sync_cb(struct bt_le_per_adv_sync *sync,
struct bt_le_per_adv_sync_synced_info *info)
{
char le_addr[BT_ADDR_LE_STR_LEN];
bt_addr_le_to_str(info->addr, le_addr, sizeof(le_addr));
printk("PER_ADV_SYNC[%u]: [DEVICE]: %s synced, "
"Interval 0x%04x (%u ms), PHY %s\n",
bt_le_per_adv_sync_get_index(sync), le_addr,
info->interval, info->interval * 5 / 4, phy2str(info->phy));
is_sync = true;
}
static void
per_adv_sync_terminated_cb(struct bt_le_per_adv_sync *sync,
const struct bt_le_per_adv_sync_term_info *info)
{
char le_addr[BT_ADDR_LE_STR_LEN];
bt_addr_le_to_str(info->addr, le_addr, sizeof(le_addr));
printk("PER_ADV_SYNC[%u]: [DEVICE]: %s sync terminated\n",
bt_le_per_adv_sync_get_index(sync), le_addr);
is_sync_lost = true;
}
static void
per_adv_sync_recv_cb(struct bt_le_per_adv_sync *sync,
const struct bt_le_per_adv_sync_recv_info *info,
struct net_buf_simple *buf)
{
char le_addr[BT_ADDR_LE_STR_LEN];
bt_addr_le_to_str(info->addr, le_addr, sizeof(le_addr));
printk("PER_ADV_SYNC[%u]: [DEVICE]: %s, tx_power %i, "
"RSSI %i, CTE %u, data length %u\n",
bt_le_per_adv_sync_get_index(sync), le_addr, info->tx_power,
info->rssi, info->cte_type, buf->len);
if (!is_sync_report) {
is_sync_report = true;
sync_report_len = buf->len;
memcpy(sync_report_data, buf->data, buf->len);
}
}
static struct bt_le_per_adv_sync_cb sync_cb = {
.synced = per_adv_sync_sync_cb,
.term = per_adv_sync_terminated_cb,
.recv = per_adv_sync_recv_cb
};
static void test_scanx_main(void)
{
struct bt_le_scan_param scan_param = {
.type = BT_HCI_LE_SCAN_ACTIVE,
.options = BT_LE_SCAN_OPT_NONE,
.interval = 0x0004,
.window = 0x0004,
};
struct bt_le_per_adv_sync_param sync_create_param;
struct bt_le_per_adv_sync *sync = NULL;
uint8_t per_adv_evt_cnt_expected;
uint8_t sync_report_len_prev;
int err;
printk("\n*Extended Scanning test*\n");
printk("Bluetooth initializing...");
err = bt_enable(NULL);
if (err) {
goto exit;
}
printk("success.\n");
printk("Scan callbacks register...");
bt_le_scan_cb_register(&scan_callbacks);
printk("success.\n");
printk("Periodic Advertising callbacks register...");
bt_le_per_adv_sync_cb_register(&sync_cb);
printk("Success.\n");
connection_to_test = true;
printk("Start scanning...");
is_reenable_addr = false;
err = bt_le_scan_start(&scan_param, scan_cb);
if (err) {
goto exit;
}
printk("success.\n");
printk("Waiting for connection...");
while (!is_connected) {
k_sleep(K_MSEC(100));
}
printk("success.\n");
printk("Waiting for disconnect...");
while (!is_disconnected) {
k_sleep(K_MSEC(100));
}
printk("success.\n");
is_connected = false;
is_disconnected = false;
connection_to_test = false;
printk("Start scanning...");
adv_data_expected = adv_data;
adv_data_expected_len = sizeof(adv_data);
err = bt_le_scan_start(&scan_param, scan_cb);
if (err) {
goto exit;
}
printk("success.\n");
printk("Waiting for advertising report, switch back from directed...");
while (!is_scanned) {
k_sleep(K_MSEC(100));
}
printk("success.\n");
printk("Waiting for advertising report, data update while directed...");
adv_data_expected = adv_data1;
adv_data_expected_len = sizeof(adv_data1);
is_scanned = false;
while (!is_scanned) {
k_sleep(K_MSEC(100));
}
printk("success.\n");
printk("Stop scanning...");
err = bt_le_scan_stop();
if (err) {
goto exit;
}
printk("success.\n");
printk("Start scanning...");
is_scannable = false;
is_scan_rsp = false;
err = bt_le_scan_start(&scan_param, scan_cb);
if (err) {
goto exit;
}
printk("success.\n");
printk("Waiting for scannable advertising report...\n");
while (!is_scannable) {
k_sleep(K_MSEC(100));
}
printk("success.\n");
printk("Waiting for scan response advertising report...\n");
while (!is_scan_rsp) {
k_sleep(K_MSEC(100));
}
printk("success.\n");
/* This wait is to ensure we match with connectable advertising in the
* advertiser's timeline.
*/
k_sleep(K_MSEC(500));
connection_to_test = true;
printk("Waiting for connection...");
while (!is_connected) {
k_sleep(K_MSEC(100));
}
printk("success.\n");
printk("Waiting for disconnect...");
while (!is_disconnected) {
k_sleep(K_MSEC(100));
}
printk("success.\n");
printk("Start scanning for a duration...");
is_scan_timeout = false;
scan_param.interval = 0x08;
scan_param.timeout = 100;
err = bt_le_scan_start(&scan_param, scan_cb);
if (err) {
goto exit;
}
printk("success.\n");
k_sleep(K_MSEC(scan_param.timeout * 10 + 10));
printk("Checking for scan timeout...");
if (!is_scan_timeout) {
err = -EIO;
goto exit;
}
printk("done.\n");
printk("Start continuous scanning for a duration...");
is_scan_timeout = false;
scan_param.interval = 0x04;
err = bt_le_scan_start(&scan_param, scan_cb);
if (err) {
goto exit;
}
printk("success.\n");
k_sleep(K_MSEC(scan_param.timeout * 10 + 10));
printk("Checking for scan timeout...");
if (!is_scan_timeout) {
err = -EIO;
goto exit;
}
printk("done.\n");
scan_param.timeout = 0;
k_sleep(K_MSEC(2000));
printk("Start scanning for Periodic Advertisements...");
is_periodic = false;
is_reenable_addr = false;
per_adv_evt_cnt_actual = 0;
per_adv_evt_cnt_expected = 3;
err = bt_le_scan_start(&scan_param, scan_cb);
if (err) {
goto exit;
}
printk("success.\n");
printk("Verify address update due to re-enable of advertising...");
while (!is_reenable_addr) {
k_sleep(K_MSEC(30));
}
printk("success.\n");
printk("Waiting...");
while (!is_periodic ||
(per_adv_evt_cnt_actual != per_adv_evt_cnt_expected)) {
k_sleep(K_MSEC(ADV_WAIT_MS));
}
printk("done.\n");
printk("Stop scanning...");
err = bt_le_scan_stop();
if (err) {
goto exit;
}
printk("success.\n");
printk("Creating Periodic Advertising Sync 0...");
bt_addr_le_copy(&sync_create_param.addr, &per_addr);
sync_create_param.options = 0;
sync_create_param.sid = 0xf;
sync_create_param.skip = 0;
sync_create_param.timeout = 0xa;
err = bt_le_per_adv_sync_create(&sync_create_param, &sync);
if (err) {
goto exit;
}
printk("success.\n");
printk("Check duplicate Periodic Advertising Sync create before sync "
"established event...");
err = bt_le_per_adv_sync_create(&sync_create_param, &sync);
if (!err) {
goto exit;
}
printk("success.\n");
printk("Start scanning...");
err = bt_le_scan_start(&scan_param, scan_cb);
if (err) {
goto exit;
}
printk("success.\n");
k_sleep(K_MSEC(400));
printk("Canceling Periodic Advertising Sync 0 while scanning...");
err = bt_le_per_adv_sync_delete(sync);
if (err) {
goto exit;
}
printk("success.\n");
printk("Stop scanning...");
err = bt_le_scan_stop();
if (err) {
goto exit;
}
printk("success.\n");
printk("Creating Periodic Advertising Sync 1...");
bt_addr_le_copy(&sync_create_param.addr, &per_addr);
sync_create_param.options = 0;
sync_create_param.sid = 0xf;
sync_create_param.skip = 0;
sync_create_param.timeout = 0xa;
err = bt_le_per_adv_sync_create(&sync_create_param, &sync);
if (err) {
goto exit;
}
printk("success.\n");
printk("Canceling Periodic Advertising Sync 1 without scanning...");
err = bt_le_per_adv_sync_delete(sync);
if (err) {
goto exit;
}
printk("success.\n");
printk("Creating Periodic Advertising Sync 2...");
is_sync = false;
bt_addr_le_copy(&sync_create_param.addr, &per_addr);
sync_create_param.options = 0;
sync_create_param.sid = per_sid;
sync_create_param.skip = 0;
sync_create_param.timeout = 0xa;
err = bt_le_per_adv_sync_create(&sync_create_param, &sync);
if (err) {
goto exit;
}
printk("success.\n");
printk("Start scanning...");
err = bt_le_scan_start(&scan_param, scan_cb);
if (err) {
goto exit;
}
printk("success.\n");
printk("Waiting for sync...");
while (!is_sync) {
k_sleep(K_MSEC(100));
}
printk("done.\n");
printk("Check duplicate Periodic Advertising Sync create after sync "
"established event...");
err = bt_le_per_adv_sync_create(&sync_create_param, &sync);
if (!err) {
goto exit;
}
printk("success.\n");
printk("Deleting Periodic Advertising Sync 2...");
err = bt_le_per_adv_sync_delete(sync);
if (err) {
goto exit;
}
printk("success.\n");
printk("Stop scanning...");
err = bt_le_scan_stop();
if (err) {
goto exit;
}
printk("success.\n");
printk("Creating Periodic Advertising Sync 3, test sync lost...");
is_sync = false;
is_sync_report = false;
sync_report_len = 0;
is_sync_lost = false;
bt_addr_le_copy(&sync_create_param.addr, &per_addr);
sync_create_param.options = 0;
sync_create_param.sid = per_sid;
sync_create_param.skip = 0;
sync_create_param.timeout = 0xa;
err = bt_le_per_adv_sync_create(&sync_create_param, &sync);
if (err) {
goto exit;
}
printk("success.\n");
printk("Start scanning...");
err = bt_le_scan_start(&scan_param, scan_cb);
if (err) {
goto exit;
}
printk("success.\n");
printk("Waiting for sync...");
while (!is_sync) {
k_sleep(K_MSEC(100));
}
printk("done.\n");
printk("Stop scanning...");
err = bt_le_scan_stop();
if (err) {
goto exit;
}
printk("success.\n");
printk("Waiting for Periodic Advertising Report of 0 bytes...");
while (!is_sync_report) {
k_sleep(K_MSEC(100));
}
printk("done.\n");
if (sync_report_len != 0) {
FAIL("Incorrect Periodic Advertising Report data.");
}
printk("Waiting for Periodic Advertising Report of %u bytes...",
sizeof(per_adv_data1));
sync_report_len_prev = sync_report_len;
while (!is_sync_report || (sync_report_len == sync_report_len_prev)) {
is_sync_report = false;
k_sleep(K_MSEC(100));
}
printk("done.\n");
if ((sync_report_len != sizeof(per_adv_data1)) ||
memcmp(sync_report_data, per_adv_data1, sizeof(per_adv_data1))) {
FAIL("Incorrect Periodic Advertising Report data.");
}
printk("Waiting for Periodic Advertising Report of %u bytes...",
sizeof(per_adv_data2));
sync_report_len_prev = sync_report_len;
while (!is_sync_report || (sync_report_len == sync_report_len_prev)) {
is_sync_report = false;
k_sleep(K_MSEC(100));
}
printk("done.\n");
if ((sync_report_len != sizeof(per_adv_data2)) ||
memcmp(sync_report_data, per_adv_data2, sizeof(per_adv_data2))) {
FAIL("Incorrect Periodic Advertising Report data.");
}
printk("Waiting for Periodic Advertising Report of %u bytes...",
sizeof(per_adv_data3));
sync_report_len_prev = sync_report_len;
while (!is_sync_report || (sync_report_len == sync_report_len_prev)) {
is_sync_report = false;
k_sleep(K_MSEC(100));
}
printk("done.\n");
if ((sync_report_len != sizeof(per_adv_data3)) ||
memcmp(sync_report_data, per_adv_data3, sizeof(per_adv_data3))) {
FAIL("Incorrect Periodic Advertising Report data.");
}
printk("Waiting for Periodic Advertising Report of %u bytes...",
sizeof(per_adv_data2));
sync_report_len_prev = sync_report_len;
while (!is_sync_report || (sync_report_len == sync_report_len_prev)) {
is_sync_report = false;
k_sleep(K_MSEC(100));
}
printk("done.\n");
if ((sync_report_len != sizeof(per_adv_data2)) ||
memcmp(sync_report_data, per_adv_data2, sizeof(per_adv_data2))) {
FAIL("Incorrect Periodic Advertising Report data.");
}
printk("Waiting for sync loss...");
while (!is_sync_lost) {
k_sleep(K_MSEC(100));
}
printk("done.\n");
printk("Add to resolving list...");
bt_addr_le_t peer_id_addr = {
.type = BT_ADDR_LE_RANDOM,
.a = {
.val = {0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5}
}
};
uint8_t pirk[16] = {0x01, };
uint8_t lirk[16] = {0x00, };
err = ll_rl_add(&peer_id_addr, pirk, lirk);
if (err) {
goto exit;
}
printk("success.\n");
printk("Enable resolving list...");
err = ll_rl_enable(BT_HCI_ADDR_RES_ENABLE);
if (err) {
goto exit;
}
printk("success.\n");
printk("Add device to periodic advertising list...");
err = bt_le_per_adv_list_add(&peer_id_addr, per_sid);
if (err) {
goto exit;
}
printk("success.\n");
printk("Creating Periodic Advertising Sync 4 after sync lost...");
is_sync = false;
is_sync_report = false;
bt_addr_le_copy(&sync_create_param.addr, &per_addr);
sync_create_param.options = BT_LE_PER_ADV_SYNC_OPT_USE_PER_ADV_LIST |
BT_LE_PER_ADV_SYNC_OPT_FILTER_DUPLICATE;
sync_create_param.sid = per_sid;
sync_create_param.skip = 0;
sync_create_param.timeout = 0xa;
err = bt_le_per_adv_sync_create(&sync_create_param, &sync);
if (err) {
goto exit;
}
printk("success.\n");
printk("Start scanning...");
err = bt_le_scan_start(&scan_param, scan_cb);
if (err) {
goto exit;
}
printk("success.\n");
printk("Waiting for sync...");
while (!is_sync) {
k_sleep(K_MSEC(100));
}
printk("done.\n");
printk("Stop scanning...");
err = bt_le_scan_stop();
if (err) {
goto exit;
}
printk("success.\n");
printk("Waiting for Periodic Advertising Report of %u bytes...",
sizeof(per_adv_data3));
sync_report_len_prev = sync_report_len;
while (!is_sync_report || (sync_report_len == sync_report_len_prev)) {
is_sync_report = false;
k_sleep(K_MSEC(100));
}
printk("done.\n");
if ((sync_report_len != sizeof(per_adv_data3)) ||
memcmp(sync_report_data, per_adv_data3, sizeof(per_adv_data3))) {
FAIL("Incorrect Periodic Advertising Report data (%u != %u).",
sync_report_len, sizeof(per_adv_data3));
}
printk("Wait for no duplicate Periodic Advertising Report"
" is generated...");
is_sync_report = false;
k_sleep(K_MSEC(400));
if (is_sync_report) {
goto exit;
}
printk("success\n");
printk("Deleting Periodic Advertising Sync 4...");
err = bt_le_per_adv_sync_delete(sync);
if (err) {
goto exit;
}
printk("success.\n");
PASS("ScanX tests Passed\n");
return;
exit:
printk("failed (%d)\n", err);
bst_result = Failed;
bs_trace_silent_exit(0);
}
static void test_advx_init(void)
{
bst_ticker_set_next_tick_absolute(30e6);
bst_result = In_progress;
}
static void test_advx_tick(bs_time_t HW_device_time)
{
bst_result = Failed;
bs_trace_error_line("Test advx/scanx finished.\n");
}
static const struct bst_test_instance test_def[] = {
{
.test_id = "advx",
.test_descr = "Extended Advertising",
.test_post_init_f = test_advx_init,
.test_tick_f = test_advx_tick,
.test_main_f = test_advx_main
},
{
.test_id = "scanx",
.test_descr = "Extended scanning",
.test_post_init_f = test_advx_init,
.test_tick_f = test_advx_tick,
.test_main_f = test_scanx_main
},
BSTEST_END_MARKER
};
struct bst_test_list *test_advx_install(struct bst_test_list *tests)
{
return bst_add_tests(tests, test_def);
}
bst_test_install_t test_installers[] = {
test_advx_install,
NULL
};
void main(void)
{
bst_main();
}