1 /* Bluetooth Mesh */
2
3 /*
4 * Copyright (c) 2017 Intel Corporation
5 * Additional Copyright (c) 2018 Espressif Systems (Shanghai) PTE LTD
6 *
7 * SPDX-License-Identifier: Apache-2.0
8 */
9
10 #include <stdint.h>
11 #include <string.h>
12 #include <errno.h>
13
14 #include "mesh_kernel.h"
15 #include "mesh.h"
16 #include "mesh_hci.h"
17 #include "mesh_common.h"
18 #include "adv.h"
19 #include "beacon.h"
20 #include "prov.h"
21 #include "foundation.h"
22 #include "proxy_server.h"
23 #include "proxy_client.h"
24 #include "provisioner_prov.h"
25 #include "mesh_bearer_adapt.h"
26
27 /* Convert from ms to 0.625ms units */
28 #define ADV_SCAN_UNIT(_ms) ((_ms) * 8 / 5)
29 /* Convert from 0.625ms units to interval(ms) */
30 #define ADV_SCAN_INT(val) ((val) * 5 / 8)
31
32 /* Pre-5.0 controllers enforce a minimum interval of 100ms
33 * whereas 5.0+ controllers can go down to 20ms.
34 */
35 #define ADV_INT_DEFAULT_MS 100
36 #define ADV_INT_FAST_MS 20
37
38 static const uint8_t adv_type[] = {
39 [BLE_MESH_ADV_PROV] = BLE_MESH_DATA_MESH_PROV,
40 [BLE_MESH_ADV_DATA] = BLE_MESH_DATA_MESH_MESSAGE,
41 [BLE_MESH_ADV_BEACON] = BLE_MESH_DATA_MESH_BEACON,
42 [BLE_MESH_ADV_URI] = BLE_MESH_DATA_URI,
43 };
44
45 NET_BUF_POOL_DEFINE(adv_buf_pool, CONFIG_BLE_MESH_ADV_BUF_COUNT,
46 BLE_MESH_ADV_DATA_SIZE, BLE_MESH_ADV_USER_DATA_SIZE, NULL);
47
48 static struct bt_mesh_adv adv_pool[CONFIG_BLE_MESH_ADV_BUF_COUNT];
49
50 struct bt_mesh_queue {
51 QueueHandle_t handle;
52 #if CONFIG_BLE_MESH_FREERTOS_STATIC_ALLOC
53 StaticQueue_t *buffer;
54 uint8_t *storage;
55 #endif
56 };
57
58 static struct bt_mesh_queue adv_queue;
59 /* We reserve one queue item for bt_mesh_adv_update() */
60 #if CONFIG_BLE_MESH_SUPPORT_BLE_ADV
61 #define BLE_MESH_ADV_QUEUE_SIZE (CONFIG_BLE_MESH_ADV_BUF_COUNT + CONFIG_BLE_MESH_BLE_ADV_BUF_COUNT + 1)
62 #else
63 #define BLE_MESH_ADV_QUEUE_SIZE (CONFIG_BLE_MESH_ADV_BUF_COUNT + 1)
64 #endif
65
66 #if defined(CONFIG_BLE_MESH_RELAY_ADV_BUF)
67 NET_BUF_POOL_DEFINE(relay_adv_buf_pool, CONFIG_BLE_MESH_RELAY_ADV_BUF_COUNT,
68 BLE_MESH_ADV_DATA_SIZE, BLE_MESH_ADV_USER_DATA_SIZE, NULL);
69
70 static struct bt_mesh_adv relay_adv_pool[CONFIG_BLE_MESH_RELAY_ADV_BUF_COUNT];
71
72 static struct bt_mesh_queue relay_queue;
73 #define BLE_MESH_RELAY_QUEUE_SIZE CONFIG_BLE_MESH_RELAY_ADV_BUF_COUNT
74
75 static QueueSetHandle_t mesh_queue_set;
76 #define BLE_MESH_QUEUE_SET_SIZE (BLE_MESH_ADV_QUEUE_SIZE + BLE_MESH_RELAY_QUEUE_SIZE)
77
78 #define BLE_MESH_RELAY_TIME_INTERVAL K_SECONDS(6)
79 #define BLE_MESH_MAX_TIME_INTERVAL 0xFFFFFFFF
80
81 static bool ignore_relay_packet(uint32_t timestamp);
82 #endif /* defined(CONFIG_BLE_MESH_RELAY_ADV_BUF) */
83
84 #if CONFIG_BLE_MESH_SUPPORT_BLE_ADV
85 /* length + advertising data + length + scan response data */
86 NET_BUF_POOL_DEFINE(ble_adv_buf_pool, CONFIG_BLE_MESH_BLE_ADV_BUF_COUNT,
87 ((BLE_MESH_ADV_DATA_SIZE + 3) << 1), BLE_MESH_ADV_USER_DATA_SIZE, NULL);
88
89 static struct bt_mesh_adv ble_adv_pool[CONFIG_BLE_MESH_BLE_ADV_BUF_COUNT];
90
91 enum {
92 TIMER_INIT, /* Resend timer is initialized */
93 NUM_FLAGS,
94 };
95
96 static struct ble_adv_tx {
97 struct bt_mesh_ble_adv_param param;
98 struct net_buf *buf;
99 struct k_delayed_work resend;
100 BLE_MESH_ATOMIC_DEFINE(flags, NUM_FLAGS);
101 } ble_adv_tx[CONFIG_BLE_MESH_BLE_ADV_BUF_COUNT];
102
103 #define SEND_BLE_ADV_INFINITE 0xFFFF
104
105 #if CONFIG_BLE_MESH_DEINIT
106 static void bt_mesh_ble_adv_deinit(void);
107 #endif /* CONFIG_BLE_MESH_DEINIT */
108 #endif /* CONFIG_BLE_MESH_SUPPORT_BLE_ADV */
109
110 struct bt_mesh_adv_task {
111 TaskHandle_t handle;
112 #if (CONFIG_BLE_MESH_FREERTOS_STATIC_ALLOC_EXTERNAL && \
113 CONFIG_SPIRAM_CACHE_WORKAROUND && \
114 CONFIG_SPIRAM_ALLOW_STACK_EXTERNAL_MEMORY)
115 StaticTask_t *task;
116 StackType_t *stack;
117 #endif
118 };
119
120 static struct bt_mesh_adv_task adv_task;
121
adv_alloc(int id)122 static struct bt_mesh_adv *adv_alloc(int id)
123 {
124 return &adv_pool[id];
125 }
126
adv_send_start(uint16_t duration,int err,const struct bt_mesh_send_cb * cb,void * cb_data)127 static inline void adv_send_start(uint16_t duration, int err,
128 const struct bt_mesh_send_cb *cb,
129 void *cb_data)
130 {
131 if (cb && cb->start) {
132 cb->start(duration, err, cb_data);
133 }
134 }
135
adv_send_end(int err,const struct bt_mesh_send_cb * cb,void * cb_data)136 static inline void adv_send_end(int err, const struct bt_mesh_send_cb *cb,
137 void *cb_data)
138 {
139 if (cb && cb->end) {
140 cb->end(err, cb_data);
141 }
142 }
143
adv_send(struct net_buf * buf)144 static inline int adv_send(struct net_buf *buf)
145 {
146 const int32_t adv_int_min = ((bt_mesh_dev.hci_version >= BLE_MESH_HCI_VERSION_5_0) ?
147 ADV_INT_FAST_MS : ADV_INT_DEFAULT_MS);
148 const struct bt_mesh_send_cb *cb = BLE_MESH_ADV(buf)->cb;
149 void *cb_data = BLE_MESH_ADV(buf)->cb_data;
150 struct bt_mesh_adv_param param = {0};
151 uint16_t duration = 0U, adv_int = 0U;
152 struct bt_mesh_adv_data ad = {0};
153 int err = 0;
154
155 BT_DBG("type %u len %u: %s", BLE_MESH_ADV(buf)->type,
156 buf->len, bt_hex(buf->data, buf->len));
157
158 #if CONFIG_BLE_MESH_SUPPORT_BLE_ADV
159 if (BLE_MESH_ADV(buf)->type != BLE_MESH_ADV_BLE) {
160 #endif
161 adv_int = MAX(adv_int_min,
162 BLE_MESH_TRANSMIT_INT(BLE_MESH_ADV(buf)->xmit));
163 duration = (BLE_MESH_TRANSMIT_COUNT(BLE_MESH_ADV(buf)->xmit) + 1) *
164 (adv_int + 10);
165
166 BT_DBG("count %u interval %ums duration %ums",
167 BLE_MESH_TRANSMIT_COUNT(BLE_MESH_ADV(buf)->xmit) + 1, adv_int,
168 duration);
169
170 ad.type = adv_type[BLE_MESH_ADV(buf)->type];
171 ad.data_len = buf->len;
172 ad.data = buf->data;
173
174 param.options = 0U;
175 param.interval_min = ADV_SCAN_UNIT(adv_int);
176 param.interval_max = param.interval_min;
177
178 bt_mesh_adv_buf_ref_debug(__func__, buf, 4U, BLE_MESH_BUF_REF_SMALL);
179
180 err = bt_le_adv_start(¶m, &ad, 1, NULL, 0);
181 #if CONFIG_BLE_MESH_SUPPORT_BLE_ADV
182 } else {
183 struct bt_mesh_ble_adv_data data = {0};
184 struct ble_adv_tx *tx = cb_data;
185
186 if (tx == NULL) {
187 BT_ERR("Invalid adv user data");
188 net_buf_unref(buf);
189 return -EINVAL;
190 }
191
192 BT_DBG("interval %dms, duration %dms, period %dms, count %d",
193 ADV_SCAN_INT(tx->param.interval), tx->param.duration,
194 tx->param.period, tx->param.count);
195
196 data.adv_data_len = tx->buf->data[0];
197 if (data.adv_data_len) {
198 memcpy(data.adv_data, tx->buf->data + 1, data.adv_data_len);
199 }
200 data.scan_rsp_data_len = tx->buf->data[data.adv_data_len + 1];
201 if (data.scan_rsp_data_len) {
202 memcpy(data.scan_rsp_data, tx->buf->data + data.adv_data_len + 2, data.scan_rsp_data_len);
203 }
204 duration = tx->param.duration;
205
206 bt_mesh_adv_buf_ref_debug(__func__, buf, 3U, BLE_MESH_BUF_REF_SMALL);
207
208 err = bt_mesh_ble_adv_start(&tx->param, &data);
209 }
210 #endif /* CONFIG_BLE_MESH_SUPPORT_BLE_ADV */
211
212 net_buf_unref(buf);
213 adv_send_start(duration, err, cb, cb_data);
214 if (err) {
215 BT_ERR("Start advertising failed: err %d", err);
216 return err;
217 }
218
219 BT_DBG("Advertising started. Sleeping %u ms", duration);
220
221 k_sleep(K_MSEC(duration));
222
223 err = bt_le_adv_stop();
224 adv_send_end(err, cb, cb_data);
225 if (err) {
226 BT_ERR("Stop advertising failed: err %d", err);
227 return 0;
228 }
229
230 BT_DBG("Advertising stopped");
231 return 0;
232 }
233
K_WAIT(int32_t val)234 static inline TickType_t K_WAIT(int32_t val)
235 {
236 return (val == K_FOREVER) ? portMAX_DELAY : (val / portTICK_PERIOD_MS);
237 }
238
adv_thread(void * p)239 static void adv_thread(void *p)
240 {
241 #if defined(CONFIG_BLE_MESH_RELAY_ADV_BUF)
242 QueueSetMemberHandle_t handle = NULL;
243 #endif
244 bt_mesh_msg_t msg = {0};
245 struct net_buf **buf = NULL;
246
247 buf = (struct net_buf **)(&msg.arg);
248
249 BT_DBG("%s, starts", __func__);
250
251 while (1) {
252 *buf = NULL;
253 #if !defined(CONFIG_BLE_MESH_RELAY_ADV_BUF)
254 #if (CONFIG_BLE_MESH_NODE && CONFIG_BLE_MESH_PB_GATT) || \
255 CONFIG_BLE_MESH_GATT_PROXY_SERVER
256 xQueueReceive(adv_queue.handle, &msg, K_NO_WAIT);
257 while (!(*buf)) {
258 int32_t timeout = 0;
259 BT_DBG("Mesh Proxy Advertising start");
260 timeout = bt_mesh_proxy_server_adv_start();
261 BT_DBG("Mesh Proxy Advertising up to %d ms", timeout);
262 xQueueReceive(adv_queue.handle, &msg, K_WAIT(timeout));
263 BT_DBG("Mesh Proxy Advertising stop");
264 bt_mesh_proxy_server_adv_stop();
265 }
266 #else
267 xQueueReceive(adv_queue.handle, &msg, portMAX_DELAY);
268 #endif /* (CONFIG_BLE_MESH_NODE && CONFIG_BLE_MESH_PB_GATT) || CONFIG_BLE_MESH_GATT_PROXY_SERVER */
269 #else /* !defined(CONFIG_BLE_MESH_RELAY_ADV_BUF) */
270 #if (CONFIG_BLE_MESH_NODE && CONFIG_BLE_MESH_PB_GATT) || \
271 CONFIG_BLE_MESH_GATT_PROXY_SERVER
272 handle = xQueueSelectFromSet(mesh_queue_set, K_NO_WAIT);
273 if (handle) {
274 if (uxQueueMessagesWaiting(adv_queue.handle)) {
275 xQueueReceive(adv_queue.handle, &msg, K_NO_WAIT);
276 } else if (uxQueueMessagesWaiting(relay_queue.handle)) {
277 xQueueReceive(relay_queue.handle, &msg, K_NO_WAIT);
278 }
279 } else {
280 while (!(*buf)) {
281 int32_t timeout = 0;
282 BT_DBG("Mesh Proxy Advertising start");
283 timeout = bt_mesh_proxy_server_adv_start();
284 BT_DBG("Mesh Proxy Advertising up to %d ms", timeout);
285 handle = xQueueSelectFromSet(mesh_queue_set, K_WAIT(timeout));
286 BT_DBG("Mesh Proxy Advertising stop");
287 bt_mesh_proxy_server_adv_stop();
288 if (handle) {
289 if (uxQueueMessagesWaiting(adv_queue.handle)) {
290 xQueueReceive(adv_queue.handle, &msg, K_NO_WAIT);
291 } else if (uxQueueMessagesWaiting(relay_queue.handle)) {
292 xQueueReceive(relay_queue.handle, &msg, K_NO_WAIT);
293 }
294 }
295 }
296 }
297 #else
298 handle = xQueueSelectFromSet(mesh_queue_set, portMAX_DELAY);
299 if (handle) {
300 if (uxQueueMessagesWaiting(adv_queue.handle)) {
301 xQueueReceive(adv_queue.handle, &msg, K_NO_WAIT);
302 } else if (uxQueueMessagesWaiting(relay_queue.handle)) {
303 xQueueReceive(relay_queue.handle, &msg, K_NO_WAIT);
304 }
305 }
306 #endif /* (CONFIG_BLE_MESH_NODE && CONFIG_BLE_MESH_PB_GATT) || CONFIG_BLE_MESH_GATT_PROXY_SERVER */
307 #endif /* !defined(CONFIG_BLE_MESH_RELAY_ADV_BUF) */
308
309 if (*buf == NULL) {
310 continue;
311 }
312
313 /* busy == 0 means this was canceled */
314 if (BLE_MESH_ADV(*buf)->busy) {
315 BLE_MESH_ADV(*buf)->busy = 0U;
316 #if !defined(CONFIG_BLE_MESH_RELAY_ADV_BUF)
317 if (adv_send(*buf)) {
318 BT_WARN("Failed to send adv packet");
319 }
320 #else /* !defined(CONFIG_BLE_MESH_RELAY_ADV_BUF) */
321 if (msg.relay && ignore_relay_packet(msg.timestamp)) {
322 /* If the interval between "current time - msg.timestamp" is bigger than
323 * BLE_MESH_RELAY_TIME_INTERVAL, this relay packet will not be sent.
324 */
325 BT_INFO("Ignore relay packet");
326 net_buf_unref(*buf);
327 } else {
328 if (adv_send(*buf)) {
329 BT_WARN("Failed to send adv packet");
330 }
331 }
332 #endif
333 } else {
334 bt_mesh_adv_buf_ref_debug(__func__, *buf, 1U, BLE_MESH_BUF_REF_EQUAL);
335 net_buf_unref(*buf);
336 }
337
338 /* Give other threads a chance to run */
339 taskYIELD();
340 }
341 }
342
bt_mesh_adv_create_from_pool(struct net_buf_pool * pool,bt_mesh_adv_alloc_t get_id,enum bt_mesh_adv_type type,uint8_t xmit,int32_t timeout)343 struct net_buf *bt_mesh_adv_create_from_pool(struct net_buf_pool *pool,
344 bt_mesh_adv_alloc_t get_id,
345 enum bt_mesh_adv_type type,
346 uint8_t xmit, int32_t timeout)
347 {
348 struct bt_mesh_adv *adv = NULL;
349 struct net_buf *buf = NULL;
350
351 if (bt_mesh_atomic_test_bit(bt_mesh.flags, BLE_MESH_SUSPENDED)) {
352 BT_WARN("Refusing to allocate buffer while suspended");
353 return NULL;
354 }
355
356 buf = net_buf_alloc(pool, timeout);
357 if (!buf) {
358 return NULL;
359 }
360
361 BT_DBG("pool %p, buf_count %d, uinit_count %d",
362 buf->pool, pool->buf_count, pool->uninit_count);
363
364 adv = get_id(net_buf_id(buf));
365 BLE_MESH_ADV(buf) = adv;
366
367 (void)memset(adv, 0, sizeof(*adv));
368
369 adv->type = type;
370 adv->xmit = xmit;
371
372 return buf;
373 }
374
bt_mesh_unref_buf_from_pool(struct net_buf_pool * pool)375 void bt_mesh_unref_buf_from_pool(struct net_buf_pool *pool)
376 {
377 int i;
378
379 if (pool == NULL) {
380 BT_ERR("%s, Invalid parameter", __func__);
381 return;
382 }
383
384 for (i = 0; i < pool->buf_count; i++) {
385 struct net_buf *buf = &pool->__bufs[i];
386 if (buf->ref > 1U) {
387 buf->ref = 1U;
388 }
389 net_buf_unref(buf);
390 }
391 }
392
bt_mesh_adv_create(enum bt_mesh_adv_type type,uint8_t xmit,int32_t timeout)393 struct net_buf *bt_mesh_adv_create(enum bt_mesh_adv_type type, uint8_t xmit,
394 int32_t timeout)
395 {
396 return bt_mesh_adv_create_from_pool(&adv_buf_pool, adv_alloc, type,
397 xmit, timeout);
398 }
399
bt_mesh_adv_buf_ref_debug(const char * func,struct net_buf * buf,uint8_t ref_cmp,bt_mesh_buf_ref_flag_t flag)400 void bt_mesh_adv_buf_ref_debug(const char *func, struct net_buf *buf,
401 uint8_t ref_cmp, bt_mesh_buf_ref_flag_t flag)
402 {
403 if (buf == NULL || func == NULL || flag >= BLE_MESH_BUF_REF_MAX) {
404 BT_ERR("%s, Invalid parameter", __func__);
405 return;
406 }
407
408 switch (flag) {
409 case BLE_MESH_BUF_REF_EQUAL:
410 if (buf->ref != ref_cmp) {
411 BT_ERR("Unexpected ref %d in %s, expect to equal to %d", buf->ref, func, ref_cmp);
412 }
413 break;
414 case BLE_MESH_BUF_REF_SMALL:
415 if (buf->ref >= ref_cmp) {
416 BT_ERR("Unexpected ref %d in %s, expect to smaller than %d", buf->ref, func, ref_cmp);
417 }
418 break;
419 default:
420 break;
421 }
422 }
423
bt_mesh_unref_buf(bt_mesh_msg_t * msg)424 static void bt_mesh_unref_buf(bt_mesh_msg_t *msg)
425 {
426 struct net_buf *buf = NULL;
427
428 if (msg->arg) {
429 buf = (struct net_buf *)msg->arg;
430 BLE_MESH_ADV(buf)->busy = 0U;
431 if (buf->ref > 1U) {
432 buf->ref = 1U;
433 }
434 net_buf_unref(buf);
435 }
436
437 return;
438 }
439
bt_mesh_task_post(bt_mesh_msg_t * msg,uint32_t timeout,bool front)440 static void bt_mesh_task_post(bt_mesh_msg_t *msg, uint32_t timeout, bool front)
441 {
442 BT_DBG("%s", __func__);
443
444 if (adv_queue.handle == NULL) {
445 BT_ERR("Invalid adv queue");
446 return;
447 }
448
449 if (front) {
450 if (xQueueSendToFront(adv_queue.handle, msg, timeout) != pdTRUE) {
451 BT_ERR("Failed to send item to adv queue front");
452 bt_mesh_unref_buf(msg);
453 }
454 } else {
455 if (xQueueSend(adv_queue.handle, msg, timeout) != pdTRUE) {
456 BT_ERR("Failed to send item to adv queue back");
457 bt_mesh_unref_buf(msg);
458 }
459 }
460 }
461
bt_mesh_adv_send(struct net_buf * buf,const struct bt_mesh_send_cb * cb,void * cb_data)462 void bt_mesh_adv_send(struct net_buf *buf, const struct bt_mesh_send_cb *cb,
463 void *cb_data)
464 {
465 bt_mesh_msg_t msg = {
466 .relay = false,
467 };
468
469 BT_DBG("type 0x%02x len %u: %s", BLE_MESH_ADV(buf)->type, buf->len,
470 bt_hex(buf->data, buf->len));
471
472 BLE_MESH_ADV(buf)->cb = cb;
473 BLE_MESH_ADV(buf)->cb_data = cb_data;
474 BLE_MESH_ADV(buf)->busy = 1U;
475
476 bt_mesh_adv_buf_ref_debug(__func__, buf, 3U, BLE_MESH_BUF_REF_SMALL);
477
478 msg.arg = (void *)net_buf_ref(buf);
479 bt_mesh_task_post(&msg, portMAX_DELAY, false);
480 }
481
bt_mesh_adv_update(void)482 void bt_mesh_adv_update(void)
483 {
484 bt_mesh_msg_t msg = {
485 .relay = false,
486 .arg = NULL,
487 };
488
489 BT_DBG("%s", __func__);
490
491 bt_mesh_task_post(&msg, K_NO_WAIT, false);
492 }
493
494 #if defined(CONFIG_BLE_MESH_RELAY_ADV_BUF)
ignore_relay_packet(uint32_t timestamp)495 static bool ignore_relay_packet(uint32_t timestamp)
496 {
497 uint32_t now = k_uptime_get_32();
498 uint32_t interval = 0U;
499
500 if (now >= timestamp) {
501 interval = now - timestamp;
502 } else {
503 interval = BLE_MESH_MAX_TIME_INTERVAL - (timestamp - now) + 1;
504 }
505
506 return (interval >= BLE_MESH_RELAY_TIME_INTERVAL) ? true : false;
507 }
508
relay_adv_alloc(int id)509 static struct bt_mesh_adv *relay_adv_alloc(int id)
510 {
511 return &relay_adv_pool[id];
512 }
513
bt_mesh_relay_adv_create(enum bt_mesh_adv_type type,uint8_t xmit,int32_t timeout)514 struct net_buf *bt_mesh_relay_adv_create(enum bt_mesh_adv_type type, uint8_t xmit,
515 int32_t timeout)
516 {
517 return bt_mesh_adv_create_from_pool(&relay_adv_buf_pool, relay_adv_alloc, type,
518 xmit, timeout);
519 }
520
ble_mesh_relay_task_post(bt_mesh_msg_t * msg,uint32_t timeout)521 static void ble_mesh_relay_task_post(bt_mesh_msg_t *msg, uint32_t timeout)
522 {
523 QueueSetMemberHandle_t handle = NULL;
524 bt_mesh_msg_t old_msg = {0};
525
526 BT_DBG("%s", __func__);
527
528 if (relay_queue.handle == NULL) {
529 BT_ERR("Invalid relay queue");
530 return;
531 }
532
533 if (xQueueSend(relay_queue.handle, msg, timeout) == pdTRUE) {
534 return;
535 }
536
537 /**
538 * If failed to send packet to the relay queue(queue is full), we will
539 * remove the oldest packet in the queue and put the new one into it.
540 */
541 handle = xQueueSelectFromSet(mesh_queue_set, K_NO_WAIT);
542 if (handle && uxQueueMessagesWaiting(relay_queue.handle)) {
543 BT_INFO("Full queue, remove the oldest relay packet");
544 /* Remove the oldest relay packet from queue */
545 if (xQueueReceive(relay_queue.handle, &old_msg, K_NO_WAIT) != pdTRUE) {
546 BT_ERR("Failed to remove item from relay queue");
547 bt_mesh_unref_buf(msg);
548 return;
549 }
550 /* Unref buf used for the oldest relay packet */
551 bt_mesh_unref_buf(&old_msg);
552 /* Send the latest relay packet to queue */
553 if (xQueueSend(relay_queue.handle, msg, K_NO_WAIT) != pdTRUE) {
554 BT_ERR("Failed to send item to relay queue");
555 bt_mesh_unref_buf(msg);
556 return;
557 }
558 } else {
559 BT_WARN("Empty queue, but failed to send the relay packet");
560 bt_mesh_unref_buf(msg);
561 }
562 }
563
bt_mesh_relay_adv_send(struct net_buf * buf,const struct bt_mesh_send_cb * cb,void * cb_data,uint16_t src,uint16_t dst)564 void bt_mesh_relay_adv_send(struct net_buf *buf, const struct bt_mesh_send_cb *cb,
565 void *cb_data, uint16_t src, uint16_t dst)
566 {
567 bt_mesh_msg_t msg = {
568 .relay = true,
569 };
570
571 BT_DBG("type 0x%02x len %u: %s", BLE_MESH_ADV(buf)->type, buf->len,
572 bt_hex(buf->data, buf->len));
573
574 BLE_MESH_ADV(buf)->cb = cb;
575 BLE_MESH_ADV(buf)->cb_data = cb_data;
576 BLE_MESH_ADV(buf)->busy = 1U;
577
578 msg.arg = (void *)net_buf_ref(buf);
579 msg.src = src;
580 msg.dst = dst;
581 msg.timestamp = k_uptime_get_32();
582 /* Use K_NO_WAIT here, if relay_queue is full return immediately */
583 ble_mesh_relay_task_post(&msg, K_NO_WAIT);
584 }
585
bt_mesh_get_stored_relay_count(void)586 uint16_t bt_mesh_get_stored_relay_count(void)
587 {
588 return (uint16_t)uxQueueMessagesWaiting(relay_queue.handle);
589 }
590 #endif /* #if defined(CONFIG_BLE_MESH_RELAY_ADV_BUF) */
591
bt_mesh_adv_init(void)592 void bt_mesh_adv_init(void)
593 {
594 #if !CONFIG_BLE_MESH_FREERTOS_STATIC_ALLOC
595 adv_queue.handle = xQueueCreate(BLE_MESH_ADV_QUEUE_SIZE, sizeof(bt_mesh_msg_t));
596 __ASSERT(adv_queue.handle, "Failed to create queue");
597 #else /* !CONFIG_BLE_MESH_FREERTOS_STATIC_ALLOC */
598 #if CONFIG_BLE_MESH_FREERTOS_STATIC_ALLOC_EXTERNAL
599 adv_queue.buffer = heap_caps_calloc_prefer(1, sizeof(StaticQueue_t), 2, MALLOC_CAP_SPIRAM|MALLOC_CAP_8BIT, MALLOC_CAP_INTERNAL|MALLOC_CAP_8BIT);
600 #elif CONFIG_BLE_MESH_FREERTOS_STATIC_ALLOC_IRAM_8BIT
601 adv_queue.buffer = heap_caps_calloc_prefer(1, sizeof(StaticQueue_t), 2, MALLOC_CAP_INTERNAL|MALLOC_CAP_IRAM_8BIT, MALLOC_CAP_INTERNAL|MALLOC_CAP_8BIT);
602 #endif
603 __ASSERT(adv_queue.buffer, "Failed to create queue buffer");
604 #if CONFIG_BLE_MESH_FREERTOS_STATIC_ALLOC_EXTERNAL
605 adv_queue.storage = heap_caps_calloc_prefer(1, (BLE_MESH_ADV_QUEUE_SIZE * sizeof(bt_mesh_msg_t)), 2, MALLOC_CAP_SPIRAM|MALLOC_CAP_8BIT, MALLOC_CAP_INTERNAL|MALLOC_CAP_8BIT);
606 #elif CONFIG_BLE_MESH_FREERTOS_STATIC_ALLOC_IRAM_8BIT
607 adv_queue.storage = heap_caps_calloc_prefer(1, (BLE_MESH_ADV_QUEUE_SIZE * sizeof(bt_mesh_msg_t)), 2, MALLOC_CAP_INTERNAL|MALLOC_CAP_IRAM_8BIT, MALLOC_CAP_INTERNAL|MALLOC_CAP_8BIT);
608 #endif
609 __ASSERT(adv_queue.storage, "Failed to create queue storage");
610 adv_queue.handle = xQueueCreateStatic(BLE_MESH_ADV_QUEUE_SIZE, sizeof(bt_mesh_msg_t), (uint8_t*)adv_queue.storage, adv_queue.buffer);
611 __ASSERT(adv_queue.handle, "Failed to create static queue");
612 #endif /* !CONFIG_BLE_MESH_FREERTOS_STATIC_ALLOC */
613
614 #if defined(CONFIG_BLE_MESH_RELAY_ADV_BUF)
615 #if !CONFIG_BLE_MESH_FREERTOS_STATIC_ALLOC
616 relay_queue.handle = xQueueCreate(BLE_MESH_RELAY_QUEUE_SIZE, sizeof(bt_mesh_msg_t));
617 __ASSERT(relay_queue.handle, "Failed to create relay queue");
618 #else /* !CONFIG_BLE_MESH_FREERTOS_STATIC_ALLOC */
619 #if CONFIG_BLE_MESH_FREERTOS_STATIC_ALLOC_EXTERNAL
620 relay_queue.buffer = heap_caps_calloc_prefer(1, sizeof(StaticQueue_t), 2, MALLOC_CAP_SPIRAM|MALLOC_CAP_8BIT, MALLOC_CAP_INTERNAL|MALLOC_CAP_8BIT);
621 #elif CONFIG_BLE_MESH_FREERTOS_STATIC_ALLOC_IRAM_8BIT
622 relay_queue.buffer = heap_caps_calloc_prefer(1, sizeof(StaticQueue_t), 2, MALLOC_CAP_INTERNAL|MALLOC_CAP_IRAM_8BIT, MALLOC_CAP_INTERNAL|MALLOC_CAP_8BIT);
623 #endif
624 __ASSERT(relay_queue.buffer, "Failed to create relay queue buffer");
625 #if CONFIG_BLE_MESH_FREERTOS_STATIC_ALLOC_EXTERNAL
626 relay_queue.storage = heap_caps_calloc_prefer(1, (BLE_MESH_RELAY_QUEUE_SIZE * sizeof(bt_mesh_msg_t)), 2, MALLOC_CAP_SPIRAM|MALLOC_CAP_8BIT, MALLOC_CAP_INTERNAL|MALLOC_CAP_8BIT);
627 #elif CONFIG_BLE_MESH_FREERTOS_STATIC_ALLOC_IRAM_8BIT
628 relay_queue.storage = heap_caps_calloc_prefer(1, (BLE_MESH_RELAY_QUEUE_SIZE * sizeof(bt_mesh_msg_t)), 2, MALLOC_CAP_INTERNAL|MALLOC_CAP_IRAM_8BIT, MALLOC_CAP_INTERNAL|MALLOC_CAP_8BIT);
629 #endif
630 __ASSERT(relay_queue.storage, "Failed to create relay queue storage");
631 relay_queue.handle = xQueueCreateStatic(BLE_MESH_RELAY_QUEUE_SIZE, sizeof(bt_mesh_msg_t), (uint8_t*)relay_queue.storage, relay_queue.buffer);
632 __ASSERT(relay_queue.handle, "Failed to create static relay queue");
633 #endif /* !CONFIG_BLE_MESH_FREERTOS_STATIC_ALLOC */
634
635 mesh_queue_set = xQueueCreateSet(BLE_MESH_QUEUE_SET_SIZE);
636 __ASSERT(mesh_queue_set, "Failed to create queue set");
637 xQueueAddToSet(adv_queue.handle, mesh_queue_set);
638 xQueueAddToSet(relay_queue.handle, mesh_queue_set);
639 #endif /* defined(CONFIG_BLE_MESH_RELAY_ADV_BUF) */
640
641 #if (CONFIG_BLE_MESH_FREERTOS_STATIC_ALLOC_EXTERNAL && \
642 CONFIG_SPIRAM_CACHE_WORKAROUND && \
643 CONFIG_SPIRAM_ALLOW_STACK_EXTERNAL_MEMORY)
644 adv_task.task = heap_caps_calloc(1, sizeof(StaticTask_t), MALLOC_CAP_INTERNAL|MALLOC_CAP_8BIT);
645 __ASSERT(adv_task.task, "Failed to create adv thread task");
646 adv_task.stack = heap_caps_calloc_prefer(1, BLE_MESH_ADV_TASK_STACK_SIZE * sizeof(StackType_t), 2, MALLOC_CAP_SPIRAM|MALLOC_CAP_8BIT, MALLOC_CAP_INTERNAL|MALLOC_CAP_8BIT);
647 __ASSERT(adv_task.stack, "Failed to create adv thread stack");
648 adv_task.handle = xTaskCreateStaticPinnedToCore(adv_thread, BLE_MESH_ADV_TASK_NAME, BLE_MESH_ADV_TASK_STACK_SIZE, NULL,
649 BLE_MESH_ADV_TASK_PRIO, adv_task.stack, adv_task.task, BLE_MESH_ADV_TASK_CORE);
650 __ASSERT(adv_task.handle, "Failed to create static adv thread");
651 #else /* CONFIG_BLE_MESH_FREERTOS_STATIC_ALLOC_EXTERNAL && CONFIG_SPIRAM_CACHE_WORKAROUND && CONFIG_SPIRAM_ALLOW_STACK_EXTERNAL_MEMORY */
652 int ret = xTaskCreatePinnedToCore(adv_thread, BLE_MESH_ADV_TASK_NAME, BLE_MESH_ADV_TASK_STACK_SIZE, NULL,
653 BLE_MESH_ADV_TASK_PRIO, &adv_task.handle, BLE_MESH_ADV_TASK_CORE);
654 __ASSERT(ret == pdTRUE, "Failed to create adv thread");
655 #endif /* CONFIG_BLE_MESH_FREERTOS_STATIC_ALLOC_EXTERNAL && CONFIG_SPIRAM_CACHE_WORKAROUND && CONFIG_SPIRAM_ALLOW_STACK_EXTERNAL_MEMORY */
656 }
657
658 #if CONFIG_BLE_MESH_DEINIT
bt_mesh_adv_deinit(void)659 void bt_mesh_adv_deinit(void)
660 {
661 if (adv_queue.handle == NULL) {
662 return;
663 }
664
665 vTaskDelete(adv_task.handle);
666 adv_task.handle = NULL;
667 #if (CONFIG_BLE_MESH_FREERTOS_STATIC_ALLOC_EXTERNAL && \
668 CONFIG_SPIRAM_CACHE_WORKAROUND && \
669 CONFIG_SPIRAM_ALLOW_STACK_EXTERNAL_MEMORY)
670 heap_caps_free(adv_task.stack);
671 adv_task.stack = NULL;
672 heap_caps_free(adv_task.task);
673 adv_task.task = NULL;
674 #endif
675
676 #if defined(CONFIG_BLE_MESH_RELAY_ADV_BUF)
677 xQueueRemoveFromSet(adv_queue.handle, mesh_queue_set);
678 xQueueRemoveFromSet(relay_queue.handle, mesh_queue_set);
679
680 vQueueDelete(relay_queue.handle);
681 relay_queue.handle = NULL;
682 #if CONFIG_BLE_MESH_FREERTOS_STATIC_ALLOC
683 heap_caps_free(relay_queue.buffer);
684 relay_queue.buffer = NULL;
685 heap_caps_free(relay_queue.storage);
686 relay_queue.storage = NULL;
687 #endif
688
689 bt_mesh_unref_buf_from_pool(&relay_adv_buf_pool);
690 memset(relay_adv_pool, 0, sizeof(relay_adv_pool));
691
692 vQueueDelete(mesh_queue_set);
693 mesh_queue_set = NULL;
694 #endif /* defined(CONFIG_BLE_MESH_RELAY_ADV_BUF) */
695
696 vQueueDelete(adv_queue.handle);
697 adv_queue.handle = NULL;
698 #if CONFIG_BLE_MESH_FREERTOS_STATIC_ALLOC
699 heap_caps_free(adv_queue.buffer);
700 adv_queue.buffer = NULL;
701 heap_caps_free(adv_queue.storage);
702 adv_queue.storage = NULL;
703 #endif
704
705 bt_mesh_unref_buf_from_pool(&adv_buf_pool);
706 memset(adv_pool, 0, sizeof(adv_pool));
707
708 #if CONFIG_BLE_MESH_SUPPORT_BLE_ADV
709 bt_mesh_ble_adv_deinit();
710 #endif
711 }
712 #endif /* CONFIG_BLE_MESH_DEINIT */
713
714 #if CONFIG_BLE_MESH_SUPPORT_BLE_ADV
ble_adv_alloc(int id)715 static struct bt_mesh_adv *ble_adv_alloc(int id)
716 {
717 return &ble_adv_pool[id];
718 }
719
bt_mesh_ble_adv_create(enum bt_mesh_adv_type type,uint8_t xmit,int32_t timeout)720 static struct net_buf *bt_mesh_ble_adv_create(enum bt_mesh_adv_type type, uint8_t xmit, int32_t timeout)
721 {
722 return bt_mesh_adv_create_from_pool(&ble_adv_buf_pool, ble_adv_alloc, type,
723 xmit, timeout);
724 }
725
bt_mesh_ble_adv_send(struct net_buf * buf,const struct bt_mesh_send_cb * cb,void * cb_data,bool front)726 static void bt_mesh_ble_adv_send(struct net_buf *buf, const struct bt_mesh_send_cb *cb,
727 void *cb_data, bool front)
728 {
729 bt_mesh_msg_t msg = {
730 .relay = false,
731 };
732
733 BT_DBG("type 0x%02x len %u: %s", BLE_MESH_ADV(buf)->type, buf->len,
734 bt_hex(buf->data, buf->len));
735
736 BLE_MESH_ADV(buf)->cb = cb;
737 BLE_MESH_ADV(buf)->cb_data = cb_data;
738 BLE_MESH_ADV(buf)->busy = 1U;
739
740 bt_mesh_adv_buf_ref_debug(__func__, buf, 3U, BLE_MESH_BUF_REF_SMALL);
741
742 msg.arg = (void *)net_buf_ref(buf);
743 bt_mesh_task_post(&msg, portMAX_DELAY, front);
744 }
745
ble_adv_tx_reset(struct ble_adv_tx * tx,bool unref)746 static void ble_adv_tx_reset(struct ble_adv_tx *tx, bool unref)
747 {
748 if (tx->buf == NULL) {
749 return;
750 }
751
752 if (bt_mesh_atomic_test_bit(tx->flags, TIMER_INIT)) {
753 k_delayed_work_free(&tx->resend);
754 }
755 bt_mesh_atomic_set(tx->flags, 0);
756 memset(&tx->param, 0, sizeof(tx->param));
757 BLE_MESH_ADV(tx->buf)->busy = 0U;
758 if (unref) {
759 net_buf_unref(tx->buf);
760 }
761 tx->buf = NULL;
762 }
763
ble_adv_send_start(uint16_t duration,int err,void * cb_data)764 static void ble_adv_send_start(uint16_t duration, int err, void *cb_data)
765 {
766 struct ble_adv_tx *tx = cb_data;
767
768 BT_DBG("%s, duration %d, err %d", __func__, duration, err);
769
770 /* If failed to send BLE adv packet, and param->count is not 0
771 * which means the timer has been initialized, here we need to
772 * free the timer.
773 */
774 if (err) {
775 ble_adv_tx_reset(tx, true);
776 }
777 }
778
ble_adv_send_end(int err,void * cb_data)779 static void ble_adv_send_end(int err, void *cb_data)
780 {
781 struct ble_adv_tx *tx = cb_data;
782
783 BT_DBG("%s, err %d", __func__, err);
784
785 if (err) {
786 ble_adv_tx_reset(tx, true);
787 return;
788 }
789
790 if (tx->param.count) {
791 if (tx->param.period) {
792 k_delayed_work_submit(&tx->resend, tx->param.period);
793 } else {
794 k_work_submit(&tx->resend.work);
795 }
796 } else {
797 ble_adv_tx_reset(tx, true);
798 }
799 }
800
801 static struct bt_mesh_send_cb ble_adv_send_cb = {
802 .start = ble_adv_send_start,
803 .end = ble_adv_send_end,
804 };
805
ble_adv_resend(struct k_work * work)806 static void ble_adv_resend(struct k_work *work)
807 {
808 struct ble_adv_tx *tx = CONTAINER_OF(work, struct ble_adv_tx, resend.work);
809 bool front = false;
810
811 if (tx->buf == NULL) {
812 /* The advertising has been cancelled */
813 return;
814 }
815
816 front = (tx->param.priority == BLE_MESH_BLE_ADV_PRIO_HIGH) ? true : false;
817 bt_mesh_ble_adv_send(tx->buf, &ble_adv_send_cb, tx, front);
818
819 if (tx->param.count == SEND_BLE_ADV_INFINITE) {
820 /* Send the BLE advertising packet infinitely */
821 return;
822 }
823
824 if (tx->param.count > 0U) {
825 tx->param.count--;
826 }
827 }
828
bt_mesh_start_ble_advertising(const struct bt_mesh_ble_adv_param * param,const struct bt_mesh_ble_adv_data * data,uint8_t * index)829 int bt_mesh_start_ble_advertising(const struct bt_mesh_ble_adv_param *param,
830 const struct bt_mesh_ble_adv_data *data, uint8_t *index)
831 {
832 struct ble_adv_tx *tx = NULL;
833 struct net_buf *buf = NULL;
834 bool front = false;
835
836 if (param == NULL || index == NULL) {
837 BT_ERR("%s, Invalid parameter", __func__);
838 return -EINVAL;
839 }
840
841 if (param->adv_type != BLE_MESH_ADV_DIRECT_IND &&
842 (param->interval < 0x20 || param->interval > 0x4000)) {
843 BT_ERR("Invalid adv interval 0x%04x", param->interval);
844 return -EINVAL;
845 }
846
847 if (param->adv_type > BLE_MESH_ADV_DIRECT_IND_LOW_DUTY) {
848 BT_ERR("Invalid adv type 0x%02x", param->adv_type);
849 return -EINVAL;
850 }
851
852 if (param->own_addr_type > BLE_MESH_ADDR_RANDOM_ID) {
853 BT_ERR("Invalid own addr type 0x%02x", param->own_addr_type);
854 return -EINVAL;
855 }
856
857 if ((param->own_addr_type == BLE_MESH_ADDR_PUBLIC_ID ||
858 param->own_addr_type == BLE_MESH_ADDR_RANDOM_ID ||
859 param->adv_type == BLE_MESH_ADV_DIRECT_IND ||
860 param->adv_type == BLE_MESH_ADV_DIRECT_IND_LOW_DUTY) &&
861 param->peer_addr_type > BLE_MESH_ADDR_RANDOM) {
862 BT_ERR("Invalid peer addr type 0x%02x", param->peer_addr_type);
863 return -EINVAL;
864 }
865
866 if (data && (data->adv_data_len > 31 || data->scan_rsp_data_len > 31)) {
867 BT_ERR("Invalid adv data length (adv %d, scan rsp %d)",
868 data->adv_data_len, data->scan_rsp_data_len);
869 return -EINVAL;
870 }
871
872 if (param->priority > BLE_MESH_BLE_ADV_PRIO_HIGH) {
873 BT_ERR("Invalid adv priority %d", param->priority);
874 return -EINVAL;
875 }
876
877 if (param->duration < ADV_SCAN_INT(param->interval)) {
878 BT_ERR("Too small duration %dms", param->duration);
879 return -EINVAL;
880 }
881
882 buf = bt_mesh_ble_adv_create(BLE_MESH_ADV_BLE, 0U, K_NO_WAIT);
883 if (!buf) {
884 BT_ERR("No empty ble adv buffer");
885 return -ENOBUFS;
886 }
887
888 /* Set advertising data and scan response data */
889 memset(buf->data, 0, buf->size);
890 if (data) {
891 net_buf_add_u8(buf, data->adv_data_len);
892 if (data->adv_data_len) {
893 net_buf_add_mem(buf, data->adv_data, data->adv_data_len);
894 }
895 net_buf_add_u8(buf, data->scan_rsp_data_len);
896 if (data->scan_rsp_data_len) {
897 net_buf_add_mem(buf, data->scan_rsp_data, data->scan_rsp_data_len);
898 }
899 }
900
901 *index = net_buf_id(buf);
902 tx = &ble_adv_tx[*index];
903 tx->buf = buf;
904 memcpy(&tx->param, param, sizeof(tx->param));
905
906 front = (tx->param.priority == BLE_MESH_BLE_ADV_PRIO_HIGH) ? true : false;
907 bt_mesh_ble_adv_send(buf, &ble_adv_send_cb, tx, front);
908 if (param->count) {
909 if (k_delayed_work_init(&tx->resend, ble_adv_resend)) {
910 /* If failed to create a timer, the BLE adv packet will be
911 * sent only once. Just give a warning here, and since the
912 * BLE adv packet can be sent, return 0 here.
913 */
914 BT_WARN("Send BLE adv packet only once");
915 tx->param.count = 0;
916 net_buf_unref(buf);
917 return 0;
918 }
919 bt_mesh_atomic_set_bit(tx->flags, TIMER_INIT);
920 } else {
921 /* Send the BLE advertising packet only once */
922 net_buf_unref(buf);
923 }
924
925 return 0;
926 }
927
bt_mesh_stop_ble_advertising(uint8_t index)928 int bt_mesh_stop_ble_advertising(uint8_t index)
929 {
930 struct ble_adv_tx *tx = NULL;
931 bool unref = true;
932
933 if (index >= ARRAY_SIZE(ble_adv_tx)) {
934 BT_ERR("Invalid adv index %d", index);
935 return -EINVAL;
936 }
937
938 tx = &ble_adv_tx[index];
939
940 if (tx->buf == NULL) {
941 BT_WARN("Already stopped, index %d", index);
942 return 0;
943 }
944
945 /* busy 1, ref 1; busy 1, ref 2;
946 * busy 0, ref 0; busy 0, ref 1;
947 */
948 if (BLE_MESH_ADV(tx->buf)->busy == 1U &&
949 tx->buf->ref == 1U) {
950 unref = false;
951 }
952 ble_adv_tx_reset(tx, unref);
953
954 return 0;
955 }
956
957 #if CONFIG_BLE_MESH_DEINIT
bt_mesh_ble_adv_deinit(void)958 static void bt_mesh_ble_adv_deinit(void)
959 {
960 for (int i = 0; i < ARRAY_SIZE(ble_adv_tx); i++) {
961 struct ble_adv_tx *tx = &ble_adv_tx[i];
962 ble_adv_tx_reset(tx, false);
963 }
964 bt_mesh_unref_buf_from_pool(&ble_adv_buf_pool);
965 memset(ble_adv_pool, 0, sizeof(ble_adv_pool));
966 }
967 #endif /* CONFIG_BLE_MESH_DEINIT */
968 #endif /* CONFIG_BLE_MESH_SUPPORT_BLE_ADV */
969