Skip to content

Commit

Permalink
pal: switch to multi-advertising BLE API
Browse files Browse the repository at this point in the history
This commit prepares PAL to be used alongside other BLE instances.

Signed-off-by: Konrad Derda <[email protected]>
  • Loading branch information
konradderda committed Sep 18, 2024
1 parent 7238295 commit f9fabab
Show file tree
Hide file tree
Showing 9 changed files with 234 additions and 36 deletions.
11 changes: 11 additions & 0 deletions Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,9 @@ if SIDEWALK
config MAIN_STACK_SIZE
default 2048

config BT_ID_MAX
default 2

config SIDEWALK_SUBGHZ_SUPPORT
bool "Enable Sub-GHz link type support in Sidewalk libraries"
default y
Expand Down Expand Up @@ -195,6 +198,14 @@ config SIDEWALK_BLE_ADV_INT_SLOW
range 20 10240
default 1000

config SIDEWALK_BLE_ID
int "Set Sidewalk's BLE identity identifier"
range 1 255
default 1
help
Specify identifier used to distinguish Sidewalk related BLE
events.

config SIDEWALK_BLE_ADV_INT_TRANSITION
int "Duration of fast advertisement after sid_start in seconds"
range 1 2147483647
Expand Down
1 change: 1 addition & 0 deletions Kconfig.dependencies
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ config SIDEWALK_BLE
default SIDEWALK
imply BT
imply BT_PERIPHERAL
imply BT_EXT_ADV
help
Sidewalk Bluetooth Low Energy (BLE) module

Expand Down
3 changes: 3 additions & 0 deletions samples/sid_end_device/Kconfig.defconfig
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,9 @@ config BT_PERIPHERAL_PREF_LATENCY
config BT_PERIPHERAL_PREF_TIMEOUT
default 400

config BT_EXT_ADV_MAX_ADV_SET
default 2

# NVM
config NVS_LOOKUP_CACHE
default y
Expand Down
44 changes: 44 additions & 0 deletions subsys/sal/common/sid_ifc/sid_app_callbacks.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
/*
* Copyright (c) 2024 Nordic Semiconductor ASA
*
* SPDX-License-Identifier: LicenseRef-Nordic-5-Clause
*/

#ifndef SID_PAL_APP_CALLBACKS_H
#define SID_PAL_APP_CALLBACKS_H

#include <stdbool.h>

/**
* This callback is called when BT is about to be disabled. It lets the
* callee decide whether the bt_disable() function should be called (as it
* may impact other modules).
*
* @return true if the Bluetooth should be disabled, false otherwise.
*/
typedef bool (* sid_bt_disable_pred_callback_t)(void);

/**
* This callback is called before loading the settings using the settings_load()
* function. It lets the callee decide wheter the settings should be loaded as
* it may have been already done at the moment if initialization.
*
* @return true if settings should be loaded, false otherwise.
*/
typedef bool (* sid_settings_load_pred_callback_t)(void);

/**
* Set @ref sid_bt_disable_pred_callback_t.
*
* @param[in] cb The callback.
*/
void sid_disable_pred_cb_set(sid_bt_disable_pred_callback_t cb);

/**
* Set @ref sid_settings_load_pred_callback_t.
*
* @param[in] cb The callback.
*/
void sid_settings_load_pred_cb_set(sid_settings_load_pred_callback_t cb);

#endif
7 changes: 7 additions & 0 deletions subsys/sal/sid_pal/include/sid_ble_advert.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,13 @@

#include <stdint.h>

/**
* @brief Initialize Bluetooth Advertising.
*
* @return Zero on success or (negative) error code on failure.
*/
int sid_ble_advert_init(void);

