diff --git a/subsys/bluetooth/mesh/cfg_srv.c b/subsys/bluetooth/mesh/cfg_srv.c index 95b8bf494ee..652b8d0bc57 100644 --- a/subsys/bluetooth/mesh/cfg_srv.c +++ b/subsys/bluetooth/mesh/cfg_srv.c @@ -2622,6 +2622,8 @@ static void node_reset(struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, struct net_buf_simple *buf) { + static struct bt_mesh_proxy_idle_cb proxy_idle = {.cb = bt_mesh_reset}; + BT_MESH_MODEL_BUF_DEFINE(msg, OP_NODE_RESET_STATUS, 0); BT_DBG("net_idx 0x%04x app_idx 0x%04x src 0x%04x len %u: %s", @@ -2638,7 +2640,15 @@ static void node_reset(struct bt_mesh_model *model, BT_ERR("Unable to send Node Reset Status"); } - bt_mesh_reset(); + if (!IS_ENABLED(CONFIG_BT_MESH_GATT_PROXY)) { + bt_mesh_reset(); + return; + } + + /* If the response goes to a proxy node, we'll wait for the sending to + * complete before moving on. + */ + bt_mesh_proxy_on_idle(&proxy_idle); } static void send_friend_status(struct bt_mesh_model *model, diff --git a/subsys/bluetooth/mesh/proxy.c b/subsys/bluetooth/mesh/proxy.c index 5ba610f06c9..c1385b75ee9 100644 --- a/subsys/bluetooth/mesh/proxy.c +++ b/subsys/bluetooth/mesh/proxy.c @@ -103,6 +103,8 @@ static struct bt_mesh_proxy_client { }, }; +static sys_slist_t idle_waiters; +static atomic_t pending_notifications; static uint8_t __noinit client_buf_data[CLIENT_BUF_SIZE * CONFIG_BT_MAX_CONN]; /* Track which service is enabled */ @@ -921,23 +923,54 @@ bool bt_mesh_proxy_relay(struct net_buf_simple *buf, uint16_t dst) #endif /* CONFIG_BT_MESH_GATT_PROXY */ -static int proxy_send(struct bt_conn *conn, const void *data, uint16_t len) +static void notify_complete(struct bt_conn *conn, void *user_data) { + sys_snode_t *n; + + if (atomic_dec(&pending_notifications) > 1) { + return; + } + + BT_DBG(""); + + while ((n = sys_slist_get(&idle_waiters))) { + CONTAINER_OF(n, struct bt_mesh_proxy_idle_cb, n)->cb(); + } +} + +static int proxy_send(struct bt_conn *conn, const void *data, + uint16_t len) +{ + struct bt_gatt_notify_params params = { + .data = data, + .len = len, + .func = notify_complete, + }; + int err; + BT_DBG("%u bytes: %s", len, bt_hex(data, len)); #if defined(CONFIG_BT_MESH_GATT_PROXY) if (gatt_svc == MESH_GATT_PROXY) { - return bt_gatt_notify(conn, &proxy_attrs[3], data, len); + params.attr = &proxy_attrs[3]; } #endif - #if defined(CONFIG_BT_MESH_PB_GATT) if (gatt_svc == MESH_GATT_PROV) { - return bt_gatt_notify(conn, &prov_attrs[3], data, len); + params.attr = &prov_attrs[3]; } #endif - return 0; + if (!params.attr) { + return 0; + } + + err = bt_gatt_notify_cb(conn, ¶ms); + if (!err) { + atomic_inc(&pending_notifications); + } + + return err; } static int proxy_segment_and_send(struct bt_conn *conn, uint8_t type, @@ -1320,3 +1353,13 @@ int bt_mesh_proxy_init(void) return 0; } + +void bt_mesh_proxy_on_idle(struct bt_mesh_proxy_idle_cb *cb) +{ + if (!atomic_get(&pending_notifications)) { + cb->cb(); + return; + } + + sys_slist_append(&idle_waiters, &cb->n); +} diff --git a/subsys/bluetooth/mesh/proxy.h b/subsys/bluetooth/mesh/proxy.h index 6bc01241231..d0f20f29ede 100644 --- a/subsys/bluetooth/mesh/proxy.h +++ b/subsys/bluetooth/mesh/proxy.h @@ -11,6 +11,12 @@ #define BT_MESH_PROXY_CONFIG 0x02 #define BT_MESH_PROXY_PROV 0x03 + +struct bt_mesh_proxy_idle_cb { + sys_snode_t n; + void (*cb)(void); +}; + int bt_mesh_proxy_send(struct bt_conn *conn, uint8_t type, struct net_buf_simple *msg); @@ -35,3 +41,4 @@ bool bt_mesh_proxy_relay(struct net_buf_simple *buf, uint16_t dst); void bt_mesh_proxy_addr_add(struct net_buf_simple *buf, uint16_t addr); int bt_mesh_proxy_init(void); +void bt_mesh_proxy_on_idle(struct bt_mesh_proxy_idle_cb *cb);