1 /*
2  * Copyright (c) 2020 Nordic Semiconductor ASA
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 #include <zephyr/bluetooth/mesh.h>
7 #include "net.h"
8 #include <zephyr/bluetooth/conn.h>
9 #include "proxy.h"
10 #include "foundation.h"
11 #include "beacon.h"
12 #include "cfg.h"
13 #include "settings.h"
14 
15 #define LOG_LEVEL CONFIG_BT_MESH_MODEL_LOG_LEVEL
16 #include <zephyr/logging/log.h>
17 LOG_MODULE_REGISTER(bt_mesh_priv_beacon_srv);
18 
19 static const struct bt_mesh_model *priv_beacon_srv;
20 
21 /* Private Beacon configuration server model states */
22 struct {
23 	uint8_t state;
24 	uint8_t interval;
25 	uint8_t proxy_state;
26 } priv_beacon_state;
27 
priv_beacon_store(bool delete)28 static int priv_beacon_store(bool delete)
29 {
30 	if (!IS_ENABLED(CONFIG_BT_SETTINGS)) {
31 		return 0;
32 	}
33 
34 	const void *data = delete ? NULL : &priv_beacon_state;
35 	size_t len = delete ? 0 : sizeof(priv_beacon_state);
36 
37 	return bt_mesh_model_data_store(priv_beacon_srv, false, "pb", data, len);
38 }
39 
beacon_status_rsp(const struct bt_mesh_model * mod,struct bt_mesh_msg_ctx * ctx)40 static int beacon_status_rsp(const struct bt_mesh_model *mod,
41 			      struct bt_mesh_msg_ctx *ctx)
42 {
43 	BT_MESH_MODEL_BUF_DEFINE(buf, OP_PRIV_BEACON_STATUS, 2);
44 	bt_mesh_model_msg_init(&buf, OP_PRIV_BEACON_STATUS);
45 
46 	net_buf_simple_add_u8(&buf, bt_mesh_priv_beacon_get());
47 	net_buf_simple_add_u8(&buf, bt_mesh_priv_beacon_update_interval_get());
48 
49 	bt_mesh_model_send(mod, ctx, &buf, NULL, NULL);
50 
51 	return 0;
52 }
53 
handle_beacon_get(const struct bt_mesh_model * mod,struct bt_mesh_msg_ctx * ctx,struct net_buf_simple * buf)54 static int handle_beacon_get(const struct bt_mesh_model *mod,
55 			     struct bt_mesh_msg_ctx *ctx,
56 			     struct net_buf_simple *buf)
57 {
58 	LOG_DBG("");
59 
60 	beacon_status_rsp(mod, ctx);
61 
62 	return 0;
63 }
64 
handle_beacon_set(const struct bt_mesh_model * mod,struct bt_mesh_msg_ctx * ctx,struct net_buf_simple * buf)65 static int handle_beacon_set(const struct bt_mesh_model *mod,
66 			     struct bt_mesh_msg_ctx *ctx,
67 			     struct net_buf_simple *buf)
68 {
69 	uint8_t beacon;
70 
71 	if (buf->len > 2U) {
72 		return -EMSGSIZE;
73 	}
74 
75 	beacon = net_buf_simple_pull_u8(buf);
76 	if (beacon != BT_MESH_BEACON_DISABLED &&
77 	    beacon != BT_MESH_BEACON_ENABLED) {
78 		LOG_WRN("Invalid beacon value %u", beacon);
79 		return -EINVAL;
80 	}
81 
82 	if (buf->len == 1U) {
83 		bt_mesh_priv_beacon_update_interval_set(net_buf_simple_pull_u8(buf));
84 	}
85 
86 	(void)bt_mesh_priv_beacon_set(beacon);
87 	beacon_status_rsp(mod, ctx);
88 
89 	return 0;
90 }
91 
gatt_proxy_status_rsp(const struct bt_mesh_model * mod,struct bt_mesh_msg_ctx * ctx)92 static void gatt_proxy_status_rsp(const struct bt_mesh_model *mod,
93 				  struct bt_mesh_msg_ctx *ctx)
94 {
95 	BT_MESH_MODEL_BUF_DEFINE(buf, OP_PRIV_GATT_PROXY_STATUS, 1);
96 	bt_mesh_model_msg_init(&buf, OP_PRIV_GATT_PROXY_STATUS);
97 
98 	net_buf_simple_add_u8(&buf, bt_mesh_priv_gatt_proxy_get());
99 
100 	bt_mesh_model_send(mod, ctx, &buf, NULL, NULL);
101 }
102 
handle_gatt_proxy_get(const struct bt_mesh_model * mod,struct bt_mesh_msg_ctx * ctx,struct net_buf_simple * buf)103 static int handle_gatt_proxy_get(const struct bt_mesh_model *mod,
104 				 struct bt_mesh_msg_ctx *ctx,
105 				 struct net_buf_simple *buf)
106 {
107 	LOG_DBG("");
108 
109 	gatt_proxy_status_rsp(mod, ctx);
110 
111 	return 0;
112 }
113 
handle_gatt_proxy_set(const struct bt_mesh_model * mod,struct bt_mesh_msg_ctx * ctx,struct net_buf_simple * buf)114 static int handle_gatt_proxy_set(const struct bt_mesh_model *mod,
115 				 struct bt_mesh_msg_ctx *ctx,
116 				 struct net_buf_simple *buf)
117 {
118 	uint8_t gatt_proxy;
119 
120 	gatt_proxy = net_buf_simple_pull_u8(buf);
121 	if (gatt_proxy != BT_MESH_GATT_PROXY_DISABLED &&
122 	    gatt_proxy != BT_MESH_GATT_PROXY_ENABLED) {
123 		LOG_WRN("Invalid GATT proxy value %u", gatt_proxy);
124 		return -EINVAL;
125 	}
126 
127 	LOG_DBG("%u", gatt_proxy);
128 
129 	bt_mesh_priv_gatt_proxy_set(gatt_proxy);
130 
131 	gatt_proxy_status_rsp(mod, ctx);
132 
133 	return 0;
134 }
135 
node_id_status_rsp(const struct bt_mesh_model * mod,struct bt_mesh_msg_ctx * ctx,uint8_t status,uint16_t net_idx,uint8_t node_id)136 static void node_id_status_rsp(const struct bt_mesh_model *mod,
137 			       struct bt_mesh_msg_ctx *ctx, uint8_t status,
138 			       uint16_t net_idx, uint8_t node_id)
139 {
140 	BT_MESH_MODEL_BUF_DEFINE(buf, OP_PRIV_NODE_ID_STATUS, 4);
141 	bt_mesh_model_msg_init(&buf, OP_PRIV_NODE_ID_STATUS);
142 
143 	net_buf_simple_add_u8(&buf, status);
144 	net_buf_simple_add_le16(&buf, net_idx);
145 	net_buf_simple_add_u8(&buf, node_id);
146 
147 	bt_mesh_model_send(mod, ctx, &buf, NULL, NULL);
148 }
149 
handle_node_id_get(const struct bt_mesh_model * mod,struct bt_mesh_msg_ctx * ctx,struct net_buf_simple * buf)150 static int handle_node_id_get(const struct bt_mesh_model *mod,
151 			      struct bt_mesh_msg_ctx *ctx,
152 			      struct net_buf_simple *buf)
153 {
154 	uint8_t node_id, status;
155 	uint16_t net_idx;
156 
157 	net_idx = net_buf_simple_pull_le16(buf) & 0xfff;
158 
159 	status = bt_mesh_subnet_priv_node_id_get(net_idx, (enum bt_mesh_feat_state *)&node_id);
160 	node_id_status_rsp(mod, ctx, status, net_idx, node_id);
161 
162 	return 0;
163 }
164 
handle_node_id_set(const struct bt_mesh_model * mod,struct bt_mesh_msg_ctx * ctx,struct net_buf_simple * buf)165 static int handle_node_id_set(const struct bt_mesh_model *mod,
166 			      struct bt_mesh_msg_ctx *ctx,
167 			      struct net_buf_simple *buf)
168 {
169 	uint8_t node_id, status;
170 	uint16_t net_idx;
171 
172 	net_idx = net_buf_simple_pull_le16(buf) & 0xfff;
173 	node_id = net_buf_simple_pull_u8(buf);
174 	if (node_id != BT_MESH_NODE_IDENTITY_RUNNING &&
175 	    node_id != BT_MESH_NODE_IDENTITY_STOPPED) {
176 		LOG_ERR("Invalid node ID value 0x%02x", node_id);
177 		return -EINVAL;
178 	}
179 
180 	status = bt_mesh_subnet_priv_node_id_set(net_idx, node_id);
181 	node_id_status_rsp(mod, ctx, status, net_idx, node_id);
182 
183 	return 0;
184 }
185 
186 const struct bt_mesh_model_op bt_mesh_priv_beacon_srv_op[] = {
187 	{ OP_PRIV_BEACON_GET, BT_MESH_LEN_EXACT(0), handle_beacon_get },
188 	{ OP_PRIV_BEACON_SET, BT_MESH_LEN_MIN(1), handle_beacon_set },
189 	{ OP_PRIV_GATT_PROXY_GET, BT_MESH_LEN_EXACT(0), handle_gatt_proxy_get },
190 	{ OP_PRIV_GATT_PROXY_SET, BT_MESH_LEN_EXACT(1), handle_gatt_proxy_set },
191 	{ OP_PRIV_NODE_ID_GET, BT_MESH_LEN_EXACT(2), handle_node_id_get },
192 	{ OP_PRIV_NODE_ID_SET, BT_MESH_LEN_EXACT(3), handle_node_id_set },
193 	BT_MESH_MODEL_OP_END
194 };
195 
priv_beacon_srv_init(const struct bt_mesh_model * mod)196 static int priv_beacon_srv_init(const struct bt_mesh_model *mod)
197 {
198 	int err;
199 	const struct bt_mesh_model *config_srv =
200 		bt_mesh_model_find(bt_mesh_model_elem(mod), BT_MESH_MODEL_ID_CFG_SRV);
201 
202 	if (config_srv == NULL) {
203 		LOG_ERR("Private Beacon server cannot extend Configuration server");
204 		return -EINVAL;
205 	}
206 
207 	priv_beacon_srv = mod;
208 	mod->keys[0] = BT_MESH_KEY_DEV_LOCAL;
209 
210 	err = bt_mesh_model_extend(mod, config_srv);
211 
212 	if (err) {
213 		return err;
214 	}
215 
216 	return 0;
217 }
218 
priv_beacon_srv_reset(const struct bt_mesh_model * model)219 static void priv_beacon_srv_reset(const struct bt_mesh_model *model)
220 {
221 	(void)memset(&priv_beacon_state, 0, sizeof(priv_beacon_state));
222 	priv_beacon_store(true);
223 }
224 
225 #ifdef CONFIG_BT_SETTINGS
priv_beacon_srv_settings_set(const struct bt_mesh_model * model,const char * name,size_t len_rd,settings_read_cb read_cb,void * cb_data)226 static int priv_beacon_srv_settings_set(const struct bt_mesh_model *model, const char *name,
227 					size_t len_rd, settings_read_cb read_cb, void *cb_data)
228 {
229 	int err;
230 
231 	if (len_rd == 0) {
232 		LOG_DBG("Cleared configuration state");
233 		return 0;
234 	}
235 
236 	err = bt_mesh_settings_set(read_cb, cb_data, &priv_beacon_state, sizeof(priv_beacon_state));
237 	if (err) {
238 		LOG_ERR("Failed to set Private Beacon state");
239 		return err;
240 	}
241 
242 	bt_mesh_priv_beacon_set(priv_beacon_state.state);
243 	bt_mesh_priv_beacon_update_interval_set(priv_beacon_state.interval);
244 	bt_mesh_priv_gatt_proxy_set(priv_beacon_state.proxy_state);
245 	return 0;
246 }
247 
priv_beacon_srv_pending_store(const struct bt_mesh_model * model)248 static void priv_beacon_srv_pending_store(const struct bt_mesh_model *model)
249 {
250 	priv_beacon_state.state = bt_mesh_priv_beacon_get();
251 	priv_beacon_state.interval = bt_mesh_priv_beacon_update_interval_get();
252 	priv_beacon_state.proxy_state = bt_mesh_priv_gatt_proxy_get();
253 
254 	priv_beacon_store(false);
255 }
256 #endif
257 
258 const struct bt_mesh_model_cb bt_mesh_priv_beacon_srv_cb = {
259 	.init = priv_beacon_srv_init,
260 	.reset = priv_beacon_srv_reset,
261 #ifdef CONFIG_BT_SETTINGS
262 	.settings_set = priv_beacon_srv_settings_set,
263 	.pending_store = priv_beacon_srv_pending_store,
264 #endif
265 };
266 
bt_mesh_priv_beacon_srv_store_schedule(void)267 void bt_mesh_priv_beacon_srv_store_schedule(void)
268 {
269 	if (IS_ENABLED(CONFIG_BT_SETTINGS)) {
270 		bt_mesh_model_data_store_schedule(priv_beacon_srv);
271 	}
272 }
273