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.
This commit is contained in:
luoxu
2025-12-11 21:02:34 +08:00
committed by BLE BOT
parent e703935a89
commit ca408103fa
4 changed files with 38 additions and 23 deletions
+6 -2
View File
@@ -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;
+19 -15
View File
@@ -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);
+3 -3
View File
@@ -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);
+10 -3
View File
@@ -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));