/**
* @brief Start Bluetooth advertising.
*
Expand Down
57 changes: 53 additions & 4 deletions subsys/sal/sid_pal/src/sid_ble_adapter.c
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
#include <sid_ble_adapter_callbacks.h>
#include <sid_ble_advert.h>
#include <sid_ble_connection.h>
#include <sid_app_callbacks.h>

#if defined(CONFIG_MAC_ADDRESS_TYPE_PUBLIC)
#include <zephyr/bluetooth/controller.h>
Expand Down Expand Up @@ -57,6 +58,40 @@ static struct sid_pal_ble_adapter_interface ble_ifc = {
.deinit = ble_adapter_deinit,
};

sid_bt_disable_pred_callback_t bt_disable_pred_cb = NULL;

void sid_pal_bt_disable_pred_cb_set(sid_bt_disable_pred_callback_t cb)
{
bt_disable_pred_cb = cb;
}

static bool should_disable_bt(void)
{
return bt_disable_pred_cb ? bt_disable_pred_cb() : true;
}

static int create_ble_id(void) {
int ret;
size_t count;

BUILD_ASSERT(CONFIG_SIDEWALK_BLE_ID < CONFIG_BT_ID_MAX, "CONFIG_BT_ID_MAX is too small.");

/* Check if Bluetooth identites weren't already created. */
bt_id_get(NULL, &count);
if (count > CONFIG_SIDEWALK_BLE_ID) {
return 0;
}

do {
ret = bt_id_create(NULL, NULL);
if (ret < 0) {
return ret;
}
} while (ret != CONFIG_SIDEWALK_BLE_ID);

return 0;
}

static sid_error_t ble_adapter_init(const sid_ble_config_t *cfg)
{
LOG_DBG("Sidewalk -> BLE");
Expand All @@ -82,6 +117,18 @@ static sid_error_t ble_adapter_init(const sid_ble_config_t *cfg)
return SID_ERROR_GENERIC;
}

err_code = create_ble_id();
if (err_code) {
LOG_ERR("BT ID init failed (err: %d)", err_code);
return SID_ERROR_GENERIC;
}

err_code = sid_ble_advert_init();
if (err_code) {
LOG_ERR("BT Advertisement failed (err: %d)", err_code);
return SID_ERROR_GENERIC;
}

sid_ble_conn_init();

return SID_ERROR_NONE;
Expand Down Expand Up @@ -256,11 +303,13 @@ static sid_error_t ble_adapter_deinit(void)
LOG_DBG("Sidewalk -> BLE");
sid_ble_conn_deinit();

