bluetooth: add HCI driver parameter to set controller's public address

This allows HCI drivers to expose vendor-specific functions to set the
public address.

Signed-off-by: Armin Brauns <armin.brauns@embedded-solutions.at>
This commit is contained in:
Armin Brauns 2023-11-15 15:13:49 +00:00 committed by Carles Cufí
commit 5b1b260f80
12 changed files with 122 additions and 13 deletions

View file

@ -52,6 +52,11 @@ Device Drivers and Device Tree
drdy-pin = <2>;
};
};
* The optional :c:func:`setup()` function in the Bluetooth HCI driver API (enabled through
:kconfig:option:`CONFIG_BT_HCI_SETUP`) has gained a function parameter of type
:c:struct:`bt_hci_setup_params`. By default, the struct is empty, but drivers can opt-in to
:kconfig:option:`CONFIG_BT_HCI_SET_PUBLIC_ADDR` if they support setting the controller's public
identity address, which will then be passed in the ``public_addr`` field.
(:github:`62994`)

View file

@ -164,6 +164,16 @@ config BT_DRIVER_QUIRK_NO_AUTO_DLE
This has to be enabled when the BLE controller connected is Zephyr
open source controller.
config BT_HCI_SET_PUBLIC_ADDR
bool
select BT_HCI_SETUP
help
Pass the controller's public address to the HCI driver in setup()
This option should be enabled by drivers for controllers that support setting the
public identity through vendor-specific commands. They can then implement the
setup() HCI driver API function and get the address to set from the public_addr field.
config BT_HCI_SETUP
bool
help

View file

@ -529,8 +529,10 @@ static int h4_open(void)
}
#if defined(CONFIG_BT_HCI_SETUP)
static int h4_setup(void)
static int h4_setup(const struct bt_hci_setup_params *params)
{
ARG_UNUSED(params);
/* Extern bt_h4_vnd_setup function.
* This function executes vendor-specific commands sequence to
* initialize BT Controller before BT Host executes Reset sequence.

View file

@ -196,8 +196,9 @@ static int psoc6_bless_send(struct net_buf *buf)
return 0;
}
static int psoc6_bless_setup(void)
static int psoc6_bless_setup(const struct bt_hci_setup_params *params)
{
ARG_UNUSED(params);
struct net_buf *buf;
int err;
uint8_t *addr = (uint8_t *)&SFLASH_BLE_DEVICE_ADDRESS[0];

View file

@ -340,6 +340,12 @@ void bt_id_get(bt_addr_le_t *addrs, size_t *count);
* If an insufficient amount of identities were recovered the app may then
* call bt_id_create() to create new ones.
*
* If supported by the HCI driver (indicated by setting
* @kconfig{CONFIG_BT_HCI_SET_PUBLIC_ADDR}), the first call to this function can be
* used to set the controller's public identity address. This call must happen
* before calling bt_enable(). Subsequent calls always add/generate random
* static addresses.
*
* @param addr Address to use for the new identity. If NULL or initialized
* to BT_ADDR_LE_ANY the stack will generate a new random
* static address for the identity and copy it to the given

View file

@ -139,6 +139,16 @@ enum bt_hci_driver_bus {
BT_HCI_DRIVER_BUS_IPM = 9,
};
#if defined(CONFIG_BT_HCI_SETUP) || defined(__DOXYGEN__)
struct bt_hci_setup_params {
/** The public identity address to give to the controller. This field is used when the
* driver selects @kconfig{CONFIG_BT_HCI_SET_PUBLIC_ADDR} to indicate that it supports
* setting the controller's public address.
*/
bt_addr_t public_addr;
};
#endif
/**
* @brief Abstraction which represents the HCI transport to the controller.
*
@ -213,7 +223,7 @@ struct bt_hci_driver {
*
* @return 0 on success or negative error number on failure.
*/
int (*setup)(void);
int (*setup)(const struct bt_hci_setup_params *params);
#endif /* defined(CONFIG_BT_HCI_SETUP) || defined(__DOXYGEN__)*/
};

View file

