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
31 #define LOG_LEVEL CONFIG_BT_MESH_ACCESS_LOG_LEVEL
32 #include <zephyr/logging/log.h>
33 LOG_MODULE_REGISTER(bt_mesh_access);
34
35 /* Model publication information for persistent storage. */
36 struct mod_pub_val {
37 uint16_t addr;
38 uint16_t key;
39 uint8_t ttl;
40 uint8_t retransmit;
41 uint8_t period;
42 uint8_t period_div:4,
43 cred:1;
44 };
45
46 struct comp_foreach_model_arg {
47 struct net_buf_simple *buf;
48 size_t *offset;
49 };
50
51 static const struct bt_mesh_comp *dev_comp;
52 static uint16_t dev_primary_addr;
53 static void (*msg_cb)(uint32_t opcode, struct bt_mesh_msg_ctx *ctx, struct net_buf_simple *buf);
54
55 /* Structure containing information about model extension */
56 struct mod_relation {
57 /** Element that composition data base model belongs to. */
58 uint8_t elem_base;
59 /** Index of composition data base model in its element. */
60 uint8_t idx_base;
61 /** Element that composition data extension model belongs to. */
62 uint8_t elem_ext;
63 /** Index of composition data extension model in its element. */
64 uint8_t idx_ext;
65 /** Type of relation; value in range 0x00-0xFE marks correspondence
66 * and equals to Correspondence ID; value 0xFF marks extension
67 */
68 uint8_t type;
69 };
70
71 #ifdef CONFIG_BT_MESH_MODEL_EXTENSION_LIST_SIZE
72 #define MOD_REL_LIST_SIZE CONFIG_BT_MESH_MODEL_EXTENSION_LIST_SIZE
73 #else
74 #define MOD_REL_LIST_SIZE 0
75 #endif
76
77 /* List of all existing extension relations between models */
78 static struct mod_relation mod_rel_list[MOD_REL_LIST_SIZE];
79
80 #define MOD_REL_LIST_FOR_EACH(idx) \
81 for ((idx) = 0; \
82 (idx) < ARRAY_SIZE(mod_rel_list) && \
83 !(mod_rel_list[(idx)].elem_base == 0 && \
84 mod_rel_list[(idx)].idx_base == 0 && \
85 mod_rel_list[(idx)].elem_ext == 0 && \
86 mod_rel_list[(idx)].idx_ext == 0); \
87 (idx)++)
88
89 #define IS_MOD_BASE(mod, idx) \
90 (mod_rel_list[(idx)].elem_base == (mod)->elem_idx && \
91 mod_rel_list[(idx)].idx_base == (mod)->mod_idx && \
92 !(mod_rel_list[(idx)].elem_ext != (mod)->elem_idx && \
93 mod_rel_list[(idx)].idx_ext != (mod)->mod_idx))
94
95 #define IS_MOD_EXTENSION(mod, idx) \
96 (mod_rel_list[(idx)].elem_ext == (mod)->elem_idx && \
97 mod_rel_list[(idx)].idx_ext == (mod)->mod_idx && \
98 !(mod_rel_list[(idx)].elem_base != (mod)->elem_idx && \
99 mod_rel_list[(idx)].idx_base != (mod)->mod_idx))
100
101 #define RELATION_TYPE_EXT 0xFF
102
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)103 void bt_mesh_model_foreach(void (*func)(struct bt_mesh_model *mod,
104 struct bt_mesh_elem *elem,
105 bool vnd, bool primary,
106 void *user_data),
107 void *user_data)
108 {
109 int i, j;
110
111 for (i = 0; i < dev_comp->elem_count; i++) {
112 struct bt_mesh_elem *elem = &dev_comp->elem[i];
113
114 for (j = 0; j < elem->model_count; j++) {
115 struct bt_mesh_model *model = &elem->models[j];
116
117 func(model, elem, false, i == 0, user_data);
118 }
119
120 for (j = 0; j < elem->vnd_model_count; j++) {
121 struct bt_mesh_model *model = &elem->vnd_models[j];
122
123 func(model, elem, true, i == 0, user_data);
124 }
125 }
126 }
127
bt_mesh_comp_elem_size(const struct bt_mesh_elem * elem)128 static size_t bt_mesh_comp_elem_size(const struct bt_mesh_elem *elem)
129 {
130 return (4 + (elem->model_count * 2U) + (elem->vnd_model_count * 4U));
131 }
132
data_buf_add_u8_offset(struct net_buf_simple * buf,uint8_t val,size_t * offset)133 static uint8_t *data_buf_add_u8_offset(struct net_buf_simple *buf,
134 uint8_t val, size_t *offset)
135 {
136 if (*offset >= 1) {
137 *offset -= 1;
138 return NULL;
139 }
140
141 return net_buf_simple_add_u8(buf, val);
142 }
143
data_buf_add_le16_offset(struct net_buf_simple * buf,uint16_t val,size_t * offset)144 static void data_buf_add_le16_offset(struct net_buf_simple *buf,
145 uint16_t val, size_t *offset)
146 {
147 if (*offset >= 2) {
148 *offset -= 2;
149 return;
150 } else if (*offset == 1) {
151 *offset -= 1;
152 net_buf_simple_add_u8(buf, (val >> 8));
153 } else {
154 net_buf_simple_add_le16(buf, val);
155 }
156 }
157
comp_add_model(struct bt_mesh_model * mod,struct bt_mesh_elem * elem,bool vnd,void * user_data)158 static void comp_add_model(struct bt_mesh_model *mod, struct bt_mesh_elem *elem,
159 bool vnd, void *user_data)
160 {
161 struct comp_foreach_model_arg *arg = user_data;
162
163 if (vnd) {
164 data_buf_add_le16_offset(arg->buf, mod->vnd.company, arg->offset);
165 data_buf_add_le16_offset(arg->buf, mod->vnd.id, arg->offset);
166 } else {
167 data_buf_add_le16_offset(arg->buf, mod->id, arg->offset);
168 }
169 }
170
171 #if defined(CONFIG_BT_MESH_LARGE_COMP_DATA_SRV)
data_buf_add_mem_offset(struct net_buf_simple * buf,const void * mem,size_t len,size_t * offset)172 static void data_buf_add_mem_offset(struct net_buf_simple *buf,
173 const void *mem, size_t len,
174 size_t *offset)
175 {
176 if (*offset >= len) {
177 *offset -= len;
178 return;
179 } else if (*offset > 0) {
180 net_buf_simple_add_mem(buf, ((uint8_t *)mem), (len - *offset));
181
182 } else {
183 net_buf_simple_add_mem(buf, mem, len);
184 }
185 }
186
metadata_model_size(struct bt_mesh_model * mod,struct bt_mesh_elem * elem,bool vnd)187 static size_t metadata_model_size(struct bt_mesh_model *mod,
188 struct bt_mesh_elem *elem, bool vnd)
189 {
190 const struct bt_mesh_models_metadata_entry *entry;
191 size_t size = 0;
192
193 if (!mod->metadata) {
194 return size;
195 }
196
197 if (vnd) {
198 size += sizeof(mod->vnd.company);
199 size += sizeof(mod->vnd.id);
200 } else {
201 size += sizeof(mod->id);
202 }
203
204 size += sizeof(uint8_t);
205
206 for (entry = *mod->metadata; entry && entry->len; ++entry) {
207 size += sizeof(entry->len) + sizeof(entry->id) + entry->len;
208 }
209
210 return size;
211 }
212
bt_mesh_metadata_page_0_size(void)213 size_t bt_mesh_metadata_page_0_size(void)
214 {
215 const struct bt_mesh_comp *comp;
216 size_t size = 0;
217 int i, j;
218
219 comp = bt_mesh_comp_get();
220
221 for (i = 0; i < dev_comp->elem_count; i++) {
222 struct bt_mesh_elem *elem = &dev_comp->elem[i];
223
224 size += sizeof(elem->model_count) +
225 sizeof(elem->vnd_model_count);
226
227 for (j = 0; j < elem->model_count; j++) {
228 struct bt_mesh_model *model = &elem->models[j];
229
230 size += metadata_model_size(model, elem, false);
231 }
232
233 for (j = 0; j < elem->vnd_model_count; j++) {
234 struct bt_mesh_model *model = &elem->vnd_models[j];
235
236 size += metadata_model_size(model, elem, true);
237 }
238 }
239
240 return size;
241 }
242
metadata_add_model(struct bt_mesh_model * mod,struct bt_mesh_elem * elem,bool vnd,void * user_data)243 static int metadata_add_model(struct bt_mesh_model *mod,
244 struct bt_mesh_elem *elem, bool vnd,
245 void *user_data)
246 {
247 const struct bt_mesh_models_metadata_entry *entry;
248 struct comp_foreach_model_arg *arg = user_data;
249 struct net_buf_simple *buf = arg->buf;
250 size_t *offset = arg->offset;
251 size_t model_size;
252 uint8_t count = 0;
253 uint8_t *count_ptr;
254
255 model_size = metadata_model_size(mod, elem, vnd);
256
257 if (*offset >= model_size) {
258 *offset -= model_size;
259 return 0;
260 }
261
262 if (net_buf_simple_tailroom(buf) < (model_size + BT_MESH_MIC_SHORT)) {
263 LOG_DBG("Model metadata didn't fit in the buffer");
264 return -E2BIG;
265 }
266
267 comp_add_model(mod, elem, vnd, user_data);
268
269 count_ptr = data_buf_add_u8_offset(buf, 0, offset);
270
271 if (mod->metadata) {
272 for (entry = *mod->metadata; entry && entry->data != NULL; ++entry) {
273 data_buf_add_le16_offset(buf, entry->len, offset);
274 data_buf_add_le16_offset(buf, entry->id, offset);
275 data_buf_add_mem_offset(buf, entry->data, entry->len, offset);
276 count++;
277 }
278 }
279
280 if (count_ptr) {
281 *count_ptr = count;
282 }
283
284 return 0;
285 }
286
bt_mesh_metadata_get_page_0(struct net_buf_simple * buf,size_t offset)287 int bt_mesh_metadata_get_page_0(struct net_buf_simple *buf, size_t offset)
288 {
289 const struct bt_mesh_comp *comp;
290 struct comp_foreach_model_arg arg = {
291 .buf = buf,
292 .offset = &offset,
293 };
294 uint8_t *mod_count_ptr;
295 uint8_t *vnd_count_ptr;
296 int i, j, err;
297
298 comp = bt_mesh_comp_get();
299
300 for (i = 0; i < comp->elem_count; i++) {
301 struct bt_mesh_elem *elem = &dev_comp->elem[i];
302
303 /* Check that the buffer has available tailroom for metadata item counts */
304 if (net_buf_simple_tailroom(buf) < (((offset == 0) ? 2 : (offset == 1) ? 1 : 0)
305 + BT_MESH_MIC_SHORT)) {
306 LOG_DBG("Model metadata didn't fit in the buffer");
307 return -E2BIG;
308 }
309 mod_count_ptr = data_buf_add_u8_offset(buf, 0, &offset);
310 vnd_count_ptr = data_buf_add_u8_offset(buf, 0, &offset);
311
312 for (j = 0; j < elem->model_count; j++) {
313 struct bt_mesh_model *model = &elem->models[j];
314
315 if (!model->metadata) {
316 continue;
317 }
318
319 err = metadata_add_model(model, elem, false, &arg);
320 if (err) {
321 return err;
322 }
323
324 if (mod_count_ptr) {
325 (*mod_count_ptr) += 1;
326 }
327 }
328
329 for (j = 0; j < elem->vnd_model_count; j++) {
330 struct bt_mesh_model *model = &elem->vnd_models[j];
331
332 if (!model->metadata) {
333 continue;
334 }
335
336 err = metadata_add_model(model, elem, true, &arg);
337 if (err) {
338 return err;
339 }
340
341 if (vnd_count_ptr) {
342 (*vnd_count_ptr) += 1;
343 }
344 }
345 }
346
347 return 0;
348 }
349 #endif
350
bt_mesh_comp_page_0_size(void)351 size_t bt_mesh_comp_page_0_size(void)
352 {
353 const struct bt_mesh_comp *comp;
354 const struct bt_mesh_elem *elem;
355 size_t size = 10;
356 int i;
357
358 comp = bt_mesh_comp_get();
359
360 for (i = 0; i < comp->elem_count; i++) {
361 elem = &comp->elem[i];
362 size += bt_mesh_comp_elem_size(elem);
363 }
364
365 return size;
366 }
367
comp_add_elem(struct net_buf_simple * buf,struct bt_mesh_elem * elem,size_t * offset)368 static int comp_add_elem(struct net_buf_simple *buf, 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 + BT_MESH_MIC_SHORT)) {
384 if (IS_ENABLED(CONFIG_BT_MESH_LARGE_COMP_DATA_SRV)) {
385 /* Mesh Profile 1.1 Section 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->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 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 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(struct bt_mesh_model * mod,uint8_t * max_offset)460 static uint8_t count_mod_ext(struct bt_mesh_model *mod, uint8_t *max_offset)
461 {
462 int i;
463 uint8_t extensions = 0;
464 int8_t offset, offset_record = 0;
465
466 MOD_REL_LIST_FOR_EACH(i) {
467 if (IS_MOD_EXTENSION(mod, i) &&
468 mod_rel_list[i].type == RELATION_TYPE_EXT) {
469 extensions++;
470 offset = mod_rel_list[i].elem_ext -
471 mod_rel_list[i].elem_base;
472 if (abs(offset) > abs(offset_record)) {
473 offset_record = offset;
474 }
475 }
476 }
477 memcpy(max_offset, &offset_record, sizeof(uint8_t));
478 return extensions;
479 }
480
is_cor_present(struct bt_mesh_model * mod,uint8_t * cor_id)481 static bool is_cor_present(struct bt_mesh_model *mod, uint8_t *cor_id)
482 {
483 int i;
484
485 MOD_REL_LIST_FOR_EACH(i) {
486 if ((IS_MOD_BASE(mod, i) ||
487 IS_MOD_EXTENSION(mod, i)) &&
488 mod_rel_list[i].type < RELATION_TYPE_EXT) {
489 memcpy(cor_id, &mod_rel_list[i].type, sizeof(uint8_t));
490 return true;
491 }
492 }
493 return false;
494 }
495
prep_model_item_header(struct bt_mesh_model * mod,uint8_t * cor_id,uint8_t * mod_cnt,struct net_buf_simple * buf)496 static void prep_model_item_header(struct bt_mesh_model *mod, uint8_t *cor_id,
497 uint8_t *mod_cnt, struct net_buf_simple *buf)
498 {
499 uint8_t ext_mod_cnt;
500 bool cor_present;
501 uint8_t mod_elem_info = 0;
502 int8_t max_offset;
503
504 ext_mod_cnt = count_mod_ext(mod, &max_offset);
505 cor_present = is_cor_present(mod, cor_id);
506
507 mod_elem_info = ext_mod_cnt << 2;
508 if (ext_mod_cnt > 31 ||
509 max_offset > 3 ||
510 max_offset < -4) {
511 mod_elem_info |= BIT(1);
512 }
513 if (cor_present) {
514 mod_elem_info |= BIT(0);
515 }
516 net_buf_simple_add_u8(buf, mod_elem_info);
517
518 if (cor_present) {
519 net_buf_simple_add_u8(buf, *cor_id);
520 }
521 memset(mod_cnt, ext_mod_cnt, sizeof(uint8_t));
522 }
523
add_items_to_page(struct net_buf_simple * buf,struct bt_mesh_model * mod,uint8_t ext_mod_cnt)524 static void add_items_to_page(struct net_buf_simple *buf, struct bt_mesh_model *mod,
525 uint8_t ext_mod_cnt)
526 {
527 int i, offset;
528 uint8_t mod_idx;
529
530 MOD_REL_LIST_FOR_EACH(i) {
531 if (IS_MOD_EXTENSION(mod, i)) {
532 offset = mod->elem_idx - mod_rel_list[i].elem_base;
533 mod_idx = mod_rel_list[i].idx_base;
534 if (ext_mod_cnt < 32 &&
535 offset < 4 &&
536 offset > -5) {
537 /* short format */
538 if (offset < 0) {
539 offset += 8;
540 }
541
542 offset |= mod_idx << 3;
543 net_buf_simple_add_u8(buf, offset);
544 } else {
545 /* long format */
546 if (offset < 0) {
547 offset += 256;
548 }
549 net_buf_simple_add_u8(buf, offset);
550 net_buf_simple_add_u8(buf, mod_idx);
551 }
552 }
553 }
554 }
555
bt_mesh_comp_data_get_page_1(struct net_buf_simple * buf)556 int bt_mesh_comp_data_get_page_1(struct net_buf_simple *buf)
557 {
558 const struct bt_mesh_comp *comp;
559 uint8_t cor_id = 0;
560 uint8_t ext_mod_cnt = 0;
561 int i, j;
562
563 comp = bt_mesh_comp_get();
564
565 for (i = 0; i < comp->elem_count; i++) {
566 net_buf_simple_add_u8(buf, comp->elem[i].model_count);
567 net_buf_simple_add_u8(buf, comp->elem[i].vnd_model_count);
568 for (j = 0; j < comp->elem[i].model_count; j++) {
569 prep_model_item_header(&comp->elem[i].models[j],
570 &cor_id, &ext_mod_cnt, buf);
571 if (ext_mod_cnt != 0) {
572 add_items_to_page(buf,
573 &comp->elem[i].models[j],
574 ext_mod_cnt);
575 }
576 }
577
578 for (j = 0; j < comp->elem[i].vnd_model_count; j++) {
579 prep_model_item_header(&comp->elem[i].vnd_models[j],
580 &cor_id, &ext_mod_cnt, buf);
581 if (ext_mod_cnt != 0) {
582 add_items_to_page(buf,
583 &comp->elem[i].vnd_models[j],
584 ext_mod_cnt);
585 }
586 }
587 }
588 return 0;
589 }
590
bt_mesh_model_pub_period_get(struct bt_mesh_model * mod)591 int32_t bt_mesh_model_pub_period_get(struct bt_mesh_model *mod)
592 {
593 int32_t period;
594
595 if (!mod->pub) {
596 return 0;
597 }
598
599 switch (mod->pub->period >> 6) {
600 case 0x00:
601 /* 1 step is 100 ms */
602 period = (mod->pub->period & BIT_MASK(6)) * 100U;
603 break;
604 case 0x01:
605 /* 1 step is 1 second */
606 period = (mod->pub->period & BIT_MASK(6)) * MSEC_PER_SEC;
607 break;
608 case 0x02:
609 /* 1 step is 10 seconds */
610 period = (mod->pub->period & BIT_MASK(6)) * 10U * MSEC_PER_SEC;
611 break;
612 case 0x03:
613 /* 1 step is 10 minutes */
614 period = (mod->pub->period & BIT_MASK(6)) * 600U * MSEC_PER_SEC;
615 break;
616 default:
617 CODE_UNREACHABLE;
618 }
619
620 if (mod->pub->fast_period) {
621 if (!period) {
622 return 0;
623 }
624
625 return MAX(period >> mod->pub->period_div, 100);
626 } else {
627 return period;
628 }
629 }
630
next_period(struct bt_mesh_model * mod)631 static int32_t next_period(struct bt_mesh_model *mod)
632 {
633 struct bt_mesh_model_pub *pub = mod->pub;
634 uint32_t period = 0;
635 uint32_t elapsed;
636
637 elapsed = k_uptime_get_32() - pub->period_start;
638 LOG_DBG("Publishing took %ums", elapsed);
639
640 if (mod->pub->count) {
641 /* If a message is to be retransmitted, period should include time since the first
642 * publication until the last publication.
643 */
644 period = BT_MESH_PUB_TRANSMIT_INT(mod->pub->retransmit);
645 period *= BT_MESH_PUB_MSG_NUM(mod->pub);
646
647 if (period && elapsed >= period) {
648 LOG_WRN("Retransmission interval is too short");
649 /* Return smallest positive number since 0 means disabled */
650 return 1;
651 }
652 }
653
654 if (!period) {
655 period = bt_mesh_model_pub_period_get(mod);
656 if (!period) {
657 return 0;
658 }
659 }
660
661 if (elapsed >= period) {
662 LOG_WRN("Publication sending took longer than the period");
663 /* Return smallest positive number since 0 means disabled */
664 return 1;
665 }
666
667 return period - elapsed;
668 }
669
publish_sent(int err,void * user_data)670 static void publish_sent(int err, void *user_data)
671 {
672 struct bt_mesh_model *mod = user_data;
673 int32_t delay;
674
675 LOG_DBG("err %d, time %u", err, k_uptime_get_32());
676
677 delay = next_period(mod);
678
679 if (delay) {
680 LOG_DBG("Publishing next time in %dms", delay);
681 /* Using schedule() in case the application has already called
682 * bt_mesh_publish, and a publication is pending.
683 */
684 k_work_schedule(&mod->pub->timer, K_MSEC(delay));
685 }
686 }
687
publish_start(uint16_t duration,int err,void * user_data)688 static void publish_start(uint16_t duration, int err, void *user_data)
689 {
690 if (err) {
691 LOG_ERR("Failed to publish: err %d", err);
692 publish_sent(err, user_data);
693 return;
694 }
695 }
696
697 static const struct bt_mesh_send_cb pub_sent_cb = {
698 .start = publish_start,
699 .end = publish_sent,
700 };
701
publish_transmit(struct bt_mesh_model * mod)702 static int publish_transmit(struct bt_mesh_model *mod)
703 {
704 NET_BUF_SIMPLE_DEFINE(sdu, BT_MESH_TX_SDU_MAX);
705 struct bt_mesh_model_pub *pub = mod->pub;
706 struct bt_mesh_msg_ctx ctx = BT_MESH_MSG_CTX_INIT_PUB(pub);
707 struct bt_mesh_net_tx tx = {
708 .ctx = &ctx,
709 .src = bt_mesh_model_elem(mod)->addr,
710 .friend_cred = pub->cred,
711 };
712
713 net_buf_simple_add_mem(&sdu, pub->msg->data, pub->msg->len);
714
715 return bt_mesh_trans_send(&tx, &sdu, &pub_sent_cb, mod);
716 }
717
pub_period_start(struct bt_mesh_model_pub * pub)718 static int pub_period_start(struct bt_mesh_model_pub *pub)
719 {
720 int err;
721
722 pub->count = BT_MESH_PUB_TRANSMIT_COUNT(pub->retransmit);
723
724 if (!pub->update) {
725 return 0;
726 }
727
728 err = pub->update(pub->mod);
729
730 pub->period_start = k_uptime_get_32();
731
732 if (err) {
733 /* Skip this publish attempt. */
734 LOG_DBG("Update failed, skipping publish (err: %d)", err);
735 pub->count = 0;
736 publish_sent(err, pub->mod);
737 return err;
738 }
739
740 return 0;
741 }
742
mod_publish(struct k_work * work)743 static void mod_publish(struct k_work *work)
744 {
745 struct k_work_delayable *dwork = k_work_delayable_from_work(work);
746 struct bt_mesh_model_pub *pub = CONTAINER_OF(dwork,
747 struct bt_mesh_model_pub,
748 timer);
749 int err;
750
751 if (pub->addr == BT_MESH_ADDR_UNASSIGNED ||
752 atomic_test_bit(bt_mesh.flags, BT_MESH_SUSPENDED)) {
753 /* Publication is no longer active, but the cancellation of the
754 * delayed work failed. Abandon recurring timer.
755 */
756 return;
757 }
758
759 LOG_DBG("%u", k_uptime_get_32());
760
761 if (pub->count) {
762 pub->count--;
763
764 if (pub->retr_update && pub->update &&
765 bt_mesh_model_pub_is_retransmission(pub->mod)) {
766 err = pub->update(pub->mod);
767 if (err) {
768 publish_sent(err, pub->mod);
769 return;
770 }
771 }
772 } else {
773 /* First publication in this period */
774 err = pub_period_start(pub);
775 if (err) {
776 return;
777 }
778 }
779
780 err = publish_transmit(pub->mod);
781 if (err) {
782 LOG_ERR("Failed to publish (err %d)", err);
783 publish_sent(err, pub->mod);
784 }
785 }
786
bt_mesh_model_elem(struct bt_mesh_model * mod)787 struct bt_mesh_elem *bt_mesh_model_elem(struct bt_mesh_model *mod)
788 {
789 return &dev_comp->elem[mod->elem_idx];
790 }
791
bt_mesh_model_get(bool vnd,uint8_t elem_idx,uint8_t mod_idx)792 struct bt_mesh_model *bt_mesh_model_get(bool vnd, uint8_t elem_idx, uint8_t mod_idx)
793 {
794 struct bt_mesh_elem *elem;
795
796 if (elem_idx >= dev_comp->elem_count) {
797 LOG_ERR("Invalid element index %u", elem_idx);
798 return NULL;
799 }
800
801 elem = &dev_comp->elem[elem_idx];
802
803 if (vnd) {
804 if (mod_idx >= elem->vnd_model_count) {
805 LOG_ERR("Invalid vendor model index %u", mod_idx);
806 return NULL;
807 }
808
809 return &elem->vnd_models[mod_idx];
810 } else {
811 if (mod_idx >= elem->model_count) {
812 LOG_ERR("Invalid SIG model index %u", mod_idx);
813 return NULL;
814 }
815
816 return &elem->models[mod_idx];
817 }
818 }
819
820 #if defined(CONFIG_BT_MESH_MODEL_VND_MSG_CID_FORCE)
bt_mesh_vnd_mod_msg_cid_check(struct bt_mesh_model * mod)821 static int bt_mesh_vnd_mod_msg_cid_check(struct bt_mesh_model *mod)
822 {
823 uint16_t cid;
824 const struct bt_mesh_model_op *op;
825
826 for (op = mod->op; op->func; op++) {
827 cid = (uint16_t)(op->opcode & 0xffff);
828
829 if (cid == mod->vnd.company) {
830 continue;
831 }
832
833 LOG_ERR("Invalid vendor model(company:0x%04x"
834 " id:0x%04x) message opcode 0x%08x",
835 mod->vnd.company, mod->vnd.id, op->opcode);
836
837 return -EINVAL;
838 }
839
840 return 0;
841 }
842 #endif
843
mod_init(struct bt_mesh_model * mod,struct bt_mesh_elem * elem,bool vnd,bool primary,void * user_data)844 static void mod_init(struct bt_mesh_model *mod, struct bt_mesh_elem *elem,
845 bool vnd, bool primary, void *user_data)
846 {
847 int i;
848 int *err = user_data;
849
850 if (*err) {
851 return;
852 }
853
854 if (mod->pub) {
855 mod->pub->mod = mod;
856 k_work_init_delayable(&mod->pub->timer, mod_publish);
857 }
858
859 for (i = 0; i < mod->keys_cnt; i++) {
860 mod->keys[i] = BT_MESH_KEY_UNUSED;
861 }
862
863 mod->elem_idx = elem - dev_comp->elem;
864 if (vnd) {
865 mod->mod_idx = mod - elem->vnd_models;
866
867 if (IS_ENABLED(CONFIG_BT_MESH_MODEL_VND_MSG_CID_FORCE)) {
868 *err = bt_mesh_vnd_mod_msg_cid_check(mod);
869 if (*err) {
870 return;
871 }
872 }
873
874 } else {
875 mod->mod_idx = mod - elem->models;
876 }
877
878 if (mod->cb && mod->cb->init) {
879 *err = mod->cb->init(mod);
880 }
881 }
882
bt_mesh_comp_register(const struct bt_mesh_comp * comp)883 int bt_mesh_comp_register(const struct bt_mesh_comp *comp)
884 {
885 int err;
886
887 /* There must be at least one element */
888 if (!comp || !comp->elem_count) {
889 return -EINVAL;
890 }
891
892 dev_comp = comp;
893
894 err = 0;
895
896 if (IS_ENABLED(CONFIG_BT_MESH_COMP_PAGE_1)) {
897 memset(mod_rel_list, 0, sizeof(mod_rel_list));
898 }
899
900 bt_mesh_model_foreach(mod_init, &err);
901
902 if (IS_ENABLED(CONFIG_BT_MESH_COMP_PAGE_1)) {
903 int i;
904
905 MOD_REL_LIST_FOR_EACH(i) {
906 LOG_DBG("registered %s",
907 mod_rel_list[i].type < RELATION_TYPE_EXT ?
908 "correspondence" : "extension");
909 LOG_DBG("\tbase: elem %u idx %u",
910 mod_rel_list[i].elem_base,
911 mod_rel_list[i].idx_base);
912 LOG_DBG("\text: elem %u idx %u",
913 mod_rel_list[i].elem_ext,
914 mod_rel_list[i].idx_ext);
915 }
916 if (i < MOD_REL_LIST_SIZE) {
917 LOG_WRN("Unused space in relation list: %d",
918 MOD_REL_LIST_SIZE - i);
919 }
920 }
921
922 return err;
923 }
924
bt_mesh_comp_provision(uint16_t addr)925 void bt_mesh_comp_provision(uint16_t addr)
926 {
927 int i;
928
929 dev_primary_addr = addr;
930
931 LOG_DBG("addr 0x%04x elem_count %zu", addr, dev_comp->elem_count);
932
933 for (i = 0; i < dev_comp->elem_count; i++) {
934 struct bt_mesh_elem *elem = &dev_comp->elem[i];
935
936 elem->addr = addr++;
937
938 LOG_DBG("addr 0x%04x mod_count %u vnd_mod_count %u", elem->addr, elem->model_count,
939 elem->vnd_model_count);
940 }
941 }
942
bt_mesh_comp_unprovision(void)943 void bt_mesh_comp_unprovision(void)
944 {
945 LOG_DBG("");
946
947 dev_primary_addr = BT_MESH_ADDR_UNASSIGNED;
948 }
949
bt_mesh_primary_addr(void)950 uint16_t bt_mesh_primary_addr(void)
951 {
952 return dev_primary_addr;
953 }
954
model_group_get(struct bt_mesh_model * mod,uint16_t addr)955 static uint16_t *model_group_get(struct bt_mesh_model *mod, uint16_t addr)
956 {
957 int i;
958
959 for (i = 0; i < mod->groups_cnt; i++) {
960 if (mod->groups[i] == addr) {
961 return &mod->groups[i];
962 }
963 }
964
965 return NULL;
966 }
967
968 struct find_group_visitor_ctx {
969 uint16_t *entry;
970 struct bt_mesh_model *mod;
971 uint16_t addr;
972 };
973
find_group_mod_visitor(struct bt_mesh_model * mod,void * user_data)974 static enum bt_mesh_walk find_group_mod_visitor(struct bt_mesh_model *mod, void *user_data)
975 {
976 struct find_group_visitor_ctx *ctx = user_data;
977
978 if (mod->elem_idx != ctx->mod->elem_idx) {
979 return BT_MESH_WALK_CONTINUE;
980 }
981
982 ctx->entry = model_group_get(mod, ctx->addr);
983 if (ctx->entry) {
984 ctx->mod = mod;
985 return BT_MESH_WALK_STOP;
986 }
987
988 return BT_MESH_WALK_CONTINUE;
989 }
990
bt_mesh_model_find_group(struct bt_mesh_model ** mod,uint16_t addr)991 uint16_t *bt_mesh_model_find_group(struct bt_mesh_model **mod, uint16_t addr)
992 {
993 struct find_group_visitor_ctx ctx = {
994 .mod = *mod,
995 .entry = NULL,
996 .addr = addr,
997 };
998
999 bt_mesh_model_extensions_walk(*mod, find_group_mod_visitor, &ctx);
1000
1001 *mod = ctx.mod;
1002 return ctx.entry;
1003 }
1004
bt_mesh_elem_find_group(struct bt_mesh_elem * elem,uint16_t group_addr)1005 static struct bt_mesh_model *bt_mesh_elem_find_group(struct bt_mesh_elem *elem,
1006 uint16_t group_addr)
1007 {
1008 struct bt_mesh_model *model;
1009 uint16_t *match;
1010 int i;
1011
1012 for (i = 0; i < elem->model_count; i++) {
1013 model = &elem->models[i];
1014
1015 match = model_group_get(model, group_addr);
1016 if (match) {
1017 return model;
1018 }
1019 }
1020
1021 for (i = 0; i < elem->vnd_model_count; i++) {
1022 model = &elem->vnd_models[i];
1023
1024 match = model_group_get(model, group_addr);
1025 if (match) {
1026 return model;
1027 }
1028 }
1029
1030 return NULL;
1031 }
1032
bt_mesh_elem_find(uint16_t addr)1033 struct bt_mesh_elem *bt_mesh_elem_find(uint16_t addr)
1034 {
1035 uint16_t index;
1036
1037 if (!BT_MESH_ADDR_IS_UNICAST(addr)) {
1038 return NULL;
1039 }
1040
1041 index = addr - dev_comp->elem[0].addr;
1042 if (index >= dev_comp->elem_count) {
1043 return NULL;
1044 }
1045
1046 return &dev_comp->elem[index];
1047 }
1048
bt_mesh_has_addr(uint16_t addr)1049 bool bt_mesh_has_addr(uint16_t addr)
1050 {
1051 uint16_t index;
1052
1053 if (BT_MESH_ADDR_IS_UNICAST(addr)) {
1054 return bt_mesh_elem_find(addr) != NULL;
1055 }
1056
1057 if (IS_ENABLED(CONFIG_BT_MESH_ACCESS_LAYER_MSG) && msg_cb) {
1058 return true;
1059 }
1060
1061 for (index = 0; index < dev_comp->elem_count; index++) {
1062 struct bt_mesh_elem *elem = &dev_comp->elem[index];
1063
1064 if (bt_mesh_elem_find_group(elem, addr)) {
1065 return true;
1066 }
1067 }
1068
1069 return false;
1070 }
1071
1072 #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))1073 void bt_mesh_msg_cb_set(void (*cb)(uint32_t opcode, struct bt_mesh_msg_ctx *ctx,
1074 struct net_buf_simple *buf))
1075 {
1076 msg_cb = cb;
1077 }
1078 #endif
1079
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)1080 int bt_mesh_access_send(struct bt_mesh_msg_ctx *ctx, struct net_buf_simple *buf, uint16_t src_addr,
1081 const struct bt_mesh_send_cb *cb, void *cb_data)
1082 {
1083 struct bt_mesh_net_tx tx = {
1084 .ctx = ctx,
1085 .src = src_addr,
1086 };
1087
1088 LOG_DBG("net_idx 0x%04x app_idx 0x%04x dst 0x%04x", tx.ctx->net_idx, tx.ctx->app_idx,
1089 tx.ctx->addr);
1090 LOG_DBG("len %u: %s", buf->len, bt_hex(buf->data, buf->len));
1091
1092 if (!bt_mesh_is_provisioned()) {
1093 LOG_ERR("Local node is not yet provisioned");
1094 return -EAGAIN;
1095 }
1096
1097 return bt_mesh_trans_send(&tx, buf, cb, cb_data);
1098 }
1099
bt_mesh_elem_count(void)1100 uint8_t bt_mesh_elem_count(void)
1101 {
1102 return dev_comp->elem_count;
1103 }
1104
bt_mesh_model_has_key(struct bt_mesh_model * mod,uint16_t key)1105 bool bt_mesh_model_has_key(struct bt_mesh_model *mod, uint16_t key)
1106 {
1107 int i;
1108
1109 for (i = 0; i < mod->keys_cnt; i++) {
1110 if (mod->keys[i] == key ||
1111 (mod->keys[i] == BT_MESH_KEY_DEV_ANY &&
1112 BT_MESH_IS_DEV_KEY(key))) {
1113 return true;
1114 }
1115 }
1116
1117 return false;
1118 }
1119
model_has_dst(struct bt_mesh_model * mod,uint16_t dst)1120 static bool model_has_dst(struct bt_mesh_model *mod, uint16_t dst)
1121 {
1122 if (BT_MESH_ADDR_IS_UNICAST(dst)) {
1123 return (dev_comp->elem[mod->elem_idx].addr == dst);
1124 } else if (BT_MESH_ADDR_IS_GROUP(dst) || BT_MESH_ADDR_IS_VIRTUAL(dst) ||
1125 (BT_MESH_ADDR_IS_FIXED_GROUP(dst) && mod->elem_idx != 0)) {
1126 return !!bt_mesh_model_find_group(&mod, dst);
1127 }
1128
1129 /* If a message with a fixed group address is sent to the access layer,
1130 * the lower layers have already confirmed that we are subscribing to
1131 * it. All models on the primary element should receive the message.
1132 */
1133 return mod->elem_idx == 0;
1134 }
1135
find_op(struct bt_mesh_elem * elem,uint32_t opcode,struct bt_mesh_model ** model)1136 static const struct bt_mesh_model_op *find_op(struct bt_mesh_elem *elem,
1137 uint32_t opcode, struct bt_mesh_model **model)
1138 {
1139 uint8_t i;
1140 uint8_t count;
1141 /* This value shall not be used in shipping end products. */
1142 uint32_t cid = UINT32_MAX;
1143 struct bt_mesh_model *models;
1144
1145 /* SIG models cannot contain 3-byte (vendor) OpCodes, and
1146 * vendor models cannot contain SIG (1- or 2-byte) OpCodes, so
1147 * we only need to do the lookup in one of the model lists.
1148 */
1149 if (BT_MESH_MODEL_OP_LEN(opcode) < 3) {
1150 models = elem->models;
1151 count = elem->model_count;
1152 } else {
1153 models = elem->vnd_models;
1154 count = elem->vnd_model_count;
1155
1156 cid = (uint16_t)(opcode & 0xffff);
1157 }
1158
1159 for (i = 0U; i < count; i++) {
1160
1161 const struct bt_mesh_model_op *op;
1162
1163 if (IS_ENABLED(CONFIG_BT_MESH_MODEL_VND_MSG_CID_FORCE) &&
1164 cid != UINT32_MAX &&
1165 cid != models[i].vnd.company) {
1166 continue;
1167 }
1168
1169 *model = &models[i];
1170
1171 for (op = (*model)->op; op->func; op++) {
1172 if (op->opcode == opcode) {
1173 return op;
1174 }
1175 }
1176 }
1177
1178 *model = NULL;
1179 return NULL;
1180 }
1181
get_opcode(struct net_buf_simple * buf,uint32_t * opcode)1182 static int get_opcode(struct net_buf_simple *buf, uint32_t *opcode)
1183 {
1184 switch (buf->data[0] >> 6) {
1185 case 0x00:
1186 case 0x01:
1187 if (buf->data[0] == 0x7f) {
1188 LOG_ERR("Ignoring RFU OpCode");
1189 return -EINVAL;
1190 }
1191
1192 *opcode = net_buf_simple_pull_u8(buf);
1193 return 0;
1194 case 0x02:
1195 if (buf->len < 2) {
1196 LOG_ERR("Too short payload for 2-octet OpCode");
1197 return -EINVAL;
1198 }
1199
1200 *opcode = net_buf_simple_pull_be16(buf);
1201 return 0;
1202 case 0x03:
1203 if (buf->len < 3) {
1204 LOG_ERR("Too short payload for 3-octet OpCode");
1205 return -EINVAL;
1206 }
1207
1208 *opcode = net_buf_simple_pull_u8(buf) << 16;
1209 /* Using LE for the CID since the model layer is defined as
1210 * little-endian in the mesh spec and using BT_MESH_MODEL_OP_3
1211 * will declare the opcode in this way.
1212 */
1213 *opcode |= net_buf_simple_pull_le16(buf);
1214 return 0;
1215 }
1216
1217 CODE_UNREACHABLE;
1218 }
1219
element_model_recv(struct bt_mesh_msg_ctx * ctx,struct net_buf_simple * buf,uint16_t addr,struct bt_mesh_elem * elem,uint32_t opcode)1220 static int element_model_recv(struct bt_mesh_msg_ctx *ctx,
1221 struct net_buf_simple *buf, uint16_t addr,
1222 struct bt_mesh_elem *elem, uint32_t opcode)
1223 {
1224 const struct bt_mesh_model_op *op;
1225 struct bt_mesh_model *model;
1226 struct net_buf_simple_state state;
1227 int err;
1228
1229 op = find_op(elem, opcode, &model);
1230 if (!op) {
1231 LOG_ERR("No OpCode 0x%08x for elem 0x%02x", opcode, elem->addr);
1232 return ACCESS_STATUS_WRONG_OPCODE;
1233 }
1234
1235 if (!bt_mesh_model_has_key(model, ctx->app_idx)) {
1236 LOG_ERR("Wrong key");
1237 return ACCESS_STATUS_WRONG_KEY;
1238 }
1239
1240 if (!model_has_dst(model, addr)) {
1241 LOG_ERR("Invalid address 0x%02x", addr);
1242 return ACCESS_STATUS_INVALID_ADDRESS;
1243 }
1244
1245 if ((op->len >= 0) && (buf->len < (size_t)op->len)) {
1246 LOG_ERR("Too short message for OpCode 0x%08x", opcode);
1247 return ACCESS_STATUS_MESSAGE_NOT_UNDERSTOOD;
1248 } else if ((op->len < 0) && (buf->len != (size_t)(-op->len))) {
1249 LOG_ERR("Invalid message size for OpCode 0x%08x", opcode);
1250 return ACCESS_STATUS_MESSAGE_NOT_UNDERSTOOD;
1251 }
1252
1253 net_buf_simple_save(buf, &state);
1254 err = op->func(model, ctx, buf);
1255 net_buf_simple_restore(buf, &state);
1256
1257 if (err) {
1258 return ACCESS_STATUS_MESSAGE_NOT_UNDERSTOOD;
1259 }
1260 return ACCESS_STATUS_SUCCESS;
1261 }
1262
bt_mesh_model_recv(struct bt_mesh_msg_ctx * ctx,struct net_buf_simple * buf)1263 int bt_mesh_model_recv(struct bt_mesh_msg_ctx *ctx, struct net_buf_simple *buf)
1264 {
1265 int err = ACCESS_STATUS_SUCCESS;
1266 uint32_t opcode;
1267 uint16_t index;
1268
1269 LOG_DBG("app_idx 0x%04x src 0x%04x dst 0x%04x", ctx->app_idx, ctx->addr,
1270 ctx->recv_dst);
1271 LOG_DBG("len %u: %s", buf->len, bt_hex(buf->data, buf->len));
1272
1273 if (IS_ENABLED(CONFIG_BT_TESTING)) {
1274 bt_test_mesh_model_recv(ctx->addr, ctx->recv_dst, buf->data,
1275 buf->len);
1276 }
1277
1278 if (get_opcode(buf, &opcode) < 0) {
1279 LOG_WRN("Unable to decode OpCode");
1280 return ACCESS_STATUS_WRONG_OPCODE;
1281 }
1282
1283 LOG_DBG("OpCode 0x%08x", opcode);
1284
1285 if (BT_MESH_ADDR_IS_UNICAST(ctx->recv_dst)) {
1286 index = ctx->recv_dst - dev_comp->elem[0].addr;
1287
1288 if (index >= dev_comp->elem_count) {
1289 LOG_ERR("Invalid address 0x%02x", ctx->recv_dst);
1290 err = ACCESS_STATUS_INVALID_ADDRESS;
1291 } else {
1292 struct bt_mesh_elem *elem = &dev_comp->elem[index];
1293
1294 err = element_model_recv(ctx, buf, ctx->recv_dst, elem, opcode);
1295 }
1296 } else {
1297 for (index = 0; index < dev_comp->elem_count; index++) {
1298 struct bt_mesh_elem *elem = &dev_comp->elem[index];
1299
1300 (void)element_model_recv(ctx, buf, ctx->recv_dst, elem, opcode);
1301 }
1302 }
1303
1304 if (IS_ENABLED(CONFIG_BT_MESH_ACCESS_LAYER_MSG) && msg_cb) {
1305 msg_cb(opcode, ctx, buf);
1306 }
1307
1308 return err;
1309 }
1310
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)1311 int bt_mesh_model_send(struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx,
1312 struct net_buf_simple *msg,
1313 const struct bt_mesh_send_cb *cb, void *cb_data)
1314 {
1315 if (IS_ENABLED(CONFIG_BT_MESH_OP_AGG) && bt_mesh_op_agg_accept(ctx)) {
1316 return bt_mesh_op_agg_send(model, ctx, msg, cb);
1317 }
1318
1319 if (!bt_mesh_model_has_key(model, ctx->app_idx)) {
1320 LOG_ERR("Model not bound to AppKey 0x%04x", ctx->app_idx);
1321 return -EINVAL;
1322 }
1323
1324 return bt_mesh_access_send(ctx, msg, bt_mesh_model_elem(model)->addr, cb, cb_data);
1325 }
1326
bt_mesh_model_publish(struct bt_mesh_model * model)1327 int bt_mesh_model_publish(struct bt_mesh_model *model)
1328 {
1329 struct bt_mesh_model_pub *pub = model->pub;
1330
1331 if (!pub) {
1332 return -ENOTSUP;
1333 }
1334
1335 LOG_DBG("");
1336
1337 if (pub->addr == BT_MESH_ADDR_UNASSIGNED) {
1338 return -EADDRNOTAVAIL;
1339 }
1340
1341 if (!pub->msg || !pub->msg->len) {
1342 LOG_ERR("No publication message");
1343 return -EINVAL;
1344 }
1345
1346 if (pub->msg->len + BT_MESH_MIC_SHORT > BT_MESH_TX_SDU_MAX) {
1347 LOG_ERR("Message does not fit maximum SDU size");
1348 return -EMSGSIZE;
1349 }
1350
1351 if (pub->count) {
1352 LOG_WRN("Clearing publish retransmit timer");
1353 }
1354
1355 /* Account for initial transmission */
1356 pub->count = BT_MESH_PUB_MSG_TOTAL(pub);
1357 pub->period_start = k_uptime_get_32();
1358
1359 LOG_DBG("Publish Retransmit Count %u Interval %ums", pub->count,
1360 BT_MESH_PUB_TRANSMIT_INT(pub->retransmit));
1361
1362 k_work_reschedule(&pub->timer, K_NO_WAIT);
1363
1364 return 0;
1365 }
1366
bt_mesh_model_find_vnd(const struct bt_mesh_elem * elem,uint16_t company,uint16_t id)1367 struct bt_mesh_model *bt_mesh_model_find_vnd(const struct bt_mesh_elem *elem,
1368 uint16_t company, uint16_t id)
1369 {
1370 uint8_t i;
1371
1372 for (i = 0U; i < elem->vnd_model_count; i++) {
1373 if (elem->vnd_models[i].vnd.company == company &&
1374 elem->vnd_models[i].vnd.id == id) {
1375 return &elem->vnd_models[i];
1376 }
1377 }
1378
1379 return NULL;
1380 }
1381
bt_mesh_model_find(const struct bt_mesh_elem * elem,uint16_t id)1382 struct bt_mesh_model *bt_mesh_model_find(const struct bt_mesh_elem *elem,
1383 uint16_t id)
1384 {
1385 uint8_t i;
1386
1387 for (i = 0U; i < elem->model_count; i++) {
1388 if (elem->models[i].id == id) {
1389 return &elem->models[i];
1390 }
1391 }
1392
1393 return NULL;
1394 }
1395
bt_mesh_comp_get(void)1396 const struct bt_mesh_comp *bt_mesh_comp_get(void)
1397 {
1398 return dev_comp;
1399 }
1400
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)1401 void bt_mesh_model_extensions_walk(struct bt_mesh_model *model,
1402 enum bt_mesh_walk (*cb)(struct bt_mesh_model *mod,
1403 void *user_data),
1404 void *user_data)
1405 {
1406 #ifndef CONFIG_BT_MESH_MODEL_EXTENSIONS
1407 (void)cb(model, user_data);
1408 return;
1409 #else
1410 struct bt_mesh_model *it;
1411
1412 if (cb(model, user_data) == BT_MESH_WALK_STOP || !model->next) {
1413 return;
1414 }
1415
1416 /* List is circular. Step through all models until we reach the start: */
1417 for (it = model->next; it != model; it = it->next) {
1418 if (cb(it, user_data) == BT_MESH_WALK_STOP) {
1419 return;
1420 }
1421 }
1422 #endif
1423 }
1424
1425 #ifdef CONFIG_BT_MESH_MODEL_EXTENSIONS
mod_rel_register(struct bt_mesh_model * base,struct bt_mesh_model * ext,uint8_t type)1426 static int mod_rel_register(struct bt_mesh_model *base,
1427 struct bt_mesh_model *ext,
1428 uint8_t type)
1429 {
1430 LOG_DBG("");
1431 struct mod_relation extension = {
1432 base->elem_idx,
1433 base->mod_idx,
1434 ext->elem_idx,
1435 ext->mod_idx,
1436 type,
1437 };
1438 int i;
1439
1440 for (i = 0; i < ARRAY_SIZE(mod_rel_list); i++) {
1441 if (mod_rel_list[i].elem_base == 0 &&
1442 mod_rel_list[i].idx_base == 0 &&
1443 mod_rel_list[i].elem_ext == 0 &&
1444 mod_rel_list[i].idx_ext == 0) {
1445 memcpy(&mod_rel_list[i], &extension,
1446 sizeof(extension));
1447 return 0;
1448 }
1449 }
1450 LOG_ERR("Failed to extend");
1451 return -ENOMEM;
1452 }
1453
bt_mesh_model_extend(struct bt_mesh_model * extending_mod,struct bt_mesh_model * base_mod)1454 int bt_mesh_model_extend(struct bt_mesh_model *extending_mod, struct bt_mesh_model *base_mod)
1455 {
1456 struct bt_mesh_model *a = extending_mod;
1457 struct bt_mesh_model *b = base_mod;
1458 struct bt_mesh_model *a_next = a->next;
1459 struct bt_mesh_model *b_next = b->next;
1460 struct bt_mesh_model *it;
1461
1462 base_mod->flags |= BT_MESH_MOD_EXTENDED;
1463
1464 if (a == b) {
1465 return 0;
1466 }
1467
1468 /* Check if a's list contains b */
1469 for (it = a; (it != NULL) && (it->next != a); it = it->next) {
1470 if (it == b) {
1471 return 0;
1472 }
1473 }
1474
1475 /* Merge lists */
1476 if (a_next) {
1477 b->next = a_next;
1478 } else {
1479 b->next = a;
1480 }
1481
1482 if (b_next) {
1483 a->next = b_next;
1484 } else {
1485 a->next = b;
1486 }
1487
1488
1489 if (IS_ENABLED(CONFIG_BT_MESH_COMP_PAGE_1)) {
1490 return mod_rel_register(base_mod, extending_mod, RELATION_TYPE_EXT);
1491 }
1492
1493 return 0;
1494 }
1495
bt_mesh_model_correspond(struct bt_mesh_model * corresponding_mod,struct bt_mesh_model * base_mod)1496 int bt_mesh_model_correspond(struct bt_mesh_model *corresponding_mod,
1497 struct bt_mesh_model *base_mod)
1498 {
1499 int i, err;
1500 uint8_t cor_id = 0;
1501
1502 if (!IS_ENABLED(CONFIG_BT_MESH_COMP_PAGE_1)) {
1503 return -ENOTSUP;
1504 }
1505
1506 MOD_REL_LIST_FOR_EACH(i) {
1507 if (mod_rel_list[i].type < RELATION_TYPE_EXT &&
1508 mod_rel_list[i].type > cor_id) {
1509 cor_id = mod_rel_list[i].type;
1510 }
1511
1512 if ((IS_MOD_BASE(base_mod, i) ||
1513 IS_MOD_EXTENSION(base_mod, i) ||
1514 IS_MOD_BASE(corresponding_mod, i) ||
1515 IS_MOD_EXTENSION(corresponding_mod, i)) &&
1516 mod_rel_list[i].type < RELATION_TYPE_EXT) {
1517 return mod_rel_register(base_mod, corresponding_mod, mod_rel_list[i].type);
1518 }
1519 }
1520 err = mod_rel_register(base_mod, corresponding_mod, cor_id);
1521 if (err) {
1522 return err;
1523 }
1524 return 0;
1525 }
1526 #endif /* CONFIG_BT_MESH_MODEL_EXTENSIONS */
1527
bt_mesh_model_is_extended(struct bt_mesh_model * model)1528 bool bt_mesh_model_is_extended(struct bt_mesh_model *model)
1529 {
1530 return model->flags & BT_MESH_MOD_EXTENDED;
1531 }
1532
mod_set_bind(struct bt_mesh_model * mod,size_t len_rd,settings_read_cb read_cb,void * cb_arg)1533 static int mod_set_bind(struct bt_mesh_model *mod, size_t len_rd,
1534 settings_read_cb read_cb, void *cb_arg)
1535 {
1536 ssize_t len;
1537 int i;
1538
1539 /* Start with empty array regardless of cleared or set value */
1540 for (i = 0; i < mod->keys_cnt; i++) {
1541 mod->keys[i] = BT_MESH_KEY_UNUSED;
1542 }
1543
1544 if (len_rd == 0) {
1545 LOG_DBG("Cleared bindings for model");
1546 return 0;
1547 }
1548
1549 len = read_cb(cb_arg, mod->keys, mod->keys_cnt * sizeof(mod->keys[0]));
1550 if (len < 0) {
1551 LOG_ERR("Failed to read value (err %zd)", len);
1552 return len;
1553 }
1554
1555 LOG_HEXDUMP_DBG(mod->keys, len, "val");
1556
1557 LOG_DBG("Decoded %zu bound keys for model", len / sizeof(mod->keys[0]));
1558 return 0;
1559 }
1560
mod_set_sub(struct bt_mesh_model * mod,size_t len_rd,settings_read_cb read_cb,void * cb_arg)1561 static int mod_set_sub(struct bt_mesh_model *mod, size_t len_rd,
1562 settings_read_cb read_cb, void *cb_arg)
1563 {
1564 size_t size = mod->groups_cnt * sizeof(mod->groups[0]);
1565 ssize_t len;
1566
1567 /* Start with empty array regardless of cleared or set value */
1568 (void)memset(mod->groups, 0, size);
1569
1570 if (len_rd == 0) {
1571 LOG_DBG("Cleared subscriptions for model");
1572 return 0;
1573 }
1574
1575 len = read_cb(cb_arg, mod->groups, size);
1576 if (len < 0) {
1577 LOG_ERR("Failed to read value (err %zd)", len);
1578 return len;
1579 }
1580
1581 LOG_HEXDUMP_DBG(mod->groups, len, "val");
1582
1583 LOG_DBG("Decoded %zu subscribed group addresses for model", len / sizeof(mod->groups[0]));
1584 return 0;
1585 }
1586
mod_set_pub(struct bt_mesh_model * mod,size_t len_rd,settings_read_cb read_cb,void * cb_arg)1587 static int mod_set_pub(struct bt_mesh_model *mod, size_t len_rd,
1588 settings_read_cb read_cb, void *cb_arg)
1589 {
1590 struct mod_pub_val pub;
1591 int err;
1592
1593 if (!mod->pub) {
1594 LOG_WRN("Model has no publication context!");
1595 return -EINVAL;
1596 }
1597
1598 if (len_rd == 0) {
1599 mod->pub->addr = BT_MESH_ADDR_UNASSIGNED;
1600 mod->pub->key = 0U;
1601 mod->pub->cred = 0U;
1602 mod->pub->ttl = 0U;
1603 mod->pub->period = 0U;
1604 mod->pub->retransmit = 0U;
1605 mod->pub->count = 0U;
1606
1607 LOG_DBG("Cleared publication for model");
1608 return 0;
1609 }
1610
1611 if (!IS_ENABLED(CONFIG_BT_SETTINGS)) {
1612 return 0;
1613 }
1614
1615 err = bt_mesh_settings_set(read_cb, cb_arg, &pub, sizeof(pub));
1616 if (err) {
1617 LOG_ERR("Failed to set \'model-pub\'");
1618 return err;
1619 }
1620
1621 mod->pub->addr = pub.addr;
1622 mod->pub->key = pub.key;
1623 mod->pub->cred = pub.cred;
1624 mod->pub->ttl = pub.ttl;
1625 mod->pub->period = pub.period;
1626 mod->pub->retransmit = pub.retransmit;
1627 mod->pub->period_div = pub.period_div;
1628 mod->pub->count = 0U;
1629
1630 LOG_DBG("Restored model publication, dst 0x%04x app_idx 0x%03x", pub.addr, pub.key);
1631
1632 return 0;
1633 }
1634
mod_data_set(struct bt_mesh_model * mod,const char * name,size_t len_rd,settings_read_cb read_cb,void * cb_arg)1635 static int mod_data_set(struct bt_mesh_model *mod,
1636 const char *name, size_t len_rd,
1637 settings_read_cb read_cb, void *cb_arg)
1638 {
1639 const char *next;
1640
1641 settings_name_next(name, &next);
1642
1643 if (mod->cb && mod->cb->settings_set) {
1644 return mod->cb->settings_set(mod, next, len_rd,
1645 read_cb, cb_arg);
1646 }
1647
1648 return 0;
1649 }
1650
mod_set(bool vnd,const char * name,size_t len_rd,settings_read_cb read_cb,void * cb_arg)1651 static int mod_set(bool vnd, const char *name, size_t len_rd,
1652 settings_read_cb read_cb, void *cb_arg)
1653 {
1654 struct bt_mesh_model *mod;
1655 uint8_t elem_idx, mod_idx;
1656 uint16_t mod_key;
1657 int len;
1658 const char *next;
1659
1660 if (!name) {
1661 LOG_ERR("Insufficient number of arguments");
1662 return -ENOENT;
1663 }
1664
1665 mod_key = strtol(name, NULL, 16);
1666 elem_idx = mod_key >> 8;
1667 mod_idx = mod_key;
1668
1669 LOG_DBG("Decoded mod_key 0x%04x as elem_idx %u mod_idx %u", mod_key, elem_idx, mod_idx);
1670
1671 mod = bt_mesh_model_get(vnd, elem_idx, mod_idx);
1672 if (!mod) {
1673 LOG_ERR("Failed to get model for elem_idx %u mod_idx %u", elem_idx, mod_idx);
1674 return -ENOENT;
1675 }
1676
1677 len = settings_name_next(name, &next);
1678
1679 if (!next) {
1680 LOG_ERR("Insufficient number of arguments");
1681 return -ENOENT;
1682 }
1683
1684 if (!strncmp(next, "bind", len)) {
1685 return mod_set_bind(mod, len_rd, read_cb, cb_arg);
1686 }
1687
1688 if (!strncmp(next, "sub", len)) {
1689 return mod_set_sub(mod, len_rd, read_cb, cb_arg);
1690 }
1691
1692 if (!strncmp(next, "pub", len)) {
1693 return mod_set_pub(mod, len_rd, read_cb, cb_arg);
1694 }
1695
1696 if (!strncmp(next, "data", len)) {
1697 return mod_data_set(mod, next, len_rd, read_cb, cb_arg);
1698 }
1699
1700 LOG_WRN("Unknown module key %s", next);
1701 return -ENOENT;
1702 }
1703
sig_mod_set(const char * name,size_t len_rd,settings_read_cb read_cb,void * cb_arg)1704 static int sig_mod_set(const char *name, size_t len_rd,
1705 settings_read_cb read_cb, void *cb_arg)
1706 {
1707 return mod_set(false, name, len_rd, read_cb, cb_arg);
1708 }
1709
1710 BT_MESH_SETTINGS_DEFINE(sig_mod, "s", sig_mod_set);
1711
vnd_mod_set(const char * name,size_t len_rd,settings_read_cb read_cb,void * cb_arg)1712 static int vnd_mod_set(const char *name, size_t len_rd,
1713 settings_read_cb read_cb, void *cb_arg)
1714 {
1715 return mod_set(true, name, len_rd, read_cb, cb_arg);
1716 }
1717
1718 BT_MESH_SETTINGS_DEFINE(vnd_mod, "v", vnd_mod_set);
1719
comp_set(const char * name,size_t len_rd,settings_read_cb read_cb,void * cb_arg)1720 static int comp_set(const char *name, size_t len_rd, settings_read_cb read_cb,
1721 void *cb_arg)
1722 {
1723 /* Only need to know that the entry exists. Will load the contents on
1724 * demand.
1725 */
1726 if (len_rd > 0) {
1727 atomic_set_bit(bt_mesh.flags, BT_MESH_COMP_DIRTY);
1728 }
1729
1730 return 0;
1731 }
1732 BT_MESH_SETTINGS_DEFINE(comp, "cmp", comp_set);
1733
encode_mod_path(struct bt_mesh_model * mod,bool vnd,const char * key,char * path,size_t path_len)1734 static void encode_mod_path(struct bt_mesh_model *mod, bool vnd,
1735 const char *key, char *path, size_t path_len)
1736 {
1737 uint16_t mod_key = (((uint16_t)mod->elem_idx << 8) | mod->mod_idx);
1738
1739 if (vnd) {
1740 snprintk(path, path_len, "bt/mesh/v/%x/%s", mod_key, key);
1741 } else {
1742 snprintk(path, path_len, "bt/mesh/s/%x/%s", mod_key, key);
1743 }
1744 }
1745
store_pending_mod_bind(struct bt_mesh_model * mod,bool vnd)1746 static void store_pending_mod_bind(struct bt_mesh_model *mod, bool vnd)
1747 {
1748 uint16_t keys[CONFIG_BT_MESH_MODEL_KEY_COUNT];
1749 char path[20];
1750 int i, count, err;
1751
1752 for (i = 0, count = 0; i < mod->keys_cnt; i++) {
1753 if (mod->keys[i] != BT_MESH_KEY_UNUSED) {
1754 keys[count++] = mod->keys[i];
1755 LOG_DBG("model key 0x%04x", mod->keys[i]);
1756 }
1757 }
1758
1759 encode_mod_path(mod, vnd, "bind", path, sizeof(path));
1760
1761 if (count) {
1762 err = settings_save_one(path, keys, count * sizeof(keys[0]));
1763 } else {
1764 err = settings_delete(path);
1765 }
1766
1767 if (err) {
1768 LOG_ERR("Failed to store %s value", path);
1769 } else {
1770 LOG_DBG("Stored %s value", path);
1771 }
1772 }
1773
store_pending_mod_sub(struct bt_mesh_model * mod,bool vnd)1774 static void store_pending_mod_sub(struct bt_mesh_model *mod, bool vnd)
1775 {
1776 uint16_t groups[CONFIG_BT_MESH_MODEL_GROUP_COUNT];
1777 char path[20];
1778 int i, count, err;
1779
1780 for (i = 0, count = 0; i < mod->groups_cnt; i++) {
1781 if (mod->groups[i] != BT_MESH_ADDR_UNASSIGNED) {
1782 groups[count++] = mod->groups[i];
1783 }
1784 }
1785
1786 encode_mod_path(mod, vnd, "sub", path, sizeof(path));
1787
1788 if (count) {
1789 err = settings_save_one(path, groups,
1790 count * sizeof(groups[0]));
1791 } else {
1792 err = settings_delete(path);
1793 }
1794
1795 if (err) {
1796 LOG_ERR("Failed to store %s value", path);
1797 } else {
1798 LOG_DBG("Stored %s value", path);
1799 }
1800 }
1801
store_pending_mod_pub(struct bt_mesh_model * mod,bool vnd)1802 static void store_pending_mod_pub(struct bt_mesh_model *mod, bool vnd)
1803 {
1804 struct mod_pub_val pub = {0};
1805 char path[20];
1806 int err;
1807
1808 encode_mod_path(mod, vnd, "pub", path, sizeof(path));
1809
1810 if (!mod->pub || mod->pub->addr == BT_MESH_ADDR_UNASSIGNED) {
1811 err = settings_delete(path);
1812 } else {
1813 pub.addr = mod->pub->addr;
1814 pub.key = mod->pub->key;
1815 pub.ttl = mod->pub->ttl;
1816 pub.retransmit = mod->pub->retransmit;
1817 pub.period = mod->pub->period;
1818 pub.period_div = mod->pub->period_div;
1819 pub.cred = mod->pub->cred;
1820
1821 err = settings_save_one(path, &pub, sizeof(pub));
1822 }
1823
1824 if (err) {
1825 LOG_ERR("Failed to store %s value", path);
1826 } else {
1827 LOG_DBG("Stored %s value", path);
1828 }
1829 }
1830
store_pending_mod(struct bt_mesh_model * mod,struct bt_mesh_elem * elem,bool vnd,bool primary,void * user_data)1831 static void store_pending_mod(struct bt_mesh_model *mod,
1832 struct bt_mesh_elem *elem, bool vnd,
1833 bool primary, void *user_data)
1834 {
1835 if (!mod->flags) {
1836 return;
1837 }
1838
1839 if (mod->flags & BT_MESH_MOD_BIND_PENDING) {
1840 mod->flags &= ~BT_MESH_MOD_BIND_PENDING;
1841 store_pending_mod_bind(mod, vnd);
1842 }
1843
1844 if (mod->flags & BT_MESH_MOD_SUB_PENDING) {
1845 mod->flags &= ~BT_MESH_MOD_SUB_PENDING;
1846 store_pending_mod_sub(mod, vnd);
1847 }
1848
1849 if (mod->flags & BT_MESH_MOD_PUB_PENDING) {
1850 mod->flags &= ~BT_MESH_MOD_PUB_PENDING;
1851 store_pending_mod_pub(mod, vnd);
1852 }
1853
1854 if (mod->flags & BT_MESH_MOD_DATA_PENDING) {
1855 mod->flags &= ~BT_MESH_MOD_DATA_PENDING;
1856 mod->cb->pending_store(mod);
1857 }
1858 }
1859
bt_mesh_model_pending_store(void)1860 void bt_mesh_model_pending_store(void)
1861 {
1862 bt_mesh_model_foreach(store_pending_mod, NULL);
1863 }
1864
bt_mesh_model_bind_store(struct bt_mesh_model * mod)1865 void bt_mesh_model_bind_store(struct bt_mesh_model *mod)
1866 {
1867 mod->flags |= BT_MESH_MOD_BIND_PENDING;
1868 bt_mesh_settings_store_schedule(BT_MESH_SETTINGS_MOD_PENDING);
1869 }
1870
bt_mesh_model_sub_store(struct bt_mesh_model * mod)1871 void bt_mesh_model_sub_store(struct bt_mesh_model *mod)
1872 {
1873 mod->flags |= BT_MESH_MOD_SUB_PENDING;
1874 bt_mesh_settings_store_schedule(BT_MESH_SETTINGS_MOD_PENDING);
1875 }
1876
bt_mesh_model_pub_store(struct bt_mesh_model * mod)1877 void bt_mesh_model_pub_store(struct bt_mesh_model *mod)
1878 {
1879 mod->flags |= BT_MESH_MOD_PUB_PENDING;
1880 bt_mesh_settings_store_schedule(BT_MESH_SETTINGS_MOD_PENDING);
1881 }
1882
bt_mesh_comp_store(void)1883 int bt_mesh_comp_store(void)
1884 {
1885 NET_BUF_SIMPLE_DEFINE(buf, BT_MESH_TX_SDU_MAX);
1886 int err;
1887
1888 err = bt_mesh_comp_data_get_page_0(&buf, 0);
1889 if (err) {
1890 LOG_ERR("Failed to read composition data: %d", err);
1891 return err;
1892 }
1893
1894 err = settings_save_one("bt/mesh/cmp", buf.data, buf.len);
1895 if (err) {
1896 LOG_ERR("Failed to store composition data: %d", err);
1897 } else {
1898 LOG_DBG("Stored composition data");
1899 }
1900
1901 return err;
1902 }
1903
bt_mesh_comp_change_prepare(void)1904 int bt_mesh_comp_change_prepare(void)
1905 {
1906 if (!IS_ENABLED(CONFIG_BT_SETTINGS)) {
1907 return -ENOTSUP;
1908 }
1909
1910 return bt_mesh_comp_store();
1911 }
1912
comp_data_clear(void)1913 static void comp_data_clear(void)
1914 {
1915 int err;
1916
1917 err = settings_delete("bt/mesh/cmp");
1918 if (err) {
1919 LOG_ERR("Failed to clear composition data: %d", err);
1920 } else {
1921 LOG_DBG("Cleared composition data page 128");
1922 }
1923
1924 atomic_clear_bit(bt_mesh.flags, BT_MESH_COMP_DIRTY);
1925 }
1926
read_comp_cb(const char * key,size_t len,settings_read_cb read_cb,void * cb_arg,void * param)1927 static int read_comp_cb(const char *key, size_t len, settings_read_cb read_cb,
1928 void *cb_arg, void *param)
1929 {
1930 struct net_buf_simple *buf = param;
1931
1932 if (len > net_buf_simple_tailroom(buf)) {
1933 return -ENOBUFS;
1934 }
1935
1936 len = read_cb(cb_arg, net_buf_simple_tail(buf), len);
1937 if (len > 0) {
1938 net_buf_simple_add(buf, len);
1939 }
1940
1941 return -EALREADY;
1942 }
1943
bt_mesh_comp_read(struct net_buf_simple * buf)1944 int bt_mesh_comp_read(struct net_buf_simple *buf)
1945 {
1946 size_t original_len = buf->len;
1947 int err;
1948
1949 if (!IS_ENABLED(CONFIG_BT_SETTINGS)) {
1950 return -ENOTSUP;
1951 }
1952
1953 err = settings_load_subtree_direct("bt/mesh/cmp", read_comp_cb, buf);
1954 if (err) {
1955 LOG_ERR("Failed reading composition data: %d", err);
1956 return err;
1957 }
1958
1959 if (buf->len == original_len) {
1960 return -ENOENT;
1961 }
1962
1963 return 0;
1964 }
1965
bt_mesh_model_data_store(struct bt_mesh_model * mod,bool vnd,const char * name,const void * data,size_t data_len)1966 int bt_mesh_model_data_store(struct bt_mesh_model *mod, bool vnd,
1967 const char *name, const void *data,
1968 size_t data_len)
1969 {
1970 char path[30];
1971 int err;
1972
1973 encode_mod_path(mod, vnd, "data", path, sizeof(path));
1974 if (name) {
1975 strcat(path, "/");
1976 strncat(path, name, SETTINGS_MAX_DIR_DEPTH);
1977 }
1978
1979 if (data_len) {
1980 err = settings_save_one(path, data, data_len);
1981 } else {
1982 err = settings_delete(path);
1983 }
1984
1985 if (err) {
1986 LOG_ERR("Failed to store %s value", path);
1987 } else {
1988 LOG_DBG("Stored %s value", path);
1989 }
1990 return err;
1991 }
1992
1993 #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)1994 static int metadata_set(const char *name, size_t len_rd, settings_read_cb read_cb, void *cb_arg)
1995 {
1996 /* Only need to know that the entry exists. Will load the contents on
1997 * demand.
1998 */
1999 if (len_rd > 0) {
2000 atomic_set_bit(bt_mesh.flags, BT_MESH_METADATA_DIRTY);
2001 }
2002
2003 return 0;
2004 }
2005 BT_MESH_SETTINGS_DEFINE(metadata, "metadata", metadata_set);
2006
bt_mesh_models_metadata_store(void)2007 int bt_mesh_models_metadata_store(void)
2008 {
2009 NET_BUF_SIMPLE_DEFINE(buf, CONFIG_BT_MESH_MODELS_METADATA_PAGE_LEN);
2010 size_t total_size;
2011 int err;
2012
2013 total_size = bt_mesh_metadata_page_0_size();
2014 LOG_DBG("bt/mesh/metadata total %d", total_size);
2015
2016 net_buf_simple_init(&buf, 0);
2017 net_buf_simple_add_le16(&buf, total_size);
2018
2019 err = bt_mesh_metadata_get_page_0(&buf, 0);
2020 if (err == -E2BIG) {
2021 LOG_ERR("Metadata too large");
2022 return err;
2023 }
2024 if (err) {
2025 LOG_ERR("Failed to read models metadata: %d", err);
2026 return err;
2027 }
2028
2029 LOG_DBG("bt/mesh/metadata len %d", buf.len);
2030
2031 err = settings_save_one("bt/mesh/metadata", buf.data, buf.len);
2032 if (err) {
2033 LOG_ERR("Failed to store models metadata: %d", err);
2034 } else {
2035 LOG_DBG("Stored models metadata");
2036 }
2037
2038 return err;
2039 }
2040
bt_mesh_models_metadata_read(struct net_buf_simple * buf,size_t offset)2041 int bt_mesh_models_metadata_read(struct net_buf_simple *buf, size_t offset)
2042 {
2043 NET_BUF_SIMPLE_DEFINE(stored_buf, CONFIG_BT_MESH_MODELS_METADATA_PAGE_LEN);
2044 size_t original_len = buf->len;
2045 int err;
2046
2047 if (!IS_ENABLED(CONFIG_BT_SETTINGS)) {
2048 return -ENOTSUP;
2049 }
2050
2051 net_buf_simple_init(&stored_buf, 0);
2052
2053 err = settings_load_subtree_direct("bt/mesh/metadata", read_comp_cb, &stored_buf);
2054 if (err) {
2055 LOG_ERR("Failed reading models metadata: %d", err);
2056 return err;
2057 }
2058
2059 /* First two bytes are total length */
2060 offset += 2;
2061
2062 net_buf_simple_add_mem(buf, &stored_buf.data, MIN(net_buf_simple_tailroom(buf), 2));
2063
2064 if (offset >= stored_buf.len) {
2065 return 0;
2066 }
2067
2068 net_buf_simple_add_mem(buf, &stored_buf.data[offset],
2069 MIN(net_buf_simple_tailroom(buf), stored_buf.len - offset));
2070
2071 LOG_DBG("metadata read %d", buf->len);
2072
2073 if (buf->len == original_len) {
2074 return -ENOENT;
2075 }
2076
2077 return 0;
2078 }
2079 #endif
2080
models_metadata_clear(void)2081 static void models_metadata_clear(void)
2082 {
2083 int err;
2084
2085 err = settings_delete("bt/mesh/metadata");
2086 if (err) {
2087 LOG_ERR("Failed to clear models metadata: %d", err);
2088 } else {
2089 LOG_DBG("Cleared models metadata");
2090 }
2091
2092 atomic_clear_bit(bt_mesh.flags, BT_MESH_METADATA_DIRTY);
2093 }
2094
bt_mesh_comp_data_pending_clear(void)2095 void bt_mesh_comp_data_pending_clear(void)
2096 {
2097 comp_data_clear();
2098 models_metadata_clear();
2099 }
2100
bt_mesh_comp_data_clear(void)2101 void bt_mesh_comp_data_clear(void)
2102 {
2103 bt_mesh_settings_store_schedule(BT_MESH_SETTINGS_COMP_PENDING);
2104 }
2105
bt_mesh_models_metadata_change_prepare(void)2106 int bt_mesh_models_metadata_change_prepare(void)
2107 {
2108 #if IS_ENABLED(CONFIG_BT_MESH_LARGE_COMP_DATA_SRV)
2109 return bt_mesh_models_metadata_store();
2110 #else
2111 return -ENOTSUP;
2112 #endif
2113 }
2114
commit_mod(struct bt_mesh_model * mod,struct bt_mesh_elem * elem,bool vnd,bool primary,void * user_data)2115 static void commit_mod(struct bt_mesh_model *mod, struct bt_mesh_elem *elem,
2116 bool vnd, bool primary, void *user_data)
2117 {
2118 if (mod->pub && mod->pub->update &&
2119 mod->pub->addr != BT_MESH_ADDR_UNASSIGNED) {
2120 int32_t ms = bt_mesh_model_pub_period_get(mod);
2121
2122 if (ms > 0) {
2123 LOG_DBG("Starting publish timer (period %u ms)", ms);
2124 k_work_schedule(&mod->pub->timer, K_MSEC(ms));
2125 }
2126 }
2127
2128 if (!IS_ENABLED(CONFIG_BT_MESH_LOW_POWER)) {
2129 return;
2130 }
2131
2132 for (int i = 0; i < mod->groups_cnt; i++) {
2133 if (mod->groups[i] != BT_MESH_ADDR_UNASSIGNED) {
2134 bt_mesh_lpn_group_add(mod->groups[i]);
2135 }
2136 }
2137 }
2138
bt_mesh_model_settings_commit(void)2139 void bt_mesh_model_settings_commit(void)
2140 {
2141 bt_mesh_model_foreach(commit_mod, NULL);
2142 }
2143
bt_mesh_model_data_store_schedule(struct bt_mesh_model * mod)2144 void bt_mesh_model_data_store_schedule(struct bt_mesh_model *mod)
2145 {
2146 mod->flags |= BT_MESH_MOD_DATA_PENDING;
2147 bt_mesh_settings_store_schedule(BT_MESH_SETTINGS_MOD_PENDING);
2148 }
2149