From ca408103faf61f4e9fdf8848bed33f5317890ef4 Mon Sep 17 00:00:00 2001 From: luoxu Date: Thu, 11 Dec 2025 21:02:34 +0800 Subject: [PATCH] fix(ble_mesh): Fix start callback timing when GATT and ADV bearers coexist Add BLE_MESH_SEND_START_CB macro to ensure start callback is called exactly once when both GATT and ADV bearers are used. --- components/bt/esp_ble_mesh/core/adv.c | 8 +++-- components/bt/esp_ble_mesh/core/adv_common.h | 34 +++++++++++--------- components/bt/esp_ble_mesh/core/ext_adv.c | 6 ++-- components/bt/esp_ble_mesh/core/net.c | 13 ++++++-- 4 files changed, 38 insertions(+), 23 deletions(-) diff --git a/components/bt/esp_ble_mesh/core/adv.c b/components/bt/esp_ble_mesh/core/adv.c index 9a12e8c125..e35d34c993 100644 --- a/components/bt/esp_ble_mesh/core/adv.c +++ b/components/bt/esp_ble_mesh/core/adv.c @@ -42,6 +42,7 @@ static int adv_send(struct net_buf *buf) uint8_t adv_cnt = 0; struct bt_mesh_adv_data ad = {0}; int err = 0; + bool start_cb_called = (BLE_MESH_ADV(buf)->flags & BLE_MESH_ADV_FLAG_SKIP_START_CB); BT_DBG("LegacyAdvSend, Type %u", BLE_MESH_ADV(buf)->type); BT_DBG("Len %u: %s", buf->len, bt_hex(buf->data, buf->len)); @@ -175,7 +176,10 @@ static int adv_send(struct net_buf *buf) net_buf_unref(buf); - adv_send_start(duration, err, cb, cb_data); + if (!start_cb_called && cb && cb->start) { + cb->start(duration, err, cb_data); + } + if (err) { BT_ERR("Start advertising failed: err %d", err); return err; @@ -194,7 +198,7 @@ static int adv_send(struct net_buf *buf) err = bt_le_adv_stop(); #endif /* CONFIG_BLE_MESH_USE_BLE_50 */ - adv_send_end(err, cb, cb_data); + BLE_MESH_SEND_END_CB(err, cb, cb_data); if (err) { BT_ERR("Stop advertising failed: err %d", err); return 0; diff --git a/components/bt/esp_ble_mesh/core/adv_common.h b/components/bt/esp_ble_mesh/core/adv_common.h index 54267ee522..d7810c94d0 100644 --- a/components/bt/esp_ble_mesh/core/adv_common.h +++ b/components/bt/esp_ble_mesh/core/adv_common.h @@ -48,6 +48,9 @@ extern "C" { #define BLE_MESH_ADV_INST_UNUSED 0xFF +/* Flags for struct bt_mesh_adv */ +#define BLE_MESH_ADV_FLAG_SKIP_START_CB BIT(0) /* Skip start callback (already called by GATT) */ + struct bt_mesh_adv { const struct bt_mesh_send_cb *cb; void *cb_data; @@ -61,6 +64,7 @@ struct bt_mesh_adv { uint32_t adv_itvl; uint8_t adv_cnt; uint8_t channel_map; + uint8_t flags; /* See BLE_MESH_ADV_FLAG_* */ }; #if CONFIG_BLE_MESH_USE_BLE_50 @@ -214,22 +218,22 @@ static inline TickType_t K_WAIT(int32_t val) return (val == K_FOREVER) ? portMAX_DELAY : (val / portTICK_PERIOD_MS); } -static inline void adv_send_start(uint16_t duration, int err, - const struct bt_mesh_send_cb *cb, - void *cb_data) -{ - if (cb && cb->start) { - cb->start(duration, err, cb_data); - } -} +#define BLE_MESH_SEND_START_CB(_buf, _duration, _err, _cb, _cb_data) \ + do { \ + if (!(BLE_MESH_ADV(_buf)->flags & BLE_MESH_ADV_FLAG_SKIP_START_CB)) { \ + if ((_cb) && (_cb)->start) { \ + (_cb)->start((_duration), (_err), (_cb_data)); \ + } \ + BLE_MESH_ADV(_buf)->flags |= BLE_MESH_ADV_FLAG_SKIP_START_CB; \ + } \ + } while (0) -static inline void adv_send_end(int err, const struct bt_mesh_send_cb *cb, - void *cb_data) -{ - if (cb && cb->end) { - cb->end(err, cb_data); - } -} +#define BLE_MESH_SEND_END_CB(_err, _cb, _cb_data) \ + do { \ + if ((_cb) && (_cb)->end) { \ + (_cb)->end((_err), (_cb_data)); \ + } \ + } while (0) struct bt_mesh_adv_queue *bt_mesh_adv_queue_get(void); diff --git a/components/bt/esp_ble_mesh/core/ext_adv.c b/components/bt/esp_ble_mesh/core/ext_adv.c index 8b85076aed..c4feaa7a4e 100644 --- a/components/bt/esp_ble_mesh/core/ext_adv.c +++ b/components/bt/esp_ble_mesh/core/ext_adv.c @@ -181,7 +181,7 @@ static int adv_send(struct bt_mesh_adv_inst *inst, uint16_t *adv_duration) break; } - adv_send_start(duration, err, cb, cb_data); + BLE_MESH_SEND_START_CB(buf, duration, err, cb, cb_data); if (err) { BT_ERR("Start advertising failed: err %d", err); return err; @@ -381,8 +381,8 @@ static uint32_t received_adv_evts_handle(uint32_t recv_evts) } else #endif { - adv_send_end(0, BLE_MESH_ADV(adv_insts[i].sending_buf)->cb, - BLE_MESH_ADV(adv_insts[i].sending_buf)->cb_data); + BLE_MESH_SEND_END_CB(0, BLE_MESH_ADV(adv_insts[i].sending_buf)->cb, + BLE_MESH_ADV(adv_insts[i].sending_buf)->cb_data); bt_mesh_adv_buf_ref_debug(__func__, adv_insts[i].sending_buf, 4U, BLE_MESH_BUF_REF_SMALL); diff --git a/components/bt/esp_ble_mesh/core/net.c b/components/bt/esp_ble_mesh/core/net.c index fde5b5cdda..b436ce5d6b 100644 --- a/components/bt/esp_ble_mesh/core/net.c +++ b/components/bt/esp_ble_mesh/core/net.c @@ -1239,6 +1239,15 @@ int bt_mesh_net_send(struct bt_mesh_net_tx *tx, struct net_buf *buf, send_cb = NULL; goto done; } + + /* GATT bearer sends faster than ADV bearer, so the remote node + * may receive the message and respond before ADV bearer starts. + * To avoid issues where the start callback hasn't been called + * when the response arrives, we call the start callback here + * immediately after GATT bearer sends successfully. The ADV + * bearer will skip start callback since the flag is set. + */ + BLE_MESH_SEND_START_CB(buf, 0, 0, send_cb, cb_data); } } #endif /* CONFIG_BLE_MESH_GATT_PROXY_CLIENT */ @@ -1253,9 +1262,7 @@ int bt_mesh_net_send(struct bt_mesh_net_tx *tx, struct net_buf *buf, * See BLEMESH24-76 for more details. */ if (BLE_MESH_ADDR_IS_UNICAST(tx->ctx->addr)) { - if (send_cb && send_cb->start) { - send_cb->start(0, 0, cb_data); - } + BLE_MESH_SEND_START_CB(buf, 0, 0, send_cb, cb_data); net_buf_slist_put(&bt_mesh.local_queue, net_buf_ref(buf));