From 4ffd7b285b889f00a63ef36413a4c9b4f56f0160 Mon Sep 17 00:00:00 2001 From: zhanghaipeng Date: Mon, 1 Dec 2025 10:48:13 +0800 Subject: [PATCH] feat(ble/bluedroid): add periodic advertising create sync retry mechanism --- components/bt/host/bluedroid/Kconfig.in | 10 +++ .../include/common/bluedroid_user_config.h | 6 ++ .../common/include/common/bt_target.h | 6 ++ .../host/bluedroid/stack/btm/btm_ble_5_gap.c | 70 ++++++++++++++++++- 4 files changed, 91 insertions(+), 1 deletion(-) diff --git a/components/bt/host/bluedroid/Kconfig.in b/components/bt/host/bluedroid/Kconfig.in index 2bd78f05f1..95efdcb9e8 100644 --- a/components/bt/host/bluedroid/Kconfig.in +++ b/components/bt/host/bluedroid/Kconfig.in @@ -1400,6 +1400,16 @@ config BT_BLE_FEAT_CREATE_SYNC_ENH help Enable the create sync enhancements +config BT_BLE_FEAT_CREATE_SYNC_RETRY_MAX + int "Maximum retry count for periodic advertising create sync" + depends on BT_BLE_50_EXTEND_SYNC_EN + default 3 + range 0 16 + help + Set the maximum retry count when periodic advertising create sync fails + with error code 0x3E (Connection Failed to be Established). + Set to 0 to disable retry. Default is 3. + menuconfig BT_BLE_FEAT_ISO_EN bool "Enable BLE 5.2 iso feature" depends on (BT_BLE_50_FEATURES_SUPPORTED && ((BT_CONTROLLER_ENABLED && SOC_BLE_AUDIO_SUPPORTED) || BT_CONTROLLER_DISABLED)) # NOERROR diff --git a/components/bt/host/bluedroid/common/include/common/bluedroid_user_config.h b/components/bt/host/bluedroid/common/include/common/bluedroid_user_config.h index 70e967b44b..e1d1ad7c9c 100644 --- a/components/bt/host/bluedroid/common/include/common/bluedroid_user_config.h +++ b/components/bt/host/bluedroid/common/include/common/bluedroid_user_config.h @@ -278,6 +278,12 @@ #define UC_BT_BLE_FEAT_CREATE_SYNC_ENH FALSE #endif +#ifdef CONFIG_BT_BLE_FEAT_CREATE_SYNC_RETRY_MAX +#define UC_BT_BLE_FEAT_CREATE_SYNC_RETRY_MAX CONFIG_BT_BLE_FEAT_CREATE_SYNC_RETRY_MAX +#else +#define UC_BT_BLE_FEAT_CREATE_SYNC_RETRY_MAX 3 +#endif + #ifdef CONFIG_BT_BLE_FEAT_ISO_EN #define UC_BT_BLE_FEAT_ISO_EN CONFIG_BT_BLE_FEAT_ISO_EN #else diff --git a/components/bt/host/bluedroid/common/include/common/bt_target.h b/components/bt/host/bluedroid/common/include/common/bt_target.h index 412ca9dd06..9f485851ef 100644 --- a/components/bt/host/bluedroid/common/include/common/bt_target.h +++ b/components/bt/host/bluedroid/common/include/common/bt_target.h @@ -319,6 +319,12 @@ #define BLE_FEAT_CREATE_SYNC_ENH FALSE #endif +#ifdef UC_BT_BLE_FEAT_CREATE_SYNC_RETRY_MAX +#define BLE_FEAT_CREATE_SYNC_RETRY_MAX UC_BT_BLE_FEAT_CREATE_SYNC_RETRY_MAX +#else +#define BLE_FEAT_CREATE_SYNC_RETRY_MAX 3 +#endif + #if (UC_BT_BLE_FEAT_ISO_EN == TRUE) #define BLE_FEAT_ISO_EN TRUE #else diff --git a/components/bt/host/bluedroid/stack/btm/btm_ble_5_gap.c b/components/bt/host/bluedroid/stack/btm/btm_ble_5_gap.c index b87c9d35f6..a302890699 100644 --- a/components/bt/host/bluedroid/stack/btm/btm_ble_5_gap.c +++ b/components/bt/host/bluedroid/stack/btm/btm_ble_5_gap.c @@ -38,6 +38,19 @@ typedef struct { tBTM_EXT_ADV_RECORD adv_record[MAX_BLE_ADV_INSTANCE] = {0}; #endif // #if (BLE_50_EXTEND_ADV_EN == TRUE) +#if (BLE_50_EXTEND_SYNC_EN == TRUE) +#if (BLE_FEAT_CREATE_SYNC_RETRY_MAX > 0) +/* Create sync retry control block */ +typedef struct { + bool in_use; /* Whether sync creation is in progress */ + uint8_t retry_count; /* Current retry count */ + tBTM_BLE_Periodic_Sync_Params params; /* Saved sync parameters for retry */ +} tBTM_BLE_SYNC_RETRY_CB; + +static tBTM_BLE_SYNC_RETRY_CB sync_retry_cb = {0}; +#endif // #if (BLE_FEAT_CREATE_SYNC_RETRY_MAX > 0) +#endif // #if (BLE_50_EXTEND_SYNC_EN == TRUE) + extern void btm_ble_inter_set(bool extble_inter); #if !UC_BT_STACK_NO_LOG @@ -879,11 +892,19 @@ tBTM_STATUS BTM_BlePeriodicAdvCreateSync(tBTM_BLE_Periodic_Sync_Params *params) SET_BIT(option, 2); } #endif // (BLE_FEAT_CREATE_SYNC_ENH == TRUE) - +#if (BLE_FEAT_CREATE_SYNC_RETRY_MAX > 0) + /* Save parameters for potential retry */ + memcpy(&sync_retry_cb.params, params, sizeof(tBTM_BLE_Periodic_Sync_Params)); + sync_retry_cb.retry_count = 0; + sync_retry_cb.in_use = true; +#endif // #if (BLE_FEAT_CREATE_SYNC_RETRY_MAX > 0) if (!btsnd_hcic_ble_periodic_adv_create_sync(option, params->sid, params->addr_type, params->addr, params->sync_timeout, params->sync_cte_type)) { BTM_TRACE_ERROR("LE PA CreateSync cmd failed"); status = BTM_ILLEGAL_VALUE; +#if (BLE_FEAT_CREATE_SYNC_RETRY_MAX > 0) + sync_retry_cb.in_use = false; +#endif // #if (BLE_FEAT_CREATE_SYNC_RETRY_MAX > 0) } end: @@ -941,6 +962,11 @@ tBTM_STATUS BTM_BlePeriodicAdvSyncCancel(void) tBTM_STATUS status = BTM_SUCCESS; tBTM_BLE_5_GAP_CB_PARAMS cb_params = {0}; +#if (BLE_FEAT_CREATE_SYNC_RETRY_MAX > 0) + /* Clear retry state when sync is cancelled */ + sync_retry_cb.in_use = false; + sync_retry_cb.retry_count = 0; +#endif // #if (BLE_FEAT_CREATE_SYNC_RETRY_MAX > 0) if ((err = btsnd_hcic_ble_periodic_adv_create_sync_cancel()) != HCI_SUCCESS) { BTM_TRACE_ERROR("LE PA SyncCancel, cmd err=0x%x", err); status = BTM_HCI_ERROR | err; @@ -1398,6 +1424,48 @@ void btm_ble_periodic_adv_sync_establish_evt(tBTM_BLE_PERIOD_ADV_SYNC_ESTAB *par return; } +#if (BLE_FEAT_CREATE_SYNC_RETRY_MAX > 0) + /* Check if retry is needed for error 0x3E (Connection Failed to be Established) */ + if (params->status == HCI_ERR_CONN_FAILED_ESTABLISHMENT && + sync_retry_cb.in_use && + sync_retry_cb.retry_count < BLE_FEAT_CREATE_SYNC_RETRY_MAX) { + + sync_retry_cb.retry_count++; + BTM_TRACE_WARNING("%s, Create sync failed with 0x3E, retry %d/%d", + __func__, sync_retry_cb.retry_count, BLE_FEAT_CREATE_SYNC_RETRY_MAX); + + /* Build option from saved parameters */ + uint8_t option = 0x00; + if (sync_retry_cb.params.filter_policy) { + SET_BIT(option, 0); + } +#if (BLE_FEAT_CREATE_SYNC_ENH == TRUE) + if (sync_retry_cb.params.reports_disabled) { + SET_BIT(option, 1); + } + if (sync_retry_cb.params.filter_duplicates) { + SET_BIT(option, 2); + } +#endif // (BLE_FEAT_CREATE_SYNC_ENH == TRUE) + + /* Retry create sync with saved parameters */ + if (btsnd_hcic_ble_periodic_adv_create_sync(option, + sync_retry_cb.params.sid, + sync_retry_cb.params.addr_type, + sync_retry_cb.params.addr, + sync_retry_cb.params.sync_timeout, + sync_retry_cb.params.sync_cte_type)) { + /* Retry command sent successfully, wait for next event */ + return; + } + /* If retry command failed, fall through to report failure */ + BTM_TRACE_ERROR("%s, Retry create sync command failed", __func__); + } + + /* Clear retry state */ + sync_retry_cb.in_use = false; + sync_retry_cb.retry_count = 0; +#endif // #if (BLE_FEAT_CREATE_SYNC_RETRY_MAX > 0) memcpy(&cb_params.sync_estab, params, sizeof(tBTM_BLE_PERIOD_ADV_SYNC_ESTAB)); // If the user has register the callback function, should callback it to the application.