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