From 613630a49643c592033417bd7581aa3acf39b695 Mon Sep 17 00:00:00 2001 From: Matthias Ringwald Date: Thu, 6 Mar 2025 15:35:50 +0100 Subject: [PATCH] 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 --- CHANGELOG.md | 3 ++- src/ble/sm.c | 19 +++++++++++++------ src/hci.c | 6 +++--- src/hci.h | 1 + 4 files changed, 19 insertions(+), 10 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0d1aeb5f8..e58c59b0d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -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 diff --git a/src/ble/sm.c b/src/ble/sm.c index 7b2892672..a2eee0a91 100644 --- a/src/ble/sm.c +++ b/src/ble/sm.c @@ -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); } diff --git a/src/hci.c b/src/hci.c index 93bb8cc47..330683f67 100644 --- a/src/hci.c +++ b/src/hci.c @@ -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; diff --git a/src/hci.h b/src/hci.h index e3d665f43..7aee204b5 100644 --- a/src/hci.h +++ b/src/hci.h @@ -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; //