1 /* Bluetooth Mesh */
2
3 /*
4 * Copyright (c) 2018 Nordic Semiconductor ASA
5 * Copyright (c) 2017 Intel Corporation
6 *
7 * SPDX-License-Identifier: Apache-2.0
8 */
9
10 #include <ble_os.h>
11 #include <bt_errno.h>
12 #include <misc/stack.h>
13 #include <misc/util.h>
14
15 #include <net/buf.h>
16 #include <bluetooth/bluetooth.h>
17 #include <bluetooth/hci.h>
18 #include <bluetooth/conn.h>
19 #include <api/mesh.h>
20
21 #define BT_DBG_ENABLED IS_ENABLED(CONFIG_BT_MESH_DEBUG_ADV)
22 #include "common/log.h"
23
24 // #include "host/hci_core.h"
25
26 #include "adv.h"
27 #include "net.h"
28 #include "foundation.h"
29 #include "beacon.h"
30 #include "prov.h"
31 #include "proxy.h"
32
33 #ifdef CONFIG_BT_MESH_PROVISIONER
34 #include "provisioner_main.h"
35 #include "provisioner_prov.h"
36 #include "provisioner_beacon.h"
37 #endif
38
39 #ifdef GENIE_ULTRA_PROV
40 #include "genie_storage.h"
41 #include "genie_provision.h"
42 #endif
43
44 /* Convert from ms to 0.625ms units */
45 #define ADV_SCAN_UNIT(_ms) ((_ms) * 8 / 5)
46
47 /* Window and Interval are equal for continuous scanning */
48 #ifndef CONFIG_MESH_SCAN_INTERVAL_MS
49 #define CONFIG_MESH_SCAN_INTERVAL_MS 30
50 #endif
51 #ifndef CONFIG_MESH_SCAN_WINDOW_MS
52 #define CONFIG_MESH_SCAN_WINDOW_MS 30
53 #endif
54
55 #define MESH_SCAN_INTERVAL ADV_SCAN_UNIT(CONFIG_MESH_SCAN_INTERVAL_MS)
56 #define MESH_SCAN_WINDOW ADV_SCAN_UNIT(CONFIG_MESH_SCAN_WINDOW_MS)
57
58 #ifndef CONFIG_ADV_SCAN_INTERVAL_TIMER
59 #define CONFIG_ADV_SCAN_INTERVAL_TIMER (1)
60 #endif
61
62 #ifndef CONFIG_ADV_INTERVAL_TIMER
63 #define CONFIG_ADV_INTERVAL_TIMER (20)
64 #endif
65
66 /* Pre-5.0 controllers enforce a minimum interval of 100ms
67 * whereas 5.0+ controllers can go down to 20ms.
68 */
69 #define ADV_INT_DEFAULT_MS 100
70 #define ADV_INT_FAST_MS 20
71
72 #ifdef CONFIG_GENIE_MESH_ENABLE
73 #ifndef GENIE_DEFAULT_DURATION
74 #define GENIE_DEFAULT_DURATION 120
75 #endif
76 #endif
77
78 #ifndef CONFIG_BT_ADV_STACK_SIZE
79
80 #if defined(CONFIG_BT_HOST_CRYPTO)
81 #define ADV_STACK_SIZE 2048
82 #else
83 #define ADV_STACK_SIZE 1024
84 #endif
85 #else
86 #define ADV_STACK_SIZE CONFIG_BT_ADV_STACK_SIZE
87 #endif
88
89 // static K_FIFO_DEFINE(adv_queue);
90 static struct kfifo adv_queue;
91
92 static struct k_thread adv_thread_data;
93 static BT_STACK_NOINIT(adv_thread_stack, ADV_STACK_SIZE);
94
95 int bt_mesh_adv_scan_schd_init();
96
97 static const u8_t adv_type[] = {
98 [BT_MESH_ADV_PROV] = BT_DATA_MESH_PROV,
99 [BT_MESH_ADV_DATA] = BT_DATA_MESH_MESSAGE,
100 [BT_MESH_ADV_BEACON] = BT_DATA_MESH_BEACON,
101 [BT_MESH_ADV_URI] = BT_DATA_URI,
102 };
103
104 NET_BUF_POOL_DEFINE(adv_buf_pool, CONFIG_BT_MESH_ADV_BUF_COUNT, BT_MESH_ADV_DATA_SIZE, BT_MESH_ADV_USER_DATA_SIZE,
105 NULL);
106
107 static struct bt_mesh_adv adv_pool[CONFIG_BT_MESH_ADV_BUF_COUNT];
108
109 #ifdef CONFIG_BT_MESH_PROVISIONER
110 static const bt_addr_le_t *dev_addr;
111 #endif
112
113 static vendor_beacon_cb g_vendor_beacon_cb = NULL;
114
115 int bt_mesh_adv_scan_init(void);
116
adv_alloc(int id)117 static struct bt_mesh_adv *adv_alloc(int id)
118 {
119 return &adv_pool[id];
120 }
121
adv_send_start(u16_t duration,int err,const struct bt_mesh_send_cb * cb,void * cb_data)122 static inline void adv_send_start(u16_t duration, int err, const struct bt_mesh_send_cb *cb, void *cb_data)
123 {
124 if (cb && cb->start) {
125 cb->start(duration, err, cb_data);
126 }
127 }
128
adv_send_end(int err,const struct bt_mesh_send_cb * cb,void * cb_data)129 static inline void adv_send_end(int err, const struct bt_mesh_send_cb *cb, void *cb_data)
130 {
131 if (cb && cb->end) {
132 cb->end(err, cb_data);
133 }
134 }
135
adv_send(struct net_buf * buf)136 static inline void adv_send(struct net_buf *buf)
137 {
138 extern int bt_le_hci_version_get();
139 const bt_s32_t adv_int_min =
140 ((bt_le_hci_version_get() >= BT_HCI_VERSION_5_0) ? ADV_INT_FAST_MS : ADV_INT_DEFAULT_MS);
141 const struct bt_mesh_send_cb *cb = BT_MESH_ADV(buf)->cb;
142 void *cb_data = BT_MESH_ADV(buf)->cb_data;
143 struct bt_le_adv_param param = { 0 };
144 u16_t duration, adv_int;
145 struct bt_data ad;
146 int err;
147
148 adv_int = MAX(adv_int_min, BT_MESH_TRANSMIT_INT(BT_MESH_ADV(buf)->xmit));
149 #ifdef CONFIG_GENIE_MESH_ENABLE
150 duration = GENIE_DEFAULT_DURATION;
151 #else
152 if (BT_MESH_TRANSMIT_COUNT(BT_MESH_ADV(buf)->xmit) == 0) {
153 duration = adv_int;
154 } else {
155 duration = (((BT_MESH_TRANSMIT_COUNT(BT_MESH_ADV(buf)->xmit) + 1) * (adv_int)) + 10);
156 }
157
158 #endif
159 BT_DBG("type %u len %u: %s", BT_MESH_ADV(buf)->type, buf->len, bt_hex(buf->data, buf->len));
160 BT_DBG("count %u interval %ums duration %ums", BT_MESH_TRANSMIT_COUNT(BT_MESH_ADV(buf)->xmit) + 1, adv_int,
161 duration);
162
163 #ifdef GENIE_ULTRA_PROV
164 if (BT_MESH_ADV(buf)->tiny_adv == 1) {
165 ad.type = GENIE_PROV_ADV_TYPE;
166 } else {
167 ad.type = adv_type[BT_MESH_ADV(buf)->type];
168 }
169 #else
170 ad.type = adv_type[BT_MESH_ADV(buf)->type];
171 #endif
172
173 ad.data_len = buf->len;
174 ad.data = buf->data;
175
176 if (IS_ENABLED(CONFIG_BT_MESH_DEBUG_USE_ID_ADDR)) {
177 param.options = BT_LE_ADV_OPT_USE_IDENTITY;
178 } else {
179 param.options = 0;
180 }
181 param.id = BT_ID_DEFAULT;
182 param.interval_min = ADV_SCAN_UNIT(adv_int);
183 param.interval_max = param.interval_min;
184 err = bt_mesh_adv_enable(¶m, &ad, 1, NULL, 0);
185 adv_send_start(duration, err, cb, cb_data);
186 if (err) {
187 net_buf_unref(buf);
188 BT_ERR("Advertising failed: err %d", err);
189 return;
190 }
191
192 BT_DBG("Advertising started. Sleeping %u ms", duration);
193
194 k_sleep(K_MSEC(duration));
195
196 err = bt_mesh_adv_disable();
197 net_buf_unref(buf);
198 adv_send_end(err, cb, cb_data);
199 if (err) {
200 net_buf_unref(buf);
201 BT_ERR("Stopping advertising failed: err %d", err);
202 return;
203 }
204
205 BT_DBG("Advertising stopped");
206 }
207
208 // static void adv_stack_dump(const struct k_thread *thread, void *user_data)
209 // {
210 // #if defined(CONFIG_THREAD_STACK_INFO)
211 // stack_analyze((char *)user_data, (char *)thread->stack_info.start,
212 // thread->stack_info.size);
213 // #endif
214 // }
215
adv_thread(void * args)216 static void adv_thread(void *args)
217 {
218 BT_DBG("started");
219
220 while (1) {
221 struct net_buf *buf;
222
223 if (IS_ENABLED(CONFIG_BT_MESH_PROXY)) {
224 buf = net_buf_get(&adv_queue, K_NO_WAIT);
225 while (!buf) {
226 bt_s32_t timeout;
227
228 timeout = bt_mesh_proxy_adv_start();
229 BT_DBG("Proxy Advertising up to %d ms", timeout);
230 buf = net_buf_get(&adv_queue, timeout);
231 bt_mesh_proxy_adv_stop();
232 }
233 } else {
234 buf = net_buf_get(&adv_queue, K_FOREVER);
235 }
236
237 if (!buf) {
238 continue;
239 }
240
241 /* busy == 0 means this was canceled */
242 if (BT_MESH_ADV(buf)->busy) {
243 adv_send(buf);
244 BT_MESH_ADV(buf)->busy = 0;
245 } else {
246 net_buf_unref(buf);
247 }
248
249 // STACK_ANALYZE("adv stack", adv_thread_stack);
250 // k_thread_foreach(adv_stack_dump, "BT_MESH");
251
252 /* Give other threads a chance to run */
253 k_yield();
254 }
255 }
256
bt_mesh_adv_update(void)257 void bt_mesh_adv_update(void)
258 {
259 BT_DBG("");
260 k_fifo_cancel_wait(&adv_queue);
261 }
262
bt_mesh_adv_create_from_pool(struct net_buf_pool * pool,bt_mesh_adv_alloc_t get_id,enum bt_mesh_adv_type type,u8_t xmit,bt_s32_t timeout)263 struct net_buf *bt_mesh_adv_create_from_pool(struct net_buf_pool *pool, bt_mesh_adv_alloc_t get_id,
264 enum bt_mesh_adv_type type, u8_t xmit, bt_s32_t timeout)
265 {
266 struct bt_mesh_adv *adv;
267 struct net_buf *buf;
268
269 if (atomic_test_bit(bt_mesh.flags, BT_MESH_SUSPENDED)) {
270 /*[Genie begin] add by wenbing.cwb at 2021-01-21*/
271 #ifdef CONFIG_GENIE_MESH_GLP
272 BT_WARN("tx need resume stack while suspended");
273 bt_mesh_resume();
274 #else
275 BT_WARN("Refusing to allocate buffer while suspended");
276 return NULL;
277 #endif
278 /*[Genie end] add by wenbing.cwb at 2021-01-21*/
279 }
280
281 buf = net_buf_alloc(pool, timeout);
282 if (!buf) {
283 return NULL;
284 }
285
286 adv = get_id(net_buf_id(buf));
287 BT_MESH_ADV(buf) = adv;
288
289 memset(adv, 0, sizeof(*adv));
290
291 adv->type = type;
292 adv->xmit = xmit;
293
294 return buf;
295 }
296
bt_mesh_adv_create(enum bt_mesh_adv_type type,u8_t xmit,bt_s32_t timeout)297 struct net_buf *bt_mesh_adv_create(enum bt_mesh_adv_type type, u8_t xmit, bt_s32_t timeout)
298 {
299 return bt_mesh_adv_create_from_pool(&adv_buf_pool, adv_alloc, type, xmit, timeout);
300 }
301
bt_mesh_adv_send(struct net_buf * buf,const struct bt_mesh_send_cb * cb,void * cb_data)302 void bt_mesh_adv_send(struct net_buf *buf, const struct bt_mesh_send_cb *cb, void *cb_data)
303 {
304 if (NULL == buf) {
305 BT_WARN("buf is null");
306 return;
307 }
308
309 BT_DBG("type 0x%02x len %u: %s", BT_MESH_ADV(buf)->type, buf->len, bt_hex(buf->data, buf->len));
310
311 BT_MESH_ADV(buf)->cb = cb;
312 BT_MESH_ADV(buf)->cb_data = cb_data;
313 BT_MESH_ADV(buf)->busy = 1;
314
315 net_buf_put(&adv_queue, net_buf_ref(buf));
316 }
317
318 #ifdef CONFIG_BT_MESH_PROVISIONER
bt_mesh_pba_get_addr(void)319 const bt_addr_le_t *bt_mesh_pba_get_addr(void)
320 {
321 return dev_addr;
322 }
323 #endif
324
bt_mesh_scan_cb(const bt_addr_le_t * addr,s8_t rssi,u8_t adv_type,struct net_buf_simple * buf)325 static void bt_mesh_scan_cb(const bt_addr_le_t *addr, s8_t rssi, u8_t adv_type, struct net_buf_simple *buf)
326 {
327 #if defined(CONFIG_BT_MESH_PROVISIONER) || defined(GENIE_ULTRA_PROV)
328 if (adv_type != BT_LE_ADV_NONCONN_IND && adv_type != BT_LE_ADV_IND) {
329 #else
330 if (adv_type != BT_LE_ADV_NONCONN_IND) {
331 #endif
332 return;
333 }
334 // BT_DBG("len %u: %s", buf->len, bt_hex(buf->data, buf->len));
335 #ifdef CONFIG_BT_MESH_PROVISIONER
336 dev_addr = addr;
337 #endif
338
339 while (buf->len > 1) {
340 struct net_buf_simple_state state;
341 u8_t len, type;
342
343 len = net_buf_simple_pull_u8(buf);
344 /* Check for early termination */
345 if (len == 0) {
346 return;
347 }
348
349 if (len > buf->len) {
350 // BT_WARN("AD malformed");
351 return;
352 }
353
354 net_buf_simple_save(buf, &state);
355
356 type = net_buf_simple_pull_u8(buf);
357
358 buf->len = len - 1;
359 if (adv_type == BT_LE_ADV_NONCONN_IND) {
360 switch (type) {
361 case BT_DATA_MESH_MESSAGE:
362 #if defined(CONFIG_BT_MESH_RELAY_SRC_DBG)
363 net_buf_trace.buf = buf;
364 memcpy(net_buf_trace.addr, addr->a.val, 6);
365 net_buf_trace.addr[6] = addr->type;
366 #endif
367
368 bt_mesh_net_recv(buf, rssi, BT_MESH_NET_IF_ADV);
369 break;
370 #if defined(CONFIG_BT_MESH_PB_ADV)
371 case BT_DATA_MESH_PROV:
372 #ifdef CONFIG_BT_MESH_PROVISIONER
373 if (bt_mesh_is_provisioner_en()) {
374 provisioner_pb_adv_recv(buf);
375 break;
376 } else
377 #endif
378 {
379 bt_mesh_pb_adv_recv(buf);
380 }
381
382 break;
383 #endif
384 case BT_DATA_MESH_BEACON:
385 #ifdef CONFIG_BT_MESH_PROVISIONER
386 if (bt_mesh_is_provisioner_en()) {
387 provisioner_beacon_recv(buf);
388 } else
389 #endif
390 {
391 bt_mesh_beacon_recv(buf);
392 }
393
394 break;
395
396 case BT_DATA_MANUFACTURER_DATA:
397 if (g_vendor_beacon_cb != NULL) {
398 g_vendor_beacon_cb(addr, rssi, adv_type, (void *)buf, buf->len);
399 }
400
401 break;
402 default:
403 break;
404 }
405 } else if (adv_type == BT_LE_ADV_IND) {
406 u16_t uuid = 0;
407 #ifdef GENIE_ULTRA_PROV
408 genie_provision_ultra_prov_handle(type, (void *)buf);
409 #endif
410 switch (type) {
411 #if defined(CONFIG_BT_MESH_PROVISIONER) && defined(CONFIG_BT_MESH_PB_GATT)
412 case BT_DATA_FLAGS:
413 if (bt_mesh_is_provisioner_en()) {
414 if (!provisioner_flags_match(buf)) {
415 BT_DBG("Flags mismatch, ignore this adv pkt");
416 return;
417 }
418 }
419 break;
420 case BT_DATA_UUID16_ALL:
421 if (bt_mesh_is_provisioner_en()) {
422 uuid = provisioner_srv_uuid_recv(buf);
423 if (!uuid) {
424 BT_DBG("Service UUID mismatch, ignore this adv pkt");
425 return;
426 }
427 }
428 break;
429 case BT_DATA_SVC_DATA16:
430 if (bt_mesh_is_provisioner_en()) {
431 provisioner_srv_data_recv(buf, addr, uuid);
432 }
433 break;
434 #endif
435 default:
436 break;
437 }
438 (void)uuid;
439 }
440
441 net_buf_simple_restore(buf, &state);
442 net_buf_simple_pull(buf, len);
443 }
444 }
445
446 void bt_mesh_adv_init(void)
447 {
448 BT_INFO("enter %s\n", __func__);
449
450 k_fifo_init(&adv_queue);
451
452 NET_BUF_POOL_INIT(adv_buf_pool);
453
454 bt_mesh_adv_scan_schd_init();
455
456 k_thread_spawn(&adv_thread_data, "mesh adv", adv_thread_stack, K_THREAD_STACK_SIZEOF(adv_thread_stack), adv_thread,
457 NULL, 7);
458 }
459
460 extern int bt_le_adv_start_instant(const struct bt_le_adv_param *param, uint8_t *ad_data, size_t ad_len,
461 uint8_t *sd_data, size_t sd_len);
462 extern int bt_le_adv_stop_instant(void);
463
464 #define SCHD_LOGD(fmt, ...) printf(fmt, ##__VA_ARGS__)
465 #define SCHD_LOGE(...) LOGE("ADV", ##__VA_ARGS__)
466
467 #define CONN_ADV_DATA_TIEMOUT (10)
468 #define NOCONN_ADV_DATA_TIEMOUT (5)
469
470 typedef enum {
471 SCHD_IDLE = 0,
472 SCHD_ADV,
473 SCHD_SCAN,
474 SCHD_ADV_SCAN,
475
476 SCHD_INVAILD,
477 } adv_scan_schd_state_en;
478
479 typedef enum {
480 ADV_ON = 0,
481 ADV_OFF,
482 SCAN_ON,
483 SCAN_OFF,
484
485 ACTION_INVAILD,
486 } adv_scan_schd_action_en;
487
488 typedef int (*adv_scan_schd_func_t)(adv_scan_schd_state_en st);
489 static int adv_scan_schd_idle_enter(adv_scan_schd_state_en st);
490 static int adv_scan_schd_idle_exit(adv_scan_schd_state_en st);
491 static int adv_scan_schd_adv_enter(adv_scan_schd_state_en st);
492 static int adv_scan_schd_adv_exit(adv_scan_schd_state_en st);
493 static int adv_scan_schd_scan_enter(adv_scan_schd_state_en st);
494 static int adv_scan_schd_scan_exit(adv_scan_schd_state_en st);
495 static int adv_scan_schd_adv_scan_enter(adv_scan_schd_state_en st);
496 static int adv_scan_schd_adv_scan_exit(adv_scan_schd_state_en st);
497
498 struct {
499 adv_scan_schd_func_t enter;
500 adv_scan_schd_func_t exit;
501 } adv_scan_schd_funcs[] = {
502 { adv_scan_schd_idle_enter, adv_scan_schd_idle_exit },
503 { adv_scan_schd_adv_enter, adv_scan_schd_adv_exit },
504 { adv_scan_schd_scan_enter, adv_scan_schd_scan_exit },
505 { adv_scan_schd_adv_scan_enter, adv_scan_schd_adv_scan_exit },
506 };
507
508 adv_scan_schd_state_en adv_scan_schd_st_change_map[4][4] = {
509 { SCHD_ADV, SCHD_IDLE, SCHD_SCAN, SCHD_IDLE },
510 { SCHD_ADV, SCHD_IDLE, SCHD_ADV_SCAN, SCHD_ADV },
511 { SCHD_ADV_SCAN, SCHD_SCAN, SCHD_SCAN, SCHD_IDLE },
512 { SCHD_ADV_SCAN, SCHD_SCAN, SCHD_ADV_SCAN, SCHD_ADV },
513 };
514
515 struct adv_scan_data_t {
516 uint8_t ad_data[31];
517 size_t ad_len;
518 uint8_t sd_data[31];
519 size_t sd_len;
520 struct bt_le_adv_param adv_param;
521 struct bt_le_scan_param scan_param;
522 bt_le_scan_cb_t *scan_cb;
523 };
524
525 #define FLAG_RESTART 1
526 #define FLAG_STOP 2
527
528 struct {
529 struct k_mutex mutex;
530 k_timer_t timer;
531 uint8_t flag;
532 adv_scan_schd_state_en cur_st;
533 struct adv_scan_data_t param;
534 } adv_scan_schd = { 0 };
535
536 static int adv_scan_schd_idle_enter(adv_scan_schd_state_en st)
537 {
538 SCHD_LOGD("idle enter\n");
539 memset(&adv_scan_schd.param, 0, sizeof(struct adv_scan_data_t));
540 return 0;
541 }
542
543 static int adv_scan_schd_idle_exit(adv_scan_schd_state_en st)
544 {
545 SCHD_LOGD("idle exit\n");
546 // do nothing
547 return 0;
548 }
549
550 static int adv_scan_schd_adv_enter(adv_scan_schd_state_en st)
551 {
552 SCHD_LOGD("adv on enter\n");
553
554 if (st == SCHD_IDLE || st == SCHD_ADV_SCAN || st == SCHD_ADV) {
555 if (adv_scan_schd.param.ad_len) {
556 adv_scan_schd.flag = FLAG_RESTART;
557 k_timer_start(&adv_scan_schd.timer, 1);
558 return 0;
559 }
560 }
561
562 return -EINVAL;
563 ;
564 }
565
566 static int adv_scan_schd_adv_exit(adv_scan_schd_state_en st)
567 {
568 SCHD_LOGD("adv on exit\n");
569 int ret = 0;
570 if (st == SCHD_ADV_SCAN || st == SCHD_IDLE || st == SCHD_ADV) {
571 adv_scan_schd.flag = FLAG_STOP;
572 k_timer_stop(&adv_scan_schd.timer);
573 ret = bt_le_adv_stop_instant();
574 if (ret && (ret != -EALREADY)) {
575 SCHD_LOGE("adv stop err %d\n", ret);
576 return ret;
577 }
578 return 0;
579 }
580
581 return -EINVAL;
582 }
583
584 static int adv_scan_schd_scan_enter(adv_scan_schd_state_en st)
585 {
586 SCHD_LOGD("scan on enter\n");
587 int ret = 0;
588 if (st == SCHD_IDLE || st == SCHD_ADV_SCAN || st == SCHD_SCAN) {
589 ret = bt_le_scan_start(&adv_scan_schd.param.scan_param, adv_scan_schd.param.scan_cb);
590 if (ret && (ret != -EALREADY)) {
591 SCHD_LOGE("scan start err %d\n", ret);
592 return ret;
593 }
594 return 0;
595 }
596
597 return -EINVAL;
598 }
599
600 static int adv_scan_schd_scan_exit(adv_scan_schd_state_en st)
601 {
602 SCHD_LOGD("scan on exit\n");
603 int ret = 0;
604 if (st == SCHD_ADV_SCAN || st == SCHD_IDLE || st == SCHD_SCAN) {
605 ret = bt_le_scan_stop();
606 if (ret && (ret != -EALREADY)) {
607 SCHD_LOGE("scan stop err %d in %s\n", ret, __func__);
608 return ret;
609 }
610 return 0;
611 }
612
613 return -EINVAL;
614 }
615
616 static int adv_scan_schd_adv_scan_enter(adv_scan_schd_state_en st)
617 {
618 SCHD_LOGD("adv scan on enter\n");
619
620 if (st == SCHD_ADV || st == SCHD_SCAN || st == SCHD_ADV_SCAN || st == SCHD_IDLE) {
621 adv_scan_schd.flag = FLAG_RESTART;
622 k_timer_start(&adv_scan_schd.timer, 1);
623 return 0;
624 }
625
626 return -EINVAL;
627 }
628
629 static int adv_scan_schd_adv_scan_exit(adv_scan_schd_state_en st)
630 {
631 int ret;
632 SCHD_LOGD("adv scan on exit\n");
633
634 if (st == SCHD_ADV || st == SCHD_SCAN || st == SCHD_ADV_SCAN) {
635 adv_scan_schd.flag = FLAG_STOP;
636 k_timer_stop(&adv_scan_schd.timer);
637
638 ret = bt_le_scan_stop();
639 // SCHD_LOGE("EALREADY = %d in %s\n", EALREADY, __func__);
640 if (ret && (ret != -114)) {
641 SCHD_LOGE("scan stop err %d in %s\n", ret, __func__);
642 return ret;
643 }
644
645 ret = bt_le_adv_stop();
646
647 if (ret && (ret != -EALREADY)) {
648 SCHD_LOGE("adv stop err %d\n", ret);
649 return ret;
650 }
651
652 return 0;
653 }
654
655 return -EINVAL;
656 }
657
658 int bt_mesh_adv_scan_schd(adv_scan_schd_state_en st)
659 {
660 int ret;
661 SCHD_LOGD("%d->%d\n", adv_scan_schd.cur_st, st);
662
663 if (st < SCHD_INVAILD) {
664 ret = adv_scan_schd_funcs[adv_scan_schd.cur_st].exit(st);
665
666 if (ret) {
667 return ret;
668 }
669
670 adv_scan_schd.cur_st = SCHD_IDLE;
671
672 ret = adv_scan_schd_funcs[st].enter(adv_scan_schd.cur_st);
673
674 if (ret) {
675 return ret;
676 }
677
678 adv_scan_schd.cur_st = st;
679
680 return 0;
681 }
682
683 return -EINVAL;
684 }
685
686 int bt_mesh_adv_scan_schd_action(adv_scan_schd_action_en action)
687 {
688 int ret;
689
690 if (action < ACTION_INVAILD) {
691 adv_scan_schd_state_en cur_st = adv_scan_schd.cur_st;
692 adv_scan_schd_state_en target_st = adv_scan_schd_st_change_map[cur_st][action];
693 k_mutex_lock(&adv_scan_schd.mutex, K_FOREVER);
694 ret = bt_mesh_adv_scan_schd(target_st);
695 k_mutex_unlock(&adv_scan_schd.mutex);
696 if (ret && (ret != -EALREADY)) {
697 SCHD_LOGE("action %d, cur_st %d target_st %d, ret %d in %s\n", action, cur_st, target_st, ret, __func__);
698 }
699
700 return ret;
701 }
702
703 return -EINVAL;
704 }
705
706 void adv_scan_timer(void *timer, void *arg)
707 {
708 int ret;
709 static enum {
710 ADV = 0,
711 SCAN,
712 ADV_IDLE,
713 } next_state = ADV;
714 static int adv_time = 0;
715
716 uint32_t next_time = 0;
717 k_mutex_lock(&adv_scan_schd.mutex, K_FOREVER);
718
719 if (adv_scan_schd.flag == FLAG_RESTART) {
720 next_state = ADV;
721 adv_scan_schd.flag = 0;
722 } else if (adv_scan_schd.flag == FLAG_STOP) {
723 k_mutex_unlock(&adv_scan_schd.mutex);
724 return;
725 }
726
727 SCHD_LOGD("adv_time %d, next_state %d, flag %d\n", adv_time, next_state, adv_scan_schd.flag);
728
729 if (next_state == ADV) {
730 ret = bt_le_scan_stop();
731
732 if (ret && (ret != -EALREADY)) {
733 SCHD_LOGE("scan stop err %d in %s\n", ret, __func__);
734 }
735
736 struct bt_le_adv_param param = adv_scan_schd.param.adv_param;
737
738 param.interval_min = BT_GAP_ADV_SLOW_INT_MIN;
739
740 param.interval_max = param.interval_min;
741
742 ret = bt_le_adv_start_instant(¶m, adv_scan_schd.param.ad_data, adv_scan_schd.param.ad_len,
743 adv_scan_schd.param.sd_data, adv_scan_schd.param.sd_len);
744
745 if (ret && (ret != -EALREADY) && (ret != -ENOMEM)) {
746 SCHD_LOGE("adv start err %d\n", ret);
747 }
748
749 if (adv_scan_schd.cur_st == SCHD_ADV_SCAN) {
750 next_state = SCAN;
751 } else if (adv_scan_schd.cur_st == SCHD_ADV) {
752 next_state = ADV_IDLE;
753 }
754
755 adv_time = (!(param.options & BT_LE_ADV_OPT_CONNECTABLE)) ? NOCONN_ADV_DATA_TIEMOUT : CONN_ADV_DATA_TIEMOUT;
756 next_time = adv_time;
757 } else if (next_state == SCAN) {
758 ret = bt_le_adv_stop();
759
760 if (ret && (ret != -EALREADY)) {
761 SCHD_LOGE("adv stop err %d\n", ret);
762 }
763
764 /* Here, we define the adv window of each package in adv duration (120ms or xmit related time)*/
765 if (adv_scan_schd.param.adv_param.options & BT_LE_ADV_OPT_CONNECTABLE) {
766 next_time = adv_scan_schd.param.adv_param.interval_min * 5 / 8 - adv_time;
767 } else {
768 next_time =
769 CONFIG_ADV_INTERVAL_TIMER - adv_time; // adv_scan_schd.param.adv_param.interval_min * 5 / 8 - adv_time;
770 }
771
772 if (next_time > CONFIG_ADV_SCAN_INTERVAL_TIMER) {
773 ret = bt_le_scan_start(&adv_scan_schd.param.scan_param, adv_scan_schd.param.scan_cb);
774
775 if (ret) {
776 SCHD_LOGE("scan err %d\n", ret);
777 }
778 }
779 adv_time = 0;
780 next_state = ADV;
781 } else if (next_state == ADV_IDLE) {
782 if (adv_scan_schd.param.adv_param.options & BT_LE_ADV_OPT_CONNECTABLE) {
783 next_time = adv_scan_schd.param.adv_param.interval_min * 5 / 8 - adv_time;
784 } else {
785 next_time =
786 CONFIG_ADV_INTERVAL_TIMER - adv_time; // adv_scan_schd.param.adv_param.interval_min * 5 / 8 - adv_time;
787 }
788 adv_time = 0;
789 next_state = ADV;
790 }
791 k_mutex_unlock(&adv_scan_schd.mutex);
792 k_timer_start(&adv_scan_schd.timer, next_time);
793 }
794
795 int bt_mesh_adv_scan_schd_init()
796 {
797 memset(&adv_scan_schd, 0, sizeof(adv_scan_schd));
798 k_timer_init(&adv_scan_schd.timer, adv_scan_timer, &adv_scan_schd);
799 k_mutex_init(&adv_scan_schd.mutex);
800 return 0;
801 }
802
803 static int set_ad_data(uint8_t *data, const struct bt_data *ad, size_t ad_len)
804 {
805 int i;
806 int set_len = 0;
807
808 for (i = 0; i < ad_len; i++) {
809 int len = ad[i].data_len;
810 u8_t type = ad[i].type;
811
812 /* Check if ad fit in the remaining buffer */
813 if (set_len + len + 2 > 31) {
814 len = 31 - (set_len + 2);
815
816 if (type != BT_DATA_NAME_COMPLETE || len <= 0) {
817 return -EINVAL;
818 }
819
820 type = BT_DATA_NAME_SHORTENED;
821 }
822
823 data[set_len++] = len + 1;
824 data[set_len++] = type;
825
826 memcpy(&data[set_len], ad[i].data, len);
827 set_len += len;
828 }
829
830 return set_len;
831 }
832 int bt_mesh_adv_enable(const struct bt_le_adv_param *param, const struct bt_data *ad, size_t ad_len,
833 const struct bt_data *sd, size_t sd_len)
834 {
835 if (param == NULL) {
836 return -EINVAL;
837 }
838
839 BT_ERR("enter %s\n", __func__);
840 k_mutex_lock(&adv_scan_schd.mutex, K_FOREVER);
841 adv_scan_schd.param.adv_param = *param;
842 adv_scan_schd.param.ad_len = set_ad_data(adv_scan_schd.param.ad_data, ad, ad_len);
843 adv_scan_schd.param.sd_len = set_ad_data(adv_scan_schd.param.sd_data, sd, sd_len);
844 k_mutex_unlock(&adv_scan_schd.mutex);
845 bt_mesh_adv_scan_schd_action(ADV_ON);
846 return 0;
847 }
848
849 int bt_mesh_adv_disable()
850 {
851 BT_ERR("enter %s\n", __func__);
852 bt_mesh_adv_scan_schd_action(ADV_OFF);
853 return 0;
854 }
855
856 int bt_mesh_scan_enable(void)
857 {
858 struct bt_le_scan_param scan_param = { .type = BT_HCI_LE_SCAN_PASSIVE,
859 .filter_dup = BT_HCI_LE_SCAN_FILTER_DUP_DISABLE,
860 .interval = MESH_SCAN_INTERVAL,
861 .window = MESH_SCAN_WINDOW };
862
863 BT_ERR("enter %s\n", __func__);
864 k_mutex_lock(&adv_scan_schd.mutex, K_FOREVER);
865 adv_scan_schd.param.scan_param = scan_param;
866 adv_scan_schd.param.scan_cb = bt_mesh_scan_cb;
867 k_mutex_unlock(&adv_scan_schd.mutex);
868 bt_mesh_adv_scan_schd_action(SCAN_ON);
869 return 0;
870 }
871
872 int bt_mesh_scan_disable(void)
873 {
874 BT_ERR("");
875 bt_mesh_adv_scan_schd_action(SCAN_OFF);
876 return 0;
877 }
878
879 int bt_mesh_adv_vnd_scan_register(vendor_beacon_cb bacon_cb)
880 {
881 if (!bacon_cb) {
882 return -EINVAL;
883 }
884 g_vendor_beacon_cb = bacon_cb;
885 return 0;
886 }
887