diff --git a/subsys/bluetooth/mesh/cfg_srv.c b/subsys/bluetooth/mesh/cfg_srv.c index 475c16f4db5..f2ef207f55f 100644 --- a/subsys/bluetooth/mesh/cfg_srv.c +++ b/subsys/bluetooth/mesh/cfg_srv.c @@ -1970,11 +1970,27 @@ send_list: } } +static void reset_send_start(uint16_t duration, int err, void *cb_data) +{ + if (err) { + BT_ERR("Sending Node Reset Status failed (err %d)", err); + bt_mesh_reset(); + } +} + +static void reset_send_end(int err, void *cb_data) +{ + bt_mesh_reset(); +} + 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}; + static const struct bt_mesh_send_cb reset_cb = { + .start = reset_send_start, + .end = reset_send_end, + }; BT_MESH_MODEL_BUF_DEFINE(msg, OP_NODE_RESET_STATUS, 0); @@ -1982,25 +1998,11 @@ static void node_reset(struct bt_mesh_model *model, ctx->net_idx, ctx->app_idx, ctx->addr, buf->len, bt_hex(buf->data, buf->len)); - bt_mesh_model_msg_init(&msg, OP_NODE_RESET_STATUS); - /* Send the response first since we wont have any keys left to - * send it later. - */ - if (bt_mesh_model_send(model, ctx, &msg, NULL, NULL)) { + if (bt_mesh_model_send(model, ctx, &msg, &reset_cb, NULL)) { BT_ERR("Unable to send Node Reset Status"); } - - 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/net.c b/subsys/bluetooth/mesh/net.c index ce41640e694..83754127f60 100644 --- a/subsys/bluetooth/mesh/net.c +++ b/subsys/bluetooth/mesh/net.c @@ -530,12 +530,13 @@ int bt_mesh_net_send(struct bt_mesh_net_tx *tx, struct net_buf *buf, goto done; } + BT_MESH_ADV(buf)->cb = cb; + BT_MESH_ADV(buf)->cb_data = cb_data; + /* Deliver to GATT Proxy Clients if necessary. */ if (IS_ENABLED(CONFIG_BT_MESH_GATT_PROXY) && - bt_mesh_proxy_relay(&buf->b, tx->ctx->addr) && + bt_mesh_proxy_relay(buf, tx->ctx->addr) && BT_MESH_ADDR_IS_UNICAST(tx->ctx->addr)) { - /* Notify completion if this only went through the Mesh Proxy */ - send_cb_finalize(cb, cb_data); err = 0; goto done; @@ -702,7 +703,7 @@ static void bt_mesh_net_relay(struct net_buf_simple *sbuf, if (IS_ENABLED(CONFIG_BT_MESH_GATT_PROXY) && (rx->friend_cred || bt_mesh_gatt_proxy_get() == BT_MESH_GATT_PROXY_ENABLED)) { - bt_mesh_proxy_relay(&buf->b, rx->ctx.recv_dst); + bt_mesh_proxy_relay(buf, rx->ctx.recv_dst); } if (relay_to_adv(rx->net_if) || rx->friend_cred) { diff --git a/subsys/bluetooth/mesh/pb_gatt.c b/subsys/bluetooth/mesh/pb_gatt.c index e591b7abe17..43028c24296 100644 --- a/subsys/bluetooth/mesh/pb_gatt.c +++ b/subsys/bluetooth/mesh/pb_gatt.c @@ -17,10 +17,16 @@ #define LOG_MODULE_NAME bt_mesh_pb_gatt #include "common/log.h" +struct prov_bearer_send_cb { + prov_bearer_send_complete_t cb; + void *cb_data; +}; + struct prov_link { struct bt_conn *conn; const struct prov_bearer_cb *cb; void *cb_data; + struct prov_bearer_send_cb comp; struct net_buf_simple *rx_buf; struct k_work_delayable prot_timer; }; @@ -123,6 +129,13 @@ static int link_accept(const struct prov_bearer_cb *cb, void *cb_data) return 0; } +static void buf_send_end(struct bt_conn *conn, void *user_data) +{ + if (link.comp.cb) { + link.comp.cb(0, link.comp.cb_data); + } +} + static int buf_send(struct net_buf_simple *buf, prov_bearer_send_complete_t cb, void *cb_data) { @@ -130,9 +143,12 @@ static int buf_send(struct net_buf_simple *buf, prov_bearer_send_complete_t cb, return -ENOTCONN; } + link.comp.cb = cb; + link.comp.cb_data = cb_data; + k_work_reschedule(&link.prot_timer, PROTOCOL_TIMEOUT); - return bt_mesh_proxy_send(link.conn, BT_MESH_PROXY_PROV, buf); + return bt_mesh_pb_gatt_send(link.conn, buf, buf_send_end, NULL); } static void clear_tx(void) diff --git a/subsys/bluetooth/mesh/proxy.c b/subsys/bluetooth/mesh/proxy.c index dce08402337..6630b34f5b6 100644 --- a/subsys/bluetooth/mesh/proxy.c +++ b/subsys/bluetooth/mesh/proxy.c @@ -114,8 +114,6 @@ 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 */ @@ -163,7 +161,8 @@ static void proxy_sar_timeout(struct k_work *work) static struct bt_mesh_subnet *beacon_sub; static int proxy_segment_and_send(struct bt_conn *conn, uint8_t type, - struct net_buf_simple *msg); + struct net_buf_simple *msg, + bt_gatt_complete_func_t end, void *user_data); static int filter_set(struct bt_mesh_proxy_client *client, struct net_buf_simple *buf) @@ -279,7 +278,8 @@ static void send_filter_status(struct bt_mesh_proxy_client *client, return; } - err = proxy_segment_and_send(client->conn, BT_MESH_PROXY_CONFIG, buf); + err = proxy_segment_and_send(client->conn, BT_MESH_PROXY_CONFIG, buf, + NULL, NULL); if (err) { BT_ERR("Failed to send proxy cfg message (err %d)", err); } @@ -354,7 +354,7 @@ static int beacon_send(struct bt_conn *conn, struct bt_mesh_subnet *sub) net_buf_simple_reserve(&buf, 1); bt_mesh_beacon_create(sub, &buf); - return proxy_segment_and_send(conn, BT_MESH_PROXY_BEACON, &buf); + return proxy_segment_and_send(conn, BT_MESH_PROXY_BEACON, &buf, NULL, NULL); } static int send_beacon_cb(struct bt_mesh_subnet *sub, void *cb_data) @@ -913,10 +913,17 @@ static bool client_filter_match(struct bt_mesh_proxy_client *client, return false; } -bool bt_mesh_proxy_relay(struct net_buf_simple *buf, uint16_t dst) +static void buf_send_end(struct bt_conn *conn, void *user_data) +{ + struct net_buf *buf = user_data; + + net_buf_unref(buf); +} + +bool bt_mesh_proxy_relay(struct net_buf *buf, uint16_t dst) { bool relayed = false; - int i; + int i, err; BT_DBG("%u bytes to dst 0x%04x", buf->len, dst); @@ -932,13 +939,26 @@ bool bt_mesh_proxy_relay(struct net_buf_simple *buf, uint16_t dst) continue; } + if (client->filter_type == PROV) { + BT_ERR("Invalid PDU type for Proxy Client"); + return -EINVAL; + } + /* Proxy PDU sending modifies the original buffer, * so we need to make a copy. */ net_buf_simple_reserve(&msg, 1); net_buf_simple_add_mem(&msg, buf->data, buf->len); - bt_mesh_proxy_send(client->conn, BT_MESH_PROXY_NET_PDU, &msg); + err = proxy_segment_and_send(client->conn, BT_MESH_PROXY_NET_PDU, + &msg, buf_send_end, net_buf_ref(buf)); + + bt_mesh_adv_send_start(0, err, BT_MESH_ADV(buf)); + if (err) { + BT_ERR("Failed to send proxy message (err %d)", err); + continue; + } + relayed = true; } @@ -947,58 +967,42 @@ bool bt_mesh_proxy_relay(struct net_buf_simple *buf, uint16_t dst) #endif /* CONFIG_BT_MESH_GATT_PROXY */ -static void notify_complete(struct bt_conn *conn, void *user_data) +static int proxy_send(struct bt_conn *conn, + const void *data, uint16_t len, + bt_gatt_complete_func_t end, 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; - + const struct bt_gatt_attr *attr; BT_DBG("%u bytes: %s", len, bt_hex(data, len)); #if defined(CONFIG_BT_MESH_GATT_PROXY) if (gatt_svc == MESH_GATT_PROXY) { - params.attr = &proxy_attrs[3]; + attr = &proxy_attrs[3]; } #endif #if defined(CONFIG_BT_MESH_PB_GATT) if (gatt_svc == MESH_GATT_PROV) { - params.attr = &prov_attrs[3]; + attr = &prov_attrs[3]; } #endif - if (!params.attr) { - return 0; + if (!attr) { + return -ENOENT; } - err = bt_gatt_notify_cb(conn, ¶ms); - if (!err) { - atomic_inc(&pending_notifications); - } + struct bt_gatt_notify_params params = { + .data = data, + .len = len, + .attr = attr, + .user_data = user_data, + .func = end, + }; - return err; + return bt_gatt_notify_cb(conn, ¶ms); } static int proxy_segment_and_send(struct bt_conn *conn, uint8_t type, - struct net_buf_simple *msg) + struct net_buf_simple *msg, + bt_gatt_complete_func_t end, void *user_data) { uint16_t mtu; @@ -1009,30 +1013,30 @@ static int proxy_segment_and_send(struct bt_conn *conn, uint8_t type, mtu = bt_gatt_get_mtu(conn) - 3; if (mtu > msg->len) { net_buf_simple_push_u8(msg, PDU_HDR(SAR_COMPLETE, type)); - return proxy_send(conn, msg->data, msg->len); + return proxy_send(conn, msg->data, msg->len, end, user_data); } net_buf_simple_push_u8(msg, PDU_HDR(SAR_FIRST, type)); - proxy_send(conn, msg->data, mtu); + proxy_send(conn, msg->data, mtu, NULL, NULL); net_buf_simple_pull(msg, mtu); while (msg->len) { if (msg->len + 1 < mtu) { net_buf_simple_push_u8(msg, PDU_HDR(SAR_LAST, type)); - proxy_send(conn, msg->data, msg->len); + proxy_send(conn, msg->data, msg->len, end, user_data); break; } net_buf_simple_push_u8(msg, PDU_HDR(SAR_CONT, type)); - proxy_send(conn, msg->data, mtu); + proxy_send(conn, msg->data, mtu, NULL, NULL); net_buf_simple_pull(msg, mtu); } return 0; } -int bt_mesh_proxy_send(struct bt_conn *conn, uint8_t type, - struct net_buf_simple *msg) +int bt_mesh_pb_gatt_send(struct bt_conn *conn, struct net_buf_simple *buf, + bt_gatt_complete_func_t end, void *user_data) { struct bt_mesh_proxy_client *client = find_client(conn); @@ -1041,12 +1045,12 @@ int bt_mesh_proxy_send(struct bt_conn *conn, uint8_t type, return -ENOTCONN; } - if ((client->filter_type == PROV) != (type == BT_MESH_PROXY_PROV)) { + if (client->filter_type != PROV) { BT_ERR("Invalid PDU type for Proxy Client"); return -EINVAL; } - return proxy_segment_and_send(conn, type, msg); + return proxy_segment_and_send(conn, BT_MESH_PROXY_PROV, buf, end, user_data); } #if defined(CONFIG_BT_MESH_PB_GATT) @@ -1395,13 +1399,3 @@ 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 56098c30e52..6b714211fbd 100644 --- a/subsys/bluetooth/mesh/proxy.h +++ b/subsys/bluetooth/mesh/proxy.h @@ -6,20 +6,19 @@ * SPDX-License-Identifier: Apache-2.0 */ +#ifndef ZEPHYR_SUBSYS_BLUETOOTH_MESH_PROXY_H_ +#define ZEPHYR_SUBSYS_BLUETOOTH_MESH_PROXY_H_ + +#include + +int bt_mesh_pb_gatt_send(struct bt_conn *conn, struct net_buf_simple *buf, + bt_gatt_complete_func_t end, void *user_data); + #define BT_MESH_PROXY_NET_PDU 0x00 #define BT_MESH_PROXY_BEACON 0x01 #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); - int bt_mesh_proxy_prov_enable(void); int bt_mesh_proxy_prov_disable(bool disconnect); @@ -36,8 +35,9 @@ int bt_mesh_proxy_adv_start(void); void bt_mesh_proxy_identity_start(struct bt_mesh_subnet *sub); void bt_mesh_proxy_identity_stop(struct bt_mesh_subnet *sub); -bool bt_mesh_proxy_relay(struct net_buf_simple *buf, uint16_t dst); +bool bt_mesh_proxy_relay(struct net_buf *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); + +#endif /* ZEPHYR_SUBSYS_BLUETOOTH_MESH_PROXY_H_ */