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:
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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));
|
||||
|
||||
|
||||
Reference in New Issue
Block a user