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