Bluetooth: Mesh: Wait for proxy on node reset

Adds idle wait callback to proxy by counting the number of pending
notifications.

Ensures that all connected nodes have received messages before resetting
the mesh stack.

Signed-off-by: Trond Einar Snekvik <Trond.Einar.Snekvik@nordicsemi.no>
This commit is contained in:
Trond Einar Snekvik 2020-07-06 14:09:16 +02:00 committed by Carles Cufí
commit cb7835d18f
3 changed files with 66 additions and 6 deletions

View file

@ -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,

View file

@ -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, &params);
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);
}

View file

@ -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);