1 /*
2  * Copyright (c) 2022 Nordic Semiconductor ASA
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #include <zephyr/bluetooth/mesh.h>
8 
9 #include "access.h"
10 #include "foundation.h"
11 #include "net.h"
12 #include "mesh.h"
13 #include "transport.h"
14 #include "op_agg.h"
15 
16 #define LOG_LEVEL CONFIG_BT_MESH_MODEL_LOG_LEVEL
17 #include <zephyr/logging/log.h>
18 LOG_MODULE_REGISTER(bt_mesh_op_agg_srv);
19 
20 NET_BUF_SIMPLE_DEFINE_STATIC(sdu, BT_MESH_TX_SDU_MAX);
21 
22 /** Mesh Opcodes Aggregator Server Model Context */
23 static struct bt_mesh_op_agg_srv {
24 	/** Composition data model entry pointer. */
25 	const struct bt_mesh_model *model;
26 	/** Response error code. */
27 	int rsp_err;
28 	/** Indicates that the received aggregated message
29 	 * was acknowledged by local server model.
30 	 */
31 	bool ack;
32 	/** Aggregator context. */
33 	struct op_agg_ctx ctx;
34 } srv = {.ctx.sdu = &sdu};
35 
handle_sequence(const struct bt_mesh_model * model,struct bt_mesh_msg_ctx * ctx,struct net_buf_simple * buf)36 static int handle_sequence(const struct bt_mesh_model *model,
37 			   struct bt_mesh_msg_ctx *ctx,
38 			   struct net_buf_simple *buf)
39 {
40 	struct net_buf_simple_state state;
41 	struct net_buf_simple msg;
42 	uint16_t elem;
43 	uint8_t *status;
44 	int err;
45 
46 	elem = net_buf_simple_pull_le16(buf);
47 	ctx->recv_dst = elem;
48 
49 	bt_mesh_model_msg_init(srv.ctx.sdu, OP_OPCODES_AGGREGATOR_STATUS);
50 	status = net_buf_simple_add_u8(srv.ctx.sdu, 0);
51 	net_buf_simple_add_le16(srv.ctx.sdu, elem);
52 
53 	srv.ctx.net_idx = ctx->net_idx;
54 	srv.ctx.app_idx = ctx->app_idx;
55 	srv.ctx.addr = ctx->addr;
56 	srv.ctx.initialized = true;
57 
58 	if (!BT_MESH_ADDR_IS_UNICAST(elem)) {
59 		LOG_WRN("Address is not unicast, ignoring.");
60 		return -EINVAL;
61 	}
62 
63 	net_buf_simple_save(buf, &state);
64 	while (buf->len > 0) {
65 		err = bt_mesh_op_agg_decode_msg(&msg, buf);
66 		if (err) {
67 			LOG_ERR("Unable to parse Opcodes Aggregator Sequence message (err %d)",
68 				err);
69 			return err;
70 		}
71 	}
72 	net_buf_simple_restore(buf, &state);
73 
74 	if (!bt_mesh_elem_find(elem)) {
75 		*status = ACCESS_STATUS_INVALID_ADDRESS;
76 		goto send;
77 	}
78 
79 	while (buf->len > 0) {
80 		(void) bt_mesh_op_agg_decode_msg(&msg, buf);
81 
82 		srv.ack = false;
83 		srv.rsp_err = 0;
84 		err = bt_mesh_model_recv(ctx, &msg);
85 
86 		if (srv.rsp_err) {
87 			*status = srv.rsp_err;
88 			break;
89 		}
90 
91 		if (err) {
92 			*status = err;
93 			break;
94 		}
95 
96 		if (!srv.ack) {
97 			net_buf_simple_add_u8(srv.ctx.sdu, 0);
98 		}
99 	}
100 
101 send:
102 	srv.ctx.initialized = false;
103 	err = bt_mesh_model_send(model, ctx, srv.ctx.sdu, NULL, NULL);
104 	if (err) {
105 		LOG_ERR("Unable to send Opcodes Aggregator Status");
106 		return err;
107 	}
108 
109 	return 0;
110 }
111 
112 const struct bt_mesh_model_op _bt_mesh_op_agg_srv_op[] = {
113 	{ OP_OPCODES_AGGREGATOR_SEQUENCE, BT_MESH_LEN_MIN(2), handle_sequence },
114 	BT_MESH_MODEL_OP_END,
115 };
116 
op_agg_srv_init(const struct bt_mesh_model * model)117 static int op_agg_srv_init(const struct bt_mesh_model *model)
118 {
119 	if (!bt_mesh_model_in_primary(model)) {
120 		LOG_ERR("Opcodes Aggregator Server only allowed in primary element");
121 		return -EINVAL;
122 	}
123 
124 	/* Opcodes Aggregator Server model shall use the device key and
125 	 * application keys.
126 	 */
127 	model->keys[0] = BT_MESH_KEY_DEV_ANY;
128 
129 	srv.model = model;
130 
131 	return 0;
132 }
133 
bt_mesh_op_agg_srv_send(const struct bt_mesh_model * model,struct net_buf_simple * msg)134 int bt_mesh_op_agg_srv_send(const struct bt_mesh_model *model, struct net_buf_simple *msg)
135 {
136 	int err;
137 
138 	/* Model responded so mark this message as acknowledged */
139 	srv.ack = true;
140 
141 	err = bt_mesh_op_agg_encode_msg(msg, srv.ctx.sdu);
142 	if (err) {
143 		srv.rsp_err = ACCESS_STATUS_RESPONSE_OVERFLOW;
144 	}
145 
146 	return err;
147 }
148 
bt_mesh_op_agg_srv_accept(struct bt_mesh_msg_ctx * ctx,struct net_buf_simple * buf)149 int bt_mesh_op_agg_srv_accept(struct bt_mesh_msg_ctx *ctx, struct net_buf_simple *buf)
150 {
151 
152 	return srv.ctx.initialized && (ctx->net_idx == srv.ctx.net_idx) &&
153 	       (ctx->addr == srv.ctx.addr) && (ctx->app_idx == srv.ctx.app_idx) &&
154 	       !bt_mesh_op_agg_is_op_agg_msg(buf);
155 }
156 
157 const struct bt_mesh_model_cb _bt_mesh_op_agg_srv_cb = {
158 	.init = op_agg_srv_init,
159 };
160