xref: /nrf52832-nimble/packages/NimBLE-latest/nimble/host/mesh/src/access.c (revision 042d53a763ad75cb1465103098bb88c245d95138)
1 /*  Bluetooth Mesh */
2 
3 /*
4  * Copyright (c) 2017 Intel Corporation
5  *
6  * SPDX-License-Identifier: Apache-2.0
7  */
8 
9 #include <errno.h>
10 
11 #include <os/os_mbuf.h>
12 #include "mesh/mesh.h"
13 
14 #include "syscfg/syscfg.h"
15 #define BT_DBG_ENABLED (MYNEWT_VAL(BLE_MESH_DEBUG_ACCESS))
16 #include "host/ble_hs_log.h"
17 
18 #include "mesh_priv.h"
19 #include "adv.h"
20 #include "net.h"
21 #include "lpn.h"
22 #include "transport.h"
23 #include "access.h"
24 #include "foundation.h"
25 #if MYNEWT_VAL(BLE_MESH_SHELL_MODELS)
26 #include "mesh/model_cli.h"
27 #endif
28 
29 static const struct bt_mesh_comp *dev_comp;
30 static u16_t dev_primary_addr;
31 
32 static const struct {
33 	const u16_t id;
34 	int (*const init)(struct bt_mesh_model *model, bool primary);
35 } model_init[] = {
36 	{ BT_MESH_MODEL_ID_CFG_SRV, bt_mesh_cfg_srv_init },
37 	{ BT_MESH_MODEL_ID_HEALTH_SRV, bt_mesh_health_srv_init },
38 #if MYNEWT_VAL(BLE_MESH_CFG_CLI)
39 	{ BT_MESH_MODEL_ID_CFG_CLI, bt_mesh_cfg_cli_init },
40 #endif
41 #if MYNEWT_VAL(BLE_MESH_HEALTH_CLI)
42 	{ BT_MESH_MODEL_ID_HEALTH_CLI, bt_mesh_health_cli_init },
43 #endif
44 #if MYNEWT_VAL(BLE_MESH_SHELL_MODELS)
45 	{ BT_MESH_MODEL_ID_GEN_ONOFF_CLI, bt_mesh_gen_model_cli_init },
46 	{ BT_MESH_MODEL_ID_GEN_LEVEL_CLI, bt_mesh_gen_model_cli_init },
47 #endif
48 };
49 
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)50 void bt_mesh_model_foreach(void (*func)(struct bt_mesh_model *mod,
51 					struct bt_mesh_elem *elem,
52 					bool vnd, bool primary,
53 					void *user_data),
54 			   void *user_data)
55 {
56 	int i, j;
57 
58 	for (i = 0; i < dev_comp->elem_count; i++) {
59 		struct bt_mesh_elem *elem = &dev_comp->elem[i];
60 
61 		for (j = 0; j < elem->model_count; j++) {
62 			struct bt_mesh_model *model = &elem->models[j];
63 
64 			func(model, elem, false, i == 0, user_data);
65 		}
66 
67 		for (j = 0; j < elem->vnd_model_count; j++) {
68 			struct bt_mesh_model *model = &elem->vnd_models[j];
69 
70 			func(model, elem, true, i == 0, user_data);
71 		}
72 	}
73 }
74 
bt_mesh_model_pub_period_get(struct bt_mesh_model * mod)75 s32_t bt_mesh_model_pub_period_get(struct bt_mesh_model *mod)
76 {
77 	int period;
78 
79 	if (!mod->pub) {
80 		return 0;
81 	}
82 
83 	switch (mod->pub->period >> 6) {
84 	case 0x00:
85 		/* 1 step is 100 ms */
86 		period = K_MSEC((mod->pub->period & BIT_MASK(6)) * 100);
87 		break;
88 	case 0x01:
89 		/* 1 step is 1 second */
90 		period = K_SECONDS(mod->pub->period & BIT_MASK(6));
91 		break;
92 	case 0x02:
93 		/* 1 step is 10 seconds */
94 		period = K_SECONDS((mod->pub->period & BIT_MASK(6)) * 10);
95 		break;
96 	case 0x03:
97 		/* 1 step is 10 minutes */
98 		period = K_MINUTES((mod->pub->period & BIT_MASK(6)) * 10);
99 		break;
100 	default:
101 		CODE_UNREACHABLE;
102 	}
103 
104 	return period >> mod->pub->period_div;
105 }
106 
next_period(struct bt_mesh_model * mod)107 static s32_t next_period(struct bt_mesh_model *mod)
108 {
109 	struct bt_mesh_model_pub *pub = mod->pub;
110 	u32_t elapsed, period;
111 
112 	period = bt_mesh_model_pub_period_get(mod);
113 	if (!period) {
114 		return 0;
115 	}
116 
117 	elapsed = k_uptime_get_32() - pub->period_start;
118 
119 	BT_DBG("Publishing took %ums", elapsed);
120 
121 	if (elapsed > period) {
122 		BT_WARN("Publication sending took longer than the period");
123 		/* Return smallest positive number since 0 means disabled */
124 		return K_MSEC(1);
125 	}
126 
127 	return period - elapsed;
128 }
129 
publish_sent(int err,void * user_data)130 static void publish_sent(int err, void *user_data)
131 {
132 	struct bt_mesh_model *mod = user_data;
133 	s32_t delay;
134 
135 	BT_DBG("err %d", err);
136 
137 	if (mod->pub->count) {
138 		delay = BT_MESH_PUB_TRANSMIT_INT(mod->pub->retransmit);
139 	} else {
140 		delay = next_period(mod);
141 	}
142 
143 	if (delay) {
144 		BT_DBG("Publishing next time in %dms", delay);
145 		k_delayed_work_submit(&mod->pub->timer, delay);
146 	}
147 }
148 
149 static const struct bt_mesh_send_cb pub_sent_cb = {
150 	.end = publish_sent,
151 };
152 
publish_retransmit(struct bt_mesh_model * mod)153 static int publish_retransmit(struct bt_mesh_model *mod)
154 {
155 	struct os_mbuf *sdu = NET_BUF_SIMPLE(BT_MESH_TX_SDU_MAX);
156 	struct bt_mesh_model_pub *pub = mod->pub;
157 	struct bt_mesh_app_key *key;
158 	struct bt_mesh_msg_ctx ctx = {
159 		.addr = pub->addr,
160 		.send_ttl = pub->ttl,
161 	};
162 	struct bt_mesh_net_tx tx = {
163 		.ctx = &ctx,
164 		.src = bt_mesh_model_elem(mod)->addr,
165 		.xmit = bt_mesh_net_transmit_get(),
166 		.friend_cred = pub->cred,
167 	};
168 	int err;
169 
170 	key = bt_mesh_app_key_find(pub->key);
171 	if (!key) {
172 		err = -EADDRNOTAVAIL;
173 		goto done;
174 	}
175 
176 	tx.sub = bt_mesh_subnet_get(key->net_idx);
177 
178 	ctx.net_idx = key->net_idx;
179 	ctx.app_idx = key->app_idx;
180 
181 	net_buf_simple_init(sdu, 0);
182 	net_buf_simple_add_mem(sdu, pub->msg->om_data, pub->msg->om_len);
183 
184 	pub->count--;
185 
186 	err = bt_mesh_trans_send(&tx, sdu, &pub_sent_cb, mod);
187 
188 done:
189 	os_mbuf_free_chain(sdu);
190 	return err;
191 }
192 
mod_publish(struct ble_npl_event * work)193 static void mod_publish(struct ble_npl_event *work)
194 {
195 	struct bt_mesh_model_pub *pub = ble_npl_event_get_arg(work);
196 	s32_t period_ms;
197 	int err;
198 
199 	BT_DBG("");
200 
201 	period_ms = bt_mesh_model_pub_period_get(pub->mod);
202 	BT_DBG("period %u ms", period_ms);
203 
204 	if (pub->count) {
205 		err = publish_retransmit(pub->mod);
206 		if (err) {
207 			BT_ERR("Failed to retransmit (err %d)", err);
208 
209 			pub->count = 0;
210 
211 			/* Continue with normal publication */
212 			if (period_ms) {
213 				k_delayed_work_submit(&pub->timer, period_ms);
214 			}
215 		}
216 
217 		return;
218 	}
219 
220 	if (!period_ms) {
221 		return;
222 	}
223 
224 	__ASSERT_NO_MSG(pub->update != NULL);
225 
226 	pub->period_start = k_uptime_get_32();
227 
228 	err = pub->update(pub->mod);
229 	if (err) {
230 		BT_ERR("Failed to update publication message");
231 		return;
232 	}
233 
234 	err = bt_mesh_model_publish(pub->mod);
235 	if (err) {
236 		BT_ERR("Publishing failed (err %d)", err);
237 	}
238 
239 	if (pub->count) {
240 		/* Retransmissions also control the timer */
241 		k_delayed_work_cancel(&pub->timer);
242 	}
243 }
244 
bt_mesh_model_elem(struct bt_mesh_model * mod)245 struct bt_mesh_elem *bt_mesh_model_elem(struct bt_mesh_model *mod)
246 {
247 	return &dev_comp->elem[mod->elem_idx];
248 }
249 
bt_mesh_model_get(bool vnd,u8_t elem_idx,u8_t mod_idx)250 struct bt_mesh_model *bt_mesh_model_get(bool vnd, u8_t elem_idx, u8_t mod_idx)
251 {
252 	struct bt_mesh_elem *elem;
253 
254 	if (elem_idx >= dev_comp->elem_count) {
255 		BT_ERR("Invalid element index %u", elem_idx);
256 		return NULL;
257 	}
258 
259 	elem = &dev_comp->elem[elem_idx];
260 
261 	if (vnd) {
262 		if (mod_idx >= elem->vnd_model_count) {
263 			BT_ERR("Invalid vendor model index %u", mod_idx);
264 			return NULL;
265 		}
266 
267 		return &elem->vnd_models[mod_idx];
268 	} else {
269 		if (mod_idx >= elem->model_count) {
270 			BT_ERR("Invalid SIG model index %u", mod_idx);
271 			return NULL;
272 		}
273 
274 		return &elem->models[mod_idx];
275 	}
276 }
277 
mod_init(struct bt_mesh_model * mod,struct bt_mesh_elem * elem,bool vnd,bool primary,void * user_data)278 static void mod_init(struct bt_mesh_model *mod, struct bt_mesh_elem *elem,
279 		     bool vnd, bool primary, void *user_data)
280 {
281 	int i;
282 
283 	if (mod->pub) {
284 		mod->pub->mod = mod;
285 		k_delayed_work_init(&mod->pub->timer, mod_publish);
286 		k_delayed_work_add_arg(&mod->pub->timer, mod->pub);
287 	}
288 
289 	for (i = 0; i < ARRAY_SIZE(mod->keys); i++) {
290 		mod->keys[i] = BT_MESH_KEY_UNUSED;
291 	}
292 
293 	mod->elem_idx = elem - dev_comp->elem;
294 	if (vnd) {
295 		mod->mod_idx = mod - elem->vnd_models;
296 	} else {
297 		mod->mod_idx = mod - elem->models;
298 	}
299 
300 	if (vnd) {
301 		return;
302 	}
303 
304 	for (i = 0; i < ARRAY_SIZE(model_init); i++) {
305 		if (model_init[i].id == mod->id) {
306 			model_init[i].init(mod, primary);
307 		}
308 	}
309 }
310 
bt_mesh_comp_register(const struct bt_mesh_comp * comp)311 int bt_mesh_comp_register(const struct bt_mesh_comp *comp)
312 {
313 	/* There must be at least one element */
314 	if (!comp->elem_count) {
315 		return -EINVAL;
316 	}
317 
318 	dev_comp = comp;
319 
320 	bt_mesh_model_foreach(mod_init, NULL);
321 
322 	return 0;
323 }
324 
bt_mesh_comp_provision(u16_t addr)325 void bt_mesh_comp_provision(u16_t addr)
326 {
327 	int i;
328 
329 	dev_primary_addr = addr;
330 
331 	BT_DBG("addr 0x%04x elem_count %zu", addr, dev_comp->elem_count);
332 
333 	for (i = 0; i < dev_comp->elem_count; i++) {
334 		struct bt_mesh_elem *elem = &dev_comp->elem[i];
335 
336 		elem->addr = addr++;
337 
338 		BT_DBG("addr 0x%04x mod_count %u vnd_mod_count %u",
339 		       elem->addr, elem->model_count, elem->vnd_model_count);
340 	}
341 }
342 
bt_mesh_comp_unprovision(void)343 void bt_mesh_comp_unprovision(void)
344 {
345 	BT_DBG("");
346 
347 	dev_primary_addr = BT_MESH_ADDR_UNASSIGNED;
348 
349 	bt_mesh_model_foreach(mod_init, NULL);
350 }
351 
bt_mesh_primary_addr(void)352 u16_t bt_mesh_primary_addr(void)
353 {
354 	return dev_primary_addr;
355 }
356 
bt_mesh_model_find_group(struct bt_mesh_model * mod,u16_t addr)357 u16_t *bt_mesh_model_find_group(struct bt_mesh_model *mod, u16_t addr)
358 {
359 	int i;
360 
361 	for (i = 0; i < ARRAY_SIZE(mod->groups); i++) {
362 		if (mod->groups[i] == addr) {
363 			return &mod->groups[i];
364 		}
365 	}
366 
367 	return NULL;
368 }
369 
bt_mesh_elem_find_group(struct bt_mesh_elem * elem,u16_t group_addr)370 static struct bt_mesh_model *bt_mesh_elem_find_group(struct bt_mesh_elem *elem,
371 						     u16_t group_addr)
372 {
373 	struct bt_mesh_model *model;
374 	u16_t *match;
375 	int i;
376 
377 	for (i = 0; i < elem->model_count; i++) {
378 		model = &elem->models[i];
379 
380 		match = bt_mesh_model_find_group(model, group_addr);
381 		if (match) {
382 			return model;
383 		}
384 	}
385 
386 	for (i = 0; i < elem->vnd_model_count; i++) {
387 		model = &elem->vnd_models[i];
388 
389 		match = bt_mesh_model_find_group(model, group_addr);
390 		if (match) {
391 			return model;
392 		}
393 	}
394 
395 	return NULL;
396 }
397 
bt_mesh_elem_find(u16_t addr)398 struct bt_mesh_elem *bt_mesh_elem_find(u16_t addr)
399 {
400 	int i;
401 
402 	for (i = 0; i < dev_comp->elem_count; i++) {
403 		struct bt_mesh_elem *elem = &dev_comp->elem[i];
404 
405 		if (BT_MESH_ADDR_IS_GROUP(addr) ||
406 		    BT_MESH_ADDR_IS_VIRTUAL(addr)) {
407 			if (bt_mesh_elem_find_group(elem, addr)) {
408 				return elem;
409 			}
410 		} else if (elem->addr == addr) {
411 			return elem;
412 		}
413 	}
414 
415 	return NULL;
416 }
417 
bt_mesh_elem_count(void)418 u8_t bt_mesh_elem_count(void)
419 {
420 	return dev_comp->elem_count;
421 }
422 
model_has_key(struct bt_mesh_model * mod,u16_t key)423 static bool model_has_key(struct bt_mesh_model *mod, u16_t key)
424 {
425 	int i;
426 
427 	for (i = 0; i < ARRAY_SIZE(mod->keys); i++) {
428 		if (mod->keys[i] == key) {
429 			return true;
430 		}
431 	}
432 
433 	return false;
434 }
435 
find_op(struct bt_mesh_model * models,u8_t model_count,u16_t dst,u16_t app_idx,u32_t opcode,struct bt_mesh_model ** model)436 static const struct bt_mesh_model_op *find_op(struct bt_mesh_model *models,
437 					      u8_t model_count, u16_t dst,
438 					      u16_t app_idx, u32_t opcode,
439 					      struct bt_mesh_model **model)
440 {
441 	u8_t i;
442 
443 	for (i = 0; i < model_count; i++) {
444 		const struct bt_mesh_model_op *op;
445 
446 		*model = &models[i];
447 
448 		if (BT_MESH_ADDR_IS_GROUP(dst) ||
449 		    BT_MESH_ADDR_IS_VIRTUAL(dst)) {
450 			if (!bt_mesh_model_find_group(*model, dst)) {
451 				continue;
452 			}
453 		}
454 
455 		if (!model_has_key(*model, app_idx)) {
456 			continue;
457 		}
458 
459 		for (op = (*model)->op; op->func; op++) {
460 			if (op->opcode == opcode) {
461 				return op;
462 			}
463 		}
464 	}
465 
466 	*model = NULL;
467 	return NULL;
468 }
469 
get_opcode(struct os_mbuf * buf,u32_t * opcode)470 static int get_opcode(struct os_mbuf *buf, u32_t *opcode)
471 {
472 	switch (buf->om_data[0] >> 6) {
473 	case 0x00:
474 	case 0x01:
475 		if (buf->om_data[0] == 0x7f) {
476 			BT_ERR("Ignoring RFU OpCode");
477 			return -EINVAL;
478 		}
479 
480 		*opcode = net_buf_simple_pull_u8(buf);
481 		return 0;
482 	case 0x02:
483 		if (buf->om_len < 2) {
484 			BT_ERR("Too short payload for 2-octet OpCode");
485 			return -EINVAL;
486 		}
487 
488 		*opcode = net_buf_simple_pull_be16(buf);
489 		return 0;
490 	case 0x03:
491 		if (buf->om_len < 3) {
492 			BT_ERR("Too short payload for 3-octet OpCode");
493 			return -EINVAL;
494 		}
495 
496 		*opcode = net_buf_simple_pull_u8(buf) << 16;
497 		*opcode |= net_buf_simple_pull_le16(buf);
498 		return 0;
499 	}
500 
501 	CODE_UNREACHABLE;
502 }
503 
bt_mesh_fixed_group_match(u16_t addr)504 bool bt_mesh_fixed_group_match(u16_t addr)
505 {
506 	/* Check for fixed group addresses */
507 	switch (addr) {
508 	case BT_MESH_ADDR_ALL_NODES:
509 		return true;
510 	case BT_MESH_ADDR_PROXIES:
511 		/* TODO: Proxy not yet supported */
512 		return false;
513 	case BT_MESH_ADDR_FRIENDS:
514 		return (bt_mesh_friend_get() == BT_MESH_FRIEND_ENABLED);
515 	case BT_MESH_ADDR_RELAYS:
516 		return (bt_mesh_relay_get() == BT_MESH_RELAY_ENABLED);
517 	default:
518 		return false;
519 	}
520 }
521 
bt_mesh_model_recv(struct bt_mesh_net_rx * rx,struct os_mbuf * buf)522 void bt_mesh_model_recv(struct bt_mesh_net_rx *rx, struct os_mbuf *buf)
523 {
524 	struct bt_mesh_model *models, *model;
525 	const struct bt_mesh_model_op *op;
526 	u32_t opcode;
527 	u8_t count;
528 	int i;
529 
530 	BT_DBG("app_idx 0x%04x src 0x%04x dst 0x%04x", rx->ctx.app_idx,
531 	       rx->ctx.addr, rx->ctx.recv_dst);
532 	BT_DBG("len %u: %s", buf->om_len, bt_hex(buf->om_data, buf->om_len));
533 
534 	if (get_opcode(buf, &opcode) < 0) {
535 		BT_WARN("Unable to decode OpCode");
536 		return;
537 	}
538 
539 	BT_DBG("OpCode 0x%08x", opcode);
540 
541 	for (i = 0; i < dev_comp->elem_count; i++) {
542 		struct bt_mesh_elem *elem = &dev_comp->elem[i];
543 
544 		if (BT_MESH_ADDR_IS_UNICAST(rx->ctx.recv_dst)) {
545 			if (elem->addr != rx->ctx.recv_dst) {
546 				continue;
547 			}
548 		} else if (BT_MESH_ADDR_IS_GROUP(rx->ctx.recv_dst) ||
549 			   BT_MESH_ADDR_IS_VIRTUAL(rx->ctx.recv_dst)) {
550 			/* find_op() will do proper model/group matching */
551 		} else if (i != 0 ||
552 			   !bt_mesh_fixed_group_match(rx->ctx.recv_dst)) {
553 			continue;
554 		}
555 
556 		/* SIG models cannot contain 3-byte (vendor) OpCodes, and
557 		 * vendor models cannot contain SIG (1- or 2-byte) OpCodes, so
558 		 * we only need to do the lookup in one of the model lists.
559 		 */
560 		if (opcode < 0x10000) {
561 			models = elem->models;
562 			count = elem->model_count;
563 		} else {
564 			models = elem->vnd_models;
565 			count = elem->vnd_model_count;
566 		}
567 
568 		op = find_op(models, count, rx->ctx.recv_dst, rx->ctx.app_idx,
569 			     opcode, &model);
570 		if (op) {
571 			struct net_buf_simple_state state;
572 
573 			if (buf->om_len < op->min_len) {
574 				BT_ERR("Too short message for OpCode 0x%08x",
575 				       opcode);
576 				continue;
577 			}
578 
579 			/* The callback will likely parse the buffer, so
580 			 * store the parsing state in case multiple models
581 			 * receive the message.
582 			 */
583 			net_buf_simple_save(buf, &state);
584 			op->func(model, &rx->ctx, buf);
585 			net_buf_simple_restore(buf, &state);
586 
587 		} else {
588 			BT_DBG("No OpCode 0x%08x for elem %d", opcode, i);
589 		}
590 	}
591 }
592 
bt_mesh_model_msg_init(struct os_mbuf * msg,u32_t opcode)593 void bt_mesh_model_msg_init(struct os_mbuf *msg, u32_t opcode)
594 {
595 	net_buf_simple_init(msg, 0);
596 
597 	if (opcode < 0x100) {
598 		/* 1-byte OpCode */
599 		net_buf_simple_add_u8(msg, opcode);
600 		return;
601 	}
602 
603 	if (opcode < 0x10000) {
604 		/* 2-byte OpCode */
605 		net_buf_simple_add_be16(msg, opcode);
606 		return;
607 	}
608 
609 	/* 3-byte OpCode */
610 	net_buf_simple_add_u8(msg, ((opcode >> 16) & 0xff));
611 	net_buf_simple_add_le16(msg, opcode & 0xffff);
612 }
613 
model_send(struct bt_mesh_model * model,struct bt_mesh_net_tx * tx,bool implicit_bind,struct os_mbuf * msg,const struct bt_mesh_send_cb * cb,void * cb_data)614 static int model_send(struct bt_mesh_model *model,
615 		      struct bt_mesh_net_tx *tx, bool implicit_bind,
616 		      struct os_mbuf *msg,
617 		      const struct bt_mesh_send_cb *cb, void *cb_data)
618 {
619 	BT_DBG("net_idx 0x%04x app_idx 0x%04x dst 0x%04x", tx->ctx->net_idx,
620 	       tx->ctx->app_idx, tx->ctx->addr);
621 	BT_DBG("len %u: %s", msg->om_len, bt_hex(msg->om_data, msg->om_len));
622 
623 	if (!bt_mesh_is_provisioned()) {
624 		BT_ERR("Local node is not yet provisioned");
625 		return -EAGAIN;
626 	}
627 
628 	if (net_buf_simple_tailroom(msg) < 4) {
629 		BT_ERR("Not enough tailroom for TransMIC");
630 		return -EINVAL;
631 	}
632 
633 	if (msg->om_len > BT_MESH_TX_SDU_MAX - 4) {
634 		BT_ERR("Too big message");
635 		return -EMSGSIZE;
636 	}
637 
638 	if (!implicit_bind && !model_has_key(model, tx->ctx->app_idx)) {
639 		BT_ERR("Model not bound to AppKey 0x%04x", tx->ctx->app_idx);
640 		return -EINVAL;
641 	}
642 
643 	return bt_mesh_trans_send(tx, msg, cb, cb_data);
644 }
645 
bt_mesh_model_send(struct bt_mesh_model * model,struct bt_mesh_msg_ctx * ctx,struct os_mbuf * msg,const struct bt_mesh_send_cb * cb,void * cb_data)646 int bt_mesh_model_send(struct bt_mesh_model *model,
647 		       struct bt_mesh_msg_ctx *ctx,
648 		       struct os_mbuf *msg,
649 		       const struct bt_mesh_send_cb *cb, void *cb_data)
650 {
651 	struct bt_mesh_net_tx tx = {
652 		.sub = bt_mesh_subnet_get(ctx->net_idx),
653 		.ctx = ctx,
654 		.src = bt_mesh_model_elem(model)->addr,
655 		.xmit = bt_mesh_net_transmit_get(),
656 		.friend_cred = 0,
657 	};
658 
659 	return model_send(model, &tx, false, msg, cb, cb_data);
660 }
661 
bt_mesh_model_publish(struct bt_mesh_model * model)662 int bt_mesh_model_publish(struct bt_mesh_model *model)
663 {
664 	struct os_mbuf *sdu = NET_BUF_SIMPLE(BT_MESH_TX_SDU_MAX);
665 	struct bt_mesh_model_pub *pub = model->pub;
666 	struct bt_mesh_app_key *key;
667 	struct bt_mesh_msg_ctx ctx = {
668 	};
669 	struct bt_mesh_net_tx tx = {
670 		.ctx = &ctx,
671 		.src = bt_mesh_model_elem(model)->addr,
672 		.xmit = bt_mesh_net_transmit_get(),
673 	};
674 	int err;
675 
676 	BT_DBG("");
677 
678 	if (!pub) {
679 		err = -ENOTSUP;
680 		goto done;
681 	}
682 
683 	if (pub->addr == BT_MESH_ADDR_UNASSIGNED) {
684 		err = -EADDRNOTAVAIL;
685 		goto done;
686 	}
687 
688 	key = bt_mesh_app_key_find(pub->key);
689 	if (!key) {
690 		err = -EADDRNOTAVAIL;
691 		goto done;
692 	}
693 
694 	if (pub->msg->om_len + 4 > BT_MESH_TX_SDU_MAX) {
695 		BT_ERR("Message does not fit maximum SDU size");
696 		err = -EMSGSIZE;
697 		goto done;
698 	}
699 
700 	if (pub->count) {
701 		BT_WARN("Clearing publish retransmit timer");
702 		k_delayed_work_cancel(&pub->timer);
703 	}
704 
705 	net_buf_simple_init(sdu, 0);
706 	net_buf_simple_add_mem(sdu, pub->msg->om_data, pub->msg->om_len);
707 
708 	ctx.addr = pub->addr;
709 	ctx.send_ttl = pub->ttl;
710 	ctx.net_idx = key->net_idx;
711 	ctx.app_idx = key->app_idx;
712 
713 	tx.friend_cred = pub->cred;
714 	tx.sub = bt_mesh_subnet_get(ctx.net_idx),
715 
716 	pub->count = BT_MESH_PUB_TRANSMIT_COUNT(pub->retransmit);
717 
718 	BT_DBG("Publish Retransmit Count %u Interval %ums", pub->count,
719 	       BT_MESH_PUB_TRANSMIT_INT(pub->retransmit));
720 
721 	err = model_send(model, &tx, true, sdu, &pub_sent_cb, model);
722 	if (err) {
723 		pub->count = 0;
724 	}
725 
726 done:
727 	os_mbuf_free_chain(sdu);
728 	return err;
729 }
730 
bt_mesh_model_find_vnd(struct bt_mesh_elem * elem,u16_t company,u16_t id)731 struct bt_mesh_model *bt_mesh_model_find_vnd(struct bt_mesh_elem *elem,
732 					     u16_t company, u16_t id)
733 {
734 	u8_t i;
735 
736 	for (i = 0; i < elem->vnd_model_count; i++) {
737 		if (elem->vnd_models[i].vnd.company == company &&
738 		    elem->vnd_models[i].vnd.id == id) {
739 			return &elem->vnd_models[i];
740 		}
741 	}
742 
743 	return NULL;
744 }
745 
bt_mesh_model_find(struct bt_mesh_elem * elem,u16_t id)746 struct bt_mesh_model *bt_mesh_model_find(struct bt_mesh_elem *elem,
747 					 u16_t id)
748 {
749 	u8_t i;
750 
751 	for (i = 0; i < elem->model_count; i++) {
752 		if (elem->models[i].id == id) {
753 			return &elem->models[i];
754 		}
755 	}
756 
757 	return NULL;
758 }
759 
bt_mesh_comp_get(void)760 const struct bt_mesh_comp *bt_mesh_comp_get(void)
761 {
762 	return dev_comp;
763 }
764