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