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