sm: fix pairing in peripheral role for non-identity address type

if extended advertising is supported and LE Set Terminated is received before connection event, null address was used
This commit is contained in:
Matthias Ringwald 2025-03-06 15:35:50 +01:00
parent 7bab55ed9a
commit 613630a496
4 changed files with 19 additions and 10 deletions

View File

@ -20,7 +20,8 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
### Fixed
- GAP: store link key for standard/non-SSP pairing
- BENP: emit channel opened with ERROR_CODE_REMOTE_USER_TERMINATED_CONNECTION if connection cannot be set up
- SM: fix pairing as Peripheral with Extended Advertising and LE Advertisement Set Terminated after Connection Complete
- BNEP: emit channel opened with ERROR_CODE_REMOTE_USER_TERMINATED_CONNECTION if connection cannot be set up
- HFP AG: avoid recursion with synchronous HCI transport
- HFP HF: send Apple Accessory information after service level connection

View File

@ -3986,10 +3986,13 @@ static void sm_event_packet_handler (uint8_t packet_type, uint16_t channel, uint
// responder - use own address from advertisements
#ifdef ENABLE_LE_EXTENDED_ADVERTISING
if (hci_le_extended_advertising_supported()){
// cache local resolvable address
// note: will be overwritten if random or private address was used in adv set by HCI_SUBEVENT_LE_ADVERTISING_SET_TERMINATED
sm_conn->sm_own_addr_type = BD_ADDR_TYPE_LE_RANDOM;
gap_subevent_le_connection_complete_get_local_resolvable_private_address(packet,sm_conn->sm_own_address);
// store resolved address if received set terminated and used identity address
// cache resolved address if we haven't received set terminated yet and don't what address types was used
if ((sm_conn->sm_advertising_set_terminated_received == false) || hci_is_le_identity_address_type(sm_conn->sm_own_addr_type)){
sm_conn->sm_own_addr_type = BD_ADDR_TYPE_LE_RANDOM;
gap_subevent_le_connection_complete_get_local_resolvable_private_address(packet,sm_conn->sm_own_address);
log_info("Cache local resolvable private address %s", bd_addr_to_str(sm_conn->sm_own_address));
}
} else
#endif
{
@ -4020,8 +4023,12 @@ static void sm_event_packet_handler (uint8_t packet_type, uint16_t channel, uint
con_handle = hci_subevent_le_advertising_set_terminated_get_connection_handle(packet);
sm_conn = sm_get_connection_for_handle(con_handle);
if (!sm_conn) break;
gap_le_get_own_advertising_set_address(&sm_conn->sm_own_addr_type, sm_conn->sm_own_address, advertising_handle);
sm_conn->sm_advertising_set_terminated_received = true;
uint8_t addr_type = BD_ADDR_TYPE_UNKNOWN;
gap_le_get_own_advertising_set_address(&addr_type, sm_conn->sm_own_address, advertising_handle);
if (hci_is_le_identity_address_type(addr_type) == false) {
sm_conn->sm_own_addr_type = addr_type;
}
log_info("Adv set %u terminated -> use addr type %u, addr %s for con handle 0x%04x", advertising_handle, sm_conn->sm_own_addr_type,
bd_addr_to_str(sm_conn->sm_own_address), con_handle);
}

View File

@ -1520,18 +1520,18 @@ void gap_le_get_own_advertising_set_address(uint8_t * addr_type, bd_addr_t addr,
} else {
le_advertising_set_t * advertising_set = hci_advertising_set_for_handle(advertising_handle);
if (advertising_set != NULL){
*addr_type = advertising_set->extended_params.own_address_type;
switch (advertising_set->extended_params.own_address_type){
case BD_ADDR_TYPE_LE_PUBLIC:
*addr_type = BD_ADDR_TYPE_LE_PUBLIC;
memcpy(addr, hci_stack->local_bd_addr, 6);
break;
case BD_ADDR_TYPE_LE_RANDOM:
*addr_type = BD_ADDR_TYPE_LE_RANDOM;
memcpy(addr, advertising_set->random_address, 6);
break;
case BD_ADDR_TYPE_LE_PUBLIC_IDENTITY:
case BD_ADDR_TYPE_LE_RANDOM_IDENTITY:
// do nothing as random address was already set from enhanced connection complete
// don't know current randomg address generated by Controller
// only set addr type here and wait for LE Set Terminated event to get current random address
break;
default:
break;

View File

@ -469,6 +469,7 @@ typedef struct sm_connection {
int sm_le_db_index;
bool sm_pairing_active;
bool sm_reencryption_active;
bool sm_advertising_set_terminated_received;
} sm_connection_t;
//