• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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