feat(ble/bluedroid): Add BLE SMP support for multi-ADV with static random addresses

(cherry picked from commit 7986e2faa8)

Co-authored-by: zhanghaipeng <zhanghaipeng@espressif.com>
This commit is contained in:
Zhang Hai Peng
2026-06-18 10:24:45 +08:00
parent bb0dcaad77
commit b35182d6f2
6 changed files with 276 additions and 20 deletions

View File

@@ -571,6 +571,12 @@ void btm_acl_removed (BD_ADDR bda, tBT_TRANSPORT transport)
btm_cb.ble_ctr_cb.inq_var.connectable_mode,
p->link_role);
if (p->transport == BT_TRANSPORT_LE) {
#if (BLE_50_FEATURE_SUPPORT == TRUE) && (BLE_50_EXTEND_ADV_EN == TRUE)
btm_ble_clear_ext_adv_ter_con_handle(p->hci_handle);
#endif
}
p_dev_rec = btm_find_dev(bda);
if ( p_dev_rec) {
BTM_TRACE_DEBUG("before update p_dev_rec->sec_flags=0x%x\n", p_dev_rec->sec_flags);

View File

@@ -1846,6 +1846,81 @@ UINT8 btm_ble_br_keys_req(tBTM_SEC_DEV_REC *p_dev_rec, tBTM_LE_IO_REQ *p_data)
#endif ///SMP_INCLUDED
#if (BLE_50_FEATURE_SUPPORT == TRUE) && (BLE_50_EXTEND_ADV_EN == TRUE) && (CONTROLLER_RPA_LIST_ENABLE == TRUE)
/*******************************************************************************
**
** Function btm_ble_adjust_conn_addr_for_ext_adv
**
** Description Rewrite p_acl->conn_addr / conn_addr_type from the
** per-set state in extend_adv_cb.inst[] for the ext-adv
** instance that produced this connection.
**
** The defaults written by btm_acl_created() and
** btm_ble_refresh_local_resolvable_private_addr() come
** from the global addr_mgnt_cb single slot, which in
** multi-ADV may not reflect the policy actually used on
** air for THIS connection and causes SMP c1 / f5 / f6
** to compute the wrong local address (pair fail 0x04).
**
** RPA paths (own_addr_type 0x02, or 0x03 with a valid
** local RPA in the LE Enhanced Connection Complete event)
** are left untouched. For 0x03 when the controller falls
** back to per-set identity (zero local_rpa), replace the
** global private_addr written by
** btm_ble_refresh_local_resolvable_private_addr().
**
** No-op when no ext-adv instance matches the handle
** (initiator role or legacy adv).
**
** Returns void
**
*******************************************************************************/
void btm_ble_adjust_conn_addr_for_ext_adv(UINT16 handle)
{
UINT8 inst;
tACL_CONN *p_acl;
tBLE_ADDR_TYPE on_air_type;
inst = BTM_BleGetExtAdvInstByConHandle(handle);
if (inst >= MAX_BLE_ADV_INSTANCE) {
return;
}
p_acl = btm_handle_to_acl(handle);
if (p_acl == NULL) {
BTM_TRACE_WARNING("%s: no ACL for handle 0x%04x, skip", __func__, handle);
return;
}
on_air_type = extend_adv_cb.inst[inst].own_addr_type;
if (on_air_type == BLE_ADDR_PUBLIC) {
p_acl->conn_addr_type = BLE_ADDR_PUBLIC;
memcpy(p_acl->conn_addr,
controller_get_interface()->get_address()->address,
BD_ADDR_LEN);
} else if (on_air_type == BLE_ADDR_RANDOM &&
extend_adv_cb.inst[inst].rand_addr_set) {
p_acl->conn_addr_type = BLE_ADDR_RANDOM;
memcpy(p_acl->conn_addr,
extend_adv_cb.inst[inst].rand_addr,
BD_ADDR_LEN);
} else if (on_air_type == BLE_ADDR_RANDOM_ID &&
extend_adv_cb.inst[inst].rand_addr_set &&
!BTM_BLE_IS_RESOLVE_BDA(p_acl->conn_addr)) {
/* Identity fallback: controller used per-set static random, not RPA. */
p_acl->conn_addr_type = BLE_ADDR_RANDOM;
memcpy(p_acl->conn_addr,
extend_adv_cb.inst[inst].rand_addr,
BD_ADDR_LEN);
}
BTM_TRACE_DEBUG("%s: handle=0x%04x inst=%u type=%u addr=%02x:%02x:%02x:%02x:%02x:%02x",
__func__, handle, inst, p_acl->conn_addr_type,
p_acl->conn_addr[0], p_acl->conn_addr[1], p_acl->conn_addr[2],
p_acl->conn_addr[3], p_acl->conn_addr[4], p_acl->conn_addr[5]);
}
#endif /* (BLE_50_FEATURE_SUPPORT == TRUE) && (BLE_50_EXTEND_ADV_EN == TRUE) && (CONTROLLER_RPA_LIST_ENABLE == TRUE) */
#if (BLE_PRIVACY_SPT == TRUE )
/*******************************************************************************
**
@@ -1904,6 +1979,11 @@ static void btm_ble_resolve_random_addr_on_conn_cmpl(void *p_rec, void *p_data)
l2cble_conn_comp (handle, role, bda, bda_type, conn_interval,
conn_latency, conn_timeout);
#if (BLE_50_FEATURE_SUPPORT == TRUE) && (BLE_50_EXTEND_ADV_EN == TRUE) && (CONTROLLER_RPA_LIST_ENABLE == TRUE)
/* Multi-ADV: fix up p_acl->conn_addr / conn_addr_type from per-set state. */
btm_ble_adjust_conn_addr_for_ext_adv(handle);
#endif /* (BLE_50_FEATURE_SUPPORT == TRUE) && (BLE_50_EXTEND_ADV_EN == TRUE) && (CONTROLLER_RPA_LIST_ENABLE == TRUE) */
return;
}
#endif
@@ -2067,6 +2147,12 @@ void btm_ble_conn_complete(UINT8 *p, UINT16 evt_len, BOOLEAN enhanced)
}
}
#endif
#if (BLE_50_FEATURE_SUPPORT == TRUE) && (BLE_50_EXTEND_ADV_EN == TRUE) && (CONTROLLER_RPA_LIST_ENABLE == TRUE)
/* Multi-ADV: must run AFTER the global-addr_mgnt_cb defaults above
* so per-set state wins for connections produced by an ext-adv set. */
btm_ble_adjust_conn_addr_for_ext_adv(handle);
#endif /* (BLE_50_FEATURE_SUPPORT == TRUE) && (BLE_50_EXTEND_ADV_EN == TRUE) && (CONTROLLER_RPA_LIST_ENABLE == TRUE) */
}
} else {
role = HCI_ROLE_UNKNOWN;

View File

@@ -6,6 +6,7 @@
#include "btm_int.h"
#include "stack/hcimsgs.h"
#include "stack/hcidefs.h"
#include "osi/allocator.h"
#include "device/controller.h"
#include <string.h>
@@ -63,7 +64,15 @@ void btm_ble_extendadvcb_init(void)
#if (BLE_50_EXTEND_ADV_EN == TRUE)
void btm_ble_advrecod_init(void)
{
memset(&adv_record[0], 0, sizeof(tBTM_EXT_ADV_RECORD)*MAX_BLE_ADV_INSTANCE);
for (uint8_t i = 0; i < MAX_BLE_ADV_INSTANCE; i++) {
adv_record[i].ter_con_handle = INVALID_VALUE_16BIT;
adv_record[i].invalid = false;
adv_record[i].enabled = false;
adv_record[i].instance = INVALID_VALUE_8BIT;
adv_record[i].duration = INVALID_VALUE_32BIT;
adv_record[i].max_events = INVALID_VALUE_32BIT;
adv_record[i].retry_count = 0;
}
}
#endif // #if (BLE_50_EXTEND_ADV_EN == TRUE)
@@ -197,6 +206,8 @@ tBTM_STATUS BTM_BleSetExtendedAdvRandaddr(UINT8 instance, BD_ADDR rand_addr)
__func__, err);
status = BTM_HCI_ERROR | err;
} else {
memcpy(extend_adv_cb.inst[instance].rand_addr, rand_addr, BD_ADDR_LEN);
extend_adv_cb.inst[instance].rand_addr_set = TRUE;
// set random address success, update address info
if(extend_adv_cb.inst[instance].configured && extend_adv_cb.inst[instance].connetable) {
BTM_BleSetStaticAddr(rand_addr);
@@ -286,6 +297,8 @@ tBTM_STATUS BTM_BleSetExtendedAdvParams(UINT8 instance, tBTM_BLE_GAP_EXT_ADV_PAR
#endif // (BT_BLE_FEAT_ADV_CODING_SELECTION == TRUE)
extend_adv_cb.inst[instance].configured = true;
/* Record the post-fallback on-air address type for per-set conn_addr fixup. */
extend_adv_cb.inst[instance].own_addr_type = params->own_addr_type;
end:
if(use_rpa_addr) {
@@ -296,6 +309,7 @@ end:
} else {
// set addr success, update address info
BTM_UpdateAddrInfor(BLE_ADDR_RANDOM, rand_addr);
extend_adv_cb.inst[instance].rand_addr_set = FALSE;
}
}
cb_params.set_params.status = status;
@@ -441,6 +455,7 @@ end:
for (uint8_t i = 0; i < MAX_BLE_ADV_INSTANCE; i++)
{
adv_record[i].ter_con_handle = INVALID_VALUE_16BIT;
adv_record[i].invalid = false;
adv_record[i].enabled = false;
adv_record[i].instance = INVALID_VALUE_8BIT;
@@ -455,6 +470,7 @@ end:
if (index >= MAX_BLE_ADV_INSTANCE) {
continue;
}
adv_record[index].ter_con_handle = INVALID_VALUE_16BIT;
adv_record[index].invalid = false;
adv_record[index].enabled = false;
adv_record[index].instance = INVALID_VALUE_8BIT;
@@ -472,6 +488,7 @@ end:
if (index >= MAX_BLE_ADV_INSTANCE) {
continue;
}
adv_record[index].ter_con_handle = INVALID_VALUE_16BIT;
adv_record[index].invalid = true;
adv_record[index].enabled = true;
adv_record[index].instance = ext_adv[i].instance;
@@ -520,6 +537,54 @@ tBTM_STATUS BTM_BleStartExtAdvRestart(uint16_t con_handle)
return BTM_BleStartExtAdv(true, 1, &ext_adv);
}
/*******************************************************************************
**
** Function BTM_BleGetExtAdvInstByConHandle
**
** Description Map an LE connection handle to the ext-adv instance
** whose adv-set-terminated event reported it.
**
** Returns instance index on success, 0xFF if no match.
**
*******************************************************************************/
UINT8 BTM_BleGetExtAdvInstByConHandle(UINT16 con_handle)
{
if (con_handle == INVALID_VALUE_16BIT) {
return 0xFF;
}
for (UINT8 i = 0; i < MAX_BLE_ADV_INSTANCE; i++) {
/* configured + connetable guard prevents an all-zero slot from
* spuriously matching a real conn_handle == 0. */
if (adv_record[i].ter_con_handle == con_handle &&
extend_adv_cb.inst[i].configured &&
extend_adv_cb.inst[i].connetable) {
return i;
}
}
return 0xFF;
}
/*******************************************************************************
**
** Function btm_ble_clear_ext_adv_ter_con_handle
**
** Description Clear stale ter_con_handle entries when an ACL link goes
** down so a reused connection handle cannot map to the
** wrong ext-adv instance.
**
** Returns void
**
*******************************************************************************/
void btm_ble_clear_ext_adv_ter_con_handle(UINT16 con_handle)
{
con_handle = HCID_GET_HANDLE(con_handle);
for (UINT8 i = 0; i < MAX_BLE_ADV_INSTANCE; i++) {
if (adv_record[i].ter_con_handle == con_handle) {
adv_record[i].ter_con_handle = INVALID_VALUE_16BIT;
}
}
}
tBTM_STATUS BTM_BleExtAdvSetRemove(UINT8 instance)
{
tBTM_STATUS status = BTM_SUCCESS;
@@ -541,6 +606,10 @@ tBTM_STATUS BTM_BleExtAdvSetRemove(UINT8 instance)
extend_adv_cb.inst[instance].directed = false;
extend_adv_cb.inst[instance].scannable = false;
extend_adv_cb.inst[instance].connetable = false;
extend_adv_cb.inst[instance].own_addr_type = BLE_ADDR_PUBLIC;
extend_adv_cb.inst[instance].rand_addr_set = FALSE;
memset(extend_adv_cb.inst[instance].rand_addr, 0, BD_ADDR_LEN);
adv_record[instance].ter_con_handle = INVALID_VALUE_16BIT;
}
end:
@@ -570,6 +639,10 @@ tBTM_STATUS BTM_BleExtAdvSetClear(void)
extend_adv_cb.inst[i].directed = false;
extend_adv_cb.inst[i].scannable = false;
extend_adv_cb.inst[i].connetable = false;
extend_adv_cb.inst[i].own_addr_type = BLE_ADDR_PUBLIC;
extend_adv_cb.inst[i].rand_addr_set = FALSE;
memset(extend_adv_cb.inst[i].rand_addr, 0, BD_ADDR_LEN);
adv_record[i].ter_con_handle = INVALID_VALUE_16BIT;
}
}
@@ -1177,7 +1250,13 @@ void btm_ble_adv_set_terminated_evt(tBTM_BLE_ADV_TERMINAT *params)
// adv terminated due to connection, save the adv handle and connection handle
if(params->status == 0x00) {
adv_record[params->adv_handle].ter_con_handle = params->conn_handle;
/* Store the masked handle to match what btm_ble_conn_complete() looks up. */
adv_record[params->adv_handle].ter_con_handle = HCID_GET_HANDLE(params->conn_handle);
/* Re-run the per-set conn_addr fixup in case this event arrives
* after LE (Enhanced) Connection Complete. */
#if (CONTROLLER_RPA_LIST_ENABLE == TRUE)
btm_ble_adjust_conn_addr_for_ext_adv(adv_record[params->adv_handle].ter_con_handle);
#endif
} else {
adv_record[params->adv_handle].ter_con_handle = INVALID_VALUE_16BIT;
adv_record[params->adv_handle].invalid = false;

View File

@@ -510,6 +510,10 @@ void btm_ble_add_default_entry_to_resolving_list(void);
void btm_ble_set_privacy_mode_complete(UINT8 *p, UINT16 evt_len);
#endif
#if (BLE_50_FEATURE_SUPPORT == TRUE) && (BLE_50_EXTEND_ADV_EN == TRUE) && (CONTROLLER_RPA_LIST_ENABLE == TRUE)
void btm_ble_adjust_conn_addr_for_ext_adv(UINT16 handle);
#endif
char btm_ble_map_adv_tx_power(int tx_power_index);
#if (BLE_TOPOLOGY_CHECK == TRUE)
BOOLEAN btm_ble_topology_check(tBTM_BLE_STATE_MASK request);
@@ -531,6 +535,9 @@ BOOLEAN btm_get_current_conn_params(BD_ADDR bda, UINT16 *interval, UINT16 *laten
#if (BLE_50_FEATURE_SUPPORT == TRUE)
void btm_ble_update_phy_evt(tBTM_BLE_UPDATE_PHY *params);
void btm_ble_scan_timeout_evt(void);
#if (BLE_50_EXTEND_ADV_EN == TRUE)
void btm_ble_clear_ext_adv_ter_con_handle(UINT16 con_handle);
#endif
void btm_ble_adv_set_terminated_evt(tBTM_BLE_ADV_TERMINAT *params);
void btm_ble_ext_adv_report_evt(tBTM_BLE_EXT_ADV_REPORT *params);
void btm_ble_scan_req_received_evt(tBTM_BLE_SCAN_REQ_RECEIVED *params);

View File

@@ -624,6 +624,14 @@ typedef struct {
BOOLEAN directed;
BOOLEAN scannable;
BOOLEAN connetable;
/* Per-set on-air address policy, captured at BTM_BleSetExtendedAdvParams()
* time. For now we only consider CONTROLLER_RPA_LIST_ENABLE == TRUE;
* CONTROLLER_RPA_LIST_ENABLE == FALSE is out of scope temporarily. The global
* addr_mgnt_cb is a single slot shared across all sets, so in multi-ADV
* it does not necessarily reflect the policy used for a given connection. */
tBLE_ADDR_TYPE own_addr_type;
BOOLEAN rand_addr_set;
BD_ADDR rand_addr;
} tBTM_BLE_EXTENDED_INST;
typedef struct {
@@ -631,6 +639,10 @@ typedef struct {
UINT8 scan_duplicate;
} tBTM_BLE_EXTENDED_CB;
/* Defined in btm_ble_5_gap.c. Exposed for per-set address lookup from
* SMP / BTM at LE connection complete. */
extern tBTM_BLE_EXTENDED_CB extend_adv_cb;
#define BTM_BLE_GAP_SET_EXT_ADV_PROP_CONNECTABLE (1 << 0)
#define BTM_BLE_GAP_SET_EXT_ADV_PROP_SCANNABLE (1 << 1)
#define BTM_BLE_GAP_SET_EXT_ADV_PROP_DIRECTED (1 << 2)
@@ -3052,6 +3064,20 @@ tBTM_STATUS BTM_BleExtAdvSetRemove(UINT8 instance);
tBTM_STATUS BTM_BleExtAdvSetClear(void);
/*******************************************************************************
**
** Function BTM_BleGetExtAdvInstByConHandle
**
** Description Map an LE connection handle to the ext-adv instance
** that produced it.
**
** Returns Instance index on success, 0xFF if no match (e.g.
** initiator role or legacy advertising).
**
*******************************************************************************/
UINT8 BTM_BleGetExtAdvInstByConHandle(UINT16 con_handle);
tBTM_STATUS BTM_BlePeriodicAdvSetParams(UINT8 instance, tBTM_BLE_Periodic_Adv_Params *params);
tBTM_STATUS BTM_BlePeriodicAdvCfgDataRaw(UINT8 instance, UINT16 len, UINT8 *data, BOOLEAN only_update_did);

View File

@@ -582,37 +582,89 @@ static BT_HDR *smp_build_identity_info_cmd(UINT8 cmd_code, tSMP_CB *p_cb)
**
** Function smp_build_id_addr_cmd
**
** Description Build identity address information command.
** Description Build SMP Identity Address Information command
** (opcode 0x09). The address distributed here is the
** local device's permanent identity; an on-air RPA must
** never be sent.
**
** In BLE 5.0 multi-ADV, each set has its own
** own_addr_type / Static Random and the global
** addr_mgnt_cb may reflect a different set, so we look
** up the ext-adv instance that produced this connection
** and use ITS per-set state. Fall back to addr_mgnt_cb
** for initiator / legacy advertising paths.
**
*******************************************************************************/
static BT_HDR *smp_build_id_addr_cmd(UINT8 cmd_code, tSMP_CB *p_cb)
{
BT_HDR *p_buf = NULL;
UINT8 *p;
BT_HDR *p_buf = NULL;
UINT8 *p;
tBLE_ADDR_TYPE id_type = BLE_ADDR_PUBLIC;
BD_ADDR id_addr = {0};
UNUSED(cmd_code);
UNUSED(p_cb);
SMP_TRACE_EVENT("smp_build_id_addr_cmd\n");
{
#if (BLE_INCLUDED == TRUE)
tBLE_ADDR_TYPE policy_type = btm_cb.ble_ctr_cb.addr_mgnt_cb.own_addr_type;
const UINT8 *policy_rand = NULL;
BOOLEAN policy_resolved = FALSE;
const BD_ADDR zero = {0};
#if (BLE_50_FEATURE_SUPPORT == TRUE) && (BLE_50_EXTEND_ADV_EN == TRUE) && (CONTROLLER_RPA_LIST_ENABLE == TRUE)
{
tACL_CONN *p_acl = btm_bda_to_acl(p_cb->pairing_bda, BT_TRANSPORT_LE);
if (p_acl != NULL) {
UINT8 inst = BTM_BleGetExtAdvInstByConHandle(p_acl->hci_handle);
if (inst < MAX_BLE_ADV_INSTANCE) {
policy_type = extend_adv_cb.inst[inst].own_addr_type;
/* Only a host-set Static Random may be sent as identity;
* a stack-generated RPA stored in rand_addr must not. */
if (extend_adv_cb.inst[inst].rand_addr_set) {
policy_rand = extend_adv_cb.inst[inst].rand_addr;
}
policy_resolved = TRUE;
}
}
}
#endif /* (BLE_50_FEATURE_SUPPORT == TRUE) && (BLE_50_EXTEND_ADV_EN == TRUE) && (CONTROLLER_RPA_LIST_ENABLE == TRUE) */
if (!policy_resolved) {
if (memcmp(btm_cb.ble_ctr_cb.addr_mgnt_cb.static_rand_addr,
zero, BD_ADDR_LEN) != 0) {
policy_rand = btm_cb.ble_ctr_cb.addr_mgnt_cb.static_rand_addr;
}
}
/* LSB(own_addr_type) selects Public (0) vs Static Random (1).
* If Random is required but unavailable, emit Public rather than
* leak an RPA or send all-zero. */
if ((policy_type & 0x01) && (policy_rand != NULL) && memcmp(policy_rand, zero, BD_ADDR_LEN) != 0) {
id_type = BLE_ADDR_RANDOM;
memcpy(id_addr, policy_rand, BD_ADDR_LEN);
} else if (policy_type & 0x01) {
SMP_TRACE_WARNING("%s: no static rand, fallback public (type=%u)",
__func__, policy_type);
}
#endif ///BLE_INCLUDED == TRUE
if (id_type == BLE_ADDR_PUBLIC) {
memcpy(id_addr,
controller_get_interface()->get_address()->address,
BD_ADDR_LEN);
}
}
if ((p_buf = (BT_HDR *)osi_malloc(sizeof(BT_HDR) + SMP_ID_ADDR_SIZE + L2CAP_MIN_OFFSET)) != NULL) {
p = (UINT8 *)(p_buf + 1) + L2CAP_MIN_OFFSET;
UINT8_TO_STREAM (p, SMP_OPCODE_ID_ADDR);
/* Identity Address Information is used in the Transport Specific Key Distribution phase to distribute
its public device address or static random address. if slave using static random address is encrypted,
it should distribute its static random address */
#if (BLE_INCLUDED == TRUE)
if(btm_cb.ble_ctr_cb.addr_mgnt_cb.own_addr_type == BLE_ADDR_RANDOM && memcmp(btm_cb.ble_ctr_cb.addr_mgnt_cb.static_rand_addr, btm_cb.ble_ctr_cb.addr_mgnt_cb.private_addr,6) == 0) {
UINT8_TO_STREAM (p, 0x01);
BDADDR_TO_STREAM (p, btm_cb.ble_ctr_cb.addr_mgnt_cb.static_rand_addr);
} else
#endif ///BLE_INCLUDED == TRUE
{
UINT8_TO_STREAM (p, 0);
BDADDR_TO_STREAM (p, controller_get_interface()->get_address()->address);
}
UINT8_TO_STREAM(p, SMP_OPCODE_ID_ADDR);
UINT8_TO_STREAM(p, id_type);
BDADDR_TO_STREAM(p, id_addr);
p_buf->offset = L2CAP_MIN_OFFSET;
p_buf->len = SMP_ID_ADDR_SIZE;
p_buf->len = SMP_ID_ADDR_SIZE;
}
return p_buf;