int err = bt_disable();
if (should_disable_bt()) {
int err = bt_disable();

if (err) {
LOG_ERR("BT disable failed (error %d)", err);
return SID_ERROR_GENERIC;
if (err) {
LOG_ERR("BT disable failed (error %d)", err);
return SID_ERROR_GENERIC;
}
}

return SID_ERROR_NONE;
Expand Down
92 changes: 72 additions & 20 deletions subsys/sal/sid_pal/src/sid_ble_advert.c
Original file line number Diff line number Diff line change
Expand Up @@ -40,17 +40,24 @@ LOG_MODULE_REGISTER(sid_ble_advert, CONFIG_SIDEWALK_BLE_ADAPTER_LOG_LEVEL);
#endif

/* Advertising parameters. */
#define AMA_ADV_PARAM_FAST \
BT_LE_ADV_PARAM(AMA_ADV_OPTIONS, MS_TO_INTERVAL_VAL(CONFIG_SIDEWALK_BLE_ADV_INT_FAST), \
MS_TO_INTERVAL_VAL(CONFIG_SIDEWALK_BLE_ADV_INT_FAST + \
CONFIG_SIDEWALK_BLE_ADV_INT_PRECISION), \
NULL)

#define AMA_ADV_PARAM_SLOW \
BT_LE_ADV_PARAM(AMA_ADV_OPTIONS, MS_TO_INTERVAL_VAL(CONFIG_SIDEWALK_BLE_ADV_INT_SLOW), \
MS_TO_INTERVAL_VAL(CONFIG_SIDEWALK_BLE_ADV_INT_SLOW + \
CONFIG_SIDEWALK_BLE_ADV_INT_PRECISION), \
NULL)
static struct bt_le_adv_param adv_param_fast = {
.id = CONFIG_SIDEWALK_BLE_ID,
.options = (AMA_ADV_OPTIONS),
.interval_min = MS_TO_INTERVAL_VAL(CONFIG_SIDEWALK_BLE_ADV_INT_FAST),
.interval_max = MS_TO_INTERVAL_VAL(CONFIG_SIDEWALK_BLE_ADV_INT_FAST + \
CONFIG_SIDEWALK_BLE_ADV_INT_PRECISION),
};

static struct bt_le_adv_param adv_param_slow = {
.id = CONFIG_SIDEWALK_BLE_ID,
.options = (AMA_ADV_OPTIONS),
.interval_min = MS_TO_INTERVAL_VAL(CONFIG_SIDEWALK_BLE_ADV_INT_SLOW),
.interval_max = MS_TO_INTERVAL_VAL(CONFIG_SIDEWALK_BLE_ADV_INT_SLOW + \
CONFIG_SIDEWALK_BLE_ADV_INT_PRECISION),
};

static struct bt_le_ext_adv *adv_set_fast;
static struct bt_le_ext_adv *adv_set_slow;

/**
* @brief Advertising data items values size in bytes.
Expand All @@ -67,7 +74,7 @@ LOG_MODULE_REGISTER(sid_ble_advert, CONFIG_SIDEWALK_BLE_ADAPTER_LOG_LEVEL);

enum adv_data_items { ADV_DATA_FLAGS, ADV_DATA_SERVICES, ADV_DATA_MANUF_DATA };

typedef enum { BLE_ADV_DISABLE, BLE_ADV_ENABLE } sid_ble_adv_state_t;
typedef enum { BLE_ADV_DISABLE, BLE_ADV_FAST, BLE_ADV_SLOW } sid_ble_adv_state_t;

static void change_advertisement_interval(struct k_work *);
K_WORK_DELAYABLE_DEFINE(change_adv_work, change_advertisement_interval);
Expand Down Expand Up @@ -107,28 +114,68 @@ static uint8_t advert_manuf_data_copy(uint8_t *data, uint8_t data_len)
static void change_advertisement_interval(struct k_work *work)
{
ARG_UNUSED(work);
if (BLE_ADV_ENABLE == atomic_get(&adv_state)) {
if (bt_le_adv_stop()) {

struct bt_le_ext_adv_start_param ext_adv_start_param = {0};

if (BLE_ADV_FAST == atomic_get(&adv_state)) {
if (bt_le_ext_adv_stop(adv_set_fast)) {
atomic_set(&adv_state, BLE_ADV_DISABLE);
return;
}
if (bt_le_adv_start(AMA_ADV_PARAM_SLOW, adv_data, ARRAY_SIZE(adv_data), NULL, 0)) {

if (bt_le_ext_adv_set_data(adv_set_slow, adv_data, ARRAY_SIZE(adv_data), NULL, 0)) {
atomic_set(&adv_state, BLE_ADV_DISABLE);
return;
}

if (bt_le_ext_adv_start(adv_set_slow, &ext_adv_start_param)) {
atomic_set(&adv_state, BLE_ADV_DISABLE);
return;
}

atomic_set(&adv_state, BLE_ADV_SLOW);

LOG_DBG("BLE -> BLE");
}
}

int sid_ble_advert_init(void)
{
int ret;

ret = bt_le_ext_adv_create(&adv_param_fast, NULL, &adv_set_fast);
if (ret) {
LOG_ERR("Failed to create fast advertising set");
return ret;
}

ret = bt_le_ext_adv_create(&adv_param_slow, NULL, &adv_set_slow);
if (ret) {
LOG_ERR("Failed to create slow advertising set");
return ret;
}

return 0;
}

int sid_ble_advert_start(void)
{
k_work_reschedule(&change_adv_work, K_SECONDS(CONFIG_SIDEWALK_BLE_ADV_INT_TRANSITION));
int err = bt_le_adv_start(AMA_ADV_PARAM_FAST, adv_data, ARRAY_SIZE(adv_data), NULL, 0);

struct bt_le_ext_adv_start_param ext_adv_start_param = {0};
int err;

err = bt_le_ext_adv_set_data(adv_set_fast, adv_data, ARRAY_SIZE(adv_data), NULL, 0);
if (err) {
return err;
}

err = bt_le_ext_adv_start(adv_set_fast, &ext_adv_start_param);;
if (err) {
return err;
}
atomic_set(&adv_state, BLE_ADV_ENABLE);

atomic_set(&adv_state, BLE_ADV_FAST);

#if defined(CONFIG_MAC_ADDRESS_TYPE_RANDOM_PRIVATE_NON_RESOLVABLE)
static struct bt_le_oob oob;
Expand All @@ -141,7 +188,8 @@ int sid_ble_advert_start(void)
int sid_ble_advert_stop(void)
{
k_work_cancel_delayable(&change_adv_work);
int err = bt_le_adv_stop();
int err = bt_le_ext_adv_stop(atomic_get(&adv_state) == BLE_ADV_FAST ? adv_set_fast :
adv_set_slow);

if (0 == err) {
atomic_set(&adv_state, BLE_ADV_DISABLE);
Expand All @@ -152,6 +200,8 @@ int sid_ble_advert_stop(void)

int sid_ble_advert_update(uint8_t *data, uint8_t data_len)
{
sid_ble_adv_state_t state = atomic_get(&adv_state);

if (!data || 0 == data_len) {
return -EINVAL;
}
Expand All @@ -160,8 +210,10 @@ int sid_ble_advert_update(uint8_t *data, uint8_t data_len)

int err = 0;

if (BLE_ADV_ENABLE == atomic_get(&adv_state)) {
err = bt_le_adv_update_data(adv_data, ARRAY_SIZE(adv_data), NULL, 0);
if (BLE_ADV_DISABLE != state) {
/* Update currently advertised set, the other one will be set on start/transition */
err = bt_le_ext_adv_set_data((state == BLE_ADV_FAST ? adv_set_fast : adv_set_slow),
adv_data, ARRAY_SIZE(adv_data), NULL, 0);
}

return err;
Expand Down
22 changes: 19 additions & 3 deletions subsys/sal/sid_pal/src/sid_ble_connection.c
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,16 @@ static struct bt_conn_cb conn_callbacks = {

static struct bt_gatt_cb gatt_callbacks = { .att_mtu_updated = ble_mtu_cb };

static bool should_handle_event(struct bt_conn *conn) {
struct bt_conn_info conn_info;

if (!conn || bt_conn_get_info(conn, &conn_info) || conn_info.id != CONFIG_SIDEWALK_BLE_ID) {
return false;
}

return true;
}

/**
* @brief The function is called when a new connection is established.
*
Expand All @@ -41,12 +51,18 @@ static struct bt_gatt_cb gatt_callbacks = { .att_mtu_updated = ble_mtu_cb };
*/
static void ble_connect_cb(struct bt_conn *conn, uint8_t err)
{
const bt_addr_le_t *bt_addr_le;

if (!should_handle_event(conn)) {
return;
}

if (err) {
LOG_ERR("Connection failed (err %u)\n", err);
return;
}

const bt_addr_le_t *bt_addr_le = bt_conn_get_dst(conn);
bt_addr_le = bt_conn_get_dst(conn);

if (bt_addr_le) {
memcpy(conn_params.addr, bt_addr_le->a.val, BT_ADDR_SIZE);
Expand All @@ -72,10 +88,10 @@ static void ble_connect_cb(struct bt_conn *conn, uint8_t err)
*/
static void ble_disconnect_cb(struct bt_conn *conn, uint8_t reason)
{
if (!conn || conn_params.conn != conn) {
LOG_WRN("Unknow connection");
if (!should_handle_event(conn)) {
return;
}

sid_ble_adapter_conn_disconnected((const uint8_t *)conn_params.addr);

k_mutex_lock(&bt_conn_mutex, K_FOREVER);
Expand Down
Loading

0 comments on commit f9fabab

Please sign in to comment.