@ -3668,9 +3668,19 @@ static void hci_vs_init(void)
static int hci_init(void)
{
int err;
#if defined(CONFIG_BT_HCI_SETUP)
struct bt_hci_setup_params setup_params = { 0 };
bt_addr_copy(&setup_params.public_addr, BT_ADDR_ANY);
#if defined(CONFIG_BT_HCI_SET_PUBLIC_ADDR)
if (bt_dev.id_count > 0 && bt_dev.id_addr[BT_ID_DEFAULT].type == BT_ADDR_LE_PUBLIC) {
bt_addr_copy(&setup_params.public_addr, &bt_dev.id_addr[BT_ID_DEFAULT].a);
}
#endif /* defined(CONFIG_BT_HCI_SET_PUBLIC_ADDR) */
if (bt_dev.drv->setup) {
err = bt_dev.drv->setup();
err = bt_dev.drv->setup(&setup_params);
if (err) {
return err;
}

View file

@ -1281,21 +1281,28 @@ int bt_id_create(bt_addr_le_t *addr, uint8_t *irk)
{
int new_id, err;
if (addr && !bt_addr_le_eq(addr, BT_ADDR_LE_ANY)) {
if (addr->type != BT_ADDR_LE_RANDOM ||
!BT_ADDR_IS_STATIC(&addr->a)) {
LOG_ERR("Only static random identity address supported");
if (!IS_ENABLED(CONFIG_BT_PRIVACY) && irk) {
return -EINVAL;
}
if (addr && !bt_addr_le_eq(addr, BT_ADDR_LE_ANY)) {
if (id_find(addr) >= 0) {
return -EALREADY;
}
}
if (!IS_ENABLED(CONFIG_BT_PRIVACY) && irk) {
if (addr->type == BT_ADDR_LE_PUBLIC && IS_ENABLED(CONFIG_BT_HCI_SET_PUBLIC_ADDR)) {
/* set the single public address */
if (bt_dev.id_count != 0) {
return -EALREADY;
}
bt_addr_le_copy(&bt_dev.id_addr[BT_ID_DEFAULT], addr);
bt_dev.id_count++;
return BT_ID_DEFAULT;
} else if (addr->type != BT_ADDR_LE_RANDOM || !BT_ADDR_IS_STATIC(&addr->a)) {
LOG_ERR("Only random static identity address supported");
return -EINVAL;
}
}
if (bt_dev.id_count == ARRAY_SIZE(bt_dev.id_addr)) {
return -ENOMEM;

View file

@ -0,0 +1,11 @@
# Copyright (c) 2023 Nordic Semiconductor ASA
#
# SPDX-License-Identifier: Apache-2.0
config SELECT_BT_HCI_SET_PUBLIC_ADDR
bool "dummy kconfig"
select BT_HCI_SET_PUBLIC_ADDR
help
dummy kconfig
source "Kconfig.zephyr"

View file

@ -215,3 +215,40 @@ ZTEST(bt_id_create, test_create_id_valid_input_address)
zassert_mem_equal(&bt_dev.id_addr[new_id], BT_STATIC_RANDOM_LE_ADDR_1, sizeof(bt_addr_le_t),
"Incorrect address was set");
}
/*
* Test creating a new public identity.
*
* Constraints:
* - A valid address of type public is used
* - Input IRK is NULL
* - 'BT_DEV_ENABLE' flag is set in bt_dev.flags
*
* Expected behaviour:
* - The public address is loaded to bt_dev.id_addr[BT_ID_DEFAULT]
* - bt_dev.id_count is incremented
*/
ZTEST(bt_id_create, test_public_address)
{
int id_count, new_id;
bt_addr_le_t addr = *BT_LE_ADDR;
if (!IS_ENABLED(CONFIG_BT_HCI_SET_PUBLIC_ADDR)) {
ztest_test_skip();
}
id_count = bt_dev.id_count;
atomic_set_bit(bt_dev.flags, BT_DEV_ENABLE);
/* Calling bt_addr_le_create_static() isn't expected */
bt_addr_le_create_static_fake.return_val = -1;
new_id = bt_id_create(&addr, NULL);
expect_not_called_bt_addr_le_create_static();
zassert_true(new_id == BT_ID_DEFAULT, "Unexpected error code '%d' was returned", new_id);
zassert_true(bt_dev.id_count == (id_count + 1), "Incorrect ID count %d was set",
bt_dev.id_count);
zassert_mem_equal(&bt_dev.id_addr[new_id], BT_LE_ADDR, sizeof(bt_addr_le_t),
"Incorrect address was set");
}

View file

@ -93,6 +93,10 @@ ZTEST(bt_id_create_invalid_inputs, test_public_address)
{
int err;
if (IS_ENABLED(CONFIG_BT_HCI_SET_PUBLIC_ADDR)) {
ztest_test_skip();
}
err = bt_id_create(BT_LE_ADDR, NULL);
zassert_true(err == -EINVAL, "Unexpected error code '%d' was returned", err);

View file

@ -5,6 +5,12 @@ common:
tests:
bluetooth.host.bt_id_create.default:
type: unit
bluetooth.host.bt_id_create.bt_set_public_addr:
type: unit
extra_configs:
- CONFIG_BT_SMP=y
- CONFIG_BT_PRIVACY=y
- CONFIG_SELECT_BT_HCI_SET_PUBLIC_ADDR=y
bluetooth.host.bt_id_create.bt_privacy_enabled:
type: unit
extra_configs: