1 /*
2 * Copyright (c) 2017 Intel Corporation
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7 #include <zephyr/kernel.h>
8 #include <errno.h>
9 #include <stdlib.h>
10 #include <zephyr/sys/util.h>
11 #include <zephyr/sys/byteorder.h>
12
13 #include <zephyr/net_buf.h>
14 #include <zephyr/bluetooth/bluetooth.h>
15 #include <zephyr/bluetooth/mesh.h>
16
17 #include "common/bt_str.h"
18
19 #include "testing.h"
20
21 #include "mesh.h"
22 #include "net.h"
23 #include "lpn.h"
24 #include "transport.h"
25 #include "access.h"
26 #include "foundation.h"
27 #include "op_agg.h"
28 #include "settings.h"
29 #include "va.h"
30 #include "delayable_msg.h"
31
32 #define LOG_LEVEL CONFIG_BT_MESH_ACCESS_LOG_LEVEL
33 #include <zephyr/logging/log.h>
34 LOG_MODULE_REGISTER(bt_mesh_access);
35
36 /* 20 - 50ms */
37 #define RANDOM_DELAY_SHORT 30
38 /* 20 - 500ms */
39 #define RANDOM_DELAY_LONG 480
40
41 /* Model publication information for persistent storage. */
42 struct mod_pub_val {
43 struct {
44 uint16_t addr;
45 uint16_t key;
46 uint8_t ttl;
47 uint8_t retransmit;
48 uint8_t period;
49 uint8_t period_div:4,
50 cred:1;
51 } base;
52 uint16_t uuidx;
53 };
54
55 struct comp_foreach_model_arg {
56 struct net_buf_simple *buf;
57 size_t *offset;
58 };
59
60 static const struct bt_mesh_comp *dev_comp;
61 static const struct bt_mesh_comp2 *dev_comp2;
62 static uint16_t dev_primary_addr;
63 static void (*msg_cb)(uint32_t opcode, struct bt_mesh_msg_ctx *ctx, struct net_buf_simple *buf);
64
65 /* Structure containing information about model extension */
66 struct mod_relation {
67 /** Element that composition data base model belongs to. */
68 uint8_t elem_base;
69 /** Index of composition data base model in its element. */
70 uint8_t idx_base;
71 /** Element that composition data extension model belongs to. */
72 uint8_t elem_ext;
73 /** Index of composition data extension model in its element. */
74 uint8_t idx_ext;
75 /** Type of relation; value in range 0x00-0xFE marks correspondence
76 * and equals to Correspondence ID; value 0xFF marks extension
77 */
78 uint8_t type;
79 };
80
81 #ifdef CONFIG_BT_MESH_MODEL_EXTENSION_LIST_SIZE
82 #define MOD_REL_LIST_SIZE CONFIG_BT_MESH_MODEL_EXTENSION_LIST_SIZE
83 #else
84 #define MOD_REL_LIST_SIZE 0
85 #endif
86
87 /* List of all existing extension relations between models */
88 static struct mod_relation mod_rel_list[MOD_REL_LIST_SIZE];
89
90 #define MOD_REL_LIST_FOR_EACH(idx) \
91 for ((idx) = 0; \
92 (idx) < ARRAY_SIZE(mod_rel_list) && \
93 !(mod_rel_list[(idx)].elem_base == 0 && \
94 mod_rel_list[(idx)].idx_base == 0 && \
95 mod_rel_list[(idx)].elem_ext == 0 && \
96 mod_rel_list[(idx)].idx_ext == 0); \
97 (idx)++)
98
99 #define IS_MOD_BASE(mod, idx, offset) \
100 (mod_rel_list[(idx)].elem_base == mod->rt->elem_idx && \
101 mod_rel_list[(idx)].idx_base == mod->rt->mod_idx + (offset))
102
103 #define IS_MOD_EXTENSION(mod, idx, offset) \
104 (mod_rel_list[(idx)].elem_ext == mod->rt->elem_idx && \
105 mod_rel_list[(idx)].idx_ext == mod->rt->mod_idx + (offset))
106
107 #define RELATION_TYPE_EXT 0xFF
108
109 static const struct {
110 uint8_t *path;
111 uint8_t page;
112 } comp_data_pages[] = {
113 { "bt/mesh/cmp/0", 0, },
114 #if defined(CONFIG_BT_MESH_COMP_PAGE_1)
115 { "bt/mesh/cmp/1", 1, },
116 #endif
117 #if defined(CONFIG_BT_MESH_COMP_PAGE_2)
118 { "bt/mesh/cmp/2", 2, },
119 #endif
120 };
121
bt_mesh_model_foreach(void (* func)(const struct bt_mesh_model * mod,const struct bt_mesh_elem * elem,bool vnd,bool primary,void * user_data),void * user_data)122 void bt_mesh_model_foreach(void (*func)(const struct bt_mesh_model *mod,
123 const struct bt_mesh_elem *elem,
124 bool vnd, bool primary,
125 void *user_data),
126 void *user_data)
127 {
128 int i, j;
129
130 for (i = 0; i < dev_comp->elem_count; i++) {
131 const struct bt_mesh_elem *elem = &dev_comp->elem[i];
132
133 for (j = 0; j < elem->model_count; j++) {
134 const struct bt_mesh_model *model = &elem->models[j];
135
136 func(model, elem, false, i == 0, user_data);
137 }
138
139 for (j = 0; j < elem->vnd_model_count; j++) {
140 const struct bt_mesh_model *model = &elem->vnd_models[j];
141
142 func(model, elem, true, i == 0, user_data);
143 }
144 }
145 }
146
bt_mesh_comp_elem_size(const struct bt_mesh_elem * elem)147 static size_t bt_mesh_comp_elem_size(const struct bt_mesh_elem *elem)
148 {
149 return (4 + (elem->model_count * 2U) + (elem->vnd_model_count * 4U));
150 }
151
data_buf_add_u8_offset(struct net_buf_simple * buf,uint8_t val,size_t * offset)152 static uint8_t *data_buf_add_u8_offset(struct net_buf_simple *buf,
153 uint8_t val, size_t *offset)
154 {
155 if (*offset >= 1) {
156 *offset -= 1;
157 return NULL;
158 }
159
160 return net_buf_simple_add_u8(buf, val);
161 }
162
data_buf_add_le16_offset(struct net_buf_simple * buf,uint16_t val,size_t * offset)163 static void data_buf_add_le16_offset(struct net_buf_simple *buf,
164 uint16_t val, size_t *offset)
165 {
166 if (*offset >= 2) {
167 *offset -= 2;
168 return;
169 } else if (*offset == 1) {
170 *offset -= 1;
171 net_buf_simple_add_u8(buf, (val >> 8));
172 } else {
173 net_buf_simple_add_le16(buf, val);
174 }
175 }
176
data_buf_add_mem_offset(struct net_buf_simple * buf,const uint8_t * data,size_t len,size_t * offset)177 static void data_buf_add_mem_offset(struct net_buf_simple *buf, const uint8_t *data, size_t len,
178 size_t *offset)
179 {
180 if (*offset >= len) {
181 *offset -= len;
182 return;
183 }
184
185 net_buf_simple_add_mem(buf, data + *offset, len - *offset);
186 *offset = 0;
187 }
188
comp_add_model(const struct bt_mesh_model * mod,const struct bt_mesh_elem * elem,bool vnd,void * user_data)189 static void comp_add_model(const struct bt_mesh_model *mod, const struct bt_mesh_elem *elem,
190 bool vnd, void *user_data)
191 {
192 struct comp_foreach_model_arg *arg = user_data;
193
194 if (vnd) {
195 data_buf_add_le16_offset(arg->buf, mod->vnd.company, arg->offset);
196 data_buf_add_le16_offset(arg->buf, mod->vnd.id, arg->offset);
197 } else {
198 data_buf_add_le16_offset(arg->buf, mod->id, arg->offset);
199 }
200 }
201
202 #if defined(CONFIG_BT_MESH_LARGE_COMP_DATA_SRV)
203
metadata_model_size(const struct bt_mesh_model * mod,const struct bt_mesh_elem * elem,bool vnd)204 static size_t metadata_model_size(const struct bt_mesh_model *mod,
205 const struct bt_mesh_elem *elem, bool vnd)
206 {
207 const struct bt_mesh_models_metadata_entry *entry;
208 size_t size = 0;
209
210 if (!mod->metadata) {
211 return size;
212 }
213
214 if (vnd) {
215 size += sizeof(mod->vnd.company);
216 size += sizeof(mod->vnd.id);
217 } else {
218 size += sizeof(mod->id);
219 }
220
221 size += sizeof(uint8_t);
222
223 for (entry = mod->metadata; entry && entry->len; ++entry) {
224 size += sizeof(entry->len) + sizeof(entry->id) + entry->len;
225 }
226
227 return size;
228 }
229
bt_mesh_metadata_page_0_size(void)230 size_t bt_mesh_metadata_page_0_size(void)
231 {
232 const struct bt_mesh_comp *comp;
233 size_t size = 0;
234 int i, j;
235
236 comp = bt_mesh_comp_get();
237
238 for (i = 0; i < dev_comp->elem_count; i++) {
239 const struct bt_mesh_elem *elem = &dev_comp->elem[i];
240
241 size += sizeof(elem->model_count) +
242 sizeof(elem->vnd_model_count);
243
244 for (j = 0; j < elem->model_count; j++) {
245 const struct bt_mesh_model *model = &elem->models[j];
246
247 size += metadata_model_size(model, elem, false);
248 }
249
250 for (j = 0; j < elem->vnd_model_count; j++) {
251 const struct bt_mesh_model *model = &elem->vnd_models[j];
252
253 size += metadata_model_size(model, elem, true);
254 }
255 }
256
257 return size;
258 }
259
metadata_add_model(const struct bt_mesh_model * mod,const struct bt_mesh_elem * elem,bool vnd,void * user_data)260 static int metadata_add_model(const struct bt_mesh_model *mod,
261 const struct bt_mesh_elem *elem, bool vnd,
262 void *user_data)
263 {
264 const struct bt_mesh_models_metadata_entry *entry;
265 struct comp_foreach_model_arg *arg = user_data;
266 struct net_buf_simple *buf = arg->buf;
267 size_t *offset = arg->offset;
268 size_t model_size;
269 uint8_t count = 0;
270 uint8_t *count_ptr;
271
272 model_size = metadata_model_size(mod, elem, vnd);
273
274 if (*offset >= model_size) {
275 *offset -= model_size;
276 return 0;
277 }
278
279 if (net_buf_simple_tailroom(buf) < (model_size + BT_MESH_MIC_SHORT)) {
280 LOG_DBG("Model metadata didn't fit in the buffer");
281 return -E2BIG;
282 }
283
284 comp_add_model(mod, elem, vnd, user_data);
285
286 count_ptr = data_buf_add_u8_offset(buf, 0, offset);
287
288 if (mod->metadata) {
289 for (entry = mod->metadata; entry && entry->data != NULL; ++entry) {
290 data_buf_add_le16_offset(buf, entry->len, offset);
291 data_buf_add_le16_offset(buf, entry->id, offset);
292 data_buf_add_mem_offset(buf, entry->data, entry->len, offset);
293 count++;
294 }
295 }
296
297 if (count_ptr) {
298 *count_ptr = count;
299 }
300
301 return 0;
302 }
303
bt_mesh_metadata_get_page_0(struct net_buf_simple * buf,size_t offset)304 int bt_mesh_metadata_get_page_0(struct net_buf_simple *buf, size_t offset)
305 {
306 const struct bt_mesh_comp *comp;
307 struct comp_foreach_model_arg arg = {
308 .buf = buf,
309 .offset = &offset,
310 };
311 uint8_t *mod_count_ptr;
312 uint8_t *vnd_count_ptr;
313 int i, j, err;
314
315 comp = bt_mesh_comp_get();
316
317 for (i = 0; i < comp->elem_count; i++) {
318 const struct bt_mesh_elem *elem = &dev_comp->elem[i];
319
320 /* Check that the buffer has available tailroom for metadata item counts */
321 if (net_buf_simple_tailroom(buf) < (((offset == 0) ? 2 : (offset == 1) ? 1 : 0)
322 + BT_MESH_MIC_SHORT)) {
323 LOG_DBG("Model metadata didn't fit in the buffer");
324 return -E2BIG;
325 }
326 mod_count_ptr = data_buf_add_u8_offset(buf, 0, &offset);
327 vnd_count_ptr = data_buf_add_u8_offset(buf, 0, &offset);
328
329 for (j = 0; j < elem->model_count; j++) {
330 const struct bt_mesh_model *model = &elem->models[j];
331
332 if (!model->metadata) {
333 continue;
334 }
335
336 err = metadata_add_model(model, elem, false, &arg);
337 if (err) {
338 return err;
339 }
340
341 if (mod_count_ptr) {
342 (*mod_count_ptr) += 1;
343 }
344 }
345
346 for (j = 0; j < elem->vnd_model_count; j++) {
347 const struct bt_mesh_model *model = &elem->vnd_models[j];
348
349 if (!model->metadata) {
350 continue;
351 }
352
353 err = metadata_add_model(model, elem, true, &arg);
354 if (err) {
355 return err;
356 }
357
358 if (vnd_count_ptr) {
359 (*vnd_count_ptr) += 1;
360 }
361 }
362 }
363
364 return 0;
365 }
366 #endif
367
comp_add_elem(struct net_buf_simple * buf,const struct bt_mesh_elem * elem,size_t * offset)368 static int comp_add_elem(struct net_buf_simple *buf, const struct bt_mesh_elem *elem,
369 size_t *offset)
370 {
371 struct comp_foreach_model_arg arg = {
372 .buf = buf,
373 .offset = offset,
374 };
375 const size_t elem_size = bt_mesh_comp_elem_size(elem);
376 int i;
377
378 if (*offset >= elem_size) {
379 *offset -= elem_size;
380 return 0;
381 }
382
383 if (net_buf_simple_tailroom(buf) < ((elem_size - *offset) + BT_MESH_MIC_SHORT)) {
384 if (IS_ENABLED(CONFIG_BT_MESH_LARGE_COMP_DATA_SRV)) {
385 /* MshPRTv1.1: 4.4.1.2.2:
386 * If the complete list of models does not fit in the Data field,
387 * the element shall not be reported.
388 */
389 LOG_DBG("Element 0x%04x didn't fit in the Data field",
390 elem->rt->addr);
391 return 0;
392 }
393
394 LOG_ERR("Too large device composition");
395 return -E2BIG;
396 }
397
398 data_buf_add_le16_offset(buf, elem->loc, offset);
399
400 data_buf_add_u8_offset(buf, elem->model_count, offset);
401 data_buf_add_u8_offset(buf, elem->vnd_model_count, offset);
402
403 for (i = 0; i < elem->model_count; i++) {
404 const struct bt_mesh_model *model = &elem->models[i];
405
406 comp_add_model(model, elem, false, &arg);
407 }
408
409 for (i = 0; i < elem->vnd_model_count; i++) {
410 const struct bt_mesh_model *model = &elem->vnd_models[i];
411
412 comp_add_model(model, elem, true, &arg);
413 }
414
415 return 0;
416 }
417
bt_mesh_comp_data_get_page_0(struct net_buf_simple * buf,size_t offset)418 int bt_mesh_comp_data_get_page_0(struct net_buf_simple *buf, size_t offset)
419 {
420 uint16_t feat = 0U;
421 const struct bt_mesh_comp *comp;
422 int i;
423
424 comp = bt_mesh_comp_get();
425
426 if (IS_ENABLED(CONFIG_BT_MESH_RELAY)) {
427 feat |= BT_MESH_FEAT_RELAY;
428 }
429
430 if (IS_ENABLED(CONFIG_BT_MESH_GATT_PROXY)) {
431 feat |= BT_MESH_FEAT_PROXY;
432 }
433
434 if (IS_ENABLED(CONFIG_BT_MESH_FRIEND)) {
435 feat |= BT_MESH_FEAT_FRIEND;
436 }
437
438 if (IS_ENABLED(CONFIG_BT_MESH_LOW_POWER)) {
439 feat |= BT_MESH_FEAT_LOW_POWER;
440 }
441
442 data_buf_add_le16_offset(buf, comp->cid, &offset);
443 data_buf_add_le16_offset(buf, comp->pid, &offset);
444 data_buf_add_le16_offset(buf, comp->vid, &offset);
445 data_buf_add_le16_offset(buf, CONFIG_BT_MESH_CRPL, &offset);
446 data_buf_add_le16_offset(buf, feat, &offset);
447
448 for (i = 0; i < comp->elem_count; i++) {
449 int err;
450
451 err = comp_add_elem(buf, &comp->elem[i], &offset);
452 if (err) {
453 return err;
454 }
455 }
456
457 return 0;
458 }
459
count_mod_ext(const struct bt_mesh_model * mod,uint8_t * max_offset,uint8_t sig_offset)460 static uint8_t count_mod_ext(const struct bt_mesh_model *mod,
461 uint8_t *max_offset, uint8_t sig_offset)
462 {
463 int i;
464 uint8_t extensions = 0;
465 int8_t offset, offset_record = 0;
466
467 MOD_REL_LIST_FOR_EACH(i) {
468 if (IS_MOD_EXTENSION(mod, i, sig_offset) &&
469 mod_rel_list[i].type == RELATION_TYPE_EXT) {
470 extensions++;
471 offset = mod_rel_list[i].elem_ext -
472 mod_rel_list[i].elem_base;
473 if (abs(offset) > abs(offset_record)) {
474 offset_record = offset;
475 }
476 }
477 }
478
479 if (max_offset) {
480 memcpy(max_offset, &offset_record, sizeof(uint8_t));
481 }
482 return extensions;
483 }
484
is_cor_present(const struct bt_mesh_model * mod,uint8_t * cor_id,uint8_t sig_offset)485 static bool is_cor_present(const struct bt_mesh_model *mod, uint8_t *cor_id, uint8_t sig_offset)
486 {
487 int i;
488
489 MOD_REL_LIST_FOR_EACH(i)
490 {
491 if ((IS_MOD_BASE(mod, i, sig_offset) ||
492 IS_MOD_EXTENSION(mod, i, sig_offset)) &&
493 mod_rel_list[i].type < RELATION_TYPE_EXT) {
494 if (cor_id) {
495 memcpy(cor_id, &mod_rel_list[i].type, sizeof(uint8_t));
496 }
497 return true;
498 }
499 }
500 return false;
501 }
502
prep_model_item_header(const struct bt_mesh_model * mod,uint8_t * cor_id,uint8_t * mod_cnt,struct net_buf_simple * buf,size_t * offset,uint8_t sig_offset)503 static void prep_model_item_header(const struct bt_mesh_model *mod, uint8_t *cor_id,
504 uint8_t *mod_cnt, struct net_buf_simple *buf,
505 size_t *offset, uint8_t sig_offset)
506 {
507 uint8_t ext_mod_cnt;
508 bool cor_present;
509 uint8_t mod_elem_info = 0;
510 int8_t max_offset;
511
512 ext_mod_cnt = count_mod_ext(mod, &max_offset, sig_offset);
513 cor_present = is_cor_present(mod, cor_id, sig_offset);
514
515 mod_elem_info = ext_mod_cnt << 2;
516 if (ext_mod_cnt > 31 ||
517 max_offset > 3 ||
518 max_offset < -4) {
519 mod_elem_info |= BIT(1);
520 }
521 if (cor_present) {
522 mod_elem_info |= BIT(0);
523 }
524 data_buf_add_u8_offset(buf, mod_elem_info, offset);
525
526 if (cor_present) {
527 data_buf_add_u8_offset(buf, *cor_id, offset);
528 }
529 memset(mod_cnt, ext_mod_cnt, sizeof(uint8_t));
530 }
531
add_items_to_page(struct net_buf_simple * buf,const struct bt_mesh_model * mod,uint8_t ext_mod_cnt,size_t * offset,uint8_t sig_offset)532 static void add_items_to_page(struct net_buf_simple *buf, const struct bt_mesh_model *mod,
533 uint8_t ext_mod_cnt, size_t *offset, uint8_t sig_offset)
534 {
535 int i, elem_offset;
536 uint8_t mod_idx;
537
538 MOD_REL_LIST_FOR_EACH(i) {
539 if (IS_MOD_EXTENSION(mod, i, sig_offset) &&
540 mod_rel_list[i].type == RELATION_TYPE_EXT) {
541 elem_offset = mod->rt->elem_idx - mod_rel_list[i].elem_base;
542 mod_idx = mod_rel_list[i].idx_base;
543 if (ext_mod_cnt < 32 &&
544 elem_offset < 4 &&
545 elem_offset > -5) {
546 /* short format */
547 if (elem_offset < 0) {
548 elem_offset += 8;
549 }
550
551 elem_offset |= mod_idx << 3;
552 data_buf_add_u8_offset(buf, elem_offset, offset);
553 } else {
554 /* long format */
555 if (elem_offset < 0) {
556 elem_offset += 256;
557 }
558 data_buf_add_u8_offset(buf, elem_offset, offset);
559 data_buf_add_u8_offset(buf, mod_idx, offset);
560 }
561 }
562 }
563 }
564
mod_items_size(const struct bt_mesh_model * mod,uint8_t sig_offset)565 static size_t mod_items_size(const struct bt_mesh_model *mod, uint8_t sig_offset)
566 {
567 int i, offset;
568 size_t temp_size = 0;
569 int ext_mod_cnt = count_mod_ext(mod, NULL, sig_offset);
570
571 if (!ext_mod_cnt) {
572 return 0;
573 }
574
575 MOD_REL_LIST_FOR_EACH(i) {
576 if (IS_MOD_EXTENSION(mod, i, sig_offset)) {
577 offset = mod->rt->elem_idx - mod_rel_list[i].elem_base;
578 temp_size += (ext_mod_cnt < 32 && offset < 4 && offset > -5) ? 1 : 2;
579 }
580 }
581
582 return temp_size;
583 }
584
page1_elem_size(const struct bt_mesh_elem * elem)585 static size_t page1_elem_size(const struct bt_mesh_elem *elem)
586 {
587 size_t temp_size = 2;
588
589 for (int i = 0; i < elem->model_count; i++) {
590 temp_size += is_cor_present(&elem->models[i], NULL, 0) ? 2 : 1;
591 temp_size += mod_items_size(&elem->models[i], 0);
592 }
593
594 for (int i = 0; i < elem->vnd_model_count; i++) {
595 temp_size += is_cor_present(&elem->vnd_models[i], NULL, elem->model_count) ? 2 : 1;
596 temp_size += mod_items_size(&elem->vnd_models[i], elem->model_count);
597 }
598
599 return temp_size;
600 }
601
bt_mesh_comp_data_get_page_1(struct net_buf_simple * buf,size_t offset)602 static int bt_mesh_comp_data_get_page_1(struct net_buf_simple *buf, size_t offset)
603 {
604 const struct bt_mesh_comp *comp;
605 uint8_t cor_id = 0;
606 uint8_t ext_mod_cnt = 0;
607 int i, j;
608
609 comp = bt_mesh_comp_get();
610
611 for (i = 0; i < comp->elem_count; i++) {
612 size_t elem_size = page1_elem_size(&comp->elem[i]);
613
614 if (offset >= elem_size) {
615 offset -= elem_size;
616 continue;
617 }
618
619 if (net_buf_simple_tailroom(buf) < ((elem_size - offset) + BT_MESH_MIC_SHORT)) {
620 if (IS_ENABLED(CONFIG_BT_MESH_LARGE_COMP_DATA_SRV)) {
621 /* MshPRTv1.1: 4.4.1.2.2:
622 * If the complete list of models does not fit in the Data field,
623 * the element shall not be reported.
624 */
625 LOG_DBG("Element 0x%04x didn't fit in the Data field",
626 comp->elem[i].rt->addr);
627 return 0;
628 }
629
630 LOG_ERR("Too large device composition");
631 return -E2BIG;
632 }
633
634 data_buf_add_u8_offset(buf, comp->elem[i].model_count, &offset);
635 data_buf_add_u8_offset(buf, comp->elem[i].vnd_model_count, &offset);
636 for (j = 0; j < comp->elem[i].model_count; j++) {
637 prep_model_item_header(&comp->elem[i].models[j], &cor_id, &ext_mod_cnt, buf,
638 &offset, 0);
639 if (ext_mod_cnt != 0) {
640 add_items_to_page(buf, &comp->elem[i].models[j], ext_mod_cnt,
641 &offset,
642 0);
643 }
644 }
645
646 for (j = 0; j < comp->elem[i].vnd_model_count; j++) {
647 prep_model_item_header(&comp->elem[i].vnd_models[j], &cor_id, &ext_mod_cnt,
648 buf, &offset,
649 comp->elem[i].model_count);
650 if (ext_mod_cnt != 0) {
651 add_items_to_page(buf, &comp->elem[i].vnd_models[j], ext_mod_cnt,
652 &offset,
653 comp->elem[i].model_count);
654 }
655 }
656 }
657 return 0;
658 }
659
bt_mesh_comp_data_get_page_2(struct net_buf_simple * buf,size_t offset)660 static int bt_mesh_comp_data_get_page_2(struct net_buf_simple *buf, size_t offset)
661 {
662 if (!dev_comp2) {
663 LOG_ERR("Composition data P2 not registered");
664 return -ENODEV;
665 }
666
667 size_t elem_size;
668
669 for (int i = 0; i < dev_comp2->record_cnt; i++) {
670 elem_size =
671 8 + dev_comp2->record[i].elem_offset_cnt + dev_comp2->record[i].data_len;
672 if (offset >= elem_size) {
673 offset -= elem_size;
674 continue;
675 }
676
677 if (net_buf_simple_tailroom(buf) < ((elem_size - offset) + BT_MESH_MIC_SHORT)) {
678 if (IS_ENABLED(CONFIG_BT_MESH_LARGE_COMP_DATA_SRV)) {
679 /* MshPRTv1.1: 4.4.1.2.2:
680 * If the complete list of models does not fit in the Data field,
681 * the element shall not be reported.
682 */
683 LOG_DBG("Record 0x%04x didn't fit in the Data field", i);
684 return 0;
685 }
686
687 LOG_ERR("Too large device composition");
688 return -E2BIG;
689 }
690
691 data_buf_add_le16_offset(buf, dev_comp2->record[i].id, &offset);
692 data_buf_add_u8_offset(buf, dev_comp2->record[i].version.x, &offset);
693 data_buf_add_u8_offset(buf, dev_comp2->record[i].version.y, &offset);
694 data_buf_add_u8_offset(buf, dev_comp2->record[i].version.z, &offset);
695 data_buf_add_u8_offset(buf, dev_comp2->record[i].elem_offset_cnt, &offset);
696 if (dev_comp2->record[i].elem_offset_cnt) {
697 data_buf_add_mem_offset(buf, dev_comp2->record[i].elem_offset,
698 dev_comp2->record[i].elem_offset_cnt, &offset);
699 }
700
701 data_buf_add_le16_offset(buf, dev_comp2->record[i].data_len, &offset);
702 if (dev_comp2->record[i].data_len) {
703 data_buf_add_mem_offset(buf, dev_comp2->record[i].data,
704 dev_comp2->record[i].data_len, &offset);
705 }
706 }
707
708 return 0;
709 }
710
bt_mesh_model_pub_period_get(const struct bt_mesh_model * mod)711 int32_t bt_mesh_model_pub_period_get(const struct bt_mesh_model *mod)
712 {
713 int32_t period;
714
715 if (!mod->pub) {
716 return 0;
717 }
718
719 switch (mod->pub->period >> 6) {
720 case 0x00:
721 /* 1 step is 100 ms */
722 period = (mod->pub->period & BIT_MASK(6)) * 100U;
723 break;
724 case 0x01:
725 /* 1 step is 1 second */
726 period = (mod->pub->period & BIT_MASK(6)) * MSEC_PER_SEC;
727 break;
728 case 0x02:
729 /* 1 step is 10 seconds */
730 period = (mod->pub->period & BIT_MASK(6)) * 10U * MSEC_PER_SEC;
731 break;
732 case 0x03:
733 /* 1 step is 10 minutes */
734 period = (mod->pub->period & BIT_MASK(6)) * 600U * MSEC_PER_SEC;
735 break;
736 default:
737 CODE_UNREACHABLE;
738 }
739
740 if (mod->pub->fast_period) {
741 if (!period) {
742 return 0;
743 }
744
745 return MAX(period >> mod->pub->period_div, 100);
746 } else {
747 return period;
748 }
749 }
750
next_period(const struct bt_mesh_model * mod)751 static int32_t next_period(const struct bt_mesh_model *mod)
752 {
753 struct bt_mesh_model_pub *pub = mod->pub;
754 uint32_t period = 0;
755 uint32_t elapsed;
756
757 elapsed = k_uptime_get_32() - pub->period_start;
758 LOG_DBG("Publishing took %ums", elapsed);
759
760 if (mod->pub->count) {
761 /* If a message is to be retransmitted, period should include time since the first
762 * publication until the last publication.
763 */
764 period = BT_MESH_PUB_TRANSMIT_INT(mod->pub->retransmit);
765 period *= BT_MESH_PUB_MSG_NUM(mod->pub);
766
767 if (period && elapsed >= period) {
768 LOG_WRN("Retransmission interval is too short");
769
770 if (!!pub->delayable) {
771 LOG_WRN("Publication period is too short for"
772 " retransmissions");
773 }
774
775 /* Keep retransmitting the message with the interval sacrificing the
776 * next publication period start.
777 */
778 return BT_MESH_PUB_TRANSMIT_INT(mod->pub->retransmit);
779 }
780 }
781
782 if (!period) {
783 period = bt_mesh_model_pub_period_get(mod);
784 if (!period) {
785 return 0;
786 }
787 }
788
789 if (elapsed >= period) {
790 LOG_WRN("Publication sending took longer than the period");
791
792 if (!!pub->delayable) {
793 LOG_WRN("Publication period is too short to be delayable");
794 }
795
796 /* Return smallest positive number since 0 means disabled */
797 return 1;
798 }
799
800 return period - elapsed;
801 }
802
publish_sent(int err,void * user_data)803 static void publish_sent(int err, void *user_data)
804 {
805 const struct bt_mesh_model *mod = user_data;
806 int32_t delay;
807
808 LOG_DBG("err %d, time %u", err, k_uptime_get_32());
809
810 delay = next_period(mod);
811
812 if (delay) {
813 LOG_DBG("Publishing next time in %dms", delay);
814 /* Using schedule() in case the application has already called
815 * bt_mesh_publish, and a publication is pending.
816 */
817 k_work_schedule(&mod->pub->timer, K_MSEC(delay));
818 }
819 }
820
publish_start(uint16_t duration,int err,void * user_data)821 static void publish_start(uint16_t duration, int err, void *user_data)
822 {
823 if (err) {
824 LOG_ERR("Failed to publish: err %d", err);
825 publish_sent(err, user_data);
826 return;
827 }
828 }
829
830 static const struct bt_mesh_send_cb pub_sent_cb = {
831 .start = publish_start,
832 .end = publish_sent,
833 };
834
publish_transmit(const struct bt_mesh_model * mod)835 static int publish_transmit(const struct bt_mesh_model *mod)
836 {
837 NET_BUF_SIMPLE_DEFINE(sdu, BT_MESH_TX_SDU_MAX);
838 struct bt_mesh_model_pub *pub = mod->pub;
839 struct bt_mesh_msg_ctx ctx = BT_MESH_MSG_CTX_INIT_PUB(pub);
840 struct bt_mesh_net_tx tx = {
841 .ctx = &ctx,
842 .src = bt_mesh_model_elem(mod)->rt->addr,
843 .friend_cred = pub->cred,
844 };
845
846 net_buf_simple_add_mem(&sdu, pub->msg->data, pub->msg->len);
847
848 return bt_mesh_trans_send(&tx, &sdu, &pub_sent_cb, (void *)mod);
849 }
850
pub_period_start(struct bt_mesh_model_pub * pub)851 static int pub_period_start(struct bt_mesh_model_pub *pub)
852 {
853 int err;
854
855 pub->count = BT_MESH_PUB_TRANSMIT_COUNT(pub->retransmit);
856
857 if (!pub->update) {
858 return 0;
859 }
860
861 err = pub->update(pub->mod);
862
863 pub->period_start = k_uptime_get_32();
864
865 if (err) {
866 /* Skip this publish attempt. */
867 LOG_DBG("Update failed, skipping publish (err: %d)", err);
868 pub->count = 0;
869 publish_sent(err, (void *)pub->mod);
870 return err;
871 }
872
873 return 0;
874 }
875
pub_delay_get(int random_delay_window)876 static uint16_t pub_delay_get(int random_delay_window)
877 {
878 if (!IS_ENABLED(CONFIG_BT_MESH_DELAYABLE_PUBLICATION)) {
879 return 0;
880 }
881
882 uint16_t num = 0;
883
884 (void)bt_rand(&num, sizeof(num));
885
886 return 20 + (num % random_delay_window);
887 }
888
pub_delay_schedule(struct bt_mesh_model_pub * pub,int delay)889 static int pub_delay_schedule(struct bt_mesh_model_pub *pub, int delay)
890 {
891 uint16_t random;
892 int err;
893
894 if (!IS_ENABLED(CONFIG_BT_MESH_DELAYABLE_PUBLICATION)) {
895 return -ENOTSUP;
896 }
897
898 random = pub_delay_get(delay);
899 err = k_work_reschedule(&pub->timer, K_MSEC(random));
900 if (err < 0) {
901 LOG_ERR("Unable to delay publication (err %d)", err);
902 return err;
903 }
904
905 LOG_DBG("Publication delayed by %dms", random);
906 return 0;
907 }
908
mod_publish(struct k_work * work)909 static void mod_publish(struct k_work *work)
910 {
911 struct k_work_delayable *dwork = k_work_delayable_from_work(work);
912 struct bt_mesh_model_pub *pub = CONTAINER_OF(dwork,
913 struct bt_mesh_model_pub,
914 timer);
915 int err;
916
917 if (pub->addr == BT_MESH_ADDR_UNASSIGNED ||
918 atomic_test_bit(bt_mesh.flags, BT_MESH_SUSPENDED)) {
919 /* Publication is no longer active, but the cancellation of the
920 * delayed work failed. Abandon recurring timer.
921 */
922 return;
923 }
924
925 LOG_DBG("timestamp: %u", k_uptime_get_32());
926
927 if (pub->count) {
928 pub->count--;
929
930 if (pub->retr_update && pub->update &&
931 bt_mesh_model_pub_is_retransmission(pub->mod)) {
932 err = pub->update(pub->mod);
933 if (err) {
934 publish_sent(err, (void *)pub->mod);
935 return;
936 }
937 }
938 } else {
939 /* First publication in this period */
940 err = pub_period_start(pub);
941 if (err) {
942 return;
943 }
944
945 /* Delay the first publication in a period. */
946 if (!!pub->delayable && !pub_delay_schedule(pub, RANDOM_DELAY_SHORT)) {
947 /* Increment count as it would do BT_MESH_PUB_MSG_TOTAL */
948 pub->count++;
949 return;
950 }
951 }
952
953 err = publish_transmit(pub->mod);
954 if (err) {
955 LOG_ERR("Failed to publish (err %d)", err);
956 publish_sent(err, (void *)pub->mod);
957 }
958 }
959
bt_mesh_model_elem(const struct bt_mesh_model * mod)960 const struct bt_mesh_elem *bt_mesh_model_elem(const struct bt_mesh_model *mod)
961 {
962 return &dev_comp->elem[mod->rt->elem_idx];
963 }
964
bt_mesh_model_get(bool vnd,uint8_t elem_idx,uint8_t mod_idx)965 const struct bt_mesh_model *bt_mesh_model_get(bool vnd, uint8_t elem_idx, uint8_t mod_idx)
966 {
967 const struct bt_mesh_elem *elem;
968
969 if (elem_idx >= dev_comp->elem_count) {
970 LOG_ERR("Invalid element index %u", elem_idx);
971 return NULL;
972 }
973
974 elem = &dev_comp->elem[elem_idx];
975
976 if (vnd) {
977 if (mod_idx >= elem->vnd_model_count) {
978 LOG_ERR("Invalid vendor model index %u", mod_idx);
979 return NULL;
980 }
981
982 return &elem->vnd_models[mod_idx];
983 } else {
984 if (mod_idx >= elem->model_count) {
985 LOG_ERR("Invalid SIG model index %u", mod_idx);
986 return NULL;
987 }
988
989 return &elem->models[mod_idx];
990 }
991 }
992
993 #if defined(CONFIG_BT_MESH_MODEL_VND_MSG_CID_FORCE)
bt_mesh_vnd_mod_msg_cid_check(const struct bt_mesh_model * mod)994 static int bt_mesh_vnd_mod_msg_cid_check(const struct bt_mesh_model *mod)
995 {
996 uint16_t cid;
997 const struct bt_mesh_model_op *op;
998
999 for (op = mod->op; op->func; op++) {
1000 cid = (uint16_t)(op->opcode & 0xffff);
1001
1002 if (cid == mod->vnd.company) {
1003 continue;
1004 }
1005
1006 LOG_ERR("Invalid vendor model(company:0x%04x"
1007 " id:0x%04x) message opcode 0x%08x",
1008 mod->vnd.company, mod->vnd.id, op->opcode);
1009
1010 return -EINVAL;
1011 }
1012
1013 return 0;
1014 }
1015 #endif
1016
mod_init(const struct bt_mesh_model * mod,const struct bt_mesh_elem * elem,bool vnd,bool primary,void * user_data)1017 static void mod_init(const struct bt_mesh_model *mod, const struct bt_mesh_elem *elem,
1018 bool vnd, bool primary, void *user_data)
1019 {
1020 int i;
1021 int *err = user_data;
1022
1023 if (*err) {
1024 return;
1025 }
1026
1027 if (mod->pub) {
1028 mod->pub->mod = mod;
1029 k_work_init_delayable(&mod->pub->timer, mod_publish);
1030 }
1031
1032 for (i = 0; i < mod->keys_cnt; i++) {
1033 mod->keys[i] = BT_MESH_KEY_UNUSED;
1034 }
1035
1036 mod->rt->elem_idx = elem - dev_comp->elem;
1037 if (vnd) {
1038 mod->rt->mod_idx = mod - elem->vnd_models;
1039
1040 if (IS_ENABLED(CONFIG_BT_MESH_MODEL_VND_MSG_CID_FORCE)) {
1041 *err = bt_mesh_vnd_mod_msg_cid_check(mod);
1042 if (*err) {
1043 return;
1044 }
1045 }
1046
1047 } else {
1048 mod->rt->mod_idx = mod - elem->models;
1049 }
1050
1051 if (mod->cb && mod->cb->init) {
1052 *err = mod->cb->init(mod);
1053 }
1054 }
1055
bt_mesh_comp_register(const struct bt_mesh_comp * comp)1056 int bt_mesh_comp_register(const struct bt_mesh_comp *comp)
1057 {
1058 int err;
1059
1060 /* There must be at least one element */
1061 if (!comp || !comp->elem_count) {
1062 return -EINVAL;
1063 }
1064
1065 dev_comp = comp;
1066
1067 err = 0;
1068
1069 if (MOD_REL_LIST_SIZE > 0) {
1070 memset(mod_rel_list, 0, sizeof(mod_rel_list));
1071 }
1072
1073 bt_mesh_model_foreach(mod_init, &err);
1074
1075 if (MOD_REL_LIST_SIZE > 0) {
1076 int i;
1077
1078 MOD_REL_LIST_FOR_EACH(i) {
1079 LOG_DBG("registered %s",
1080 mod_rel_list[i].type < RELATION_TYPE_EXT ?
1081 "correspondence" : "extension");
1082 LOG_DBG("\tbase: elem %u idx %u",
1083 mod_rel_list[i].elem_base,
1084 mod_rel_list[i].idx_base);
1085 LOG_DBG("\text: elem %u idx %u",
1086 mod_rel_list[i].elem_ext,
1087 mod_rel_list[i].idx_ext);
1088 }
1089 if (i < MOD_REL_LIST_SIZE) {
1090 LOG_WRN("Unused space in relation list: %d",
1091 MOD_REL_LIST_SIZE - i);
1092 }
1093 }
1094
1095 return err;
1096 }
1097
bt_mesh_comp2_register(const struct bt_mesh_comp2 * comp2)1098 int bt_mesh_comp2_register(const struct bt_mesh_comp2 *comp2)
1099 {
1100 if (!IS_ENABLED(CONFIG_BT_MESH_COMP_PAGE_2)) {
1101 return -EINVAL;
1102 }
1103
1104 dev_comp2 = comp2;
1105
1106 return 0;
1107 }
1108
bt_mesh_comp_provision(uint16_t addr)1109 void bt_mesh_comp_provision(uint16_t addr)
1110 {
1111 int i;
1112
1113 dev_primary_addr = addr;
1114
1115 LOG_DBG("addr 0x%04x elem_count %zu", addr, dev_comp->elem_count);
1116
1117 for (i = 0; i < dev_comp->elem_count; i++) {
1118 const struct bt_mesh_elem *elem = &dev_comp->elem[i];
1119
1120 elem->rt->addr = addr++;
1121
1122 LOG_DBG("addr 0x%04x mod_count %u vnd_mod_count %u", elem->rt->addr,
1123 elem->model_count, elem->vnd_model_count);
1124 }
1125 }
1126
bt_mesh_comp_unprovision(void)1127 void bt_mesh_comp_unprovision(void)
1128 {
1129 LOG_DBG("");
1130
1131 dev_primary_addr = BT_MESH_ADDR_UNASSIGNED;
1132
1133 for (int i = 0; i < dev_comp->elem_count; i++) {
1134 const struct bt_mesh_elem *elem = &dev_comp->elem[i];
1135
1136 elem->rt->addr = BT_MESH_ADDR_UNASSIGNED;
1137 }
1138 }
1139
bt_mesh_primary_addr(void)1140 uint16_t bt_mesh_primary_addr(void)
1141 {
1142 return dev_primary_addr;
1143 }
1144
model_group_get(const struct bt_mesh_model * mod,uint16_t addr)1145 static uint16_t *model_group_get(const struct bt_mesh_model *mod, uint16_t addr)
1146 {
1147 int i;
1148
1149 for (i = 0; i < mod->groups_cnt; i++) {
1150 if (mod->groups[i] == addr) {
1151 return &mod->groups[i];
1152 }
1153 }
1154
1155 return NULL;
1156 }
1157
1158 struct find_group_visitor_ctx {
1159 uint16_t *entry;
1160 const struct bt_mesh_model *mod;
1161 uint16_t addr;
1162 };
1163
find_group_mod_visitor(const struct bt_mesh_model * mod,void * user_data)1164 static enum bt_mesh_walk find_group_mod_visitor(const struct bt_mesh_model *mod, void *user_data)
1165 {
1166 struct find_group_visitor_ctx *ctx = user_data;
1167
1168 if (mod->rt->elem_idx != ctx->mod->rt->elem_idx) {
1169 return BT_MESH_WALK_CONTINUE;
1170 }
1171
1172 ctx->entry = model_group_get(mod, ctx->addr);
1173 if (ctx->entry) {
1174 ctx->mod = mod;
1175 return BT_MESH_WALK_STOP;
1176 }
1177
1178 return BT_MESH_WALK_CONTINUE;
1179 }
1180
bt_mesh_model_find_group(const struct bt_mesh_model ** mod,uint16_t addr)1181 uint16_t *bt_mesh_model_find_group(const struct bt_mesh_model **mod, uint16_t addr)
1182 {
1183 struct find_group_visitor_ctx ctx = {
1184 .mod = *mod,
1185 .entry = NULL,
1186 .addr = addr,
1187 };
1188
1189 bt_mesh_model_extensions_walk(*mod, find_group_mod_visitor, &ctx);
1190
1191 *mod = ctx.mod;
1192 return ctx.entry;
1193 }
1194
1195 #if CONFIG_BT_MESH_LABEL_COUNT > 0
model_uuid_get(const struct bt_mesh_model * mod,const uint8_t * uuid)1196 static const uint8_t **model_uuid_get(const struct bt_mesh_model *mod, const uint8_t *uuid)
1197 {
1198 int i;
1199
1200 for (i = 0; i < CONFIG_BT_MESH_LABEL_COUNT; i++) {
1201 if (mod->uuids[i] == uuid) {
1202 /* If we are looking for a new entry, ensure that we find a model where
1203 * there is empty entry in both, uuids and groups list.
1204 */
1205 if (uuid == NULL && !model_group_get(mod, BT_MESH_ADDR_UNASSIGNED)) {
1206 continue;
1207 }
1208
1209 return &mod->uuids[i];
1210 }
1211 }
1212
1213 return NULL;
1214 }
1215
1216 struct find_uuid_visitor_ctx {
1217 const uint8_t **entry;
1218 const struct bt_mesh_model *mod;
1219 const uint8_t *uuid;
1220 };
1221
find_uuid_mod_visitor(const struct bt_mesh_model * mod,void * user_data)1222 static enum bt_mesh_walk find_uuid_mod_visitor(const struct bt_mesh_model *mod, void *user_data)
1223 {
1224 struct find_uuid_visitor_ctx *ctx = user_data;
1225
1226 if (mod->rt->elem_idx != ctx->mod->rt->elem_idx) {
1227 return BT_MESH_WALK_CONTINUE;
1228 }
1229
1230 ctx->entry = model_uuid_get(mod, ctx->uuid);
1231 if (ctx->entry) {
1232 ctx->mod = mod;
1233 return BT_MESH_WALK_STOP;
1234 }
1235
1236 return BT_MESH_WALK_CONTINUE;
1237 }
1238 #endif /* CONFIG_BT_MESH_LABEL_COUNT > 0 */
1239
bt_mesh_model_find_uuid(const struct bt_mesh_model ** mod,const uint8_t * uuid)1240 const uint8_t **bt_mesh_model_find_uuid(const struct bt_mesh_model **mod, const uint8_t *uuid)
1241 {
1242 #if CONFIG_BT_MESH_LABEL_COUNT > 0
1243 struct find_uuid_visitor_ctx ctx = {
1244 .mod = *mod,
1245 .entry = NULL,
1246 .uuid = uuid,
1247 };
1248
1249 bt_mesh_model_extensions_walk(*mod, find_uuid_mod_visitor, &ctx);
1250
1251 *mod = ctx.mod;
1252 return ctx.entry;
1253 #else
1254 return NULL;
1255 #endif
1256 }
1257
bt_mesh_elem_find_group(const struct bt_mesh_elem * elem,uint16_t group_addr)1258 static const struct bt_mesh_model *bt_mesh_elem_find_group(const struct bt_mesh_elem *elem,
1259 uint16_t group_addr)
1260 {
1261 const struct bt_mesh_model *model;
1262 uint16_t *match;
1263 int i;
1264
1265 for (i = 0; i < elem->model_count; i++) {
1266 model = &elem->models[i];
1267
1268 match = model_group_get(model, group_addr);
1269 if (match) {
1270 return model;
1271 }
1272 }
1273
1274 for (i = 0; i < elem->vnd_model_count; i++) {
1275 model = &elem->vnd_models[i];
1276
1277 match = model_group_get(model, group_addr);
1278 if (match) {
1279 return model;
1280 }
1281 }
1282
1283 return NULL;
1284 }
1285
bt_mesh_elem_find(uint16_t addr)1286 const struct bt_mesh_elem *bt_mesh_elem_find(uint16_t addr)
1287 {
1288 uint16_t index;
1289
1290 if (!BT_MESH_ADDR_IS_UNICAST(addr)) {
1291 return NULL;
1292 }
1293
1294 index = addr - dev_comp->elem[0].rt->addr;
1295 if (index >= dev_comp->elem_count) {
1296 return NULL;
1297 }
1298
1299 return &dev_comp->elem[index];
1300 }
1301
bt_mesh_has_addr(uint16_t addr)1302 bool bt_mesh_has_addr(uint16_t addr)
1303 {
1304 uint16_t index;
1305
1306 if (BT_MESH_ADDR_IS_UNICAST(addr)) {
1307 return bt_mesh_elem_find(addr) != NULL;
1308 }
1309
1310 if (IS_ENABLED(CONFIG_BT_MESH_ACCESS_LAYER_MSG) && msg_cb) {
1311 return true;
1312 }
1313
1314 for (index = 0; index < dev_comp->elem_count; index++) {
1315 const struct bt_mesh_elem *elem = &dev_comp->elem[index];
1316
1317 if (bt_mesh_elem_find_group(elem, addr)) {
1318 return true;
1319 }
1320 }
1321
1322 return false;
1323 }
1324
1325 #if defined(CONFIG_BT_MESH_ACCESS_LAYER_MSG)
bt_mesh_msg_cb_set(void (* cb)(uint32_t opcode,struct bt_mesh_msg_ctx * ctx,struct net_buf_simple * buf))1326 void bt_mesh_msg_cb_set(void (*cb)(uint32_t opcode, struct bt_mesh_msg_ctx *ctx,
1327 struct net_buf_simple *buf))
1328 {
1329 msg_cb = cb;
1330 }
1331 #endif
1332
bt_mesh_access_send(struct bt_mesh_msg_ctx * ctx,struct net_buf_simple * buf,uint16_t src_addr,const struct bt_mesh_send_cb * cb,void * cb_data)1333 int bt_mesh_access_send(struct bt_mesh_msg_ctx *ctx, struct net_buf_simple *buf, uint16_t src_addr,
1334 const struct bt_mesh_send_cb *cb, void *cb_data)
1335 {
1336 struct bt_mesh_net_tx tx = {
1337 .ctx = ctx,
1338 .src = src_addr,
1339 };
1340
1341 LOG_DBG("net_idx 0x%04x app_idx 0x%04x dst 0x%04x", tx.ctx->net_idx, tx.ctx->app_idx,
1342 tx.ctx->addr);
1343 LOG_DBG("len %u: %s", buf->len, bt_hex(buf->data, buf->len));
1344
1345 if (!bt_mesh_is_provisioned()) {
1346 LOG_ERR("Local node is not yet provisioned");
1347 return -EAGAIN;
1348 }
1349
1350 return bt_mesh_trans_send(&tx, buf, cb, cb_data);
1351 }
1352
bt_mesh_elem_count(void)1353 uint8_t bt_mesh_elem_count(void)
1354 {
1355 return dev_comp->elem_count;
1356 }
1357
bt_mesh_model_has_key(const struct bt_mesh_model * mod,uint16_t key)1358 bool bt_mesh_model_has_key(const struct bt_mesh_model *mod, uint16_t key)
1359 {
1360 int i;
1361
1362 for (i = 0; i < mod->keys_cnt; i++) {
1363 if (mod->keys[i] == key ||
1364 (mod->keys[i] == BT_MESH_KEY_DEV_ANY &&
1365 BT_MESH_IS_DEV_KEY(key))) {
1366 return true;
1367 }
1368 }
1369
1370 return false;
1371 }
1372
model_has_dst(const struct bt_mesh_model * mod,uint16_t dst,const uint8_t * uuid)1373 static bool model_has_dst(const struct bt_mesh_model *mod, uint16_t dst, const uint8_t *uuid)
1374 {
1375 if (BT_MESH_ADDR_IS_UNICAST(dst)) {
1376 return (dev_comp->elem[mod->rt->elem_idx].rt->addr == dst);
1377 } else if (BT_MESH_ADDR_IS_VIRTUAL(dst)) {
1378 return !!bt_mesh_model_find_uuid(&mod, uuid);
1379 } else if (BT_MESH_ADDR_IS_GROUP(dst) ||
1380 (BT_MESH_ADDR_IS_FIXED_GROUP(dst) && mod->rt->elem_idx != 0)) {
1381 return !!bt_mesh_model_find_group(&mod, dst);
1382 }
1383
1384 /* If a message with a fixed group address is sent to the access layer,
1385 * the lower layers have already confirmed that we are subscribing to
1386 * it. All models on the primary element should receive the message.
1387 */
1388 return mod->rt->elem_idx == 0;
1389 }
1390
find_op(const struct bt_mesh_elem * elem,uint32_t opcode,const struct bt_mesh_model ** model)1391 static const struct bt_mesh_model_op *find_op(const struct bt_mesh_elem *elem,
1392 uint32_t opcode, const struct bt_mesh_model **model)
1393 {
1394 uint8_t i;
1395 uint8_t count;
1396 /* This value shall not be used in shipping end products. */
1397 uint32_t cid = UINT32_MAX;
1398 const struct bt_mesh_model *models;
1399
1400 /* SIG models cannot contain 3-byte (vendor) OpCodes, and
1401 * vendor models cannot contain SIG (1- or 2-byte) OpCodes, so
1402 * we only need to do the lookup in one of the model lists.
1403 */
1404 if (BT_MESH_MODEL_OP_LEN(opcode) < 3) {
1405 models = elem->models;
1406 count = elem->model_count;
1407 } else {
1408 models = elem->vnd_models;
1409 count = elem->vnd_model_count;
1410
1411 cid = (uint16_t)(opcode & 0xffff);
1412 }
1413
1414 for (i = 0U; i < count; i++) {
1415
1416 const struct bt_mesh_model_op *op;
1417
1418 if (IS_ENABLED(CONFIG_BT_MESH_MODEL_VND_MSG_CID_FORCE) &&
1419 cid != UINT32_MAX &&
1420 cid != models[i].vnd.company) {
1421 continue;
1422 }
1423
1424 *model = &models[i];
1425
1426 for (op = (*model)->op; op->func; op++) {
1427 if (op->opcode == opcode) {
1428 return op;
1429 }
1430 }
1431 }
1432
1433 *model = NULL;
1434 return NULL;
1435 }
1436
get_opcode(struct net_buf_simple * buf,uint32_t * opcode)1437 static int get_opcode(struct net_buf_simple *buf, uint32_t *opcode)
1438 {
1439 switch (buf->data[0] >> 6) {
1440 case 0x00:
1441 case 0x01:
1442 if (buf->data[0] == 0x7f) {
1443 LOG_ERR("Ignoring RFU OpCode");
1444 return -EINVAL;
1445 }
1446
1447 *opcode = net_buf_simple_pull_u8(buf);
1448 return 0;
1449 case 0x02:
1450 if (buf->len < 2) {
1451 LOG_ERR("Too short payload for 2-octet OpCode");
1452 return -EINVAL;
1453 }
1454
1455 *opcode = net_buf_simple_pull_be16(buf);
1456 return 0;
1457 case 0x03:
1458 if (buf->len < 3) {
1459 LOG_ERR("Too short payload for 3-octet OpCode");
1460 return -EINVAL;
1461 }
1462
1463 *opcode = net_buf_simple_pull_u8(buf) << 16;
1464 /* Using LE for the CID since the model layer is defined as
1465 * little-endian in the mesh spec and using BT_MESH_MODEL_OP_3
1466 * will declare the opcode in this way.
1467 */
1468 *opcode |= net_buf_simple_pull_le16(buf);
1469 return 0;
1470 }
1471
1472 CODE_UNREACHABLE;
1473 }
1474
element_model_recv(struct bt_mesh_msg_ctx * ctx,struct net_buf_simple * buf,const struct bt_mesh_elem * elem,uint32_t opcode)1475 static int element_model_recv(struct bt_mesh_msg_ctx *ctx, struct net_buf_simple *buf,
1476 const struct bt_mesh_elem *elem, uint32_t opcode)
1477 {
1478 const struct bt_mesh_model_op *op;
1479 const struct bt_mesh_model *model;
1480 struct net_buf_simple_state state;
1481 int err;
1482
1483 op = find_op(elem, opcode, &model);
1484 if (!op) {
1485 LOG_DBG("No OpCode 0x%08x for elem 0x%02x", opcode, elem->rt->addr);
1486 return ACCESS_STATUS_WRONG_OPCODE;
1487 }
1488
1489 if (!bt_mesh_model_has_key(model, ctx->app_idx)) {
1490 LOG_DBG("Model at 0x%04x is not bound to app idx %d", elem->rt->addr, ctx->app_idx);
1491 return ACCESS_STATUS_WRONG_KEY;
1492 }
1493
1494 if (!model_has_dst(model, ctx->recv_dst, ctx->uuid)) {
1495 LOG_DBG("Dst addr 0x%02x is invalid for model at 0x%04x", ctx->recv_dst,
1496 elem->rt->addr);
1497 return ACCESS_STATUS_INVALID_ADDRESS;
1498 }
1499
1500 if ((op->len >= 0) && (buf->len < (size_t)op->len)) {
1501 LOG_ERR("Too short message for OpCode 0x%08x", opcode);
1502 return ACCESS_STATUS_MESSAGE_NOT_UNDERSTOOD;
1503 } else if ((op->len < 0) && (buf->len != (size_t)(-op->len))) {
1504 LOG_ERR("Invalid message size for OpCode 0x%08x", opcode);
1505 return ACCESS_STATUS_MESSAGE_NOT_UNDERSTOOD;
1506 }
1507
1508 if (IS_ENABLED(CONFIG_BT_MESH_ACCESS_DELAYABLE_MSG_CTX_ENABLED)) {
1509 ctx->rnd_delay = true;
1510 }
1511
1512 net_buf_simple_save(buf, &state);
1513 err = op->func(model, ctx, buf);
1514 net_buf_simple_restore(buf, &state);
1515
1516 if (err) {
1517 return ACCESS_STATUS_MESSAGE_NOT_UNDERSTOOD;
1518 }
1519 return ACCESS_STATUS_SUCCESS;
1520 }
1521
bt_mesh_model_recv(struct bt_mesh_msg_ctx * ctx,struct net_buf_simple * buf)1522 int bt_mesh_model_recv(struct bt_mesh_msg_ctx *ctx, struct net_buf_simple *buf)
1523 {
1524 int err = ACCESS_STATUS_SUCCESS;
1525 uint32_t opcode;
1526 uint16_t index;
1527
1528 LOG_DBG("app_idx 0x%04x src 0x%04x dst 0x%04x", ctx->app_idx, ctx->addr,
1529 ctx->recv_dst);
1530 LOG_DBG("len %u: %s", buf->len, bt_hex(buf->data, buf->len));
1531
1532 if (IS_ENABLED(CONFIG_BT_TESTING)) {
1533 bt_mesh_test_model_recv(ctx->addr, ctx->recv_dst, buf->data, buf->len);
1534 }
1535
1536 if (get_opcode(buf, &opcode) < 0) {
1537 LOG_WRN("Unable to decode OpCode");
1538 return ACCESS_STATUS_WRONG_OPCODE;
1539 }
1540
1541 LOG_DBG("OpCode 0x%08x", opcode);
1542
1543 if (BT_MESH_ADDR_IS_UNICAST(ctx->recv_dst)) {
1544 index = ctx->recv_dst - dev_comp->elem[0].rt->addr;
1545
1546 if (index >= dev_comp->elem_count) {
1547 LOG_ERR("Invalid address 0x%02x", ctx->recv_dst);
1548 return ACCESS_STATUS_INVALID_ADDRESS;
1549 } else {
1550 const struct bt_mesh_elem *elem = &dev_comp->elem[index];
1551
1552 err = element_model_recv(ctx, buf, elem, opcode);
1553 }
1554 } else {
1555 err = ACCESS_STATUS_MESSAGE_NOT_UNDERSTOOD;
1556 for (index = 0; index < dev_comp->elem_count; index++) {
1557 const struct bt_mesh_elem *elem = &dev_comp->elem[index];
1558 int err_elem;
1559
1560 err_elem = element_model_recv(ctx, buf, elem, opcode);
1561 err = err_elem == ACCESS_STATUS_SUCCESS ? err_elem : err;
1562 }
1563 }
1564
1565 if (IS_ENABLED(CONFIG_BT_MESH_ACCESS_LAYER_MSG) && msg_cb) {
1566 msg_cb(opcode, ctx, buf);
1567 }
1568
1569 return err;
1570 }
1571
bt_mesh_access_recv(struct bt_mesh_msg_ctx * ctx,struct net_buf_simple * buf)1572 int bt_mesh_access_recv(struct bt_mesh_msg_ctx *ctx, struct net_buf_simple *buf)
1573 {
1574 int err;
1575
1576 err = bt_mesh_model_recv(ctx, buf);
1577
1578 if (IS_ENABLED(CONFIG_BT_MESH_ACCESS_LAYER_MSG) && msg_cb) {
1579 /* Mesh assumes that the application has processed the message.
1580 * Access layer returns success to trigger RPL update and prevent
1581 * replay attack over application.
1582 */
1583 err = 0;
1584 }
1585
1586 return err;
1587 }
1588
bt_mesh_model_send(const struct bt_mesh_model * model,struct bt_mesh_msg_ctx * ctx,struct net_buf_simple * msg,const struct bt_mesh_send_cb * cb,void * cb_data)1589 int bt_mesh_model_send(const struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx,
1590 struct net_buf_simple *msg,
1591 const struct bt_mesh_send_cb *cb, void *cb_data)
1592 {
1593 if (IS_ENABLED(CONFIG_BT_MESH_OP_AGG_SRV) && bt_mesh_op_agg_srv_accept(ctx, msg)) {
1594 return bt_mesh_op_agg_srv_send(model, msg);
1595 } else if (IS_ENABLED(CONFIG_BT_MESH_OP_AGG_CLI) && bt_mesh_op_agg_cli_accept(ctx, msg)) {
1596 return bt_mesh_op_agg_cli_send(model, msg);
1597 }
1598
1599 if (!bt_mesh_model_has_key(model, ctx->app_idx)) {
1600 LOG_ERR("Model not bound to AppKey 0x%04x", ctx->app_idx);
1601 return -EINVAL;
1602 }
1603
1604 #if defined CONFIG_BT_MESH_ACCESS_DELAYABLE_MSG
1605 /* No sense to use delayable message for unicast loopback. */
1606 if (ctx->rnd_delay &&
1607 !(bt_mesh_has_addr(ctx->addr) && BT_MESH_ADDR_IS_UNICAST(ctx->addr))) {
1608 return bt_mesh_delayable_msg_manage(ctx, msg, bt_mesh_model_elem(model)->rt->addr,
1609 cb, cb_data);
1610 }
1611 #endif
1612
1613 return bt_mesh_access_send(ctx, msg, bt_mesh_model_elem(model)->rt->addr, cb, cb_data);
1614 }
1615
bt_mesh_model_publish(const struct bt_mesh_model * model)1616 int bt_mesh_model_publish(const struct bt_mesh_model *model)
1617 {
1618 struct bt_mesh_model_pub *pub = model->pub;
1619
1620 if (!pub) {
1621 return -ENOTSUP;
1622 }
1623
1624 LOG_DBG("");
1625
1626 if (pub->addr == BT_MESH_ADDR_UNASSIGNED) {
1627 return -EADDRNOTAVAIL;
1628 }
1629
1630 if (!pub->msg || !pub->msg->len) {
1631 LOG_ERR("No publication message");
1632 return -EINVAL;
1633 }
1634
1635 if (pub->msg->len + BT_MESH_MIC_SHORT > BT_MESH_TX_SDU_MAX) {
1636 LOG_ERR("Message does not fit maximum SDU size");
1637 return -EMSGSIZE;
1638 }
1639
1640 if (pub->count) {
1641 LOG_WRN("Clearing publish retransmit timer");
1642 }
1643
1644 /* Account for initial transmission */
1645 pub->count = BT_MESH_PUB_MSG_TOTAL(pub);
1646 pub->period_start = k_uptime_get_32();
1647
1648 LOG_DBG("Publish Retransmit Count %u Interval %ums", pub->count,
1649 BT_MESH_PUB_TRANSMIT_INT(pub->retransmit));
1650
1651 /* Delay the publication for longer time when the publication is triggered manually (section
1652 * 3.7.3.1):
1653 *
1654 * When the publication of a message is the result of a power-up, a state transition
1655 * progress update, or completion of a state transition, multiple nodes may be reporting the
1656 * state change at the same time. To reduce the probability of a message collision, these
1657 * messages should be sent with a random delay between 20 and 500 milliseconds.
1658 */
1659 if (!!pub->delayable && !pub_delay_schedule(pub, RANDOM_DELAY_LONG)) {
1660 return 0;
1661 }
1662
1663 k_work_reschedule(&pub->timer, K_NO_WAIT);
1664
1665 return 0;
1666 }
1667
bt_mesh_model_find_vnd(const struct bt_mesh_elem * elem,uint16_t company,uint16_t id)1668 const struct bt_mesh_model *bt_mesh_model_find_vnd(const struct bt_mesh_elem *elem,
1669 uint16_t company, uint16_t id)
1670 {
1671 uint8_t i;
1672
1673 for (i = 0U; i < elem->vnd_model_count; i++) {
1674 if (elem->vnd_models[i].vnd.company == company &&
1675 elem->vnd_models[i].vnd.id == id) {
1676 return &elem->vnd_models[i];
1677 }
1678 }
1679
1680 return NULL;
1681 }
1682
bt_mesh_model_find(const struct bt_mesh_elem * elem,uint16_t id)1683 const struct bt_mesh_model *bt_mesh_model_find(const struct bt_mesh_elem *elem,
1684 uint16_t id)
1685 {
1686 uint8_t i;
1687
1688 for (i = 0U; i < elem->model_count; i++) {
1689 if (elem->models[i].id == id) {
1690 return &elem->models[i];
1691 }
1692 }
1693
1694 return NULL;
1695 }
1696
bt_mesh_comp_get(void)1697 const struct bt_mesh_comp *bt_mesh_comp_get(void)
1698 {
1699 return dev_comp;
1700 }
1701
bt_mesh_model_extensions_walk(const struct bt_mesh_model * model,enum bt_mesh_walk (* cb)(const struct bt_mesh_model * mod,void * user_data),void * user_data)1702 void bt_mesh_model_extensions_walk(const struct bt_mesh_model *model,
1703 enum bt_mesh_walk (*cb)(const struct bt_mesh_model *mod,
1704 void *user_data),
1705 void *user_data)
1706 {
1707 #ifndef CONFIG_BT_MESH_MODEL_EXTENSIONS
1708 (void)cb(model, user_data);
1709 return;
1710 #else
1711 const struct bt_mesh_model *it;
1712
1713 if (cb(model, user_data) == BT_MESH_WALK_STOP || !model->rt->next) {
1714 return;
1715 }
1716
1717 /* List is circular. Step through all models until we reach the start: */
1718 for (it = model->rt->next; it != model; it = it->rt->next) {
1719 if (cb(it, user_data) == BT_MESH_WALK_STOP) {
1720 return;
1721 }
1722 }
1723 #endif
1724 }
1725
1726 #ifdef CONFIG_BT_MESH_MODEL_EXTENSIONS
1727 /* For vendor models, determine the offset within the model relation list
1728 * by counting the number of standard SIG models in the associated element.
1729 */
get_sig_offset(const struct bt_mesh_model * mod)1730 static uint8_t get_sig_offset(const struct bt_mesh_model *mod)
1731 {
1732 const struct bt_mesh_elem *elem = bt_mesh_model_elem(mod);
1733 uint8_t i;
1734
1735 for (i = 0U; i < elem->vnd_model_count; i++) {
1736 if (&elem->vnd_models[i] == mod) {
1737 return elem->model_count;
1738 }
1739 }
1740 return 0;
1741 }
1742
mod_rel_register(const struct bt_mesh_model * base,const struct bt_mesh_model * ext,uint8_t type)1743 static int mod_rel_register(const struct bt_mesh_model *base,
1744 const struct bt_mesh_model *ext,
1745 uint8_t type)
1746 {
1747 LOG_DBG("");
1748 struct mod_relation extension = {
1749 base->rt->elem_idx,
1750 base->rt->mod_idx + get_sig_offset(base),
1751 ext->rt->elem_idx,
1752 ext->rt->mod_idx + get_sig_offset(ext),
1753 type,
1754 };
1755 int i;
1756
1757 for (i = 0; i < ARRAY_SIZE(mod_rel_list); i++) {
1758 if (mod_rel_list[i].elem_base == 0 &&
1759 mod_rel_list[i].idx_base == 0 &&
1760 mod_rel_list[i].elem_ext == 0 &&
1761 mod_rel_list[i].idx_ext == 0) {
1762 memcpy(&mod_rel_list[i], &extension,
1763 sizeof(extension));
1764 return 0;
1765 }
1766 }
1767
1768 LOG_ERR("CONFIG_BT_MESH_MODEL_EXTENSION_LIST_SIZE is too small");
1769 return -ENOMEM;
1770 }
1771
bt_mesh_model_extend(const struct bt_mesh_model * extending_mod,const struct bt_mesh_model * base_mod)1772 int bt_mesh_model_extend(const struct bt_mesh_model *extending_mod,
1773 const struct bt_mesh_model *base_mod)
1774 {
1775 const struct bt_mesh_model *a = extending_mod;
1776 const struct bt_mesh_model *b = base_mod;
1777 const struct bt_mesh_model *a_next = a->rt->next;
1778 const struct bt_mesh_model *b_next = b->rt->next;
1779 const struct bt_mesh_model *it;
1780
1781 base_mod->rt->flags |= BT_MESH_MOD_EXTENDED;
1782
1783 if (a == b) {
1784 return 0;
1785 }
1786
1787 /* Check if a's list contains b */
1788 for (it = a; (it != NULL) && (it->rt->next != a); it = it->rt->next) {
1789 if (it == b) {
1790 goto register_extension;
1791 }
1792 }
1793
1794 /* Merge lists */
1795 if (a_next) {
1796 b->rt->next = a_next;
1797 } else {
1798 b->rt->next = a;
1799 }
1800
1801 if (b_next) {
1802 a->rt->next = b_next;
1803 } else {
1804 a->rt->next = b;
1805 }
1806
1807 register_extension:
1808 if (MOD_REL_LIST_SIZE > 0) {
1809 return mod_rel_register(base_mod, extending_mod, RELATION_TYPE_EXT);
1810 } else if (IS_ENABLED(CONFIG_BT_MESH_COMP_PAGE_1)) {
1811 LOG_ERR("CONFIG_BT_MESH_MODEL_EXTENSION_LIST_SIZE is too small");
1812 return -ENOMEM;
1813 }
1814
1815 return 0;
1816 }
1817
bt_mesh_model_correspond(const struct bt_mesh_model * corresponding_mod,const struct bt_mesh_model * base_mod)1818 int bt_mesh_model_correspond(const struct bt_mesh_model *corresponding_mod,
1819 const struct bt_mesh_model *base_mod)
1820 {
1821 int i, err;
1822 uint8_t cor_id = 0;
1823
1824 if (MOD_REL_LIST_SIZE == 0) {
1825 return -ENOTSUP;
1826 }
1827
1828 uint8_t base_offset = get_sig_offset(base_mod);
1829 uint8_t corresponding_offset = get_sig_offset(corresponding_mod);
1830
1831 MOD_REL_LIST_FOR_EACH(i) {
1832 if (mod_rel_list[i].type < RELATION_TYPE_EXT &&
1833 mod_rel_list[i].type > cor_id) {
1834 cor_id = mod_rel_list[i].type;
1835 }
1836
1837 if ((IS_MOD_BASE(base_mod, i, base_offset) ||
1838 IS_MOD_EXTENSION(base_mod, i, base_offset) ||
1839 IS_MOD_BASE(corresponding_mod, i, corresponding_offset) ||
1840 IS_MOD_EXTENSION(corresponding_mod, i, corresponding_offset)) &&
1841 mod_rel_list[i].type < RELATION_TYPE_EXT) {
1842 return mod_rel_register(base_mod, corresponding_mod, mod_rel_list[i].type);
1843 }
1844 }
1845 err = mod_rel_register(base_mod, corresponding_mod, cor_id);
1846 if (err) {
1847 return err;
1848 }
1849 return 0;
1850 }
1851 #endif /* CONFIG_BT_MESH_MODEL_EXTENSIONS */
1852
bt_mesh_model_is_extended(const struct bt_mesh_model * model)1853 bool bt_mesh_model_is_extended(const struct bt_mesh_model *model)
1854 {
1855 return model->rt->flags & BT_MESH_MOD_EXTENDED;
1856 }
1857
mod_set_bind(const struct bt_mesh_model * mod,size_t len_rd,settings_read_cb read_cb,void * cb_arg)1858 static int mod_set_bind(const struct bt_mesh_model *mod, size_t len_rd,
1859 settings_read_cb read_cb, void *cb_arg)
1860 {
1861 ssize_t len;
1862 int i;
1863
1864 /* Start with empty array regardless of cleared or set value */
1865 for (i = 0; i < mod->keys_cnt; i++) {
1866 mod->keys[i] = BT_MESH_KEY_UNUSED;
1867 }
1868
1869 if (len_rd == 0) {
1870 LOG_DBG("Cleared bindings for model");
1871 return 0;
1872 }
1873
1874 len = read_cb(cb_arg, mod->keys, mod->keys_cnt * sizeof(mod->keys[0]));
1875 if (len < 0) {
1876 LOG_ERR("Failed to read value (err %zd)", len);
1877 return len;
1878 }
1879
1880 LOG_HEXDUMP_DBG(mod->keys, len, "val");
1881
1882 LOG_DBG("Decoded %zu bound keys for model", len / sizeof(mod->keys[0]));
1883 return 0;
1884 }
1885
mod_set_sub(const struct bt_mesh_model * mod,size_t len_rd,settings_read_cb read_cb,void * cb_arg)1886 static int mod_set_sub(const struct bt_mesh_model *mod, size_t len_rd,
1887 settings_read_cb read_cb, void *cb_arg)
1888 {
1889 size_t size = mod->groups_cnt * sizeof(mod->groups[0]);
1890 ssize_t len;
1891
1892 /* Start with empty array regardless of cleared or set value */
1893 (void)memset(mod->groups, 0, size);
1894
1895 if (len_rd == 0) {
1896 LOG_DBG("Cleared subscriptions for model");
1897 return 0;
1898 }
1899
1900 len = read_cb(cb_arg, mod->groups, size);
1901 if (len < 0) {
1902 LOG_ERR("Failed to read value (err %zd)", len);
1903 return len;
1904 }
1905
1906 LOG_HEXDUMP_DBG(mod->groups, len, "val");
1907
1908 LOG_DBG("Decoded %zu subscribed group addresses for model", len / sizeof(mod->groups[0]));
1909
1910 return 0;
1911 }
1912
mod_set_sub_va(const struct bt_mesh_model * mod,size_t len_rd,settings_read_cb read_cb,void * cb_arg)1913 static int mod_set_sub_va(const struct bt_mesh_model *mod, size_t len_rd,
1914 settings_read_cb read_cb, void *cb_arg)
1915 {
1916 #if CONFIG_BT_MESH_LABEL_COUNT > 0
1917 uint16_t uuidxs[CONFIG_BT_MESH_LABEL_COUNT];
1918 ssize_t len;
1919 int i;
1920 int count;
1921
1922 /* Start with empty array regardless of cleared or set value */
1923 (void)memset(mod->uuids, 0, CONFIG_BT_MESH_LABEL_COUNT * sizeof(mod->uuids[0]));
1924
1925 if (len_rd == 0) {
1926 LOG_DBG("Cleared subscriptions for model");
1927 return 0;
1928 }
1929
1930 len = read_cb(cb_arg, uuidxs, sizeof(uuidxs));
1931 if (len < 0) {
1932 LOG_ERR("Failed to read value (err %zd)", len);
1933 return len;
1934 }
1935
1936 LOG_HEXDUMP_DBG(uuidxs, len, "val");
1937
1938 for (i = 0, count = 0; i < len / sizeof(uint16_t); i++) {
1939 mod->uuids[count] = bt_mesh_va_get_uuid_by_idx(uuidxs[i]);
1940 if (mod->uuids[count] != NULL) {
1941 count++;
1942 }
1943 }
1944
1945 LOG_DBG("Decoded %zu subscribed virtual addresses for model", count);
1946 #endif /* CONFIG_BT_MESH_LABEL_COUNT > 0 */
1947 return 0;
1948 }
1949
mod_set_pub(const struct bt_mesh_model * mod,size_t len_rd,settings_read_cb read_cb,void * cb_arg)1950 static int mod_set_pub(const struct bt_mesh_model *mod, size_t len_rd,
1951 settings_read_cb read_cb, void *cb_arg)
1952 {
1953 struct mod_pub_val pub;
1954 int err;
1955
1956 if (!mod->pub) {
1957 LOG_WRN("Model has no publication context!");
1958 return -EINVAL;
1959 }
1960
1961 if (len_rd == 0) {
1962 mod->pub->addr = BT_MESH_ADDR_UNASSIGNED;
1963 mod->pub->key = 0U;
1964 mod->pub->cred = 0U;
1965 mod->pub->ttl = 0U;
1966 mod->pub->period = 0U;
1967 mod->pub->retransmit = 0U;
1968 mod->pub->count = 0U;
1969 mod->pub->uuid = NULL;
1970
1971 LOG_DBG("Cleared publication for model");
1972 return 0;
1973 }
1974
1975 if (!IS_ENABLED(CONFIG_BT_SETTINGS)) {
1976 return 0;
1977 }
1978
1979 err = bt_mesh_settings_set(read_cb, cb_arg, &pub, sizeof(pub));
1980 if (err) {
1981 LOG_ERR("Failed to set \'model-pub\'");
1982 return err;
1983 }
1984
1985 if (BT_MESH_ADDR_IS_VIRTUAL(pub.base.addr)) {
1986 mod->pub->uuid = bt_mesh_va_get_uuid_by_idx(pub.uuidx);
1987 }
1988
1989 mod->pub->addr = pub.base.addr;
1990 mod->pub->key = pub.base.key;
1991 mod->pub->cred = pub.base.cred;
1992 mod->pub->ttl = pub.base.ttl;
1993 mod->pub->period = pub.base.period;
1994 mod->pub->retransmit = pub.base.retransmit;
1995 mod->pub->period_div = pub.base.period_div;
1996 mod->pub->count = 0U;
1997
1998 LOG_DBG("Restored model publication, dst 0x%04x app_idx 0x%03x", pub.base.addr,
1999 pub.base.key);
2000
2001 return 0;
2002 }
2003
mod_data_set(const struct bt_mesh_model * mod,const char * name,size_t len_rd,settings_read_cb read_cb,void * cb_arg)2004 static int mod_data_set(const struct bt_mesh_model *mod,
2005 const char *name, size_t len_rd,
2006 settings_read_cb read_cb, void *cb_arg)
2007 {
2008 const char *next;
2009
2010 settings_name_next(name, &next);
2011
2012 if (mod->cb && mod->cb->settings_set) {
2013 return mod->cb->settings_set(mod, next, len_rd,
2014 read_cb, cb_arg);
2015 }
2016
2017 return 0;
2018 }
2019
mod_set(bool vnd,const char * name,size_t len_rd,settings_read_cb read_cb,void * cb_arg)2020 static int mod_set(bool vnd, const char *name, size_t len_rd,
2021 settings_read_cb read_cb, void *cb_arg)
2022 {
2023 const struct bt_mesh_model *mod;
2024 uint8_t elem_idx, mod_idx;
2025 uint16_t mod_key;
2026 int len;
2027 const char *next;
2028
2029 if (!name) {
2030 LOG_ERR("Insufficient number of arguments");
2031 return -ENOENT;
2032 }
2033
2034 mod_key = strtol(name, NULL, 16);
2035 elem_idx = mod_key >> 8;
2036 mod_idx = mod_key;
2037
2038 LOG_DBG("Decoded mod_key 0x%04x as elem_idx %u mod_idx %u", mod_key, elem_idx, mod_idx);
2039
2040 mod = bt_mesh_model_get(vnd, elem_idx, mod_idx);
2041 if (!mod) {
2042 LOG_ERR("Failed to get model for elem_idx %u mod_idx %u", elem_idx, mod_idx);
2043 return -ENOENT;
2044 }
2045
2046 len = settings_name_next(name, &next);
2047 if (!next) {
2048 LOG_ERR("Insufficient number of arguments");
2049 return -ENOENT;
2050 }
2051
2052 /* `len` contains length of model id string representation. Call settings_name_next() again
2053 * to get length of `next`.
2054 */
2055 switch (settings_name_next(next, NULL)) {
2056 case 4:
2057 if (!strncmp(next, "bind", 4)) {
2058 return mod_set_bind(mod, len_rd, read_cb, cb_arg);
2059 } else if (!strncmp(next, "subv", 4)) {
2060 return mod_set_sub_va(mod, len_rd, read_cb, cb_arg);
2061 } else if (!strncmp(next, "data", 4)) {
2062 return mod_data_set(mod, next, len_rd, read_cb, cb_arg);
2063 }
2064
2065 break;
2066 case 3:
2067 if (!strncmp(next, "sub", 3)) {
2068 return mod_set_sub(mod, len_rd, read_cb, cb_arg);
2069 } else if (!strncmp(next, "pub", 3)) {
2070 return mod_set_pub(mod, len_rd, read_cb, cb_arg);
2071 }
2072
2073 break;
2074 default:
2075 break;
2076 }
2077
2078 LOG_WRN("Unknown module key %s", next);
2079 return -ENOENT;
2080 }
2081
sig_mod_set(const char * name,size_t len_rd,settings_read_cb read_cb,void * cb_arg)2082 static int sig_mod_set(const char *name, size_t len_rd,
2083 settings_read_cb read_cb, void *cb_arg)
2084 {
2085 return mod_set(false, name, len_rd, read_cb, cb_arg);
2086 }
2087
2088 BT_MESH_SETTINGS_DEFINE(sig_mod, "s", sig_mod_set);
2089
vnd_mod_set(const char * name,size_t len_rd,settings_read_cb read_cb,void * cb_arg)2090 static int vnd_mod_set(const char *name, size_t len_rd,
2091 settings_read_cb read_cb, void *cb_arg)
2092 {
2093 return mod_set(true, name, len_rd, read_cb, cb_arg);
2094 }
2095
2096 BT_MESH_SETTINGS_DEFINE(vnd_mod, "v", vnd_mod_set);
2097
comp_set(const char * name,size_t len_rd,settings_read_cb read_cb,void * cb_arg)2098 static int comp_set(const char *name, size_t len_rd, settings_read_cb read_cb,
2099 void *cb_arg)
2100 {
2101 /* Only need to know that the entry exists. Will load the contents on
2102 * demand.
2103 */
2104 if (len_rd > 0) {
2105 atomic_set_bit(bt_mesh.flags, BT_MESH_COMP_DIRTY);
2106 }
2107
2108 return 0;
2109 }
2110 BT_MESH_SETTINGS_DEFINE(comp, "cmp", comp_set);
2111
encode_mod_path(const struct bt_mesh_model * mod,bool vnd,const char * key,char * path,size_t path_len)2112 static void encode_mod_path(const struct bt_mesh_model *mod, bool vnd,
2113 const char *key, char *path, size_t path_len)
2114 {
2115 uint16_t mod_key = (((uint16_t)mod->rt->elem_idx << 8) | mod->rt->mod_idx);
2116
2117 if (vnd) {
2118 snprintk(path, path_len, "bt/mesh/v/%x/%s", mod_key, key);
2119 } else {
2120 snprintk(path, path_len, "bt/mesh/s/%x/%s", mod_key, key);
2121 }
2122 }
2123
store_pending_mod_bind(const struct bt_mesh_model * mod,bool vnd)2124 static void store_pending_mod_bind(const struct bt_mesh_model *mod, bool vnd)
2125 {
2126 uint16_t keys[CONFIG_BT_MESH_MODEL_KEY_COUNT];
2127 char path[20];
2128 int i, count, err;
2129
2130 for (i = 0, count = 0; i < mod->keys_cnt; i++) {
2131 if (mod->keys[i] != BT_MESH_KEY_UNUSED) {
2132 keys[count++] = mod->keys[i];
2133 LOG_DBG("model key 0x%04x", mod->keys[i]);
2134 }
2135 }
2136
2137 encode_mod_path(mod, vnd, "bind", path, sizeof(path));
2138
2139 if (count) {
2140 err = settings_save_one(path, keys, count * sizeof(keys[0]));
2141 } else {
2142 err = settings_delete(path);
2143 }
2144
2145 if (err) {
2146 LOG_ERR("Failed to store %s value", path);
2147 } else {
2148 LOG_DBG("Stored %s value", path);
2149 }
2150 }
2151
store_pending_mod_sub(const struct bt_mesh_model * mod,bool vnd)2152 static void store_pending_mod_sub(const struct bt_mesh_model *mod, bool vnd)
2153 {
2154 uint16_t groups[CONFIG_BT_MESH_MODEL_GROUP_COUNT];
2155 char path[20];
2156 int i, count, err;
2157
2158 for (i = 0, count = 0; i < mod->groups_cnt; i++) {
2159 if (mod->groups[i] != BT_MESH_ADDR_UNASSIGNED) {
2160 groups[count++] = mod->groups[i];
2161 }
2162 }
2163
2164 encode_mod_path(mod, vnd, "sub", path, sizeof(path));
2165
2166 if (count) {
2167 err = settings_save_one(path, groups, count * sizeof(groups[0]));
2168 } else {
2169 err = settings_delete(path);
2170 }
2171
2172 if (err) {
2173 LOG_ERR("Failed to store %s value", path);
2174 } else {
2175 LOG_DBG("Stored %s value", path);
2176 }
2177 }
2178
store_pending_mod_sub_va(const struct bt_mesh_model * mod,bool vnd)2179 static void store_pending_mod_sub_va(const struct bt_mesh_model *mod, bool vnd)
2180 {
2181 #if CONFIG_BT_MESH_LABEL_COUNT > 0
2182 uint16_t uuidxs[CONFIG_BT_MESH_LABEL_COUNT];
2183 char path[20];
2184 int i, count, err;
2185
2186 for (i = 0, count = 0; i < CONFIG_BT_MESH_LABEL_COUNT; i++) {
2187 if (mod->uuids[i] != NULL) {
2188 err = bt_mesh_va_get_idx_by_uuid(mod->uuids[i], &uuidxs[count]);
2189 if (!err) {
2190 count++;
2191 }
2192 }
2193 }
2194
2195 encode_mod_path(mod, vnd, "subv", path, sizeof(path));
2196
2197 if (count) {
2198 err = settings_save_one(path, uuidxs, count * sizeof(uuidxs[0]));
2199 } else {
2200 err = settings_delete(path);
2201 }
2202
2203 if (err) {
2204 LOG_ERR("Failed to store %s value", path);
2205 } else {
2206 LOG_DBG("Stored %s value", path);
2207 }
2208 #endif /* CONFIG_BT_MESH_LABEL_COUNT > 0 */
2209 }
2210
store_pending_mod_pub(const struct bt_mesh_model * mod,bool vnd)2211 static void store_pending_mod_pub(const struct bt_mesh_model *mod, bool vnd)
2212 {
2213 struct mod_pub_val pub = {0};
2214 char path[20];
2215 int err;
2216
2217 encode_mod_path(mod, vnd, "pub", path, sizeof(path));
2218
2219 if (!mod->pub || mod->pub->addr == BT_MESH_ADDR_UNASSIGNED) {
2220 err = settings_delete(path);
2221 } else {
2222 pub.base.addr = mod->pub->addr;
2223 pub.base.key = mod->pub->key;
2224 pub.base.ttl = mod->pub->ttl;
2225 pub.base.retransmit = mod->pub->retransmit;
2226 pub.base.period = mod->pub->period;
2227 pub.base.period_div = mod->pub->period_div;
2228 pub.base.cred = mod->pub->cred;
2229
2230 if (BT_MESH_ADDR_IS_VIRTUAL(mod->pub->addr)) {
2231 (void)bt_mesh_va_get_idx_by_uuid(mod->pub->uuid, &pub.uuidx);
2232 }
2233
2234 err = settings_save_one(path, &pub, sizeof(pub));
2235 }
2236
2237 if (err) {
2238 LOG_ERR("Failed to store %s value", path);
2239 } else {
2240 LOG_DBG("Stored %s value", path);
2241 }
2242 }
2243
store_pending_mod(const struct bt_mesh_model * mod,const struct bt_mesh_elem * elem,bool vnd,bool primary,void * user_data)2244 static void store_pending_mod(const struct bt_mesh_model *mod,
2245 const struct bt_mesh_elem *elem, bool vnd,
2246 bool primary, void *user_data)
2247 {
2248 if (!mod->rt->flags) {
2249 return;
2250 }
2251
2252 if (mod->rt->flags & BT_MESH_MOD_BIND_PENDING) {
2253 mod->rt->flags &= ~BT_MESH_MOD_BIND_PENDING;
2254 store_pending_mod_bind(mod, vnd);
2255 }
2256
2257 if (mod->rt->flags & BT_MESH_MOD_SUB_PENDING) {
2258 mod->rt->flags &= ~BT_MESH_MOD_SUB_PENDING;
2259 store_pending_mod_sub(mod, vnd);
2260 store_pending_mod_sub_va(mod, vnd);
2261 }
2262
2263 if (mod->rt->flags & BT_MESH_MOD_PUB_PENDING) {
2264 mod->rt->flags &= ~BT_MESH_MOD_PUB_PENDING;
2265 store_pending_mod_pub(mod, vnd);
2266 }
2267
2268 if (mod->rt->flags & BT_MESH_MOD_DATA_PENDING) {
2269 mod->rt->flags &= ~BT_MESH_MOD_DATA_PENDING;
2270 mod->cb->pending_store(mod);
2271 }
2272 }
2273
bt_mesh_model_pending_store(void)2274 void bt_mesh_model_pending_store(void)
2275 {
2276 bt_mesh_model_foreach(store_pending_mod, NULL);
2277 }
2278
bt_mesh_model_bind_store(const struct bt_mesh_model * mod)2279 void bt_mesh_model_bind_store(const struct bt_mesh_model *mod)
2280 {
2281 mod->rt->flags |= BT_MESH_MOD_BIND_PENDING;
2282 bt_mesh_settings_store_schedule(BT_MESH_SETTINGS_MOD_PENDING);
2283 }
2284
bt_mesh_model_sub_store(const struct bt_mesh_model * mod)2285 void bt_mesh_model_sub_store(const struct bt_mesh_model *mod)
2286 {
2287 mod->rt->flags |= BT_MESH_MOD_SUB_PENDING;
2288 bt_mesh_settings_store_schedule(BT_MESH_SETTINGS_MOD_PENDING);
2289 }
2290
bt_mesh_model_pub_store(const struct bt_mesh_model * mod)2291 void bt_mesh_model_pub_store(const struct bt_mesh_model *mod)
2292 {
2293 mod->rt->flags |= BT_MESH_MOD_PUB_PENDING;
2294 bt_mesh_settings_store_schedule(BT_MESH_SETTINGS_MOD_PENDING);
2295 }
2296
bt_mesh_comp_data_get_page(struct net_buf_simple * buf,size_t page,size_t offset)2297 int bt_mesh_comp_data_get_page(struct net_buf_simple *buf, size_t page, size_t offset)
2298 {
2299 if (page == 0 || page == 128) {
2300 return bt_mesh_comp_data_get_page_0(buf, offset);
2301 } else if (IS_ENABLED(CONFIG_BT_MESH_COMP_PAGE_1) && (page == 1 || page == 129)) {
2302 return bt_mesh_comp_data_get_page_1(buf, offset);
2303 } else if (IS_ENABLED(CONFIG_BT_MESH_COMP_PAGE_2) && (page == 2 || page == 130)) {
2304 return bt_mesh_comp_data_get_page_2(buf, offset);
2305 }
2306
2307 return -EINVAL;
2308 }
2309
comp_page_0_size(void)2310 size_t comp_page_0_size(void)
2311 {
2312 const struct bt_mesh_comp *comp;
2313 const struct bt_mesh_elem *elem;
2314 size_t size = 10; /* Non-variable length params of comp page 0. */
2315
2316 comp = bt_mesh_comp_get();
2317
2318 for (int i = 0; i < comp->elem_count; i++) {
2319 elem = &comp->elem[i];
2320 size += bt_mesh_comp_elem_size(elem);
2321 }
2322
2323 return size;
2324 }
2325
comp_page_1_size(void)2326 size_t comp_page_1_size(void)
2327 {
2328 const struct bt_mesh_comp *comp;
2329 size_t size = 0;
2330
2331 comp = bt_mesh_comp_get();
2332
2333 for (int i = 0; i < comp->elem_count; i++) {
2334
2335 size += page1_elem_size(&comp->elem[i]);
2336 }
2337
2338 return size;
2339 }
2340
comp_page_2_size(void)2341 size_t comp_page_2_size(void)
2342 {
2343 size_t size = 0;
2344
2345 if (!dev_comp2) {
2346 LOG_ERR("Composition data P2 not registered");
2347 return size;
2348 }
2349
2350 for (int i = 0; i < dev_comp2->record_cnt; i++) {
2351 size += 8 + dev_comp2->record[i].elem_offset_cnt + dev_comp2->record[i].data_len;
2352 }
2353 return size;
2354 }
2355
bt_mesh_comp_page_size(uint8_t page)2356 size_t bt_mesh_comp_page_size(uint8_t page)
2357 {
2358 if (page == 0 || page == 128) {
2359 return comp_page_0_size();
2360 } else if (IS_ENABLED(CONFIG_BT_MESH_COMP_PAGE_1) && (page == 1 || page == 129)) {
2361 return comp_page_1_size();
2362 } else if (IS_ENABLED(CONFIG_BT_MESH_COMP_PAGE_2) && (page == 2 || page == 130)) {
2363 return comp_page_2_size();
2364 }
2365
2366 return 0;
2367 }
2368
bt_mesh_comp_store(void)2369 int bt_mesh_comp_store(void)
2370 {
2371 NET_BUF_SIMPLE_DEFINE(buf, CONFIG_BT_MESH_COMP_PST_BUF_SIZE);
2372 int err;
2373
2374 for (int i = 0; i < ARRAY_SIZE(comp_data_pages); i++) {
2375 size_t page_size = bt_mesh_comp_page_size(i);
2376
2377 if (page_size > CONFIG_BT_MESH_COMP_PST_BUF_SIZE) {
2378 LOG_WRN("CDP%d is larger than the CDP persistence buffer. "
2379 "Please increase the CDP persistence buffer size "
2380 "to the required size (%d bytes)",
2381 i, page_size);
2382 }
2383
2384 net_buf_simple_reset(&buf);
2385
2386 err = bt_mesh_comp_data_get_page(&buf, comp_data_pages[i].page, 0);
2387 if (err) {
2388 LOG_ERR("Failed to read CDP%d: %d", comp_data_pages[i].page, err);
2389 return err;
2390 }
2391
2392 err = settings_save_one(comp_data_pages[i].path, buf.data, buf.len);
2393 if (err) {
2394 LOG_ERR("Failed to store CDP%d: %d", comp_data_pages[i].page, err);
2395 return err;
2396 }
2397
2398 LOG_DBG("Stored CDP%d", comp_data_pages[i].page);
2399 }
2400
2401 return 0;
2402 }
2403
bt_mesh_comp_change_prepare(void)2404 int bt_mesh_comp_change_prepare(void)
2405 {
2406 if (!IS_ENABLED(CONFIG_BT_SETTINGS)) {
2407 return -ENOTSUP;
2408 }
2409
2410 return bt_mesh_comp_store();
2411 }
2412
comp_data_clear(void)2413 static void comp_data_clear(void)
2414 {
2415 int err;
2416
2417 for (int i = 0; i < ARRAY_SIZE(comp_data_pages); i++) {
2418 err = settings_delete(comp_data_pages[i].path);
2419 if (err) {
2420 LOG_ERR("Failed to clear CDP%d: %d", comp_data_pages[i].page,
2421 err);
2422 }
2423 }
2424
2425 atomic_clear_bit(bt_mesh.flags, BT_MESH_COMP_DIRTY);
2426 }
2427
read_comp_cb(const char * key,size_t len,settings_read_cb read_cb,void * cb_arg,void * param)2428 static int read_comp_cb(const char *key, size_t len, settings_read_cb read_cb,
2429 void *cb_arg, void *param)
2430 {
2431 struct net_buf_simple *buf = param;
2432
2433 if (len > net_buf_simple_tailroom(buf)) {
2434 return -ENOBUFS;
2435 }
2436
2437 len = read_cb(cb_arg, net_buf_simple_tail(buf), len);
2438 if (len > 0) {
2439 net_buf_simple_add(buf, len);
2440 }
2441
2442 return -EALREADY;
2443 }
2444
bt_mesh_comp_read(struct net_buf_simple * buf,uint8_t page)2445 int bt_mesh_comp_read(struct net_buf_simple *buf, uint8_t page)
2446 {
2447 size_t original_len = buf->len;
2448 int i;
2449 int err;
2450
2451 if (!IS_ENABLED(CONFIG_BT_SETTINGS)) {
2452 return -ENOTSUP;
2453 }
2454
2455 for (i = 0; i < ARRAY_SIZE(comp_data_pages); i++) {
2456 if (comp_data_pages[i].page == page) {
2457 break;
2458 }
2459 }
2460
2461 if (i == ARRAY_SIZE(comp_data_pages)) {
2462 return -ENOENT;
2463 }
2464
2465 err = settings_load_subtree_direct(comp_data_pages[i].path, read_comp_cb, buf);
2466
2467 if (err) {
2468 LOG_ERR("Failed reading composition data: %d", err);
2469 return err;
2470 }
2471 if (buf->len == original_len) {
2472 return -ENOENT;
2473 }
2474 return 0;
2475 }
2476
bt_mesh_model_data_store(const struct bt_mesh_model * mod,bool vnd,const char * name,const void * data,size_t data_len)2477 int bt_mesh_model_data_store(const struct bt_mesh_model *mod, bool vnd,
2478 const char *name, const void *data,
2479 size_t data_len)
2480 {
2481 char path[30];
2482 int err;
2483
2484 encode_mod_path(mod, vnd, "data", path, sizeof(path));
2485 if (name) {
2486 strcat(path, "/");
2487 strncat(path, name, SETTINGS_MAX_DIR_DEPTH);
2488 }
2489
2490 if (data_len) {
2491 err = settings_save_one(path, data, data_len);
2492 } else {
2493 err = settings_delete(path);
2494 }
2495
2496 if (err) {
2497 LOG_ERR("Failed to store %s value", path);
2498 } else {
2499 LOG_DBG("Stored %s value", path);
2500 }
2501 return err;
2502 }
2503
2504 #if defined(CONFIG_BT_MESH_LARGE_COMP_DATA_SRV)
metadata_set(const char * name,size_t len_rd,settings_read_cb read_cb,void * cb_arg)2505 static int metadata_set(const char *name, size_t len_rd, settings_read_cb read_cb, void *cb_arg)
2506 {
2507 /* Only need to know that the entry exists. Will load the contents on
2508 * demand.
2509 */
2510 if (len_rd > 0) {
2511 atomic_set_bit(bt_mesh.flags, BT_MESH_METADATA_DIRTY);
2512 }
2513
2514 return 0;
2515 }
2516 BT_MESH_SETTINGS_DEFINE(metadata, "metadata", metadata_set);
2517
bt_mesh_models_metadata_store(void)2518 int bt_mesh_models_metadata_store(void)
2519 {
2520 NET_BUF_SIMPLE_DEFINE(buf, CONFIG_BT_MESH_MODELS_METADATA_PAGE_LEN);
2521 size_t total_size;
2522 int err;
2523
2524 total_size = bt_mesh_metadata_page_0_size();
2525 LOG_DBG("bt/mesh/metadata total %d", total_size);
2526
2527 net_buf_simple_init(&buf, 0);
2528 net_buf_simple_add_le16(&buf, total_size);
2529
2530 err = bt_mesh_metadata_get_page_0(&buf, 0);
2531 if (err == -E2BIG) {
2532 LOG_ERR("Metadata too large");
2533 return err;
2534 }
2535 if (err) {
2536 LOG_ERR("Failed to read models metadata: %d", err);
2537 return err;
2538 }
2539
2540 LOG_DBG("bt/mesh/metadata len %d", buf.len);
2541
2542 err = settings_save_one("bt/mesh/metadata", buf.data, buf.len);
2543 if (err) {
2544 LOG_ERR("Failed to store models metadata: %d", err);
2545 } else {
2546 LOG_DBG("Stored models metadata");
2547 }
2548
2549 return err;
2550 }
2551
bt_mesh_models_metadata_read(struct net_buf_simple * buf,size_t offset)2552 int bt_mesh_models_metadata_read(struct net_buf_simple *buf, size_t offset)
2553 {
2554 NET_BUF_SIMPLE_DEFINE(stored_buf, CONFIG_BT_MESH_MODELS_METADATA_PAGE_LEN);
2555 size_t original_len = buf->len;
2556 int err;
2557
2558 if (!IS_ENABLED(CONFIG_BT_SETTINGS)) {
2559 return -ENOTSUP;
2560 }
2561
2562 net_buf_simple_init(&stored_buf, 0);
2563
2564 err = settings_load_subtree_direct("bt/mesh/metadata", read_comp_cb, &stored_buf);
2565 if (err) {
2566 LOG_ERR("Failed reading models metadata: %d", err);
2567 return err;
2568 }
2569
2570 /* First two bytes are total length */
2571 offset += 2;
2572
2573 net_buf_simple_add_mem(buf, &stored_buf.data, MIN(net_buf_simple_tailroom(buf), 2));
2574
2575 if (offset >= stored_buf.len) {
2576 return 0;
2577 }
2578
2579 net_buf_simple_add_mem(buf, &stored_buf.data[offset],
2580 MIN(net_buf_simple_tailroom(buf), stored_buf.len - offset));
2581
2582 LOG_DBG("metadata read %d", buf->len);
2583
2584 if (buf->len == original_len) {
2585 return -ENOENT;
2586 }
2587
2588 return 0;
2589 }
2590 #endif
2591
models_metadata_clear(void)2592 static void models_metadata_clear(void)
2593 {
2594 int err;
2595
2596 err = settings_delete("bt/mesh/metadata");
2597 if (err) {
2598 LOG_ERR("Failed to clear models metadata: %d", err);
2599 } else {
2600 LOG_DBG("Cleared models metadata");
2601 }
2602
2603 atomic_clear_bit(bt_mesh.flags, BT_MESH_METADATA_DIRTY);
2604 }
2605
bt_mesh_comp_data_pending_clear(void)2606 void bt_mesh_comp_data_pending_clear(void)
2607 {
2608 comp_data_clear();
2609 models_metadata_clear();
2610 }
2611
bt_mesh_comp_data_clear(void)2612 void bt_mesh_comp_data_clear(void)
2613 {
2614 bt_mesh_settings_store_schedule(BT_MESH_SETTINGS_COMP_PENDING);
2615 }
2616
bt_mesh_models_metadata_change_prepare(void)2617 int bt_mesh_models_metadata_change_prepare(void)
2618 {
2619 #if defined(CONFIG_BT_MESH_LARGE_COMP_DATA_SRV)
2620 return bt_mesh_models_metadata_store();
2621 #else
2622 return -ENOTSUP;
2623 #endif
2624 }
2625
commit_mod(const struct bt_mesh_model * mod,const struct bt_mesh_elem * elem,bool vnd,bool primary,void * user_data)2626 static void commit_mod(const struct bt_mesh_model *mod, const struct bt_mesh_elem *elem,
2627 bool vnd, bool primary, void *user_data)
2628 {
2629 if (mod->pub && mod->pub->update &&
2630 mod->pub->addr != BT_MESH_ADDR_UNASSIGNED) {
2631 int32_t ms = bt_mesh_model_pub_period_get(mod);
2632
2633 if (ms > 0) {
2634 /* Delay the first publication after power-up for longer time (section
2635 * 3.7.3.1):
2636 *
2637 * When the publication of a message is the result of a power-up, a state
2638 * transition progress update, or completion of a state transition, multiple
2639 * nodes may be reporting the state change at the same time. To reduce the
2640 * probability of a message collision, these messages should be sent with a
2641 * random delay between 20 and 500 milliseconds.
2642 */
2643 uint16_t random;
2644
2645 random = !!mod->pub->delayable ? pub_delay_get(RANDOM_DELAY_LONG) : 0;
2646
2647 LOG_DBG("Starting publish timer (period %u ms, delay %u ms)", ms, random);
2648 k_work_schedule(&mod->pub->timer, K_MSEC(ms + random));
2649 }
2650 }
2651
2652 if (!IS_ENABLED(CONFIG_BT_MESH_LOW_POWER)) {
2653 return;
2654 }
2655
2656 for (int i = 0; i < mod->groups_cnt; i++) {
2657 if (mod->groups[i] != BT_MESH_ADDR_UNASSIGNED) {
2658 bt_mesh_lpn_group_add(mod->groups[i]);
2659 }
2660 }
2661 }
2662
bt_mesh_model_settings_commit(void)2663 void bt_mesh_model_settings_commit(void)
2664 {
2665 bt_mesh_model_foreach(commit_mod, NULL);
2666 }
2667
bt_mesh_model_data_store_schedule(const struct bt_mesh_model * mod)2668 void bt_mesh_model_data_store_schedule(const struct bt_mesh_model *mod)
2669 {
2670 mod->rt->flags |= BT_MESH_MOD_DATA_PENDING;
2671 bt_mesh_settings_store_schedule(BT_MESH_SETTINGS_MOD_PENDING);
2672 }
2673
bt_mesh_comp_parse_page(struct net_buf_simple * buf)2674 uint8_t bt_mesh_comp_parse_page(struct net_buf_simple *buf)
2675 {
2676 uint8_t page = net_buf_simple_pull_u8(buf);
2677
2678 if (page >= 130U && IS_ENABLED(CONFIG_BT_MESH_COMP_PAGE_2) &&
2679 (atomic_test_bit(bt_mesh.flags, BT_MESH_COMP_DIRTY) ||
2680 IS_ENABLED(CONFIG_BT_MESH_RPR_SRV))) {
2681 page = 130U;
2682 } else if (page >= 129U && IS_ENABLED(CONFIG_BT_MESH_COMP_PAGE_1) &&
2683 (atomic_test_bit(bt_mesh.flags, BT_MESH_COMP_DIRTY) ||
2684 IS_ENABLED(CONFIG_BT_MESH_RPR_SRV))) {
2685 page = 129U;
2686 } else if (page >= 128U && (atomic_test_bit(bt_mesh.flags, BT_MESH_COMP_DIRTY) ||
2687 IS_ENABLED(CONFIG_BT_MESH_RPR_SRV))) {
2688 page = 128U;
2689 } else if (page >= 2U && IS_ENABLED(CONFIG_BT_MESH_COMP_PAGE_2)) {
2690 page = 2U;
2691 } else if (page >= 1U && IS_ENABLED(CONFIG_BT_MESH_COMP_PAGE_1)) {
2692 page = 1U;
2693 } else if (page != 0U) {
2694 LOG_DBG("Composition page %u not available", page);
2695 page = 0U;
2696 }
2697
2698 return page;
2699 }
2700
bt_mesh_access_init(void)2701 void bt_mesh_access_init(void)
2702 {
2703 #if defined CONFIG_BT_MESH_ACCESS_DELAYABLE_MSG
2704 bt_mesh_delayable_msg_init();
2705 #endif
2706 }
2707
bt_mesh_access_suspend(void)2708 void bt_mesh_access_suspend(void)
2709 {
2710 #if defined CONFIG_BT_MESH_ACCESS_DELAYABLE_MSG
2711 bt_mesh_delayable_msg_stop();
2712 #endif
2713 }
2714
bt_mesh_access_reset(void)2715 void bt_mesh_access_reset(void)
2716 {
2717 #if defined CONFIG_BT_MESH_ACCESS_DELAYABLE_MSG
2718 bt_mesh_delayable_msg_stop();
2719 #endif
2720 }
2721