1 /* Bluetooth Mesh */
2
3 /*
4 * Copyright (c) 2017 Intel Corporation
5 *
6 * SPDX-License-Identifier: Apache-2.0
7 */
8
9 #include <stdint.h>
10 #include <ble_os.h>
11 #include <misc/byteorder.h>
12
13 #include <net/buf.h>
14 #include <bluetooth/bluetooth.h>
15 #include <api/mesh.h>
16
17 #ifdef CONFIG_BT_MESH_LOW_POWER
18 #define BT_DBG_ENABLED IS_ENABLED(CONFIG_BT_MESH_DEBUG_LOW_POWER)
19 #include "common/log.h"
20
21 #include "crypto.h"
22 #include "adv.h"
23 #include "mesh.h"
24 #include "net.h"
25 #include "ble_transport.h"
26 #include "access.h"
27 #include "beacon.h"
28 #include "foundation.h"
29 #include "lpn.h"
30 #include "bt_errno.h"
31
32 #if defined(CONFIG_BT_MESH_LPN_AUTO)
33 #define LPN_AUTO_TIMEOUT K_SECONDS(CONFIG_BT_MESH_LPN_AUTO_TIMEOUT)
34 #else
35 #define LPN_AUTO_TIMEOUT 0
36 #endif
37
38 #define LPN_RECV_DELAY CONFIG_BT_MESH_LPN_RECV_DELAY
39 #define SCAN_LATENCY MIN(CONFIG_BT_MESH_LPN_SCAN_LATENCY, \
40 LPN_RECV_DELAY)
41
42 #define FRIEND_REQ_RETRY_TIMEOUT K_SECONDS(CONFIG_BT_MESH_LPN_RETRY_TIMEOUT)
43
44 #define FRIEND_REQ_WAIT K_MSEC(100)
45 #define FRIEND_REQ_SCAN K_SECONDS(1)
46 #define FRIEND_REQ_TIMEOUT (FRIEND_REQ_WAIT + FRIEND_REQ_SCAN)
47
48 #define POLL_RETRY_TIMEOUT K_MSEC(100)
49
50 #define REQ_RETRY_DURATION(lpn) (4 * (LPN_RECV_DELAY + (lpn)->adv_duration + \
51 (lpn)->recv_win + POLL_RETRY_TIMEOUT))
52
53 #define POLL_TIMEOUT_INIT (CONFIG_BT_MESH_LPN_INIT_POLL_TIMEOUT * 100)
54 #define POLL_TIMEOUT_MAX(lpn) ((CONFIG_BT_MESH_LPN_POLL_TIMEOUT * 100) - \
55 REQ_RETRY_DURATION(lpn))
56 #ifndef CONFIG_BT_BQB
57 #define REQ_ATTEMPTS(lpn) (POLL_TIMEOUT_MAX(lpn) < K_SECONDS(3) ? 2 : 4)
58 #else
59 #define REQ_ATTEMPTS(lpn) (POLL_TIMEOUT_MAX(lpn) < K_SECONDS(3) ? 2 : 16)
60 #endif
61 #define CLEAR_ATTEMPTS 2
62
63 #define LPN_CRITERIA ((CONFIG_BT_MESH_LPN_MIN_QUEUE_SIZE) | \
64 (CONFIG_BT_MESH_LPN_RSSI_FACTOR << 3) | \
65 (CONFIG_BT_MESH_LPN_RECV_WIN_FACTOR << 5))
66
67 #define POLL_TO(to) { (u8_t)((to) >> 16), (u8_t)((to) >> 8), (u8_t)(to) }
68 #define LPN_POLL_TO POLL_TO(CONFIG_BT_MESH_LPN_POLL_TIMEOUT)
69
70 /* 2 transmissions, 20ms interval */
71 #define POLL_XMIT BT_MESH_TRANSMIT(1, 20)
72
73 static void (*lpn_cb)(u16_t friend_addr, bool established);
74
75 extern void lpn_hb_send();
76
77 #if defined(CONFIG_BT_MESH_DEBUG_LOW_POWER)
state2str(int state)78 static const char *state2str(int state)
79 {
80 switch (state) {
81 case BT_MESH_LPN_DISABLED:
82 return "disabled";
83 case BT_MESH_LPN_CLEAR:
84 return "clear";
85 case BT_MESH_LPN_TIMER:
86 return "timer";
87 case BT_MESH_LPN_ENABLED:
88 return "enabled";
89 case BT_MESH_LPN_REQ_WAIT:
90 return "req wait";
91 case BT_MESH_LPN_WAIT_OFFER:
92 return "wait offer";
93 case BT_MESH_LPN_ESTABLISHED:
94 return "established";
95 case BT_MESH_LPN_RECV_DELAY:
96 return "recv delay";
97 case BT_MESH_LPN_WAIT_UPDATE:
98 return "wait update";
99 default:
100 return "(unknown)";
101 }
102 }
103 #endif /* CONFIG_BT_MESH_DEBUG_LOW_POWER */
104
lpn_set_state(int state)105 static inline void lpn_set_state(int state)
106 {
107 #if defined(CONFIG_BT_MESH_DEBUG_LOW_POWER)
108 BT_DBG("%s -> %s", state2str(bt_mesh.lpn.state), state2str(state));
109 #endif
110 bt_mesh.lpn.state = state;
111 }
112
group_zero(atomic_t * target)113 static inline void group_zero(atomic_t *target)
114 {
115 #if CONFIG_BT_MESH_LPN_GROUPS > 32
116 int i;
117
118 for (i = 0; i < ARRAY_SIZE(bt_mesh.lpn.added); i++) {
119 atomic_set(&target[i], 0);
120 }
121 #else
122 atomic_set(target, 0);
123 #endif
124 }
125
group_set(atomic_t * target,atomic_t * source)126 static inline void group_set(atomic_t *target, atomic_t *source)
127 {
128 #if CONFIG_BT_MESH_LPN_GROUPS > 32
129 int i;
130
131 for (i = 0; i < ARRAY_SIZE(bt_mesh.lpn.added); i++) {
132 atomic_or(&target[i], atomic_get(&source[i]));
133 }
134 #else
135 atomic_or(target, atomic_get(source));
136 #endif
137 }
138
group_clear(atomic_t * target,atomic_t * source)139 static inline void group_clear(atomic_t *target, atomic_t *source)
140 {
141 #if CONFIG_BT_MESH_LPN_GROUPS > 32
142 int i;
143
144 for (i = 0; i < ARRAY_SIZE(bt_mesh.lpn.added); i++) {
145 atomic_and(&target[i], ~atomic_get(&source[i]));
146 }
147 #else
148 atomic_and(target, ~atomic_get(source));
149 #endif
150 }
151
152 static void clear_friendship(bool force, bool disable);
153
friend_clear_sent(int err,void * user_data)154 static void friend_clear_sent(int err, void *user_data)
155 {
156 struct bt_mesh_lpn *lpn = &bt_mesh.lpn;
157
158 /* We're switching away from Low Power behavior, so permanently
159 * enable scanning.
160 */
161 bt_mesh_scan_enable();
162
163 lpn->req_attempts++;
164
165 if (err) {
166 BT_ERR("Sending Friend Request failed (err %d)", err);
167 lpn_set_state(BT_MESH_LPN_ENABLED);
168 clear_friendship(false, lpn->disable);
169 return;
170 }
171
172 lpn_set_state(BT_MESH_LPN_CLEAR);
173 k_delayed_work_submit(&lpn->timer, FRIEND_REQ_TIMEOUT);
174 }
175
176 static const struct bt_mesh_send_cb clear_sent_cb = {
177 .end = friend_clear_sent,
178 };
179
send_friend_clear(void)180 static int send_friend_clear(void)
181 {
182 struct bt_mesh_msg_ctx ctx = {
183 .net_idx = bt_mesh.sub[0].net_idx,
184 .app_idx = BT_MESH_KEY_UNUSED,
185 .addr = bt_mesh.lpn.frnd,
186 .send_ttl = 0,
187 };
188 struct bt_mesh_net_tx tx = {
189 .sub = &bt_mesh.sub[0],
190 .ctx = &ctx,
191 .src = bt_mesh_primary_addr(),
192 .xmit = bt_mesh_net_transmit_get(),
193 };
194 struct bt_mesh_ctl_friend_clear req = {
195 .lpn_addr = sys_cpu_to_be16(tx.src),
196 .lpn_counter = sys_cpu_to_be16(bt_mesh.lpn.counter),
197 };
198
199 BT_DBG("");
200
201 return bt_mesh_ctl_send(&tx, TRANS_CTL_OP_FRIEND_CLEAR, &req,
202 sizeof(req), NULL, &clear_sent_cb, NULL);
203 }
204
clear_friendship(bool force,bool disable)205 static void clear_friendship(bool force, bool disable)
206 {
207 struct bt_mesh_lpn *lpn = &bt_mesh.lpn;
208
209 BT_DBG("force %u disable %u", force, disable);
210
211 if (!force && lpn->established && !lpn->clear_success &&
212 lpn->req_attempts < CLEAR_ATTEMPTS) {
213 send_friend_clear();
214 lpn->disable = disable;
215 return;
216 }
217
218 bt_mesh_rx_reset();
219
220 k_delayed_work_cancel(&lpn->timer);
221
222 friend_cred_del(bt_mesh.sub[0].net_idx, lpn->frnd);
223
224 if (lpn->clear_success) {
225 lpn->old_friend = BT_MESH_ADDR_UNASSIGNED;
226 } else {
227 lpn->old_friend = lpn->frnd;
228 }
229
230 if (lpn_cb && lpn->frnd != BT_MESH_ADDR_UNASSIGNED) {
231 lpn_cb(lpn->frnd, false);
232 }
233
234 lpn->frnd = BT_MESH_ADDR_UNASSIGNED;
235 lpn->fsn = 0;
236 lpn->req_attempts = 0;
237 lpn->recv_win = 0;
238 lpn->queue_size = 0;
239 lpn->disable = 0;
240 lpn->sent_req = 0;
241 lpn->established = 0;
242 lpn->clear_success = 0;
243
244 group_zero(lpn->added);
245 group_zero(lpn->pending);
246 group_zero(lpn->to_remove);
247
248 /* Set this to 1 to force group subscription when the next
249 * Friendship is created, in case lpn->groups doesn't get
250 * modified meanwhile.
251 */
252 lpn->groups_changed = 1;
253
254 if (disable) {
255 lpn_set_state(BT_MESH_LPN_DISABLED);
256 lpn_hb_send();
257 return;
258 }
259
260 lpn_set_state(BT_MESH_LPN_ENABLED);
261 lpn_hb_send();
262 k_delayed_work_submit(&lpn->timer, FRIEND_REQ_RETRY_TIMEOUT);
263 }
264
friend_req_sent(u16_t duration,int err,void * user_data)265 static void friend_req_sent(u16_t duration, int err, void *user_data)
266 {
267 struct bt_mesh_lpn *lpn = &bt_mesh.lpn;
268
269 if (err) {
270 BT_ERR("Sending Friend Request failed (err %d)", err);
271 return;
272 }
273
274 lpn->adv_duration = duration;
275
276 if (IS_ENABLED(CONFIG_BT_MESH_LPN_ESTABLISHMENT)) {
277 k_delayed_work_submit(&lpn->timer, FRIEND_REQ_WAIT);
278 lpn_set_state(BT_MESH_LPN_REQ_WAIT);
279 } else {
280 k_delayed_work_submit(&lpn->timer,
281 duration + FRIEND_REQ_TIMEOUT);
282 lpn_set_state(BT_MESH_LPN_WAIT_OFFER);
283 }
284 }
285
286 static const struct bt_mesh_send_cb friend_req_sent_cb = {
287 .start = friend_req_sent,
288 };
289
send_friend_req(struct bt_mesh_lpn * lpn)290 static int send_friend_req(struct bt_mesh_lpn *lpn)
291 {
292 const struct bt_mesh_comp *comp = bt_mesh_comp_get();
293 struct bt_mesh_msg_ctx ctx = {
294 .net_idx = bt_mesh.sub[0].net_idx,
295 .app_idx = BT_MESH_KEY_UNUSED,
296 .addr = BT_MESH_ADDR_FRIENDS,
297 .send_ttl = 0,
298 };
299 struct bt_mesh_net_tx tx = {
300 .sub = &bt_mesh.sub[0],
301 .ctx = &ctx,
302 .src = bt_mesh_primary_addr(),
303 .xmit = POLL_XMIT,
304 };
305 struct bt_mesh_ctl_friend_req req = {
306 .criteria = LPN_CRITERIA,
307 .recv_delay = LPN_RECV_DELAY,
308 .poll_to = LPN_POLL_TO,
309 .prev_addr = sys_cpu_to_be16(lpn->old_friend),
310 .num_elem = comp->elem_count,
311 .lpn_counter = sys_cpu_to_be16(lpn->counter),
312 };
313
314 BT_DBG("");
315
316 return bt_mesh_ctl_send(&tx, TRANS_CTL_OP_FRIEND_REQ, &req,
317 sizeof(req), NULL, &friend_req_sent_cb, NULL);
318 }
319
req_sent(u16_t duration,int err,void * user_data)320 static void req_sent(u16_t duration, int err, void *user_data)
321 {
322 struct bt_mesh_lpn *lpn = &bt_mesh.lpn;
323
324 #if defined(CONFIG_BT_MESH_DEBUG_LOW_POWER)
325 BT_DBG("req 0x%02x duration %u err %d state %s",
326 lpn->sent_req, duration, err, state2str(lpn->state));
327 #endif
328
329 if (err) {
330 BT_ERR("Sending request failed (err %d)", err);
331 lpn->sent_req = 0;
332 group_zero(lpn->pending);
333 return;
334 }
335
336 lpn->req_attempts++;
337 lpn->adv_duration = duration;
338
339 if (lpn->established || IS_ENABLED(CONFIG_BT_MESH_LPN_ESTABLISHMENT)) {
340 lpn_set_state(BT_MESH_LPN_RECV_DELAY);
341 /* We start scanning a bit early to elimitate risk of missing
342 * response data due to HCI and other latencies.
343 */
344 k_delayed_work_submit(&lpn->timer,
345 LPN_RECV_DELAY - SCAN_LATENCY);
346 } else {
347 k_delayed_work_submit(&lpn->timer,
348 LPN_RECV_DELAY + duration +
349 lpn->recv_win);
350 }
351 }
352
353 static const struct bt_mesh_send_cb req_sent_cb = {
354 .start = req_sent,
355 };
356
send_friend_poll(void)357 static int send_friend_poll(void)
358 {
359 struct bt_mesh_msg_ctx ctx = {
360 .net_idx = bt_mesh.sub[0].net_idx,
361 .app_idx = BT_MESH_KEY_UNUSED,
362 .addr = bt_mesh.lpn.frnd,
363 .send_ttl = 0,
364 };
365 struct bt_mesh_net_tx tx = {
366 .sub = &bt_mesh.sub[0],
367 .ctx = &ctx,
368 .src = bt_mesh_primary_addr(),
369 .xmit = POLL_XMIT,
370 .friend_cred = true,
371 };
372 struct bt_mesh_lpn *lpn = &bt_mesh.lpn;
373 u8_t fsn = lpn->fsn;
374 int err;
375
376 BT_DBG("lpn->sent_req 0x%02x", lpn->sent_req);
377
378 if (lpn->sent_req) {
379 if (lpn->sent_req != TRANS_CTL_OP_FRIEND_POLL) {
380 lpn->pending_poll = 1;
381 }
382
383 return 0;
384 }
385
386 err = bt_mesh_ctl_send(&tx, TRANS_CTL_OP_FRIEND_POLL, &fsn, 1,
387 NULL, &req_sent_cb, NULL);
388 if (err == 0) {
389 lpn->pending_poll = 0;
390 lpn->sent_req = TRANS_CTL_OP_FRIEND_POLL;
391 }
392
393 return err;
394 }
395
bt_mesh_lpn_disable(bool force)396 void bt_mesh_lpn_disable(bool force)
397 {
398 if (bt_mesh.lpn.state == BT_MESH_LPN_DISABLED) {
399 return;
400 }
401
402 clear_friendship(force, true);
403 }
404
bt_mesh_lpn_set(bool enable)405 int bt_mesh_lpn_set(bool enable)
406 {
407 struct bt_mesh_lpn *lpn = &bt_mesh.lpn;
408
409 if (enable) {
410 if (lpn->state != BT_MESH_LPN_DISABLED) {
411 return 0;
412 }
413 } else {
414 if (lpn->state == BT_MESH_LPN_DISABLED) {
415 return 0;
416 }
417 }
418
419 if (!bt_mesh_is_provisioned()) {
420 if (enable) {
421 lpn_set_state(BT_MESH_LPN_ENABLED);
422 } else {
423 lpn_set_state(BT_MESH_LPN_DISABLED);
424 }
425
426 return 0;
427 }
428
429 if (enable) {
430 lpn_set_state(BT_MESH_LPN_ENABLED);
431
432 if (IS_ENABLED(CONFIG_BT_MESH_LPN_ESTABLISHMENT)) {
433 bt_mesh_scan_disable();
434 }
435
436 send_friend_req(lpn);
437 } else {
438 if (IS_ENABLED(CONFIG_BT_MESH_LPN_AUTO) &&
439 lpn->state == BT_MESH_LPN_TIMER) {
440 k_delayed_work_cancel(&lpn->timer);
441 lpn_set_state(BT_MESH_LPN_DISABLED);
442 } else {
443 bt_mesh_lpn_disable(false);
444 }
445 }
446
447 return 0;
448 }
449
friend_response_received(struct bt_mesh_lpn * lpn)450 static void friend_response_received(struct bt_mesh_lpn *lpn)
451 {
452 BT_DBG("lpn->sent_req 0x%02x", lpn->sent_req);
453
454 if (lpn->sent_req == TRANS_CTL_OP_FRIEND_POLL) {
455 lpn->fsn++;
456 }
457
458 k_delayed_work_cancel(&lpn->timer);
459 bt_mesh_scan_disable();
460 lpn_set_state(BT_MESH_LPN_ESTABLISHED);
461 lpn->req_attempts = 0;
462 lpn->sent_req = 0;
463 }
464
bt_mesh_lpn_msg_received(struct bt_mesh_net_rx * rx)465 void bt_mesh_lpn_msg_received(struct bt_mesh_net_rx *rx)
466 {
467 struct bt_mesh_lpn *lpn = &bt_mesh.lpn;
468
469 if (lpn->state == BT_MESH_LPN_TIMER) {
470 BT_DBG("Restarting establishment timer");
471 k_delayed_work_submit(&lpn->timer, LPN_AUTO_TIMEOUT);
472 return;
473 }
474
475 if (lpn->sent_req != TRANS_CTL_OP_FRIEND_POLL) {
476 BT_WARN("Unexpected message withouth a preceding Poll");
477 return;
478 }
479
480 friend_response_received(lpn);
481
482 BT_DBG("Requesting more messages from Friend");
483
484 send_friend_poll();
485 }
486
bt_mesh_lpn_friend_offer(struct bt_mesh_net_rx * rx,struct net_buf_simple * buf)487 int bt_mesh_lpn_friend_offer(struct bt_mesh_net_rx *rx,
488 struct net_buf_simple *buf)
489 {
490 struct bt_mesh_ctl_friend_offer *msg = (void *)buf->data;
491 struct bt_mesh_lpn *lpn = &bt_mesh.lpn;
492 struct bt_mesh_subnet *sub = rx->sub;
493 struct friend_cred *cred;
494 u16_t frnd_counter;
495 int err;
496
497 if (buf->len < sizeof(*msg)) {
498 BT_WARN("Too short Friend Offer");
499 return -EINVAL;
500 }
501
502 if (lpn->state != BT_MESH_LPN_WAIT_OFFER) {
503 BT_WARN("Ignoring unexpected Friend Offer");
504 return 0;
505 }
506
507 if (!msg->recv_win) {
508 BT_WARN("Prohibited ReceiveWindow value");
509 return -EINVAL;
510 }
511
512 frnd_counter = sys_be16_to_cpu(msg->frnd_counter);
513
514 BT_DBG("recv_win %u queue_size %u sub_list_size %u rssi %d counter %u",
515 msg->recv_win, msg->queue_size, msg->sub_list_size, msg->rssi,
516 frnd_counter);
517
518 lpn->frnd = rx->ctx.addr;
519
520 cred = friend_cred_create(sub, lpn->frnd, lpn->counter, frnd_counter);
521 if (!cred) {
522 lpn->frnd = BT_MESH_ADDR_UNASSIGNED;
523 return -ENOMEM;
524 }
525
526 /* TODO: Add offer acceptance criteria check */
527
528 k_delayed_work_cancel(&lpn->timer);
529
530 lpn->recv_win = msg->recv_win;
531 lpn->queue_size = msg->queue_size;
532
533 err = send_friend_poll();
534 if (err) {
535 friend_cred_clear(cred);
536 lpn->frnd = BT_MESH_ADDR_UNASSIGNED;
537 lpn->recv_win = 0;
538 lpn->queue_size = 0;
539 return err;
540 }
541
542 lpn->counter++;
543
544 return 0;
545 }
546
bt_mesh_lpn_friend_clear_cfm(struct bt_mesh_net_rx * rx,struct net_buf_simple * buf)547 int bt_mesh_lpn_friend_clear_cfm(struct bt_mesh_net_rx *rx,
548 struct net_buf_simple *buf)
549 {
550 struct bt_mesh_ctl_friend_clear_confirm *msg = (void *)buf->data;
551 struct bt_mesh_lpn *lpn = &bt_mesh.lpn;
552 u16_t addr, counter;
553
554 if (buf->len < sizeof(*msg)) {
555 BT_WARN("Too short Friend Clear Confirm");
556 return -EINVAL;
557 }
558
559 if (lpn->state != BT_MESH_LPN_CLEAR) {
560 BT_WARN("Ignoring unexpected Friend Clear Confirm");
561 return 0;
562 }
563
564 addr = sys_be16_to_cpu(msg->lpn_addr);
565 counter = sys_be16_to_cpu(msg->lpn_counter);
566
567 BT_DBG("LPNAddress 0x%04x LPNCounter 0x%04x", addr, counter);
568
569 if (addr != bt_mesh_primary_addr() || counter != lpn->counter) {
570 BT_WARN("Invalid parameters in Friend Clear Confirm");
571 return 0;
572 }
573
574 lpn->clear_success = 1;
575 clear_friendship(false, lpn->disable);
576
577 return 0;
578 }
579
lpn_group_add(u16_t group)580 static void lpn_group_add(u16_t group)
581 {
582 struct bt_mesh_lpn *lpn = &bt_mesh.lpn;
583 u16_t *free_slot = NULL;
584 int i;
585
586 for (i = 0; i < ARRAY_SIZE(lpn->groups); i++) {
587 if (lpn->groups[i] == group) {
588 atomic_clear_bit(lpn->to_remove, i);
589 return;
590 }
591
592 if (!free_slot && lpn->groups[i] == BT_MESH_ADDR_UNASSIGNED) {
593 free_slot = &lpn->groups[i];
594 }
595 }
596
597 if (!free_slot) {
598 BT_WARN("Friend Subscription List exceeded!");
599 return;
600 }
601
602 *free_slot = group;
603 lpn->groups_changed = 1;
604 }
605
lpn_group_del(u16_t group)606 static void lpn_group_del(u16_t group)
607 {
608 struct bt_mesh_lpn *lpn = &bt_mesh.lpn;
609 int i;
610
611 for (i = 0; i < ARRAY_SIZE(lpn->groups); i++) {
612 if (lpn->groups[i] == group) {
613 if (atomic_test_bit(lpn->added, i) ||
614 atomic_test_bit(lpn->pending, i)) {
615 atomic_set_bit(lpn->to_remove, i);
616 lpn->groups_changed = 1;
617 } else {
618 lpn->groups[i] = BT_MESH_ADDR_UNASSIGNED;
619 }
620 }
621 }
622 }
623
group_popcount(atomic_t * target)624 static inline int group_popcount(atomic_t *target)
625 {
626 #if CONFIG_BT_MESH_LPN_GROUPS > 32
627 int i, count = 0;
628
629 for (i = 0; i < ARRAY_SIZE(bt_mesh.lpn.added); i++) {
630 count += popcount(atomic_get(&target[i]));
631 }
632 #else
633 return popcount(atomic_get(target));
634 #endif
635 }
636
sub_update(u8_t op)637 static bool sub_update(u8_t op)
638 {
639 struct bt_mesh_lpn *lpn = &bt_mesh.lpn;
640 int added_count = group_popcount(lpn->added);
641 struct bt_mesh_msg_ctx ctx = {
642 .net_idx = bt_mesh.sub[0].net_idx,
643 .app_idx = BT_MESH_KEY_UNUSED,
644 .addr = lpn->frnd,
645 .send_ttl = 0,
646 };
647 struct bt_mesh_net_tx tx = {
648 .sub = &bt_mesh.sub[0],
649 .ctx = &ctx,
650 .src = bt_mesh_primary_addr(),
651 .xmit = POLL_XMIT,
652 .friend_cred = true,
653 };
654 struct bt_mesh_ctl_friend_sub req;
655 size_t i, g;
656
657 BT_DBG("op 0x%02x sent_req 0x%02x", op, lpn->sent_req);
658
659 if (lpn->sent_req) {
660 return false;
661 }
662
663 for (i = 0, g = 0; i < ARRAY_SIZE(lpn->groups); i++) {
664 if (lpn->groups[i] == BT_MESH_ADDR_UNASSIGNED) {
665 continue;
666 }
667
668 if (op == TRANS_CTL_OP_FRIEND_SUB_ADD) {
669 if (atomic_test_bit(lpn->added, i)) {
670 continue;
671 }
672 } else {
673 if (!atomic_test_bit(lpn->to_remove, i)) {
674 continue;
675 }
676 }
677
678 if (added_count + g >= lpn->queue_size) {
679 BT_WARN("Friend Queue Size exceeded");
680 break;
681 }
682
683 req.addr_list[g++] = sys_cpu_to_be16(lpn->groups[i]);
684 atomic_set_bit(lpn->pending, i);
685
686 if (g == ARRAY_SIZE(req.addr_list)) {
687 break;
688 }
689 }
690
691 if (g == 0) {
692 group_zero(lpn->pending);
693 return false;
694 }
695
696 req.xact = lpn->xact_next++;
697
698 if (bt_mesh_ctl_send(&tx, op, &req, 1 + g * 2, NULL,
699 &req_sent_cb, NULL) < 0) {
700 group_zero(lpn->pending);
701 return false;
702 }
703
704 lpn->xact_pending = req.xact;
705 lpn->sent_req = op;
706 return true;
707 }
708
update_timeout(struct bt_mesh_lpn * lpn)709 static void update_timeout(struct bt_mesh_lpn *lpn)
710 {
711 if (lpn->established) {
712 BT_WARN("No response from Friend during ReceiveWindow");
713 bt_mesh_scan_disable();
714 lpn_set_state(BT_MESH_LPN_ESTABLISHED);
715 k_delayed_work_submit(&lpn->timer, POLL_RETRY_TIMEOUT);
716 } else {
717 if (IS_ENABLED(CONFIG_BT_MESH_LPN_ESTABLISHMENT)) {
718 bt_mesh_scan_disable();
719 }
720
721 if (lpn->req_attempts < 6) {
722 BT_WARN("Retrying first Friend Poll");
723 lpn->sent_req = 0;
724 if (send_friend_poll() == 0) {
725 return;
726 }
727 }
728
729 BT_ERR("Timed out waiting for first Friend Update");
730 clear_friendship(false, false);
731 }
732 }
733
lpn_timeout(struct k_work * work)734 static void lpn_timeout(struct k_work *work)
735 {
736 struct bt_mesh_lpn *lpn = &bt_mesh.lpn;
737
738 #if defined(CONFIG_BT_MESH_DEBUG_LOW_POWER)
739 BT_DBG("state: %s", state2str(lpn->state));
740 #endif
741
742 switch (lpn->state) {
743 case BT_MESH_LPN_DISABLED:
744 break;
745 case BT_MESH_LPN_CLEAR:
746 clear_friendship(false, bt_mesh.lpn.disable);
747 break;
748 case BT_MESH_LPN_TIMER:
749 BT_DBG("Starting to look for Friend nodes");
750 lpn_set_state(BT_MESH_LPN_ENABLED);
751 if (IS_ENABLED(CONFIG_BT_MESH_LPN_ESTABLISHMENT)) {
752 bt_mesh_scan_disable();
753 }
754 /* fall through */
755 case BT_MESH_LPN_ENABLED:
756 send_friend_req(lpn);
757 break;
758 case BT_MESH_LPN_REQ_WAIT:
759 bt_mesh_scan_enable();
760 k_delayed_work_submit(&lpn->timer,
761 lpn->adv_duration + FRIEND_REQ_SCAN);
762 lpn_set_state(BT_MESH_LPN_WAIT_OFFER);
763 break;
764 case BT_MESH_LPN_WAIT_OFFER:
765 BT_WARN("No acceptable Friend Offers received");
766 if (IS_ENABLED(CONFIG_BT_MESH_LPN_ESTABLISHMENT)) {
767 bt_mesh_scan_disable();
768 }
769 lpn->counter++;
770 lpn_set_state(BT_MESH_LPN_ENABLED);
771 k_delayed_work_submit(&lpn->timer, FRIEND_REQ_RETRY_TIMEOUT);
772 break;
773 case BT_MESH_LPN_ESTABLISHED:
774 if (lpn->req_attempts < REQ_ATTEMPTS(lpn)) {
775 u8_t req = lpn->sent_req;
776
777 lpn->sent_req = 0;
778
779 if (!req || req == TRANS_CTL_OP_FRIEND_POLL) {
780 send_friend_poll();
781 } else {
782 sub_update(req);
783 }
784
785 break;
786 }
787
788 BT_ERR("No response from Friend after %u retries",
789 lpn->req_attempts);
790 lpn->req_attempts = 0;
791 clear_friendship(false, false);
792 break;
793 case BT_MESH_LPN_RECV_DELAY:
794 k_delayed_work_submit(&lpn->timer,
795 lpn->adv_duration + SCAN_LATENCY +
796 lpn->recv_win);
797 bt_mesh_scan_enable();
798 lpn_set_state(BT_MESH_LPN_WAIT_UPDATE);
799 break;
800 case BT_MESH_LPN_WAIT_UPDATE:
801 update_timeout(lpn);
802 break;
803 default:
804 __ASSERT(0, "Unhandled LPN state");
805 break;
806 }
807 }
808
bt_mesh_lpn_group_add(u16_t group)809 void bt_mesh_lpn_group_add(u16_t group)
810 {
811 BT_DBG("group 0x%04x", group);
812
813 lpn_group_add(group);
814
815 if (!bt_mesh_lpn_established() || bt_mesh.lpn.sent_req) {
816 return;
817 }
818
819 sub_update(TRANS_CTL_OP_FRIEND_SUB_ADD);
820 }
821
bt_mesh_lpn_group_del(u16_t * groups,size_t group_count)822 void bt_mesh_lpn_group_del(u16_t *groups, size_t group_count)
823 {
824 int i;
825
826 for (i = 0; i < group_count; i++) {
827 if (groups[i] != BT_MESH_ADDR_UNASSIGNED) {
828 BT_DBG("group 0x%04x", groups[i]);
829 lpn_group_del(groups[i]);
830 }
831 }
832
833 if (!bt_mesh_lpn_established() || bt_mesh.lpn.sent_req) {
834 return;
835 }
836
837 sub_update(TRANS_CTL_OP_FRIEND_SUB_REM);
838 }
839
poll_timeout(struct bt_mesh_lpn * lpn)840 static bt_s32_t poll_timeout(struct bt_mesh_lpn *lpn)
841 {
842 /* If we're waiting for segment acks keep polling at high freq */
843 if (bt_mesh_tx_in_progress()) {
844 return MIN(POLL_TIMEOUT_MAX(lpn), K_SECONDS(1));
845 }
846
847 if (lpn->poll_timeout < POLL_TIMEOUT_MAX(lpn)) {
848 lpn->poll_timeout *= 2;
849 lpn->poll_timeout = MIN(lpn->poll_timeout,
850 POLL_TIMEOUT_MAX(lpn));
851 }
852
853 BT_DBG("Poll Timeout is %ums", lpn->poll_timeout);
854
855 return lpn->poll_timeout;
856 }
857
bt_mesh_lpn_friend_sub_cfm(struct bt_mesh_net_rx * rx,struct net_buf_simple * buf)858 int bt_mesh_lpn_friend_sub_cfm(struct bt_mesh_net_rx *rx,
859 struct net_buf_simple *buf)
860 {
861 struct bt_mesh_ctl_friend_sub_confirm *msg = (void *)buf->data;
862 struct bt_mesh_lpn *lpn = &bt_mesh.lpn;
863
864 if (buf->len < sizeof(*msg)) {
865 BT_WARN("Too short Friend Subscription Confirm");
866 return -EINVAL;
867 }
868
869 BT_DBG("xact 0x%02x", msg->xact);
870
871 if (!lpn->sent_req) {
872 BT_WARN("No pending subscription list message");
873 return 0;
874 }
875
876 if (msg->xact != lpn->xact_pending) {
877 BT_WARN("Transaction mismatch (0x%02x != 0x%02x)",
878 msg->xact, lpn->xact_pending);
879 return 0;
880 }
881
882 if (lpn->sent_req == TRANS_CTL_OP_FRIEND_SUB_ADD) {
883 group_set(lpn->added, lpn->pending);
884 group_zero(lpn->pending);
885 } else if (lpn->sent_req == TRANS_CTL_OP_FRIEND_SUB_REM) {
886 int i;
887
888 group_clear(lpn->added, lpn->pending);
889
890 for (i = 0; i < ARRAY_SIZE(lpn->groups); i++) {
891 if (atomic_test_and_clear_bit(lpn->pending, i) &&
892 atomic_test_and_clear_bit(lpn->to_remove, i)) {
893 lpn->groups[i] = BT_MESH_ADDR_UNASSIGNED;
894 }
895 }
896 } else {
897 BT_WARN("Unexpected Friend Subscription Confirm");
898 return 0;
899 }
900
901 friend_response_received(lpn);
902
903 if (lpn->groups_changed) {
904 sub_update(TRANS_CTL_OP_FRIEND_SUB_ADD);
905 sub_update(TRANS_CTL_OP_FRIEND_SUB_REM);
906
907 if (!lpn->sent_req) {
908 lpn->groups_changed = 0;
909 }
910 }
911
912 if (lpn->pending_poll) {
913 send_friend_poll();
914 }
915
916 if (!lpn->sent_req) {
917 k_delayed_work_submit(&lpn->timer, poll_timeout(lpn));
918 }
919
920 return 0;
921 }
922
bt_mesh_lpn_friend_update(struct bt_mesh_net_rx * rx,struct net_buf_simple * buf)923 int bt_mesh_lpn_friend_update(struct bt_mesh_net_rx *rx,
924 struct net_buf_simple *buf)
925 {
926 struct bt_mesh_ctl_friend_update *msg = (void *)buf->data;
927 struct bt_mesh_lpn *lpn = &bt_mesh.lpn;
928 struct bt_mesh_subnet *sub = rx->sub;
929 bt_u32_t iv_index;
930
931 if (buf->len < sizeof(*msg)) {
932 BT_WARN("Too short Friend Update");
933 return -EINVAL;
934 }
935
936 if (lpn->sent_req != TRANS_CTL_OP_FRIEND_POLL) {
937 BT_WARN("Unexpected friend update");
938 return 0;
939 }
940
941 if (sub->kr_phase == BT_MESH_KR_PHASE_2 && !rx->new_key) {
942 BT_WARN("Ignoring Phase 2 KR Update secured using old key");
943 return 0;
944 }
945
946 if (atomic_test_bit(bt_mesh.flags, BT_MESH_IVU_INITIATOR) &&
947 (atomic_test_bit(bt_mesh.flags, BT_MESH_IVU_IN_PROGRESS) ==
948 BT_MESH_IV_UPDATE(msg->flags))) {
949 bt_mesh_beacon_ivu_initiator(false);
950 }
951
952 if (!lpn->established) {
953 /* This is normally checked on the transport layer, however
954 * in this state we're also still accepting master
955 * credentials so we need to ensure the right ones (Friend
956 * Credentials) were used for this message.
957 */
958 if (!rx->friend_cred) {
959 BT_WARN("Friend Update with wrong credentials");
960 return -EINVAL;
961 }
962
963 lpn->established = 1;
964
965 BT_INFO("Friendship established with 0x%04x", lpn->frnd);
966
967 if (lpn_cb) {
968 lpn_cb(lpn->frnd, true);
969 }
970
971 lpn_hb_send();
972
973 /* Set initial poll timeout */
974 lpn->poll_timeout = MIN(POLL_TIMEOUT_MAX(lpn),
975 POLL_TIMEOUT_INIT);
976 }
977
978 friend_response_received(lpn);
979
980 iv_index = sys_be32_to_cpu(msg->iv_index);
981
982 BT_DBG("flags 0x%02x iv_index 0x%08x md %u", msg->flags, iv_index,
983 msg->md);
984
985 if (bt_mesh_kr_update(sub, BT_MESH_KEY_REFRESH(msg->flags),
986 rx->new_key)) {
987 bt_mesh_net_beacon_update(sub);
988 }
989
990 bt_mesh_net_iv_update(iv_index, BT_MESH_IV_UPDATE(msg->flags));
991
992 if (lpn->groups_changed) {
993 sub_update(TRANS_CTL_OP_FRIEND_SUB_ADD);
994 sub_update(TRANS_CTL_OP_FRIEND_SUB_REM);
995
996 if (!lpn->sent_req) {
997 lpn->groups_changed = 0;
998 }
999 }
1000
1001 if (msg->md) {
1002 BT_DBG("Requesting for more messages");
1003 send_friend_poll();
1004 }
1005
1006 if (!lpn->sent_req) {
1007 k_delayed_work_submit(&lpn->timer, poll_timeout(lpn));
1008 }
1009
1010 return 0;
1011 }
1012
bt_mesh_lpn_poll(void)1013 int bt_mesh_lpn_poll(void)
1014 {
1015 if (!bt_mesh.lpn.established) {
1016 return -EAGAIN;
1017 }
1018
1019 BT_DBG("Requesting more messages");
1020
1021 return send_friend_poll();
1022 }
1023
bt_mesh_lpn_set_cb(void (* cb)(u16_t friend_addr,bool established))1024 void bt_mesh_lpn_set_cb(void (*cb)(u16_t friend_addr, bool established))
1025 {
1026 lpn_cb = cb;
1027 }
1028
bt_mesh_lpn_init(void)1029 int bt_mesh_lpn_init(void)
1030 {
1031 struct bt_mesh_lpn *lpn = &bt_mesh.lpn;
1032
1033 BT_DBG("");
1034
1035 k_delayed_work_init(&lpn->timer, lpn_timeout);
1036
1037 if (lpn->state == BT_MESH_LPN_ENABLED) {
1038 if (IS_ENABLED(CONFIG_BT_MESH_LPN_ESTABLISHMENT)) {
1039 bt_mesh_scan_disable();
1040 } else {
1041 bt_mesh_scan_enable();
1042 }
1043
1044 send_friend_req(lpn);
1045 } else {
1046 bt_mesh_scan_enable();
1047
1048 if (IS_ENABLED(CONFIG_BT_MESH_LPN_AUTO)) {
1049 BT_DBG("Waiting %u ms for messages", LPN_AUTO_TIMEOUT);
1050 lpn_set_state(BT_MESH_LPN_TIMER);
1051 k_delayed_work_submit(&lpn->timer, LPN_AUTO_TIMEOUT);
1052 }
1053 }
1054
1055 return 0;
1056 }
1057 #endif
1058