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>; 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`) (: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 This has to be enabled when the BLE controller connected is Zephyr
open source controller. 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 config BT_HCI_SETUP
bool bool
help help

View file

@ -529,8 +529,10 @@ static int h4_open(void)
} }
#if defined(CONFIG_BT_HCI_SETUP) #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. /* Extern bt_h4_vnd_setup function.
* This function executes vendor-specific commands sequence to * This function executes vendor-specific commands sequence to
* initialize BT Controller before BT Host executes Reset sequence. * 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; 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; struct net_buf *buf;
int err; int err;
uint8_t *addr = (uint8_t *)&SFLASH_BLE_DEVICE_ADDRESS[0]; 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 * If an insufficient amount of identities were recovered the app may then
* call bt_id_create() to create new ones. * 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 * @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 * to BT_ADDR_LE_ANY the stack will generate a new random
* static address for the identity and copy it to the given * 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, 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. * @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. * @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__)*/ #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) static int hci_init(void)
{ {
int err; int err;
#if defined(CONFIG_BT_HCI_SETUP) #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) { if (bt_dev.drv->setup) {
err = bt_dev.drv->setup(); err = bt_dev.drv->setup(&setup_params);
if (err) { if (err) {
return err; return err;
} }

View file

@ -1281,20 +1281,27 @@ int bt_id_create(bt_addr_le_t *addr, uint8_t *irk)
{ {
int new_id, err; int new_id, err;
if (addr && !bt_addr_le_eq(addr, BT_ADDR_LE_ANY)) { if (!IS_ENABLED(CONFIG_BT_PRIVACY) && irk) {
if (addr->type != BT_ADDR_LE_RANDOM || return -EINVAL;
!BT_ADDR_IS_STATIC(&addr->a)) { }
LOG_ERR("Only static random identity address supported");
return -EINVAL;
}
if (addr && !bt_addr_le_eq(addr, BT_ADDR_LE_ANY)) {
if (id_find(addr) >= 0) { if (id_find(addr) >= 0) {
return -EALREADY; return -EALREADY;
} }
}
if (!IS_ENABLED(CONFIG_BT_PRIVACY) && irk) { if (addr->type == BT_ADDR_LE_PUBLIC && IS_ENABLED(CONFIG_BT_HCI_SET_PUBLIC_ADDR)) {
return -EINVAL; /* 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)) { if (bt_dev.id_count == ARRAY_SIZE(bt_dev.id_addr)) {

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), zassert_mem_equal(&bt_dev.id_addr[new_id], BT_STATIC_RANDOM_LE_ADDR_1, sizeof(bt_addr_le_t),
"Incorrect address was set"); "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; int err;
if (IS_ENABLED(CONFIG_BT_HCI_SET_PUBLIC_ADDR)) {
ztest_test_skip();
}
err = bt_id_create(BT_LE_ADDR, NULL); err = bt_id_create(BT_LE_ADDR, NULL);
zassert_true(err == -EINVAL, "Unexpected error code '%d' was returned", err); zassert_true(err == -EINVAL, "Unexpected error code '%d' was returned", err);

View file

@ -5,6 +5,12 @@ common:
tests: tests:
bluetooth.host.bt_id_create.default: bluetooth.host.bt_id_create.default:
type: unit 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: bluetooth.host.bt_id_create.bt_privacy_enabled:
type: unit type: unit
extra_configs: extra_configs: