1 /*
2 * Copyright (c) 2020 Nordic Semiconductor ASA
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7 #include <zephyr/bluetooth/mesh.h>
8 #include <zephyr/bluetooth/bluetooth.h>
9
10 #include "mesh.h"
11 #include "net.h"
12 #include "rpl.h"
13 #include "beacon.h"
14 #include "settings.h"
15 #include "heartbeat.h"
16 #include "friend.h"
17 #include "adv.h"
18 #include "cfg.h"
19 #include "od_priv_proxy.h"
20 #include "priv_beacon.h"
21
22 #define LOG_LEVEL CONFIG_BT_MESH_CFG_LOG_LEVEL
23 #include <zephyr/logging/log.h>
24 LOG_MODULE_REGISTER(bt_mesh_cfg);
25
26 /* Miscellaneous configuration server model states */
27 struct cfg_val {
28 uint8_t net_transmit;
29 uint8_t relay;
30 uint8_t relay_retransmit;
31 uint8_t beacon;
32 uint8_t gatt_proxy;
33 uint8_t frnd;
34 uint8_t default_ttl;
35 };
36
bt_mesh_beacon_set(bool beacon)37 void bt_mesh_beacon_set(bool beacon)
38 {
39 if (atomic_test_bit(bt_mesh.flags, BT_MESH_BEACON) == beacon) {
40 return;
41 }
42
43 atomic_set_bit_to(bt_mesh.flags, BT_MESH_BEACON, beacon);
44
45 if (beacon) {
46 bt_mesh_beacon_enable();
47 } else {
48 /* Beacon timer will stop automatically when all beacons are disabled. */
49 }
50
51 if (IS_ENABLED(CONFIG_BT_SETTINGS) &&
52 atomic_test_bit(bt_mesh.flags, BT_MESH_VALID)) {
53 bt_mesh_settings_store_schedule(BT_MESH_SETTINGS_CFG_PENDING);
54 }
55 }
56
bt_mesh_beacon_enabled(void)57 bool bt_mesh_beacon_enabled(void)
58 {
59 return atomic_test_bit(bt_mesh.flags, BT_MESH_BEACON);
60 }
61
feature_set(int feature_flag,enum bt_mesh_feat_state state)62 static int feature_set(int feature_flag, enum bt_mesh_feat_state state)
63 {
64 if (state != BT_MESH_FEATURE_DISABLED &&
65 state != BT_MESH_FEATURE_ENABLED) {
66 return -EINVAL;
67 }
68
69 if (atomic_test_bit(bt_mesh.flags, feature_flag) ==
70 (state == BT_MESH_FEATURE_ENABLED)) {
71 return -EALREADY;
72 }
73
74 atomic_set_bit_to(bt_mesh.flags, feature_flag,
75 (state == BT_MESH_FEATURE_ENABLED));
76
77 return 0;
78 }
79
feature_get(int feature_flag)80 static enum bt_mesh_feat_state feature_get(int feature_flag)
81 {
82 return atomic_test_bit(bt_mesh.flags, feature_flag) ?
83 BT_MESH_FEATURE_ENABLED :
84 BT_MESH_FEATURE_DISABLED;
85 }
86
bt_mesh_priv_beacon_set(enum bt_mesh_feat_state priv_beacon)87 int bt_mesh_priv_beacon_set(enum bt_mesh_feat_state priv_beacon)
88 {
89 int err;
90
91 if (!IS_ENABLED(CONFIG_BT_MESH_PRIV_BEACONS)) {
92 return -ENOTSUP;
93 }
94
95 err = feature_set(BT_MESH_PRIV_BEACON, priv_beacon);
96 if (err) {
97 return err;
98 }
99
100 if (priv_beacon == BT_MESH_FEATURE_ENABLED) {
101 bt_mesh_beacon_enable();
102 } else {
103 /* Beacon timer will stop automatically when all beacons are disabled. */
104 }
105
106 if (IS_ENABLED(CONFIG_BT_SETTINGS) && IS_ENABLED(CONFIG_BT_MESH_PRIV_BEACON_SRV) &&
107 atomic_test_bit(bt_mesh.flags, BT_MESH_VALID)) {
108 bt_mesh_priv_beacon_srv_store_schedule();
109 }
110
111 return 0;
112 }
113
bt_mesh_priv_beacon_get(void)114 enum bt_mesh_feat_state bt_mesh_priv_beacon_get(void)
115 {
116 if (!IS_ENABLED(CONFIG_BT_MESH_PRIV_BEACONS)) {
117 return BT_MESH_FEATURE_NOT_SUPPORTED;
118 }
119
120 return feature_get(BT_MESH_PRIV_BEACON);
121 }
122
bt_mesh_priv_beacon_update_interval_set(uint8_t interval)123 void bt_mesh_priv_beacon_update_interval_set(uint8_t interval)
124 {
125 #if defined(CONFIG_BT_MESH_PRIV_BEACONS)
126 bt_mesh.priv_beacon_int = interval;
127 #endif
128 }
129
bt_mesh_priv_beacon_update_interval_get(void)130 uint8_t bt_mesh_priv_beacon_update_interval_get(void)
131 {
132 #if defined(CONFIG_BT_MESH_PRIV_BEACONS)
133 return bt_mesh.priv_beacon_int;
134 #else
135 return 0;
136 #endif
137 }
138
bt_mesh_od_priv_proxy_get(void)139 int bt_mesh_od_priv_proxy_get(void)
140 {
141 #if IS_ENABLED(CONFIG_BT_MESH_OD_PRIV_PROXY_SRV)
142 return bt_mesh.on_demand_state;
143 #else
144 return -ENOTSUP;
145 #endif
146 }
147
bt_mesh_od_priv_proxy_set(uint8_t on_demand_proxy)148 int bt_mesh_od_priv_proxy_set(uint8_t on_demand_proxy)
149 {
150 #if !IS_ENABLED(CONFIG_BT_MESH_OD_PRIV_PROXY_SRV)
151 return -ENOTSUP;
152 #else
153
154 if (bt_mesh_priv_gatt_proxy_get() != BT_MESH_FEATURE_NOT_SUPPORTED) {
155 bt_mesh.on_demand_state = on_demand_proxy;
156 }
157
158 if (IS_ENABLED(CONFIG_BT_SETTINGS) && IS_ENABLED(CONFIG_BT_MESH_OD_PRIV_PROXY_SRV) &&
159 atomic_test_bit(bt_mesh.flags, BT_MESH_VALID)) {
160 bt_mesh_od_priv_proxy_srv_store_schedule();
161 }
162 return 0;
163 #endif
164 }
165
node_id_is_running(struct bt_mesh_subnet * sub,void * cb_data)166 static bool node_id_is_running(struct bt_mesh_subnet *sub, void *cb_data)
167 {
168 return sub->node_id == BT_MESH_NODE_IDENTITY_RUNNING;
169 }
170
bt_mesh_gatt_proxy_set(enum bt_mesh_feat_state gatt_proxy)171 int bt_mesh_gatt_proxy_set(enum bt_mesh_feat_state gatt_proxy)
172 {
173 int err;
174
175 if (!IS_ENABLED(CONFIG_BT_MESH_GATT_PROXY)) {
176 return -ENOTSUP;
177 }
178
179 err = feature_set(BT_MESH_GATT_PROXY, gatt_proxy);
180 if (err) {
181 return err;
182 }
183
184 /* The binding from section 4.2.45.1 disables Private GATT Proxy state when non-private
185 * state is enabled.
186 */
187 if (gatt_proxy == BT_MESH_FEATURE_ENABLED) {
188 feature_set(BT_MESH_PRIV_GATT_PROXY, BT_MESH_FEATURE_DISABLED);
189 }
190
191 if ((gatt_proxy == BT_MESH_FEATURE_ENABLED) ||
192 (gatt_proxy == BT_MESH_FEATURE_DISABLED &&
193 !bt_mesh_subnet_find(node_id_is_running, NULL))) {
194 bt_mesh_adv_gatt_update();
195 }
196
197 bt_mesh_hb_feature_changed(BT_MESH_FEAT_PROXY);
198
199 if (IS_ENABLED(CONFIG_BT_SETTINGS) &&
200 atomic_test_bit(bt_mesh.flags, BT_MESH_VALID)) {
201 bt_mesh_settings_store_schedule(BT_MESH_SETTINGS_CFG_PENDING);
202 }
203
204 return 0;
205 }
206
bt_mesh_gatt_proxy_get(void)207 enum bt_mesh_feat_state bt_mesh_gatt_proxy_get(void)
208 {
209 if (!IS_ENABLED(CONFIG_BT_MESH_GATT_PROXY)) {
210 return BT_MESH_FEATURE_NOT_SUPPORTED;
211 }
212
213 return feature_get(BT_MESH_GATT_PROXY);
214 }
215
bt_mesh_priv_gatt_proxy_set(enum bt_mesh_feat_state priv_gatt_proxy)216 int bt_mesh_priv_gatt_proxy_set(enum bt_mesh_feat_state priv_gatt_proxy)
217 {
218 int err;
219
220 if (!IS_ENABLED(CONFIG_BT_MESH_GATT_PROXY) || !IS_ENABLED(CONFIG_BT_MESH_PRIV_BEACONS)) {
221 return BT_MESH_FEATURE_NOT_SUPPORTED;
222 }
223
224 /* Reverse binding from section 4.2.45.1 doesn't allow to enable private state if
225 * non-private state is enabled.
226 */
227 if (bt_mesh_gatt_proxy_get() == BT_MESH_FEATURE_ENABLED) {
228 return BT_MESH_FEATURE_DISABLED;
229 }
230
231 err = feature_set(BT_MESH_PRIV_GATT_PROXY, priv_gatt_proxy);
232 if (err) {
233 return err;
234 }
235
236 if (priv_gatt_proxy == BT_MESH_FEATURE_ENABLED) {
237 /* Re-generate proxy beacon */
238 bt_mesh_adv_gatt_update();
239 }
240
241 if (IS_ENABLED(CONFIG_BT_SETTINGS) && IS_ENABLED(CONFIG_BT_MESH_PRIV_BEACON_SRV) &&
242 atomic_test_bit(bt_mesh.flags, BT_MESH_VALID)) {
243 bt_mesh_priv_beacon_srv_store_schedule();
244 }
245
246 return 0;
247 }
248
bt_mesh_priv_gatt_proxy_get(void)249 enum bt_mesh_feat_state bt_mesh_priv_gatt_proxy_get(void)
250 {
251 if (!IS_ENABLED(CONFIG_BT_MESH_GATT_PROXY) || !IS_ENABLED(CONFIG_BT_MESH_PRIV_BEACONS)) {
252 return BT_MESH_FEATURE_NOT_SUPPORTED;
253 }
254
255 return feature_get(BT_MESH_PRIV_GATT_PROXY);
256 }
257
bt_mesh_default_ttl_set(uint8_t default_ttl)258 int bt_mesh_default_ttl_set(uint8_t default_ttl)
259 {
260 if (default_ttl == 1 || default_ttl > BT_MESH_TTL_MAX) {
261 return -EINVAL;
262 }
263
264 if (default_ttl == bt_mesh.default_ttl) {
265 return 0;
266 }
267
268 bt_mesh.default_ttl = default_ttl;
269
270 if (IS_ENABLED(CONFIG_BT_SETTINGS) &&
271 atomic_test_bit(bt_mesh.flags, BT_MESH_VALID)) {
272 bt_mesh_settings_store_schedule(BT_MESH_SETTINGS_CFG_PENDING);
273 }
274
275 return 0;
276 }
277
bt_mesh_default_ttl_get(void)278 uint8_t bt_mesh_default_ttl_get(void)
279 {
280 return bt_mesh.default_ttl;
281 }
282
bt_mesh_friend_set(enum bt_mesh_feat_state friendship)283 int bt_mesh_friend_set(enum bt_mesh_feat_state friendship)
284 {
285 int err;
286
287 if (!IS_ENABLED(CONFIG_BT_MESH_FRIEND)) {
288 return -ENOTSUP;
289 }
290
291 err = feature_set(BT_MESH_FRIEND, friendship);
292 if (err) {
293 return err;
294 }
295
296 bt_mesh_hb_feature_changed(BT_MESH_FEAT_FRIEND);
297
298 if (IS_ENABLED(CONFIG_BT_SETTINGS) &&
299 atomic_test_bit(bt_mesh.flags, BT_MESH_VALID)) {
300 bt_mesh_settings_store_schedule(BT_MESH_SETTINGS_CFG_PENDING);
301 }
302
303 if (friendship == BT_MESH_FEATURE_DISABLED) {
304 bt_mesh_friends_clear();
305 }
306
307 return 0;
308 }
309
bt_mesh_friend_get(void)310 enum bt_mesh_feat_state bt_mesh_friend_get(void)
311 {
312 if (!IS_ENABLED(CONFIG_BT_MESH_FRIEND)) {
313 return BT_MESH_FEATURE_NOT_SUPPORTED;
314 }
315
316 return feature_get(BT_MESH_FRIEND);
317 }
318
bt_mesh_net_transmit_set(uint8_t xmit)319 void bt_mesh_net_transmit_set(uint8_t xmit)
320 {
321 if (bt_mesh.net_xmit == xmit) {
322 return;
323 }
324
325 bt_mesh.net_xmit = xmit;
326
327 if (IS_ENABLED(CONFIG_BT_SETTINGS) &&
328 atomic_test_bit(bt_mesh.flags, BT_MESH_VALID)) {
329 bt_mesh_settings_store_schedule(BT_MESH_SETTINGS_CFG_PENDING);
330 }
331 }
332
bt_mesh_net_transmit_get(void)333 uint8_t bt_mesh_net_transmit_get(void)
334 {
335 return bt_mesh.net_xmit;
336 }
337
bt_mesh_relay_set(enum bt_mesh_feat_state relay,uint8_t xmit)338 int bt_mesh_relay_set(enum bt_mesh_feat_state relay, uint8_t xmit)
339 {
340 int err;
341
342 if (!IS_ENABLED(CONFIG_BT_MESH_RELAY)) {
343 return -ENOTSUP;
344 }
345
346 err = feature_set(BT_MESH_RELAY, relay);
347 if (err == -EINVAL) {
348 return err;
349 }
350
351 if (err == -EALREADY && bt_mesh.relay_xmit == xmit) {
352 return -EALREADY;
353 }
354
355 bt_mesh.relay_xmit = xmit;
356 bt_mesh_hb_feature_changed(BT_MESH_FEAT_RELAY);
357
358 if (IS_ENABLED(CONFIG_BT_SETTINGS) &&
359 atomic_test_bit(bt_mesh.flags, BT_MESH_VALID)) {
360 bt_mesh_settings_store_schedule(BT_MESH_SETTINGS_CFG_PENDING);
361 }
362
363 return 0;
364 }
365
bt_mesh_relay_get(void)366 enum bt_mesh_feat_state bt_mesh_relay_get(void)
367 {
368 return feature_get(BT_MESH_RELAY);
369 }
370
bt_mesh_relay_retransmit_get(void)371 uint8_t bt_mesh_relay_retransmit_get(void)
372 {
373 if (!IS_ENABLED(CONFIG_BT_MESH_RELAY)) {
374 return 0;
375 }
376
377 return bt_mesh.relay_xmit;
378 }
379
bt_mesh_fixed_group_match(uint16_t addr)380 bool bt_mesh_fixed_group_match(uint16_t addr)
381 {
382 /* Check for fixed group addresses */
383 switch (addr) {
384 case BT_MESH_ADDR_ALL_NODES:
385 return true;
386 case BT_MESH_ADDR_PROXIES:
387 return (bt_mesh_gatt_proxy_get() == BT_MESH_FEATURE_ENABLED);
388 case BT_MESH_ADDR_FRIENDS:
389 return (bt_mesh_friend_get() == BT_MESH_FEATURE_ENABLED);
390 case BT_MESH_ADDR_RELAYS:
391 return (bt_mesh_relay_get() == BT_MESH_FEATURE_ENABLED);
392 default:
393 return false;
394 }
395 }
396
bt_mesh_cfg_default_set(void)397 void bt_mesh_cfg_default_set(void)
398 {
399 bt_mesh.default_ttl = CONFIG_BT_MESH_DEFAULT_TTL;
400 bt_mesh.net_xmit =
401 BT_MESH_TRANSMIT(CONFIG_BT_MESH_NETWORK_TRANSMIT_COUNT,
402 CONFIG_BT_MESH_NETWORK_TRANSMIT_INTERVAL);
403
404 #if defined(CONFIG_BT_MESH_RELAY)
405 bt_mesh.relay_xmit =
406 BT_MESH_TRANSMIT(CONFIG_BT_MESH_RELAY_RETRANSMIT_COUNT,
407 CONFIG_BT_MESH_RELAY_RETRANSMIT_INTERVAL);
408 #endif
409
410 if (IS_ENABLED(CONFIG_BT_MESH_RELAY_ENABLED)) {
411 atomic_set_bit(bt_mesh.flags, BT_MESH_RELAY);
412 }
413
414 if (IS_ENABLED(CONFIG_BT_MESH_BEACON_ENABLED)) {
415 atomic_set_bit(bt_mesh.flags, BT_MESH_BEACON);
416 }
417
418 if (IS_ENABLED(CONFIG_BT_MESH_GATT_PROXY_ENABLED)) {
419 atomic_set_bit(bt_mesh.flags, BT_MESH_GATT_PROXY);
420 }
421
422 if (IS_ENABLED(CONFIG_BT_MESH_FRIEND_ENABLED)) {
423 atomic_set_bit(bt_mesh.flags, BT_MESH_FRIEND);
424 }
425 }
426
cfg_set(const char * name,size_t len_rd,settings_read_cb read_cb,void * cb_arg)427 static int cfg_set(const char *name, size_t len_rd,
428 settings_read_cb read_cb, void *cb_arg)
429 {
430 struct cfg_val cfg;
431 int err;
432
433 if (len_rd == 0) {
434 LOG_DBG("Cleared configuration state");
435 return 0;
436 }
437
438 err = bt_mesh_settings_set(read_cb, cb_arg, &cfg, sizeof(cfg));
439 if (err) {
440 LOG_ERR("Failed to set \'cfg\'");
441 return err;
442 }
443
444 bt_mesh_net_transmit_set(cfg.net_transmit);
445 bt_mesh_relay_set(cfg.relay, cfg.relay_retransmit);
446 bt_mesh_beacon_set(cfg.beacon);
447 bt_mesh_gatt_proxy_set(cfg.gatt_proxy);
448 bt_mesh_friend_set(cfg.frnd);
449 bt_mesh_default_ttl_set(cfg.default_ttl);
450
451 LOG_DBG("Restored configuration state");
452
453 return 0;
454 }
455
456 BT_MESH_SETTINGS_DEFINE(cfg, "Cfg", cfg_set);
457
clear_cfg(void)458 static void clear_cfg(void)
459 {
460 int err;
461
462 err = settings_delete("bt/mesh/Cfg");
463 if (err) {
464 LOG_ERR("Failed to clear configuration (err: %d)", err);
465 } else {
466 LOG_DBG("Cleared configuration");
467 }
468 }
469
store_pending_cfg(void)470 static void store_pending_cfg(void)
471 {
472 struct cfg_val val;
473 int err;
474
475 val.net_transmit = bt_mesh_net_transmit_get();
476 val.relay = bt_mesh_relay_get();
477 val.relay_retransmit = bt_mesh_relay_retransmit_get();
478 val.beacon = bt_mesh_beacon_enabled();
479 val.gatt_proxy = bt_mesh_gatt_proxy_get();
480 val.frnd = bt_mesh_friend_get();
481 val.default_ttl = bt_mesh_default_ttl_get();
482
483 err = settings_save_one("bt/mesh/Cfg", &val, sizeof(val));
484 if (err) {
485 LOG_ERR("Failed to store configuration value");
486 } else {
487 LOG_DBG("Stored configuration value");
488 LOG_HEXDUMP_DBG(&val, sizeof(val), "raw value");
489 }
490 }
491
bt_mesh_cfg_pending_store(void)492 void bt_mesh_cfg_pending_store(void)
493 {
494 if (atomic_test_bit(bt_mesh.flags, BT_MESH_VALID)) {
495 store_pending_cfg();
496 } else {
497 clear_cfg();
498 }
499 }
500