diff --git a/components/bt/CMakeLists.txt b/components/bt/CMakeLists.txt index 36837c6812a..77493be647d 100644 --- a/components/bt/CMakeLists.txt +++ b/components/bt/CMakeLists.txt @@ -501,13 +501,15 @@ if(CONFIG_BT_ENABLED) "esp_ble_mesh/common/common.c" "esp_ble_mesh/common/kernel.c" "esp_ble_mesh/common/mutex.c" + "esp_ble_mesh/common/queue.c" "esp_ble_mesh/common/timer.c" "esp_ble_mesh/common/utils.c" "esp_ble_mesh/core/storage/settings_nvs.c" "esp_ble_mesh/core/storage/settings_uid.c" "esp_ble_mesh/core/storage/settings.c" "esp_ble_mesh/core/access.c" - "esp_ble_mesh/core/adv.c" + "esp_ble_mesh/core/adv_common.c" + "esp_ble_mesh/core/ble_adv.c" "esp_ble_mesh/core/beacon.c" "esp_ble_mesh/core/cfg_cli.c" "esp_ble_mesh/core/cfg_srv.c" @@ -579,6 +581,11 @@ if(CONFIG_BT_ENABLED) list(APPEND srcs "esp_ble_mesh/core/transport.c") endif() + if(CONFIG_BLE_MESH_SUPPORT_MULTI_ADV) + list(APPEND srcs "esp_ble_mesh/core/ext_adv.c") + else() + list(APPEND srcs "esp_ble_mesh/core/adv.c") + endif() endif() diff --git a/components/bt/esp_ble_mesh/Kconfig.in b/components/bt/esp_ble_mesh/Kconfig.in index a6895aa9134..e805231edc6 100644 --- a/components/bt/esp_ble_mesh/Kconfig.in +++ b/components/bt/esp_ble_mesh/Kconfig.in @@ -34,6 +34,63 @@ if BLE_MESH help This option to enable BLE Mesh using some BLE 5.0 APIs. + config BLE_MESH_ADV_INST_ID + depends on BLE_MESH_USE_BLE_50 + int "Extended adv instance for Mesh normal packets" + default 0 + range 0 3 + help + Extended ADV instance used by Mesh normal advertising packets. + + menuconfig BLE_MESH_SUPPORT_MULTI_ADV + bool "Support using multiple adv instance for BLE Mesh" + depends on BLE_MESH_USE_BLE_50 + default n + help + Enable this option to support using multiple adv instance while running BLE Mesh. + + config BLE_MESH_PROXY_ADV_INST_ID + int "Extended adv instance for Mesh proxy packets" + depends on BLE_MESH_PROXY + depends on (BLE_MESH_PB_GATT || BLE_MESH_GATT_PROXY_SERVER) + depends on BLE_MESH_SUPPORT_MULTI_ADV + default 1 + range 0 3 + help + Extended ADV instance used by Mesh proxy advertising packets. + + menuconfig BLE_MESH_SEPARATE_RELAY_ADV_INSTANCE + bool "Use separate extended adv instance for Mesh relay packets" + depends on BLE_MESH_SUPPORT_MULTI_ADV + depends on BLE_MESH_RELAY_ADV_BUF + default n + help + Enable this option to support using a separate extended ADV instance for Mesh relay packets. + + config BLE_MESH_RELAY_ADV_INST_ID + int "Extended adv instance for Mesh relay packets" + depends on BLE_MESH_SEPARATE_RELAY_ADV_INSTANCE + default 2 + range 0 3 + help + Extended ADV instance used by Mesh relay advertising packets. + + menuconfig BLE_MESH_SEPARATE_BLE_ADV_INSTANCE + bool "Use separate extended adv instance for BLE normal packets" + depends on BLE_MESH_SUPPORT_MULTI_ADV + depends on BLE_MESH_SUPPORT_BLE_ADV + default n + help + Enable this option to support using a separate extended ADV instance for normal BLE advertising packets. + + config BLE_MESH_BLE_ADV_INST_ID + int "Extended adv instance for normal BLE packets" + depends on BLE_MESH_SEPARATE_BLE_ADV_INSTANCE + default 3 + range 0 3 + help + Extended ADV instance used by normal BLE advertising packets. + config BLE_MESH_USE_DUPLICATE_SCAN bool "Support Duplicate Scan in BLE Mesh" select BTDM_BLE_SCAN_DUPL if IDF_TARGET_ESP32 diff --git a/components/bt/esp_ble_mesh/common/include/mesh/mutex.h b/components/bt/esp_ble_mesh/common/include/mesh/mutex.h index ee89750029f..0cc47eb01a0 100644 --- a/components/bt/esp_ble_mesh/common/include/mesh/mutex.h +++ b/components/bt/esp_ble_mesh/common/include/mesh/mutex.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2017-2021 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2017-2024 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -32,6 +32,11 @@ void bt_mesh_r_mutex_free(bt_mesh_mutex_t *mutex); void bt_mesh_r_mutex_lock(bt_mesh_mutex_t *mutex); void bt_mesh_r_mutex_unlock(bt_mesh_mutex_t *mutex); +void bt_mesh_c_semaphore_create(bt_mesh_mutex_t *mutex, int max, int init); +void bt_mesh_c_semaphore_free(bt_mesh_mutex_t *mutex); +void bt_mesh_c_semaphore_give(bt_mesh_mutex_t *mutex); +void bt_mesh_c_semaphore_take(bt_mesh_mutex_t *mutex, uint32_t timeout); + void bt_mesh_alarm_lock(void); void bt_mesh_alarm_unlock(void); diff --git a/components/bt/esp_ble_mesh/common/include/mesh/queue.h b/components/bt/esp_ble_mesh/common/include/mesh/queue.h new file mode 100644 index 00000000000..8ec7a5c678d --- /dev/null +++ b/components/bt/esp_ble_mesh/common/include/mesh/queue.h @@ -0,0 +1,33 @@ +/* + * SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef _BLE_MESH_QUEUE_H_ +#define _BLE_MESH_QUEUE_H_ + +#include "mesh/kernel.h" +#include "mesh/slist.h" +#include "mesh/atomic.h" + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct { + QueueHandle_t handle; +#if CONFIG_BLE_MESH_FREERTOS_STATIC_ALLOC + StaticQueue_t *buffer; + uint8_t *storage; +#endif +} bt_mesh_queue_t; + +int bt_mesh_queue_init(bt_mesh_queue_t *queue, uint8_t queue_size, uint8_t item_size); +int bt_mesh_queue_deinit(bt_mesh_queue_t *queue); + +#ifdef __cplusplus +} +#endif + +#endif /* _BLE_MESH_QUEUE_H_ */ diff --git a/components/bt/esp_ble_mesh/common/mutex.c b/components/bt/esp_ble_mesh/common/mutex.c index 6c3b2bf6f72..3a3dedb80d4 100644 --- a/components/bt/esp_ble_mesh/common/mutex.c +++ b/components/bt/esp_ble_mesh/common/mutex.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2017-2021 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2017-2024 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -125,6 +125,57 @@ void bt_mesh_r_mutex_unlock(bt_mesh_mutex_t *mutex) } } +void bt_mesh_c_semaphore_free(bt_mesh_mutex_t *mutex) +{ + bt_mesh_mutex_free(mutex); +} + +void bt_mesh_c_semaphore_create(bt_mesh_mutex_t *mutex, int max, int init) +{ + if (!mutex) { + BT_ERR("Create, invalid mutex"); + return; + } + +#if CONFIG_BLE_MESH_FREERTOS_STATIC_ALLOC +#if CONFIG_BLE_MESH_FREERTOS_STATIC_ALLOC_EXTERNAL + mutex->buffer = heap_caps_calloc_prefer(1, sizeof(StaticQueue_t), 2, MALLOC_CAP_SPIRAM|MALLOC_CAP_8BIT, MALLOC_CAP_INTERNAL|MALLOC_CAP_8BIT); +#elif CONFIG_BLE_MESH_FREERTOS_STATIC_ALLOC_IRAM_8BIT + mutex->buffer = heap_caps_calloc_prefer(1, sizeof(StaticQueue_t), 2, MALLOC_CAP_INTERNAL|MALLOC_CAP_IRAM_8BIT, MALLOC_CAP_INTERNAL|MALLOC_CAP_8BIT); +#endif + __ASSERT(mutex->buffer, "Failed to create counting semaphore buffer"); + mutex->mutex = xSemaphoreCreateCountingStatic(max, init, mutex->buffer); + __ASSERT(mutex->mutex, "Failed to create static counting semaphore"); +#else /* CONFIG_BLE_MESH_FREERTOS_STATIC_ALLOC */ + mutex->mutex = xSemaphoreCreateCounting(max, init); + __ASSERT(mutex->mutex, "Failed to create counting semaphore"); +#endif /* CONFIG_BLE_MESH_FREERTOS_STATIC_ALLOC */ +} + +void bt_mesh_c_semaphore_take(bt_mesh_mutex_t *mutex, uint32_t timeout) +{ + if (!mutex) { + BT_ERR("Lock, invalid counting semaphore"); + return; + } + + if (mutex->mutex) { + xSemaphoreTake(mutex->mutex, timeout / portTICK_PERIOD_MS); + } +} + +void bt_mesh_c_semaphore_give(bt_mesh_mutex_t *mutex) +{ + if (!mutex) { + BT_ERR("Unlock, invalid counting semaphore"); + return; + } + + if (mutex->mutex) { + xSemaphoreGive(mutex->mutex); + } +} + void bt_mesh_alarm_lock(void) { bt_mesh_mutex_lock(&alarm_lock); diff --git a/components/bt/esp_ble_mesh/common/queue.c b/components/bt/esp_ble_mesh/common/queue.c new file mode 100644 index 00000000000..3f44843ca1c --- /dev/null +++ b/components/bt/esp_ble_mesh/common/queue.c @@ -0,0 +1,48 @@ +/* + * SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "mesh/common.h" +#include "mesh/queue.h" + +int bt_mesh_queue_init(bt_mesh_queue_t *queue, uint8_t queue_size, uint8_t item_size) +{ + __ASSERT(queue && queue_size && item_size, "Invalid queue init parameters"); + +#if !CONFIG_BLE_MESH_FREERTOS_STATIC_ALLOC + queue->handle = xQueueCreate(queue_size, item_size); + __ASSERT(queue->handle, "Failed to create queue"); +#else /* !CONFIG_BLE_MESH_FREERTOS_STATIC_ALLOC */ +#if CONFIG_BLE_MESH_FREERTOS_STATIC_ALLOC_EXTERNAL + queue->buffer = heap_caps_calloc_prefer(1, sizeof(StaticQueue_t), 2, MALLOC_CAP_SPIRAM|MALLOC_CAP_8BIT, MALLOC_CAP_INTERNAL|MALLOC_CAP_8BIT); +#elif CONFIG_BLE_MESH_FREERTOS_STATIC_ALLOC_IRAM_8BIT + queue->buffer = heap_caps_calloc_prefer(1, sizeof(StaticQueue_t), 2, MALLOC_CAP_INTERNAL|MALLOC_CAP_IRAM_8BIT, MALLOC_CAP_INTERNAL|MALLOC_CAP_8BIT); +#endif + __ASSERT(queue->buffer, "Failed to create queue buffer"); +#if CONFIG_BLE_MESH_FREERTOS_STATIC_ALLOC_EXTERNAL + queue->storage = heap_caps_calloc_prefer(1, (queue_size * item_size), 2, MALLOC_CAP_SPIRAM|MALLOC_CAP_8BIT, MALLOC_CAP_INTERNAL|MALLOC_CAP_8BIT); +#elif CONFIG_BLE_MESH_FREERTOS_STATIC_ALLOC_IRAM_8BIT + queue->storage = heap_caps_calloc_prefer(1, (queue_size * item_size), 2, MALLOC_CAP_INTERNAL|MALLOC_CAP_IRAM_8BIT, MALLOC_CAP_INTERNAL|MALLOC_CAP_8BIT); +#endif + __ASSERT(queue->storage, "Failed to create queue storage"); + queue->handle = xQueueCreateStatic(queue_size, item_size, (uint8_t*)queue->storage, queue->buffer); + __ASSERT(queue->handle, "Failed to create static queue"); +#endif /* !CONFIG_BLE_MESH_FREERTOS_STATIC_ALLOC */ + return 0; +} + +int bt_mesh_queue_deinit(bt_mesh_queue_t *queue) +{ + __ASSERT(queue, "Invalid queue init parameters"); + vQueueDelete(queue->handle); + queue->handle = NULL; +#if CONFIG_BLE_MESH_FREERTOS_STATIC_ALLOC + heap_caps_free(queue->buffer); + queue->buffer = NULL; + heap_caps_free(queue->storage); + queue->storage = NULL; +#endif + return 0; +} diff --git a/components/bt/esp_ble_mesh/core/adv.c b/components/bt/esp_ble_mesh/core/adv.c index 70341bbfa42..34639fadc7d 100644 --- a/components/bt/esp_ble_mesh/core/adv.c +++ b/components/bt/esp_ble_mesh/core/adv.c @@ -23,158 +23,20 @@ #include "proxy_client.h" #include "prov_pvnr.h" #include "mesh/adapter.h" +#include "adv_common.h" +#include "ble_adv.h" -/* Convert from ms to 0.625ms units */ -#define ADV_SCAN_UNIT(_ms) ((_ms) * 8 / 5) -/* Convert from 0.625ms units to interval(ms) */ -#define ADV_SCAN_INT(val) ((val) * 5 / 8) - -/* Pre-5.0 controllers enforce a minimum interval of 100ms - * whereas 5.0+ controllers can go down to 20ms. - */ -#if CONFIG_BLE_MESH_HCI_5_0 -#define ADV_ITVL_MIN 20 -#else -#define ADV_ITVL_MIN 100 -#endif - -static const uint8_t adv_type[] = { - [BLE_MESH_ADV_PROV] = BLE_MESH_DATA_MESH_PROV, - [BLE_MESH_ADV_DATA] = BLE_MESH_DATA_MESH_MESSAGE, - [BLE_MESH_ADV_BEACON] = BLE_MESH_DATA_MESH_BEACON, - [BLE_MESH_ADV_URI] = BLE_MESH_DATA_URI, -}; - -#if CONFIG_BLE_MESH_USE_BLE_50 -#define ESP_BLE_MESH_INST_UNUSED_ELT_(IDX, _) [IDX] = {.id = IDX} - -static struct bt_mesh_adv_inst adv_insts[BLE_MESH_ADV_INS_CNT] = { - LISTIFY(BLE_MESH_ADV_INS_CNT, ESP_BLE_MESH_INST_UNUSED_ELT_, (,)), -}; -#endif - -NET_BUF_POOL_DEFINE(adv_buf_pool, CONFIG_BLE_MESH_ADV_BUF_COUNT, - BLE_MESH_ADV_DATA_SIZE, BLE_MESH_ADV_USER_DATA_SIZE, NULL); - -static struct bt_mesh_adv adv_pool[CONFIG_BLE_MESH_ADV_BUF_COUNT]; - -struct bt_mesh_queue { - QueueHandle_t handle; -#if CONFIG_BLE_MESH_FREERTOS_STATIC_ALLOC - StaticQueue_t *buffer; - uint8_t *storage; -#endif -}; - -static struct bt_mesh_queue adv_queue; -/* We reserve one queue item for bt_mesh_adv_update() */ -#if CONFIG_BLE_MESH_SUPPORT_BLE_ADV -#define BLE_MESH_ADV_QUEUE_SIZE (CONFIG_BLE_MESH_ADV_BUF_COUNT + CONFIG_BLE_MESH_BLE_ADV_BUF_COUNT + 1) -#else -#define BLE_MESH_ADV_QUEUE_SIZE (CONFIG_BLE_MESH_ADV_BUF_COUNT + 1) -#endif +static struct bt_mesh_adv_queue *adv_queue; #if CONFIG_BLE_MESH_RELAY_ADV_BUF -NET_BUF_POOL_DEFINE(relay_adv_buf_pool, CONFIG_BLE_MESH_RELAY_ADV_BUF_COUNT, - BLE_MESH_ADV_DATA_SIZE, BLE_MESH_ADV_USER_DATA_SIZE, NULL); -static struct bt_mesh_adv relay_adv_pool[CONFIG_BLE_MESH_RELAY_ADV_BUF_COUNT]; - -static struct bt_mesh_queue relay_queue; #define BLE_MESH_RELAY_QUEUE_SIZE CONFIG_BLE_MESH_RELAY_ADV_BUF_COUNT static QueueSetHandle_t mesh_queue_set; #define BLE_MESH_QUEUE_SET_SIZE (BLE_MESH_ADV_QUEUE_SIZE + BLE_MESH_RELAY_QUEUE_SIZE) -#define BLE_MESH_RELAY_TIME_INTERVAL K_SECONDS(6) -#define BLE_MESH_MAX_TIME_INTERVAL 0xFFFFFFFF - -static bool ignore_relay_packet(uint32_t timestamp); #endif /* CONFIG_BLE_MESH_RELAY_ADV_BUF */ -#if CONFIG_BLE_MESH_SUPPORT_BLE_ADV -/* length + advertising data + length + scan response data */ -NET_BUF_POOL_DEFINE(ble_adv_buf_pool, CONFIG_BLE_MESH_BLE_ADV_BUF_COUNT, - ((BLE_MESH_ADV_DATA_SIZE + 3) << 1), BLE_MESH_ADV_USER_DATA_SIZE, NULL); - -static struct bt_mesh_adv ble_adv_pool[CONFIG_BLE_MESH_BLE_ADV_BUF_COUNT]; - -enum { - TIMER_INIT, /* Resend timer is initialized */ - NUM_FLAGS, -}; - -static struct ble_adv_tx { - struct bt_mesh_ble_adv_param param; - struct net_buf *buf; - struct k_delayed_work resend; - BLE_MESH_ATOMIC_DEFINE(flags, NUM_FLAGS); -} ble_adv_tx[CONFIG_BLE_MESH_BLE_ADV_BUF_COUNT]; - -#define SEND_BLE_ADV_INFINITE 0xFFFF - -#if CONFIG_BLE_MESH_DEINIT -static void bt_mesh_ble_adv_deinit(void); -#endif /* CONFIG_BLE_MESH_DEINIT */ -#endif /* CONFIG_BLE_MESH_SUPPORT_BLE_ADV */ - -struct bt_mesh_adv_task { - TaskHandle_t handle; -#if (CONFIG_BLE_MESH_FREERTOS_STATIC_ALLOC_EXTERNAL && \ - (CONFIG_SPIRAM_CACHE_WORKAROUND || !CONFIG_IDF_TARGET_ESP32) && \ - CONFIG_SPIRAM_ALLOW_STACK_EXTERNAL_MEMORY) - StaticTask_t *task; - StackType_t *stack; -#endif -}; - -static struct bt_mesh_adv_task adv_task; - -#if CONFIG_BLE_MESH_USE_BLE_50 -bool bt_mesh_is_adv_inst_used(uint8_t adv_inst_id) -{ - uint8_t i; - - for (i = 0; i < ARRAY_SIZE(adv_insts); i++) { - if (adv_insts[i].id == adv_inst_id) { - return true; - } - } - return false; -} - -uint8_t bt_mesh_get_proxy_inst(void) -{ - return adv_insts[0].id; -} - -void bt_mesh_adv_inst_deinit(void) -{ - uint8_t i; - - for (i = 0; i < ARRAY_SIZE(adv_insts); i++) { - bt_le_ext_adv_stop(adv_insts[i].id); - } - return; -} -#endif - -static struct bt_mesh_adv *adv_alloc(int id) -{ - return &adv_pool[id]; -} - -int ble_mesh_adv_task_wakeup(uint16_t adv_inst_id) -{ - xTaskNotify(adv_task.handle, BIT(adv_inst_id), eSetBits); - return 0; -} - -static inline bool ble_mesh_adv_task_wait(uint32_t timeout, uint32_t *notify) -{ - return xTaskNotifyWait(UINT32_MAX, UINT32_MAX, notify, timeout) == pdTRUE; -} - static inline void adv_send_start(uint16_t duration, int err, const struct bt_mesh_send_cb *cb, void *cb_data) @@ -192,27 +54,8 @@ static inline void adv_send_end(int err, const struct bt_mesh_send_cb *cb, } } -uint16_t bt_mesh_pdu_duration(uint8_t xmit) -{ - uint16_t duration = 0U; - uint16_t adv_int = 0U; - - adv_int = MAX(ADV_ITVL_MIN, BLE_MESH_TRANSMIT_INT(xmit)); - duration = (BLE_MESH_TRANSMIT_COUNT(xmit) + 1) * (adv_int + 10); - - return duration; -} - -static inline TickType_t K_WAIT(int32_t val) -{ - return (val == K_FOREVER) ? portMAX_DELAY : (val / portTICK_PERIOD_MS); -} - static inline int adv_send(struct net_buf *buf) { -#if CONFIG_BLE_MESH_USE_BLE_50 - struct bt_mesh_adv_inst *adv_ins = &adv_insts[0]; -#endif const struct bt_mesh_send_cb *cb = BLE_MESH_ADV(buf)->cb; void *cb_data = BLE_MESH_ADV(buf)->cb_data; struct bt_mesh_adv_param param = {0}; @@ -259,7 +102,7 @@ static inline int adv_send(struct net_buf *buf) #if CONFIG_BLE_MESH_USE_BLE_50 param.primary_phy = BLE_MESH_ADV_PHY_1M; param.secondary_phy = BLE_MESH_ADV_PHY_1M; - err = bt_le_ext_adv_start(adv_ins->id, ¶m, &ad, 3, NULL, 0); + err = bt_le_ext_adv_start(CONFIG_BLE_MESH_ADV_INST_ID, ¶m, &ad, 3, NULL, 0); #else /* CONFIG_BLE_MESH_USE_BLE_50 */ err = bt_le_adv_start(¶m, &ad, 3, NULL, 0); #endif /* CONFIG_BLE_MESH_USE_BLE_50 */ @@ -270,7 +113,7 @@ static inline int adv_send(struct net_buf *buf) #if CONFIG_BLE_MESH_USE_BLE_50 param.primary_phy = BLE_MESH_ADV_PHY_1M; param.secondary_phy = BLE_MESH_ADV_PHY_1M; - err = bt_le_ext_adv_start(adv_ins->id, ¶m, &ad, 1, NULL, 0); + err = bt_le_ext_adv_start(CONFIG_BLE_MESH_ADV_INST_ID, ¶m, &ad, 1, NULL, 0); #else /* CONFIG_BLE_MESH_USE_BLE_50 */ err = bt_le_adv_start(¶m, &ad, 1, NULL, 0); #endif /* CONFIG_BLE_MESH_USE_BLE_50 */ @@ -278,7 +121,7 @@ static inline int adv_send(struct net_buf *buf) #if CONFIG_BLE_MESH_SUPPORT_BLE_ADV } else { struct bt_mesh_ble_adv_data data = {0}; - struct ble_adv_tx *tx = cb_data; + struct bt_mesh_ble_adv_tx *tx = cb_data; if (tx == NULL) { BT_ERR("Invalid adv user data"); @@ -303,7 +146,7 @@ static inline int adv_send(struct net_buf *buf) bt_mesh_adv_buf_ref_debug(__func__, buf, 3U, BLE_MESH_BUF_REF_SMALL); #if CONFIG_BLE_MESH_USE_BLE_50 - err = bt_mesh_ble_ext_adv_start(adv_ins->id, &tx->param, &data); + err = bt_mesh_ble_ext_adv_start(CONFIG_BLE_MESH_ADV_INST_ID, &tx->param, &data); #else /* CONFIG_BLE_MESH_USE_BLE_50 */ err = bt_mesh_ble_adv_start(&tx->param, &data); #endif /* CONFIG_BLE_MESH_USE_BLE_50 */ @@ -320,12 +163,12 @@ static inline int adv_send(struct net_buf *buf) BT_DBG("Advertising started. Sleeping %u ms", duration); #if CONFIG_BLE_MESH_USE_BLE_50 - if (!ble_mesh_adv_task_wait(K_WAIT(K_FOREVER), NULL)) { + if (!ble_mesh_adv_task_wait(UINT32_MAX, K_FOREVER, NULL)) { BT_WARN("Advertising didn't finish on time"); - bt_le_ext_adv_stop(adv_ins->id); + bt_le_ext_adv_stop(CONFIG_BLE_MESH_ADV_INST_ID); } #else /* CONFIG_BLE_MESH_USE_BLE_50 */ - k_sleep(K_MSEC(duration)); + ble_mesh_adv_task_wait(K_MSEC(duration)); #endif /* CONFIG_BLE_MESH_USE_BLE_50 */ #if !CONFIG_BLE_MESH_USE_BLE_50 @@ -346,6 +189,8 @@ static void adv_thread(void *p) { #if CONFIG_BLE_MESH_RELAY_ADV_BUF QueueSetMemberHandle_t handle = NULL; + QueueHandle_t relay_adv_handle = + bt_mesh_adv_types_mgnt_get(BLE_MESH_ADV_RELAY_DATA)->adv_q->q.handle; #endif bt_mesh_msg_t msg = {0}; struct net_buf **buf = NULL; @@ -359,28 +204,28 @@ static void adv_thread(void *p) #if !CONFIG_BLE_MESH_RELAY_ADV_BUF #if (CONFIG_BLE_MESH_NODE && CONFIG_BLE_MESH_PB_GATT) || \ CONFIG_BLE_MESH_GATT_PROXY_SERVER - xQueueReceive(adv_queue.handle, &msg, K_NO_WAIT); + xQueueReceive(adv_queue->q.handle, &msg, K_NO_WAIT); while (!(*buf)) { int32_t timeout = 0; BT_DBG("Mesh Proxy Advertising start"); timeout = bt_mesh_proxy_server_adv_start(); BT_DBG("Mesh Proxy Advertising up to %d ms", timeout); - xQueueReceive(adv_queue.handle, &msg, K_WAIT(timeout)); + xQueueReceive(adv_queue->q.handle, &msg, K_WAIT(timeout)); BT_DBG("Mesh Proxy Advertising stop"); bt_mesh_proxy_server_adv_stop(); } #else - xQueueReceive(adv_queue.handle, &msg, portMAX_DELAY); + xQueueReceive(adv_queue->q.handle, &msg, portMAX_DELAY); #endif /* (CONFIG_BLE_MESH_NODE && CONFIG_BLE_MESH_PB_GATT) || CONFIG_BLE_MESH_GATT_PROXY_SERVER */ #else /* !CONFIG_BLE_MESH_RELAY_ADV_BUF */ #if (CONFIG_BLE_MESH_NODE && CONFIG_BLE_MESH_PB_GATT) || \ CONFIG_BLE_MESH_GATT_PROXY_SERVER handle = xQueueSelectFromSet(mesh_queue_set, K_NO_WAIT); if (handle) { - if (uxQueueMessagesWaiting(adv_queue.handle)) { - xQueueReceive(adv_queue.handle, &msg, K_NO_WAIT); - } else if (uxQueueMessagesWaiting(relay_queue.handle)) { - xQueueReceive(relay_queue.handle, &msg, K_NO_WAIT); + if (uxQueueMessagesWaiting(adv_queue->q.handle)) { + xQueueReceive(adv_queue->q.handle, &msg, K_NO_WAIT); + } else if (uxQueueMessagesWaiting(relay_adv_handle)) { + xQueueReceive(relay_adv_handle, &msg, K_NO_WAIT); } } else { while (!(*buf)) { @@ -392,10 +237,10 @@ static void adv_thread(void *p) BT_DBG("Mesh Proxy Advertising stop"); bt_mesh_proxy_server_adv_stop(); if (handle) { - if (uxQueueMessagesWaiting(adv_queue.handle)) { - xQueueReceive(adv_queue.handle, &msg, K_NO_WAIT); - } else if (uxQueueMessagesWaiting(relay_queue.handle)) { - xQueueReceive(relay_queue.handle, &msg, K_NO_WAIT); + if (uxQueueMessagesWaiting(adv_queue->q.handle)) { + xQueueReceive(adv_queue->q.handle, &msg, K_NO_WAIT); + } else if (uxQueueMessagesWaiting(relay_adv_handle)) { + xQueueReceive(relay_adv_handle, &msg, K_NO_WAIT); } } } @@ -403,10 +248,10 @@ static void adv_thread(void *p) #else handle = xQueueSelectFromSet(mesh_queue_set, portMAX_DELAY); if (handle) { - if (uxQueueMessagesWaiting(adv_queue.handle)) { - xQueueReceive(adv_queue.handle, &msg, K_NO_WAIT); - } else if (uxQueueMessagesWaiting(relay_queue.handle)) { - xQueueReceive(relay_queue.handle, &msg, K_NO_WAIT); + if (uxQueueMessagesWaiting(adv_queue->q.handle)) { + xQueueReceive(adv_queue->q.handle, &msg, K_NO_WAIT); + } else if (uxQueueMessagesWaiting(relay_adv_handle)) { + xQueueReceive(relay_adv_handle, &msg, K_NO_WAIT); } } #endif /* (CONFIG_BLE_MESH_NODE && CONFIG_BLE_MESH_PB_GATT) || CONFIG_BLE_MESH_GATT_PROXY_SERVER */ @@ -423,7 +268,7 @@ static void adv_thread(void *p) BT_WARN("Failed to send adv packet"); } #else /* !CONFIG_BLE_MESH_RELAY_ADV_BUF */ - if (msg.relay && ignore_relay_packet(msg.timestamp)) { + if (msg.relay && bt_mesh_ignore_relay_packet(msg.timestamp)) { /* If the interval between "current time - msg.timestamp" is bigger than * BLE_MESH_RELAY_TIME_INTERVAL, this relay packet will not be sent. */ @@ -445,119 +290,6 @@ static void adv_thread(void *p) } } -struct net_buf *bt_mesh_adv_create_from_pool(struct net_buf_pool *pool, - bt_mesh_adv_alloc_t get_id, - enum bt_mesh_adv_type type, - int32_t timeout) -{ - struct bt_mesh_adv *adv = NULL; - struct net_buf *buf = NULL; - - if (bt_mesh_atomic_test_bit(bt_mesh.flags, BLE_MESH_SUSPENDED)) { - BT_WARN("Refusing to allocate buffer while suspended"); - return NULL; - } - - buf = net_buf_alloc(pool, timeout); - if (!buf) { - return NULL; - } - - BT_DBG("pool %p, buf_count %d, uinit_count %d", - buf->pool, pool->buf_count, pool->uninit_count); - - adv = get_id(net_buf_id(buf)); - BLE_MESH_ADV(buf) = adv; - - (void)memset(adv, 0, sizeof(*adv)); - - adv->type = type; - - return buf; -} - -void bt_mesh_unref_buf_from_pool(struct net_buf_pool *pool) -{ - int i; - - if (pool == NULL) { - BT_ERR("%s, Invalid parameter", __func__); - return; - } - - for (i = 0; i < pool->buf_count; i++) { - struct net_buf *buf = &pool->__bufs[i]; - if (buf->ref > 1U) { - buf->ref = 1U; - } - net_buf_unref(buf); - } -} - -struct net_buf *bt_mesh_adv_create(enum bt_mesh_adv_type type, int32_t timeout) -{ - return bt_mesh_adv_create_from_pool(&adv_buf_pool, adv_alloc, - type, timeout); -} - -void bt_mesh_adv_buf_ref_debug(const char *func, struct net_buf *buf, - uint8_t ref_cmp, bt_mesh_buf_ref_flag_t flag) -{ - if (buf == NULL || func == NULL || flag >= BLE_MESH_BUF_REF_MAX) { - BT_ERR("%s, Invalid parameter", __func__); - return; - } - - switch (flag) { - case BLE_MESH_BUF_REF_EQUAL: - if (buf->ref != ref_cmp) { - BT_ERR("Unexpected ref %d in %s, expect to equal to %d", buf->ref, func, ref_cmp); - } - break; - case BLE_MESH_BUF_REF_SMALL: - if (buf->ref >= ref_cmp) { - BT_ERR("Unexpected ref %d in %s, expect to smaller than %d", buf->ref, func, ref_cmp); - } - break; - default: - break; - } -} - -static void bt_mesh_unref_buf(bt_mesh_msg_t *msg) -{ - struct net_buf *buf = NULL; - - if (msg->arg) { - buf = (struct net_buf *)msg->arg; - bt_mesh_atomic_set(&BLE_MESH_ADV_BUSY(buf), 0); - if (buf->ref > 1U) { - buf->ref = 1U; - } - net_buf_unref(buf); - } -} - -static void bt_mesh_task_post(bt_mesh_msg_t *msg, uint32_t timeout, bool front) -{ - if (adv_queue.handle == NULL) { - BT_ERR("Invalid adv queue"); - return; - } - - if (front) { - if (xQueueSendToFront(adv_queue.handle, msg, timeout) != pdTRUE) { - BT_ERR("Failed to send item to adv queue front"); - bt_mesh_unref_buf(msg); - } - } else { - if (xQueueSend(adv_queue.handle, msg, timeout) != pdTRUE) { - BT_ERR("Failed to send item to adv queue back"); - bt_mesh_unref_buf(msg); - } - } -} - void bt_mesh_adv_send(struct net_buf *buf, uint8_t xmit, const struct bt_mesh_send_cb *cb, void *cb_data) @@ -590,481 +322,55 @@ void bt_mesh_adv_update(void) bt_mesh_task_post(&msg, K_NO_WAIT, false); } -#if CONFIG_BLE_MESH_RELAY_ADV_BUF -static bool ignore_relay_packet(uint32_t timestamp) -{ - uint32_t now = k_uptime_get_32(); - uint32_t interval = 0U; - - if (now >= timestamp) { - interval = now - timestamp; - } else { - interval = BLE_MESH_MAX_TIME_INTERVAL - (timestamp - now) + 1; - } - - return (interval >= BLE_MESH_RELAY_TIME_INTERVAL) ? true : false; -} - -static struct bt_mesh_adv *relay_adv_alloc(int id) -{ - return &relay_adv_pool[id]; -} - -struct net_buf *bt_mesh_relay_adv_create(enum bt_mesh_adv_type type, int32_t timeout) -{ - return bt_mesh_adv_create_from_pool(&relay_adv_buf_pool, relay_adv_alloc, - type, timeout); -} - -static void ble_mesh_relay_task_post(bt_mesh_msg_t *msg, uint32_t timeout) -{ - QueueSetMemberHandle_t handle = NULL; - bt_mesh_msg_t old_msg = {0}; - - if (relay_queue.handle == NULL) { - BT_ERR("Invalid relay queue"); - return; - } - - if (xQueueSend(relay_queue.handle, msg, timeout) == pdTRUE) { - return; - } - - /* If failed to send packet to the relay queue(queue is full), we will - * remove the oldest packet in the queue and put the new one into it. - */ - handle = xQueueSelectFromSet(mesh_queue_set, K_NO_WAIT); - if (handle && uxQueueMessagesWaiting(relay_queue.handle)) { - BT_INFO("Full queue, remove the oldest relay packet"); - /* Remove the oldest relay packet from queue */ - if (xQueueReceive(relay_queue.handle, &old_msg, K_NO_WAIT) != pdTRUE) { - BT_ERR("Failed to remove item from relay queue"); - bt_mesh_unref_buf(msg); - return; - } - /* Unref buf used for the oldest relay packet */ - bt_mesh_unref_buf(&old_msg); - /* Send the latest relay packet to queue */ - if (xQueueSend(relay_queue.handle, msg, K_NO_WAIT) != pdTRUE) { - BT_ERR("Failed to send item to relay queue"); - bt_mesh_unref_buf(msg); - return; - } - } else { - BT_WARN("Empty queue, but failed to send the relay packet"); - bt_mesh_unref_buf(msg); - } -} - -void bt_mesh_relay_adv_send(struct net_buf *buf, uint8_t xmit, - uint16_t src, uint16_t dst, - const struct bt_mesh_send_cb *cb, - void *cb_data) -{ - bt_mesh_msg_t msg = { - .relay = true, - }; - - BT_DBG("type 0x%02x len %u: %s", BLE_MESH_ADV(buf)->type, buf->len, - bt_hex(buf->data, buf->len)); - - BLE_MESH_ADV(buf)->cb = cb; - BLE_MESH_ADV(buf)->cb_data = cb_data; - bt_mesh_atomic_set(&BLE_MESH_ADV_BUSY(buf), 1); - BLE_MESH_ADV(buf)->xmit = xmit; - - msg.arg = (void *)net_buf_ref(buf); - msg.src = src; - msg.dst = dst; - msg.timestamp = k_uptime_get_32(); - /* Use K_NO_WAIT here, if relay_queue is full return immediately */ - ble_mesh_relay_task_post(&msg, K_NO_WAIT); -} - -uint16_t bt_mesh_get_stored_relay_count(void) -{ - return (uint16_t)uxQueueMessagesWaiting(relay_queue.handle); -} -#endif /* #if CONFIG_BLE_MESH_RELAY_ADV_BUF */ - void bt_mesh_adv_init(void) { -#if !CONFIG_BLE_MESH_FREERTOS_STATIC_ALLOC - adv_queue.handle = xQueueCreate(BLE_MESH_ADV_QUEUE_SIZE, sizeof(bt_mesh_msg_t)); - __ASSERT(adv_queue.handle, "Failed to create queue"); -#else /* !CONFIG_BLE_MESH_FREERTOS_STATIC_ALLOC */ -#if CONFIG_BLE_MESH_FREERTOS_STATIC_ALLOC_EXTERNAL - adv_queue.buffer = heap_caps_calloc_prefer(1, sizeof(StaticQueue_t), 2, MALLOC_CAP_SPIRAM|MALLOC_CAP_8BIT, MALLOC_CAP_INTERNAL|MALLOC_CAP_8BIT); -#elif CONFIG_BLE_MESH_FREERTOS_STATIC_ALLOC_IRAM_8BIT - 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); -#endif - __ASSERT(adv_queue.buffer, "Failed to create queue buffer"); -#if CONFIG_BLE_MESH_FREERTOS_STATIC_ALLOC_EXTERNAL - 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); -#elif CONFIG_BLE_MESH_FREERTOS_STATIC_ALLOC_IRAM_8BIT - 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); -#endif - __ASSERT(adv_queue.storage, "Failed to create queue storage"); - adv_queue.handle = xQueueCreateStatic(BLE_MESH_ADV_QUEUE_SIZE, sizeof(bt_mesh_msg_t), (uint8_t*)adv_queue.storage, adv_queue.buffer); - __ASSERT(adv_queue.handle, "Failed to create static queue"); -#endif /* !CONFIG_BLE_MESH_FREERTOS_STATIC_ALLOC */ #if CONFIG_BLE_MESH_RELAY_ADV_BUF -#if !CONFIG_BLE_MESH_FREERTOS_STATIC_ALLOC - relay_queue.handle = xQueueCreate(BLE_MESH_RELAY_QUEUE_SIZE, sizeof(bt_mesh_msg_t)); - __ASSERT(relay_queue.handle, "Failed to create relay queue"); -#else /* !CONFIG_BLE_MESH_FREERTOS_STATIC_ALLOC */ -#if CONFIG_BLE_MESH_FREERTOS_STATIC_ALLOC_EXTERNAL - relay_queue.buffer = heap_caps_calloc_prefer(1, sizeof(StaticQueue_t), 2, MALLOC_CAP_SPIRAM|MALLOC_CAP_8BIT, MALLOC_CAP_INTERNAL|MALLOC_CAP_8BIT); -#elif CONFIG_BLE_MESH_FREERTOS_STATIC_ALLOC_IRAM_8BIT - 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); + bt_mesh_relay_adv_init(); #endif - __ASSERT(relay_queue.buffer, "Failed to create relay queue buffer"); -#if CONFIG_BLE_MESH_FREERTOS_STATIC_ALLOC_EXTERNAL - 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); -#elif CONFIG_BLE_MESH_FREERTOS_STATIC_ALLOC_IRAM_8BIT - 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); + +#if CONFIG_BLE_MESH_SUPPORT_BLE_ADV + bt_mesh_ble_adv_init(); #endif - __ASSERT(relay_queue.storage, "Failed to create relay queue storage"); - relay_queue.handle = xQueueCreateStatic(BLE_MESH_RELAY_QUEUE_SIZE, sizeof(bt_mesh_msg_t), (uint8_t*)relay_queue.storage, relay_queue.buffer); - __ASSERT(relay_queue.handle, "Failed to create static relay queue"); -#endif /* !CONFIG_BLE_MESH_FREERTOS_STATIC_ALLOC */ + bt_mesh_adv_common_init(); + adv_queue = bt_mesh_adv_queue_get(); + assert(adv_queue && adv_queue->q.handle && adv_queue->send); + +#if CONFIG_BLE_MESH_RELAY_ADV_BUF && !CONFIG_BLE_MESH_SUPPORT_MULTI_ADV + QueueHandle_t relay_adv_handle = + bt_mesh_adv_types_mgnt_get(BLE_MESH_ADV_RELAY_DATA)->adv_q->q.handle; mesh_queue_set = xQueueCreateSet(BLE_MESH_QUEUE_SET_SIZE); __ASSERT(mesh_queue_set, "Failed to create queue set"); - xQueueAddToSet(adv_queue.handle, mesh_queue_set); - xQueueAddToSet(relay_queue.handle, mesh_queue_set); -#endif /* CONFIG_BLE_MESH_RELAY_ADV_BUF */ + xQueueAddToSet(adv_queue->q.handle, mesh_queue_set); + xQueueAddToSet(relay_adv_handle, mesh_queue_set); +#endif -#if (CONFIG_BLE_MESH_FREERTOS_STATIC_ALLOC_EXTERNAL && \ - (CONFIG_SPIRAM_CACHE_WORKAROUND || !CONFIG_IDF_TARGET_ESP32) && \ - CONFIG_SPIRAM_ALLOW_STACK_EXTERNAL_MEMORY) - adv_task.task = heap_caps_calloc(1, sizeof(StaticTask_t), MALLOC_CAP_INTERNAL|MALLOC_CAP_8BIT); - __ASSERT(adv_task.task, "Failed to create adv thread task"); - 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); - __ASSERT(adv_task.stack, "Failed to create adv thread stack"); - adv_task.handle = xTaskCreateStaticPinnedToCore(adv_thread, BLE_MESH_ADV_TASK_NAME, BLE_MESH_ADV_TASK_STACK_SIZE, NULL, - BLE_MESH_ADV_TASK_PRIO, adv_task.stack, adv_task.task, BLE_MESH_ADV_TASK_CORE); - __ASSERT(adv_task.handle, "Failed to create static adv thread"); -#else /* CONFIG_BLE_MESH_FREERTOS_STATIC_ALLOC_EXTERNAL && (CONFIG_SPIRAM_CACHE_WORKAROUND || !CONFIG_IDF_TARGET_ESP32) && CONFIG_SPIRAM_ALLOW_STACK_EXTERNAL_MEMORY */ - int ret = xTaskCreatePinnedToCore(adv_thread, BLE_MESH_ADV_TASK_NAME, BLE_MESH_ADV_TASK_STACK_SIZE, NULL, - BLE_MESH_ADV_TASK_PRIO, &adv_task.handle, BLE_MESH_ADV_TASK_CORE); - __ASSERT(ret == pdTRUE, "Failed to create adv thread"); - (void)ret; -#endif /* CONFIG_BLE_MESH_FREERTOS_STATIC_ALLOC_EXTERNAL && (CONFIG_SPIRAM_CACHE_WORKAROUND || !CONFIG_IDF_TARGET_ESP32) && CONFIG_SPIRAM_ALLOW_STACK_EXTERNAL_MEMORY */ + bt_mesh_adv_task_init(adv_thread); } #if CONFIG_BLE_MESH_DEINIT void bt_mesh_adv_deinit(void) { - if (adv_queue.handle == NULL) { - return; - } - -#if CONFIG_BLE_MESH_USE_BLE_50 - bt_mesh_adv_inst_deinit(); -#endif - - vTaskDelete(adv_task.handle); - adv_task.handle = NULL; -#if (CONFIG_BLE_MESH_FREERTOS_STATIC_ALLOC_EXTERNAL && \ - (CONFIG_SPIRAM_CACHE_WORKAROUND || !CONFIG_IDF_TARGET_ESP32) && \ - CONFIG_SPIRAM_ALLOW_STACK_EXTERNAL_MEMORY) - heap_caps_free(adv_task.stack); - adv_task.stack = NULL; - heap_caps_free(adv_task.task); - adv_task.task = NULL; -#endif + /* Adv task must be deinit first */ + bt_mesh_adv_task_deinit(); #if CONFIG_BLE_MESH_RELAY_ADV_BUF - xQueueRemoveFromSet(adv_queue.handle, mesh_queue_set); - xQueueRemoveFromSet(relay_queue.handle, mesh_queue_set); - - vQueueDelete(relay_queue.handle); - relay_queue.handle = NULL; -#if CONFIG_BLE_MESH_FREERTOS_STATIC_ALLOC - heap_caps_free(relay_queue.buffer); - relay_queue.buffer = NULL; - heap_caps_free(relay_queue.storage); - relay_queue.storage = NULL; -#endif /* CONFIG_BLE_MESH_FREERTOS_STATIC_ALLOC */ - - bt_mesh_unref_buf_from_pool(&relay_adv_buf_pool); - memset(relay_adv_pool, 0, sizeof(relay_adv_pool)); + QueueHandle_t relay_adv_handle = + bt_mesh_adv_types_mgnt_get(BLE_MESH_ADV_RELAY_DATA)->adv_q->q.handle; + xQueueRemoveFromSet(adv_queue->q.handle, mesh_queue_set); + xQueueRemoveFromSet(relay_adv_handle, mesh_queue_set); vQueueDelete(mesh_queue_set); mesh_queue_set = NULL; -#endif /* CONFIG_BLE_MESH_RELAY_ADV_BUF */ - vQueueDelete(adv_queue.handle); - adv_queue.handle = NULL; -#if CONFIG_BLE_MESH_FREERTOS_STATIC_ALLOC - heap_caps_free(adv_queue.buffer); - adv_queue.buffer = NULL; - heap_caps_free(adv_queue.storage); - adv_queue.storage = NULL; -#endif /* CONFIG_BLE_MESH_FREERTOS_STATIC_ALLOC */ - - bt_mesh_unref_buf_from_pool(&adv_buf_pool); - memset(adv_pool, 0, sizeof(adv_pool)); + bt_mesh_relay_adv_deinit(); +#endif /* CONFIG_BLE_MESH_RELAY_ADV_BUF */ #if CONFIG_BLE_MESH_SUPPORT_BLE_ADV bt_mesh_ble_adv_deinit(); #endif /* CONFIG_BLE_MESH_SUPPORT_BLE_ADV */ -} -#endif /* CONFIG_BLE_MESH_DEINIT */ - -#if CONFIG_BLE_MESH_SUPPORT_BLE_ADV -static struct bt_mesh_adv *ble_adv_alloc(int id) -{ - return &ble_adv_pool[id]; -} - -static struct net_buf *bt_mesh_ble_adv_create(enum bt_mesh_adv_type type, int32_t timeout) -{ - return bt_mesh_adv_create_from_pool(&ble_adv_buf_pool, ble_adv_alloc, - type, timeout); -} - -static void bt_mesh_ble_adv_send(struct net_buf *buf, const struct bt_mesh_send_cb *cb, - void *cb_data, bool front) -{ - bt_mesh_msg_t msg = { - .relay = false, - }; - - BT_DBG("type 0x%02x len %u: %s", BLE_MESH_ADV(buf)->type, buf->len, - bt_hex(buf->data, buf->len)); - - BLE_MESH_ADV(buf)->cb = cb; - BLE_MESH_ADV(buf)->cb_data = cb_data; - bt_mesh_atomic_set(&BLE_MESH_ADV_BUSY(buf), 1); - - bt_mesh_adv_buf_ref_debug(__func__, buf, 3U, BLE_MESH_BUF_REF_SMALL); - - msg.arg = (void *)net_buf_ref(buf); - bt_mesh_task_post(&msg, portMAX_DELAY, front); -} - -static void ble_adv_tx_reset(struct ble_adv_tx *tx, bool unref) -{ - if (tx->buf == NULL) { - return; - } - - if (bt_mesh_atomic_test_bit(tx->flags, TIMER_INIT)) { - k_delayed_work_free(&tx->resend); - } - bt_mesh_atomic_set(tx->flags, 0); - memset(&tx->param, 0, sizeof(tx->param)); - bt_mesh_atomic_set(&BLE_MESH_ADV_BUSY(tx->buf), 0); - if (unref) { - net_buf_unref(tx->buf); - } - tx->buf = NULL; -} - -static void ble_adv_send_start(uint16_t duration, int err, void *cb_data) -{ - struct ble_adv_tx *tx = cb_data; - - BT_DBG("%s, duration %d, err %d", __func__, duration, err); - - /* If failed to send BLE adv packet, and param->count is not 0 - * which means the timer has been initialized, here we need to - * free the timer. - */ - if (err) { - ble_adv_tx_reset(tx, true); - } -} -static void ble_adv_send_end(int err, void *cb_data) -{ - struct ble_adv_tx *tx = cb_data; - - BT_DBG("%s, err %d", __func__, err); - - if (err) { - ble_adv_tx_reset(tx, true); - return; - } - - if (tx->param.count) { - k_delayed_work_submit(&tx->resend, tx->param.period); - } else { - ble_adv_tx_reset(tx, true); - } -} - -static struct bt_mesh_send_cb ble_adv_send_cb = { - .start = ble_adv_send_start, - .end = ble_adv_send_end, -}; - -static void ble_adv_resend(struct k_work *work) -{ - struct ble_adv_tx *tx = CONTAINER_OF(work, - struct ble_adv_tx, - resend.work); - bool front = false; - - if (tx->buf == NULL) { - /* The advertising has been cancelled */ - return; - } - - front = (tx->param.priority == BLE_MESH_BLE_ADV_PRIO_HIGH) ? true : false; - bt_mesh_ble_adv_send(tx->buf, &ble_adv_send_cb, tx, front); - - if (tx->param.count == SEND_BLE_ADV_INFINITE) { - /* Send the BLE advertising packet infinitely */ - return; - } - - if (tx->param.count > 0U) { - tx->param.count--; - } -} - -int bt_mesh_start_ble_advertising(const struct bt_mesh_ble_adv_param *param, - const struct bt_mesh_ble_adv_data *data, uint8_t *index) -{ - struct ble_adv_tx *tx = NULL; - struct net_buf *buf = NULL; - bool front = false; - - if (param == NULL || index == NULL) { - BT_ERR("%s, Invalid parameter", __func__); - return -EINVAL; - } - - if (param->adv_type != BLE_MESH_ADV_DIRECT_IND && - (param->interval < 0x20 || param->interval > 0x4000)) { - BT_ERR("Invalid adv interval 0x%04x", param->interval); - return -EINVAL; - } - - if (param->adv_type > BLE_MESH_ADV_DIRECT_IND_LOW_DUTY) { - BT_ERR("Invalid adv type 0x%02x", param->adv_type); - return -EINVAL; - } - - if (param->own_addr_type > BLE_MESH_ADDR_RANDOM_ID) { - BT_ERR("Invalid own addr type 0x%02x", param->own_addr_type); - return -EINVAL; - } - - if ((param->own_addr_type == BLE_MESH_ADDR_PUBLIC_ID || - param->own_addr_type == BLE_MESH_ADDR_RANDOM_ID || - param->adv_type == BLE_MESH_ADV_DIRECT_IND || - param->adv_type == BLE_MESH_ADV_DIRECT_IND_LOW_DUTY) && - param->peer_addr_type > BLE_MESH_ADDR_RANDOM) { - BT_ERR("Invalid peer addr type 0x%02x", param->peer_addr_type); - return -EINVAL; - } - - if (data && (data->adv_data_len > 31 || data->scan_rsp_data_len > 31)) { - BT_ERR("Invalid adv data length (adv %d, scan rsp %d)", - data->adv_data_len, data->scan_rsp_data_len); - return -EINVAL; - } - - if (param->priority > BLE_MESH_BLE_ADV_PRIO_HIGH) { - BT_ERR("Invalid adv priority %d", param->priority); - return -EINVAL; - } - - if (param->duration < ADV_SCAN_INT(param->interval)) { - BT_ERR("Too small duration %dms", param->duration); - return -EINVAL; - } - - buf = bt_mesh_ble_adv_create(BLE_MESH_ADV_BLE, K_NO_WAIT); - if (!buf) { - BT_ERR("No empty ble adv buffer"); - return -ENOBUFS; - } - - /* Set advertising data and scan response data */ - memset(buf->data, 0, buf->size); - if (data) { - net_buf_add_u8(buf, data->adv_data_len); - if (data->adv_data_len) { - net_buf_add_mem(buf, data->adv_data, data->adv_data_len); - } - net_buf_add_u8(buf, data->scan_rsp_data_len); - if (data->scan_rsp_data_len) { - net_buf_add_mem(buf, data->scan_rsp_data, data->scan_rsp_data_len); - } - } - - *index = net_buf_id(buf); - tx = &ble_adv_tx[*index]; - tx->buf = buf; - memcpy(&tx->param, param, sizeof(tx->param)); - - front = (tx->param.priority == BLE_MESH_BLE_ADV_PRIO_HIGH) ? true : false; - bt_mesh_ble_adv_send(buf, &ble_adv_send_cb, tx, front); - if (param->count) { - if (k_delayed_work_init(&tx->resend, ble_adv_resend)) { - /* If failed to create a timer, the BLE adv packet will be - * sent only once. Just give a warning here, and since the - * BLE adv packet can be sent, return 0 here. - */ - BT_WARN("Send BLE adv packet only once"); - tx->param.count = 0; - net_buf_unref(buf); - return 0; - } - bt_mesh_atomic_set_bit(tx->flags, TIMER_INIT); - } else { - /* Send the BLE advertising packet only once */ - net_buf_unref(buf); - } - - return 0; -} - -int bt_mesh_stop_ble_advertising(uint8_t index) -{ - struct ble_adv_tx *tx = NULL; - bool unref = true; - - if (index >= ARRAY_SIZE(ble_adv_tx)) { - BT_ERR("Invalid adv index %d", index); - return -EINVAL; - } - - tx = &ble_adv_tx[index]; - - if (tx->buf == NULL) { - BT_WARN("Already stopped, index %d", index); - return 0; - } - - /* busy 1, ref 1; busy 1, ref 2; - * busy 0, ref 0; busy 0, ref 1; - */ - - if (bt_mesh_atomic_get(&BLE_MESH_ADV_BUSY(tx->buf)) && - tx->buf->ref == 1U) { - unref = false; - } - ble_adv_tx_reset(tx, unref); - - return 0; -} - -#if CONFIG_BLE_MESH_DEINIT -static void bt_mesh_ble_adv_deinit(void) -{ - for (int i = 0; i < ARRAY_SIZE(ble_adv_tx); i++) { - struct ble_adv_tx *tx = &ble_adv_tx[i]; - ble_adv_tx_reset(tx, false); - } - bt_mesh_unref_buf_from_pool(&ble_adv_buf_pool); - memset(ble_adv_pool, 0, sizeof(ble_adv_pool)); + bt_mesh_adv_common_deinit(); } #endif /* CONFIG_BLE_MESH_DEINIT */ -#endif /* CONFIG_BLE_MESH_SUPPORT_BLE_ADV */ diff --git a/components/bt/esp_ble_mesh/core/adv.h b/components/bt/esp_ble_mesh/core/adv.h index d2fb7baca39..5770364a2e3 100644 --- a/components/bt/esp_ble_mesh/core/adv.h +++ b/components/bt/esp_ble_mesh/core/adv.h @@ -10,118 +10,30 @@ #ifndef _ADV_H_ #define _ADV_H_ +#if CONFIG_BLE_MESH_SUPPORT_MULTI_ADV +#include "ext_adv.h" +#else /* CONFIG_BLE_MESH_SUPPORT_MULTI_ADV */ #include "mesh/atomic.h" #include "mesh/access.h" #include "mesh/adapter.h" #include "mesh/utils.h" +#include "adv_common.h" #ifdef __cplusplus extern "C" { #endif -/* Maximum advertising data payload for a single data type */ -#define BLE_MESH_ADV_DATA_SIZE 29 - -/* The user data is a pointer (4 bytes) to struct bt_mesh_adv */ -#define BLE_MESH_ADV_USER_DATA_SIZE 4 - -#define BLE_MESH_ADV(buf) (*(struct bt_mesh_adv **)net_buf_user_data(buf)) -#define BLE_MESH_ADV_BUSY(buf) (BLE_MESH_ADV(buf)->busy) - -uint16_t bt_mesh_pdu_duration(uint8_t xmit); - -typedef struct bt_mesh_msg { - bool relay; /* Flag indicates if the packet is a relayed one */ - void *arg; /* Pointer to the struct net_buf */ - uint16_t src; /* Source address for relay packets */ - uint16_t dst; /* Destination address for relay packets */ - uint32_t timestamp; /* Timestamp recorded when the relay packet is posted to queue */ -} bt_mesh_msg_t; - -enum bt_mesh_adv_type { - BLE_MESH_ADV_PROV, - BLE_MESH_ADV_DATA, - BLE_MESH_ADV_BEACON, - BLE_MESH_ADV_URI, - BLE_MESH_ADV_BLE, - BLE_MESH_ADV_PROXY_SOLIC, -}; - -struct bt_mesh_adv { - const struct bt_mesh_send_cb *cb; - void *cb_data; - - uint8_t type:3; - - bt_mesh_atomic_t busy; - - uint8_t xmit; -}; - -typedef struct bt_mesh_adv *(*bt_mesh_adv_alloc_t)(int id); - -struct net_buf *bt_mesh_adv_create(enum bt_mesh_adv_type type, int32_t timeout); - -typedef enum { - BLE_MESH_BUF_REF_EQUAL, - BLE_MESH_BUF_REF_SMALL, - BLE_MESH_BUF_REF_MAX, -} bt_mesh_buf_ref_flag_t; - -#if CONFIG_BLE_MESH_USE_BLE_50 - -#define BLE_MESH_ADV_INS_UNUSED 0xFF -#define BLE_MESH_ADV_INS_CNT 1 - -struct bt_mesh_adv_inst { - uint8_t id; -}; - -int ble_mesh_adv_task_wakeup(uint16_t adv_inst_id); -bool bt_mesh_is_adv_inst_used(uint8_t adv_inst_id); -#endif /* CONFIG_BLE_MESH_USE_BLE_50 */ - -void bt_mesh_adv_buf_ref_debug(const char *func, struct net_buf *buf, - uint8_t ref_cmp, bt_mesh_buf_ref_flag_t flag); - -struct net_buf *bt_mesh_adv_create_from_pool(struct net_buf_pool *pool, - bt_mesh_adv_alloc_t get_id, - enum bt_mesh_adv_type type, - int32_t timeout); - -void bt_mesh_unref_buf_from_pool(struct net_buf_pool *pool); - void bt_mesh_adv_send(struct net_buf *buf, uint8_t xmit, const struct bt_mesh_send_cb *cb, void *cb_data); -#if CONFIG_BLE_MESH_USE_BLE_50 && (CONFIG_BLE_MESH_GATT_PROXY_SERVER || CONFIG_BLE_MESH_PB_GATT) -uint8_t bt_mesh_get_proxy_inst(void); -#endif - -struct net_buf *bt_mesh_relay_adv_create(enum bt_mesh_adv_type type, int32_t timeout); - -void bt_mesh_relay_adv_send(struct net_buf *buf, uint8_t xmit, - uint16_t src, uint16_t dst, - const struct bt_mesh_send_cb *cb, - void *cb_data); - -uint16_t bt_mesh_get_stored_relay_count(void); - void bt_mesh_adv_update(void); void bt_mesh_adv_init(void); void bt_mesh_adv_deinit(void); -#if CONFIG_BLE_MESH_SUPPORT_BLE_ADV -int bt_mesh_start_ble_advertising(const struct bt_mesh_ble_adv_param *param, - const struct bt_mesh_ble_adv_data *data, uint8_t *index); - -int bt_mesh_stop_ble_advertising(uint8_t index); -#endif /* CONFIG_BLE_MESH_SUPPORT_BLE_ADV */ - #ifdef __cplusplus } #endif - +#endif /* CONFIG_BLE_MESH_SUPPORT_MULTI_ADV */ #endif /* _ADV_H_ */ diff --git a/components/bt/esp_ble_mesh/core/adv_common.c b/components/bt/esp_ble_mesh/core/adv_common.c new file mode 100644 index 00000000000..40f000bb02b --- /dev/null +++ b/components/bt/esp_ble_mesh/core/adv_common.c @@ -0,0 +1,680 @@ +/* Bluetooth Mesh */ + +/* + * SPDX-FileCopyrightText: 2017 Intel Corporation + * SPDX-FileContributor: 2018-2024 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include + +#include "adv_common.h" +#include "net.h" +#include "ble_adv.h" + +NET_BUF_POOL_DEFINE(adv_buf_pool, CONFIG_BLE_MESH_ADV_BUF_COUNT, + BLE_MESH_ADV_DATA_SIZE, BLE_MESH_ADV_USER_DATA_SIZE, NULL); + +static struct bt_mesh_adv adv_pool[CONFIG_BLE_MESH_ADV_BUF_COUNT]; + +static struct bt_mesh_adv_queue adv_queue; + +#if CONFIG_BLE_MESH_RELAY_ADV_BUF +NET_BUF_POOL_DEFINE(relay_adv_buf_pool, CONFIG_BLE_MESH_RELAY_ADV_BUF_COUNT, + BLE_MESH_ADV_DATA_SIZE, BLE_MESH_ADV_USER_DATA_SIZE, NULL); + +static struct bt_mesh_adv relay_adv_pool[CONFIG_BLE_MESH_RELAY_ADV_BUF_COUNT]; +struct bt_mesh_adv_queue relay_adv_queue; + +#define BLE_MESH_RELAY_TIME_INTERVAL K_SECONDS(6) +#define BLE_MESH_MAX_TIME_INTERVAL 0xFFFFFFFF + +#endif + +#if CONFIG_BLE_MESH_FRIEND +/* We reserve one extra buffer for each friendship, since we need to be able + * to resend the last sent PDU, which sits separately outside of the queue. + */ +#define FRIEND_BUF_COUNT ((CONFIG_BLE_MESH_FRIEND_QUEUE_SIZE + 1) * \ + CONFIG_BLE_MESH_FRIEND_LPN_COUNT) + +NET_BUF_POOL_FIXED_DEFINE(friend_buf_pool, FRIEND_BUF_COUNT, + BLE_MESH_ADV_DATA_SIZE, NULL); + +bt_mesh_friend_adv_t frnd_adv_pool[FRIEND_BUF_COUNT]; + +struct bt_mesh_adv *bt_mesh_frnd_adv_buf_get(int idx) +{ + frnd_adv_pool[idx].app_idx = BLE_MESH_KEY_UNUSED; + return &frnd_adv_pool[idx].adv; +} +#endif + +struct bt_mesh_adv_task { + TaskHandle_t handle; +#if (CONFIG_BLE_MESH_FREERTOS_STATIC_ALLOC_EXTERNAL && \ + (CONFIG_SPIRAM_CACHE_WORKAROUND || !CONFIG_IDF_TARGET_ESP32) && \ + CONFIG_SPIRAM_ALLOW_STACK_EXTERNAL_MEMORY) + StaticTask_t *task; + StackType_t *stack; +#endif +}; + +static struct bt_mesh_adv_task adv_task; +static struct bt_mesh_adv_type_manager adv_types[BLE_MESH_ADV_TYPES_NUM]; + +#if CONFIG_BLE_MESH_USE_BLE_50 +static struct bt_mesh_adv_inst adv_insts[] = { + [BLE_MESH_ADV_INS] = { + .id = CONFIG_BLE_MESH_ADV_INST_ID, +#if CONFIG_BLE_MESH_SUPPORT_MULTI_ADV + .busy = false, +#endif + }, +#if CONFIG_BLE_MESH_SUPPORT_MULTI_ADV +#if (CONFIG_BLE_MESH_NODE && CONFIG_BLE_MESH_PB_GATT) || \ + CONFIG_BLE_MESH_GATT_PROXY_SERVER + [BLE_MESH_ADV_PROXY_INS] = { + .id = CONFIG_BLE_MESH_PROXY_ADV_INST_ID, + .busy = false, + }, +#endif +#if CONFIG_BLE_MESH_SEPARATE_RELAY_ADV_INSTANCE + [BLE_MESH_RELAY_ADV_INS] = { + .id = CONFIG_BLE_MESH_RELAY_ADV_INST_ID, + .busy = false, + }, +#endif +#if CONFIG_BLE_MESH_SEPARATE_BLE_ADV_INSTANCE + [BLE_MESH_BLE_ADV_INS] = { + .id = CONFIG_BLE_MESH_BLE_ADV_INST_ID, + .busy = false, + }, +#endif +#endif /* CONFIG_BLE_MESH_SUPPORT_MULTI_ADV */ +}; + +static struct bt_mesh_adv_inst *find_adv_inst_with_inst_id(uint8_t id) +{ + for (int i = 0; i < ARRAY_SIZE(adv_insts); i++) { + if (adv_insts[i].id == id) { + return &adv_insts[i]; + } + } + + return NULL; +} + +struct bt_mesh_adv_inst *bt_mesh_get_adv_insts_set(void) +{ + return adv_insts; +} + +bool bt_mesh_is_adv_inst_used(uint8_t adv_inst_id) +{ + return (find_adv_inst_with_inst_id(adv_inst_id) != NULL); +} + +int bt_mesh_adv_inst_init(enum bt_mesh_adv_inst_type inst_type, uint8_t inst_id) +{ + if (inst_type >= BLE_MESH_ADV_INS_TYPES_NUM) { + BT_ERR("Invalid instance type %d", inst_type); + return -EINVAL; + } + + if (inst_id == BLE_MESH_ADV_INS_UNUSED) { + BT_ERR("Invalid instance id %d", inst_id); + return -EINVAL; + } + + adv_insts[inst_type].id = inst_id; + return 0; +} + +int bt_mesh_adv_inst_deinit(enum bt_mesh_adv_inst_type inst_type) +{ + if (inst_type >= BLE_MESH_ADV_INS_TYPES_NUM) { + BT_ERR("Invalid instance type %d", inst_type); + return -EINVAL; + } + + bt_le_ext_adv_stop(adv_insts[inst_type].id); + + adv_insts[inst_type].id = BLE_MESH_ADV_INS_UNUSED; +#if CONFIG_BLE_MESH_SUPPORT_MULTI_ADV + adv_insts[inst_type].spt_mask = 0; +#endif + return 0; +} + +#endif /* CONFIG_BLE_MESH_USE_BLE_50 */ + +struct bt_mesh_adv *adv_alloc(int id) +{ + return &adv_pool[id]; +} + +struct bt_mesh_adv_type_manager *bt_mesh_adv_types_mgnt_get(enum bt_mesh_adv_type adv_type) +{ + return &adv_types[adv_type]; +} + +void bt_mesh_adv_buf_ref_debug(const char *func, struct net_buf *buf, + uint8_t ref_cmp, bt_mesh_buf_ref_flag_t flag) +{ + if (buf == NULL || func == NULL || flag >= BLE_MESH_BUF_REF_MAX) { + BT_ERR("%s, Invalid parameter", __func__); + return; + } + + switch (flag) { + case BLE_MESH_BUF_REF_EQUAL: + if (buf->ref != ref_cmp) { + BT_ERR("Unexpected ref %d in %s, expect to equal to %d", buf->ref, func, ref_cmp); + } + break; + case BLE_MESH_BUF_REF_SMALL: + if (buf->ref >= ref_cmp) { + BT_ERR("Unexpected ref %d in %s, expect to smaller than %d", buf->ref, func, ref_cmp); + } + break; + default: + break; + } +} + +#if CONFIG_BLE_MESH_SUPPORT_MULTI_ADV +void bt_mesh_adv_inst_supported_adv_type_add(enum bt_mesh_adv_inst_type inst_type, + enum bt_mesh_adv_type adv_type) +{ + if (inst_type >= BLE_MESH_ADV_INS_TYPES_NUM) { + BT_ERR("Invalid instance type %d", inst_type); + return; + } + + if (adv_type >= BLE_MESH_ADV_TYPES_NUM) { + BT_ERR("Invalid adv type %d", adv_type); + return; + } + + adv_insts[inst_type].spt_mask |= BIT(adv_type); +} + +void bt_mesh_adv_inst_supported_adv_type_rm(enum bt_mesh_adv_inst_type inst_type, + enum bt_mesh_adv_type adv_type) +{ + if (inst_type >= BLE_MESH_ADV_INS_TYPES_NUM) { + BT_ERR("Invalid instance type %d", inst_type); + return; + } + + if (adv_type >= BLE_MESH_ADV_TYPES_NUM) { + BT_ERR("Invalid adv type %d", adv_type); + return; + } + + adv_insts[inst_type].spt_mask &= ~BIT(adv_type); +} + +void bt_mesh_adv_inst_supported_adv_type_clear(enum bt_mesh_adv_inst_type inst_type, + enum bt_mesh_adv_type adv_type) +{ + if (inst_type >= BLE_MESH_ADV_INS_TYPES_NUM) { + BT_ERR("Invalid instance type %d", inst_type); + return; + } + + if (adv_type >= BLE_MESH_ADV_TYPES_NUM) { + BT_ERR("Invalid adv type %d", adv_type); + return; + } + + adv_insts[inst_type].spt_mask = 0; +} +#endif + +int bt_mesh_adv_queue_init(struct bt_mesh_adv_queue *adv_queue, uint16_t queue_size, + bt_mesh_adv_queue_send_cb_t cb) +{ + if (!adv_queue || !queue_size || !cb) { + BT_ERR("Invalid param %s", __func__); + return -EINVAL; + } + + bt_mesh_queue_init(&adv_queue->q, queue_size, sizeof(bt_mesh_msg_t)); + + adv_queue->send = cb; + + return 0; +} + +int bt_mesh_adv_queue_deinit(struct bt_mesh_adv_queue *adv_queue) +{ + if (!adv_queue) { + BT_ERR("Invalid param %s", __func__); + return -EINVAL; + } + + bt_mesh_queue_deinit(&adv_queue->q); + + adv_queue->send = NULL; + + return 0; +} + +void bt_mesh_adv_type_init(enum bt_mesh_adv_type adv_type, + struct bt_mesh_adv_queue *adv_queue, + struct net_buf_pool *buf_pool, + bt_mesh_pool_allocator_t adv_alloc) +{ + if (adv_type >= BLE_MESH_ADV_TYPES_NUM) { + BT_ERR("%s Invalid adv type %d",__func__, adv_type); + return; + } + + if (!adv_queue || !buf_pool || !adv_alloc) { + BT_ERR("Invalid parameters %s", __func__); + return; + } + + adv_types[adv_type].adv_q = adv_queue; + adv_types[adv_type].pool = buf_pool; + adv_types[adv_type].pool_allocator = adv_alloc; +} + +void bt_mesh_adv_type_deinit(enum bt_mesh_adv_type adv_type) +{ + if (adv_type >= BLE_MESH_ADV_TYPES_NUM) { + BT_ERR("%s Invalid adv type %d",__func__, adv_type); + return; + } + + adv_types[adv_type].adv_q = NULL; + adv_types[adv_type].pool = NULL; + adv_types[adv_type].pool_allocator = NULL; +} + +#if CONFIG_BLE_MESH_USE_BLE_50 +int ble_mesh_adv_task_wakeup(uint32_t evt) +{ + xTaskNotify(adv_task.handle, evt, eSetBits); + return 0; +} + +bool ble_mesh_adv_task_wait(uint32_t wait_bits, uint32_t timeout, uint32_t *notify) +{ + return (xTaskNotifyWait(wait_bits, UINT32_MAX, notify, K_WAIT(timeout)) == pdTRUE); +} +#else /* CONFIG_BLE_MESH_USE_BLE_50 */ +bool ble_mesh_adv_task_wait(uint32_t timeout) +{ + vTaskDelay(K_WAIT(timeout)); + return true; +} +#endif /* CONFIG_BLE_MESH_USE_BLE_50 */ + +uint16_t bt_mesh_pdu_duration(uint8_t xmit) +{ + uint16_t duration = 0U; + uint16_t adv_int = 0U; + + adv_int = MAX(ADV_ITVL_MIN, BLE_MESH_TRANSMIT_INT(xmit)); + duration = (BLE_MESH_TRANSMIT_COUNT(xmit) + 1) * (adv_int + 10); + + return duration; +} + +struct net_buf *bt_mesh_adv_create_from_pool(enum bt_mesh_adv_type type, + int32_t timeout) +{ + struct bt_mesh_adv *adv = NULL; + struct net_buf *buf = NULL; + struct net_buf_pool *pool = adv_types[type].pool; + + if (bt_mesh_atomic_test_bit(bt_mesh.flags, BLE_MESH_SUSPENDED)) { + BT_WARN("Refusing to allocate buffer while suspended"); + return NULL; + } + + if (!pool || !adv_types[type].pool_allocator) { + BT_ERR("Uninitialized adv type %d", type); + return NULL; + } + + buf = net_buf_alloc(pool, timeout); + if (!buf) { + BT_WARN("Buf alloc failed"); + return NULL; + } + + BT_DBG("pool %p, buf_count %d, uinit_count %d, ref %d", + buf->pool, pool->buf_count, pool->uninit_count, buf->ref); + + adv = adv_types[type].pool_allocator(net_buf_id(buf)); + BLE_MESH_ADV(buf) = adv; + + (void)memset(adv, 0, sizeof(*adv)); + + adv->type = type; + + return buf; +} + +void bt_mesh_unref_buf_from_pool(struct net_buf_pool *pool) +{ + if (pool == NULL) { + BT_ERR("%s, Invalid parameter", __func__); + return; + } + + for (int i = 0; i < pool->buf_count; i++) { + struct net_buf *buf = &pool->__bufs[i]; + if (buf->ref > 1U) { + buf->ref = 1U; + } + net_buf_unref(buf); + } +} + +void bt_mesh_unref_buf(bt_mesh_msg_t *msg) +{ + struct net_buf *buf = NULL; + + if (msg->arg) { + buf = (struct net_buf *)msg->arg; + bt_mesh_atomic_set(&BLE_MESH_ADV_BUSY(buf), 0); + if (buf->ref > 1U) { + buf->ref = 1U; + } + net_buf_unref(buf); + } +} + +void bt_mesh_generic_adv_send(struct net_buf *buf, uint8_t xmit, + const struct bt_mesh_send_cb *cb, + void *cb_data, uint16_t src, + uint16_t dst, bool front) +{ + bt_mesh_msg_t msg = { + .relay = false, /* useless flag in multi-instance mode */ + }; + + BT_DBG("type 0x%02x len %u: %s", BLE_MESH_ADV(buf)->type, buf->len, + bt_hex(buf->data, buf->len)); + + BLE_MESH_ADV(buf)->cb = cb; + BLE_MESH_ADV(buf)->cb_data = cb_data; + bt_mesh_atomic_set(&BLE_MESH_ADV_BUSY(buf), 1); + BLE_MESH_ADV(buf)->xmit = xmit; + + bt_mesh_adv_buf_ref_debug(__func__, buf, 3U, BLE_MESH_BUF_REF_SMALL); + + msg.arg = (void *)net_buf_ref(buf); + +#if CONFIG_BLE_MESH_RELAY_ADV_BUF + if (BLE_MESH_ADV(buf)->type == BLE_MESH_ADV_RELAY_DATA) { + msg.relay = true; + msg.src = src; + msg.dst = dst; + msg.timestamp = k_uptime_get_32(); + } +#endif + + assert(adv_types[BLE_MESH_ADV(buf)->type].adv_q && adv_types[BLE_MESH_ADV(buf)->type].adv_q->send); + + adv_types[BLE_MESH_ADV(buf)->type].adv_q->send(&msg, portMAX_DELAY, front); + +#if CONFIG_BLE_MESH_SUPPORT_MULTI_ADV + ble_mesh_adv_task_wakeup(ADV_TASK_PKT_SEND_EVT); +#endif +} + +struct bt_mesh_adv_queue *bt_mesh_adv_queue_get(void) +{ + return &adv_queue; +} + +void bt_mesh_task_post(bt_mesh_msg_t *msg, uint32_t timeout, bool front) +{ + if (adv_queue.q.handle == NULL) { + BT_ERR("Invalid adv queue"); + return; + } + + if (front) { + if (xQueueSendToFront(adv_queue.q.handle, msg, timeout) != pdTRUE) { + BT_ERR("Failed to send item to adv queue front"); + bt_mesh_unref_buf(msg); + } + } else { + if (xQueueSend(adv_queue.q.handle, msg, timeout) != pdTRUE) { + BT_ERR("Failed to send item to adv queue back"); + bt_mesh_unref_buf(msg); + } + } +} + +#if CONFIG_BLE_MESH_RELAY_ADV_BUF +bool bt_mesh_ignore_relay_packet(uint32_t timestamp) +{ + uint32_t now = k_uptime_get_32(); + uint32_t interval = 0U; + + if (now >= timestamp) { + interval = now - timestamp; + } else { + interval = BLE_MESH_MAX_TIME_INTERVAL - (timestamp - now) + 1; + } + + return ((interval >= BLE_MESH_RELAY_TIME_INTERVAL) ? true : false); +} + +static struct bt_mesh_adv *relay_adv_alloc(int id) +{ + return &relay_adv_pool[id]; +} + +struct net_buf *bt_mesh_relay_adv_create(enum bt_mesh_adv_type type, int32_t timeout) +{ + return bt_mesh_adv_create_from_pool(type, timeout); +} + +static void ble_mesh_relay_task_post(bt_mesh_msg_t *msg, uint32_t timeout, bool front) +{ + bt_mesh_msg_t old_msg = {0}; + + ARG_UNUSED(front); + + if (relay_adv_queue.q.handle == NULL) { + BT_ERR("Invalid relay queue"); + return; + } + + if (xQueueSend(relay_adv_queue.q.handle, msg, timeout) == pdTRUE) { + return; + } + + /* If failed to send packet to the relay queue(queue is full), we will + * remove the oldest packet in the queue and put the new one into it. + */ + if (uxQueueMessagesWaiting(relay_adv_queue.q.handle)) { + BT_INFO("Full queue, remove the oldest relay packet"); + /* Remove the oldest relay packet from queue */ + if (xQueueReceive(relay_adv_queue.q.handle, &old_msg, K_NO_WAIT) != pdTRUE) { + BT_ERR("Failed to remove item from relay queue"); + bt_mesh_unref_buf(msg); + return; + } + /* Unref buf used for the oldest relay packet */ + bt_mesh_unref_buf(&old_msg); + /* Send the latest relay packet to queue */ + if (xQueueSend(relay_adv_queue.q.handle, msg, K_NO_WAIT) != pdTRUE) { + BT_ERR("Failed to send item to relay queue"); + bt_mesh_unref_buf(msg); + return; + } + } else { + BT_WARN("Empty queue, but failed to send the relay packet"); + bt_mesh_unref_buf(msg); + } +} + +uint16_t bt_mesh_get_stored_relay_count(void) +{ + return (uint16_t)uxQueueMessagesWaiting(relay_adv_queue.q.handle); +} + +void bt_mesh_relay_adv_init(void) +{ + bt_mesh_adv_queue_init(&relay_adv_queue, CONFIG_BLE_MESH_RELAY_ADV_BUF_COUNT, + ble_mesh_relay_task_post); + bt_mesh_adv_type_init(BLE_MESH_ADV_RELAY_DATA, &relay_adv_queue, + &relay_adv_buf_pool, &relay_adv_alloc); +#if CONFIG_BLE_MESH_USE_BLE_50 +#if CONFIG_BLE_MESH_SEPARATE_RELAY_ADV_INSTANCE + bt_mesh_adv_inst_init(BLE_MESH_RELAY_ADV_INS, + CONFIG_BLE_MESH_RELAY_ADV_INST_ID); + bt_mesh_adv_inst_supported_adv_type_add(BLE_MESH_RELAY_ADV_INS, BLE_MESH_ADV_RELAY_DATA); +#else +#if CONFIG_BLE_MESH_SUPPORT_MULTI_ADV + bt_mesh_adv_inst_supported_adv_type_add(BLE_MESH_ADV_INS, BLE_MESH_ADV_RELAY_DATA); +#endif +#endif /* CONFIG_BLE_MESH_SEPARATE_RELAY_ADV_INSTANCE */ +#endif /* CONFIG_BLE_MESH_USE_BLE_50 */ +} +#if CONFIG_BLE_MESH_DEINIT +void bt_mesh_relay_adv_deinit(void) +{ + bt_mesh_adv_queue_deinit(&relay_adv_queue); + bt_mesh_adv_type_deinit(BLE_MESH_ADV_RELAY_DATA); +#if CONFIG_BLE_MESH_USE_BLE_50 +#if CONFIG_BLE_MESH_SEPARATE_RELAY_ADV_INSTANCE + bt_mesh_adv_inst_supported_adv_type_rm(BLE_MESH_RELAY_ADV_INS, BLE_MESH_ADV_RELAY_DATA); + bt_mesh_adv_inst_deinit(BLE_MESH_RELAY_ADV_INS); +#else +#if CONFIG_BLE_MESH_SUPPORT_MULTI_ADV + bt_mesh_adv_inst_supported_adv_type_rm(BLE_MESH_ADV_INS, BLE_MESH_ADV_RELAY_DATA); +#endif +#endif /* CONFIG_BLE_MESH_SEPARATE_RELAY_ADV_INSTANCE */ +#endif /* CONFIG_BLE_MESH_USE_BLE_50 */ + bt_mesh_unref_buf_from_pool(&relay_adv_buf_pool); + memset(relay_adv_pool, 0, sizeof(relay_adv_pool)); +} +#endif /* CONFIG_BLE_MESH_DEINIT */ +#endif /* CONFIG_BLE_MESH_RELAY_ADV_BUF */ + +#if CONFIG_BLE_MESH_FRIEND +struct net_buf_pool *bt_mesh_frnd_adv_pool_get(void) +{ + return &friend_buf_pool; +} + +void bt_mesh_frnd_adv_init(void) +{ + bt_mesh_adv_type_init(BLE_MESH_ADV_FRIEND, &adv_queue, &friend_buf_pool, bt_mesh_frnd_adv_buf_get); +#if CONFIG_BLE_MESH_SUPPORT_MULTI_ADV + bt_mesh_adv_inst_supported_adv_type_add(BLE_MESH_ADV_INS, BLE_MESH_ADV_FRIEND); +#endif /* CONFIG_BLE_MESH_SUPPORT_MULTI_ADV */ +} + +void bt_mesh_frnd_adv_deinit(void) +{ + bt_mesh_adv_type_deinit(BLE_MESH_ADV_FRIEND); + +#if CONFIG_BLE_MESH_FRIEND && CONFIG_BLE_MESH_SUPPORT_MULTI_ADV + bt_mesh_adv_inst_supported_adv_type_rm(BLE_MESH_ADV_INS, BLE_MESH_ADV_FRIEND); +#endif /* CONFIG_BLE_MESH_FRIEND */ + + bt_mesh_unref_buf_from_pool(&friend_buf_pool); + memset(frnd_adv_pool, 0, sizeof(frnd_adv_pool)); +} +#endif /* CONFIG_BLE_MESH_FRIEND */ + +void bt_mesh_adv_task_init(void adv_thread(void *p)) +{ + if (!adv_thread) { + BT_ERR("Invalid param %s", __func__); + return; + } + +#if (CONFIG_BLE_MESH_FREERTOS_STATIC_ALLOC_EXTERNAL && \ + (CONFIG_SPIRAM_CACHE_WORKAROUND || !CONFIG_IDF_TARGET_ESP32) && \ + CONFIG_SPIRAM_ALLOW_STACK_EXTERNAL_MEMORY) + adv_task.task = heap_caps_calloc(1, sizeof(StaticTask_t), MALLOC_CAP_INTERNAL|MALLOC_CAP_8BIT); + __ASSERT(adv_task.task, "Failed to create adv thread task"); + 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); + __ASSERT(adv_task.stack, "Failed to create adv thread stack"); + adv_task.handle = xTaskCreateStaticPinnedToCore(adv_thread, BLE_MESH_ADV_TASK_NAME, BLE_MESH_ADV_TASK_STACK_SIZE, NULL, + BLE_MESH_ADV_TASK_PRIO, adv_task.stack, adv_task.task, BLE_MESH_ADV_TASK_CORE); + __ASSERT(adv_task.handle, "Failed to create static adv thread"); +#else /* CONFIG_BLE_MESH_FREERTOS_STATIC_ALLOC_EXTERNAL && (CONFIG_SPIRAM_CACHE_WORKAROUND || !CONFIG_IDF_TARGET_ESP32) && CONFIG_SPIRAM_ALLOW_STACK_EXTERNAL_MEMORY */ + int ret = xTaskCreatePinnedToCore(adv_thread, BLE_MESH_ADV_TASK_NAME, BLE_MESH_ADV_TASK_STACK_SIZE, NULL, + BLE_MESH_ADV_TASK_PRIO, &adv_task.handle, BLE_MESH_ADV_TASK_CORE); + __ASSERT(ret == pdTRUE, "Failed to create adv thread"); + (void)ret; +#endif /* CONFIG_BLE_MESH_FREERTOS_STATIC_ALLOC_EXTERNAL && (CONFIG_SPIRAM_CACHE_WORKAROUND || !CONFIG_IDF_TARGET_ESP32) && CONFIG_SPIRAM_ALLOW_STACK_EXTERNAL_MEMORY */ +} + +void bt_mesh_adv_common_init(void) +{ + bt_mesh_adv_queue_init(&adv_queue, BLE_MESH_ADV_QUEUE_SIZE, bt_mesh_task_post); + bt_mesh_adv_type_init(BLE_MESH_ADV_PROV, &adv_queue, &adv_buf_pool, adv_alloc); + bt_mesh_adv_type_init(BLE_MESH_ADV_DATA, &adv_queue, &adv_buf_pool, adv_alloc); + bt_mesh_adv_type_init(BLE_MESH_ADV_BEACON, &adv_queue, &adv_buf_pool, adv_alloc); + bt_mesh_adv_type_init(BLE_MESH_ADV_URI, &adv_queue, &adv_buf_pool, adv_alloc); + +#if CONFIG_BLE_MESH_USE_BLE_50 + bt_mesh_adv_inst_init(BLE_MESH_ADV_INS, CONFIG_BLE_MESH_ADV_INST_ID); +#endif + +#if CONFIG_BLE_MESH_SUPPORT_MULTI_ADV + /** + * Due to the limitation of the sequence number in the network layer, + * it is not possible to use multiple advertising instances to process + * data from the same message queue when sending mesh packets. + * + * Therefore, shall to check whether there are + * duplicates in the queue buffer corresponding to each advertising instance. + */ + bt_mesh_adv_inst_supported_adv_type_add(BLE_MESH_ADV_INS, BLE_MESH_ADV_PROV); + bt_mesh_adv_inst_supported_adv_type_add(BLE_MESH_ADV_INS, BLE_MESH_ADV_DATA); + bt_mesh_adv_inst_supported_adv_type_add(BLE_MESH_ADV_INS, BLE_MESH_ADV_BEACON); + bt_mesh_adv_inst_supported_adv_type_add(BLE_MESH_ADV_INS, BLE_MESH_ADV_URI); +#endif +} + +#if CONFIG_BLE_MESH_DEINIT +void bt_mesh_adv_task_deinit(void) +{ + vTaskDelete(adv_task.handle); + adv_task.handle = NULL; + +#if (CONFIG_BLE_MESH_FREERTOS_STATIC_ALLOC_EXTERNAL && \ + (CONFIG_SPIRAM_CACHE_WORKAROUND || !CONFIG_IDF_TARGET_ESP32) && \ + CONFIG_SPIRAM_ALLOW_STACK_EXTERNAL_MEMORY) + heap_caps_free(adv_task.stack); + adv_task.stack = NULL; + heap_caps_free(adv_task.task); + adv_task.task = NULL; +#endif +} + +void bt_mesh_adv_common_deinit(void) +{ + bt_mesh_adv_type_deinit(BLE_MESH_ADV_PROV); + bt_mesh_adv_type_deinit(BLE_MESH_ADV_DATA); + bt_mesh_adv_type_deinit(BLE_MESH_ADV_BEACON); + bt_mesh_adv_type_deinit(BLE_MESH_ADV_URI); + + bt_mesh_adv_queue_deinit(&adv_queue); +#if CONFIG_BLE_MESH_USE_BLE_50 + bt_mesh_adv_inst_deinit(BLE_MESH_ADV_INS); +#endif + + bt_mesh_unref_buf_from_pool(&adv_buf_pool); + memset(adv_pool, 0, sizeof(adv_pool)); +} +#endif /* CONFIG_BLE_MESH_DEINIT */ diff --git a/components/bt/esp_ble_mesh/core/adv_common.h b/components/bt/esp_ble_mesh/core/adv_common.h new file mode 100644 index 00000000000..400ccbec692 --- /dev/null +++ b/components/bt/esp_ble_mesh/core/adv_common.h @@ -0,0 +1,290 @@ +/* Bluetooth Mesh */ + +/* + * SPDX-FileCopyrightText: 2017 Intel Corporation + * SPDX-FileContributor: 2024 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef _ADV_COMMON_H_ +#define _ADV_COMMON_H_ + +#include "mesh/common.h" +#include "mesh/atomic.h" +#include "mesh/access.h" +#include "mesh/adapter.h" +#include "mesh/queue.h" +#include "mesh/timer.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* Pre-5.0 controllers enforce a minimum interval of 100ms + * whereas 5.0+ controllers can go down to 20ms. + */ +#if CONFIG_BLE_MESH_HCI_5_0 +#define ADV_ITVL_MIN 20 +#else +#define ADV_ITVL_MIN 100 +#endif + +/* Convert from ms to 0.625ms units */ +#define ADV_SCAN_UNIT(_ms) ((_ms) * 8 / 5) +/* Convert from 0.625ms units to interval(ms) */ +#define ADV_SCAN_INT(val) ((val) * 5 / 8) + +/* Maximum advertising data payload for a single data type */ +#define BLE_MESH_ADV_DATA_SIZE 29 + +/* The user data is a pointer (4 bytes) to struct bt_mesh_adv */ +#define BLE_MESH_ADV_USER_DATA_SIZE 4 + +#define BLE_MESH_ADV(buf) (*(struct bt_mesh_adv **)net_buf_user_data(buf)) +#define BLE_MESH_ADV_BUSY(buf) (BLE_MESH_ADV(buf)->busy) + +#define BLE_MESH_MSG_NET_BUF(msg) ((struct net_buf *)(msg->arg)) + +#define BLE_MESH_ADV_INS_UNUSED 0xFF + +/* We reserve one queue item for bt_mesh_adv_update() */ +#define BLE_MESH_ADV_QUEUE_SIZE (CONFIG_BLE_MESH_ADV_BUF_COUNT + 1) + +struct bt_mesh_adv { + const struct bt_mesh_send_cb *cb; + void *cb_data; + + uint8_t type; + + bt_mesh_atomic_t busy; + + uint8_t xmit; +}; + +#if CONFIG_BLE_MESH_FRIEND + +#define FRIEND_ADV(buf) CONTAINER_OF(BLE_MESH_ADV(buf), bt_mesh_friend_adv_t, adv) + +typedef struct { + struct bt_mesh_adv adv; + uint16_t app_idx; +} bt_mesh_friend_adv_t; + +#endif + +enum { +#if CONFIG_BLE_MESH_USE_BLE_50 + ADV_TASK_MESH_ADV_INST_EVT = BIT(CONFIG_BLE_MESH_ADV_INST_ID), + +#if CONFIG_BLE_MESH_SUPPORT_MULTI_ADV +#if (CONFIG_BLE_MESH_NODE && CONFIG_BLE_MESH_PB_GATT) || \ + CONFIG_BLE_MESH_GATT_PROXY_SERVER + ADV_TASK_PROX_ADV_INST_EVT = BIT(CONFIG_BLE_MESH_PROXY_ADV_INST_ID), +#endif + +#if CONFIG_BLE_MESH_SEPARATE_RELAY_ADV_INSTANCE + ADV_TASK_RELAY_ADV_INST_EVT = BIT(CONFIG_BLE_MESH_RELAY_ADV_INST_ID), +#endif + +#if CONFIG_BLE_MESH_SEPARATE_BLE_ADV_INSTANCE + ADV_TASK_BLE_ADV_INST_EVT = BIT(CONFIG_BLE_MESH_BLE_ADV_INST_ID), +#endif +#endif /* CONFIG_BLE_MESH_SUPPORT_MULTI_ADV */ +#if (CONFIG_BLE_MESH_NODE && CONFIG_BLE_MESH_PB_GATT) || \ + CONFIG_BLE_MESH_GATT_PROXY_SERVER + ADV_TASK_PROXY_ADV_UPD_EVT = BIT(30), +#endif +#endif /* CONFIG_BLE_MESH_USE_BLE_50 */ + ADV_TASK_PKT_SEND_EVT = BIT(31), + ADV_TASK_EVT_MAX, +}; + +uint16_t bt_mesh_pdu_duration(uint8_t xmit); + +typedef struct bt_mesh_msg { + bool relay; /* Flag indicates if the packet is a relayed one */ + void *arg; /* Pointer to the struct net_buf */ + uint16_t src; /* Source address for relay packets */ + uint16_t dst; /* Destination address for relay packets */ + uint32_t timestamp; /* Timestamp recorded when the relay packet is posted to queue */ +} bt_mesh_msg_t; + +typedef struct bt_mesh_adv *(*bt_mesh_pool_allocator_t)(int id); +typedef void (*bt_mesh_adv_queue_send_cb_t)(bt_mesh_msg_t *msg, uint32_t timeout, bool front); + +struct bt_mesh_adv_queue { + bt_mesh_queue_t q; + bt_mesh_adv_queue_send_cb_t send; +}; + +struct bt_mesh_adv_inst { + uint8_t id; +#if CONFIG_BLE_MESH_SUPPORT_MULTI_ADV + bool busy; + struct net_buf *sending_buf; + + /* indicates that which adv_type is supported by this instance */ + uint32_t spt_mask; +#endif /* CONFIG_BLE_MESH_SUPPORT_MULTI_ADV */ +}; + +enum bt_mesh_adv_type { + BLE_MESH_ADV_PROV, + BLE_MESH_ADV_DATA, +#if CONFIG_BLE_MESH_FRIEND + BLE_MESH_ADV_FRIEND, +#endif +#if CONFIG_BLE_MESH_RELAY_ADV_BUF + BLE_MESH_ADV_RELAY_DATA, +#endif + BLE_MESH_ADV_BEACON, + BLE_MESH_ADV_URI, +#if CONFIG_BLE_MESH_SUPPORT_BLE_ADV + BLE_MESH_ADV_BLE, +#endif + BLE_MESH_ADV_TYPES_NUM, +}; + +typedef enum { + BLE_MESH_BUF_REF_EQUAL, + BLE_MESH_BUF_REF_SMALL, + BLE_MESH_BUF_REF_MAX, +} bt_mesh_buf_ref_flag_t; + +struct bt_mesh_adv_type_manager { + struct bt_mesh_adv_queue *adv_q; + struct net_buf_pool *pool; + bt_mesh_pool_allocator_t pool_allocator; +}; + +static const uint8_t adv_type[] = { + [BLE_MESH_ADV_PROV] = BLE_MESH_DATA_MESH_PROV, + [BLE_MESH_ADV_DATA] = BLE_MESH_DATA_MESH_MESSAGE, +#if CONFIG_BLE_MESH_FRIEND + [BLE_MESH_ADV_FRIEND] = BLE_MESH_DATA_MESH_MESSAGE, +#endif +#if CONFIG_BLE_MESH_RELAY_ADV_BUF + [BLE_MESH_ADV_RELAY_DATA] = BLE_MESH_DATA_MESH_MESSAGE, +#endif + [BLE_MESH_ADV_BEACON] = BLE_MESH_DATA_MESH_BEACON, + [BLE_MESH_ADV_URI] = BLE_MESH_DATA_URI, +}; + +static inline TickType_t K_WAIT(int32_t val) +{ + return (val == K_FOREVER) ? portMAX_DELAY : (val / portTICK_PERIOD_MS); +} + +struct bt_mesh_adv_queue *bt_mesh_adv_queue_get(void); + +struct net_buf *bt_mesh_adv_create_from_pool(enum bt_mesh_adv_type type, + int32_t timeout); + +static inline struct net_buf *bt_mesh_adv_create(enum bt_mesh_adv_type type, int32_t timeout) +{ + return bt_mesh_adv_create_from_pool(type, timeout); +} + +void bt_mesh_adv_buf_ref_debug(const char *func, struct net_buf *buf, + uint8_t ref_cmp, bt_mesh_buf_ref_flag_t flag); + +struct bt_mesh_adv_type_manager *bt_mesh_adv_types_mgnt_get(enum bt_mesh_adv_type adv_type); + +void bt_mesh_generic_adv_send(struct net_buf *buf, uint8_t xmit, + const struct bt_mesh_send_cb *cb, + void *cb_data, uint16_t src, + uint16_t dst, bool front); + +void bt_mesh_unref_buf_from_pool(struct net_buf_pool *pool); +void bt_mesh_unref_buf(bt_mesh_msg_t *msg); + +int bt_mesh_adv_queue_init(struct bt_mesh_adv_queue *adv_queue, + uint16_t queue_size, + bt_mesh_adv_queue_send_cb_t cb); + +int bt_mesh_adv_queue_deinit(struct bt_mesh_adv_queue *adv_queue); + +void bt_mesh_adv_type_init(enum bt_mesh_adv_type adv_type, + struct bt_mesh_adv_queue *adv_queue, + struct net_buf_pool *buf_pool, + bt_mesh_pool_allocator_t adv_alloc); + +void bt_mesh_adv_type_deinit(enum bt_mesh_adv_type adv_type); + +void bt_mesh_task_post(bt_mesh_msg_t *msg, uint32_t timeout, bool front); + +#if CONFIG_BLE_MESH_USE_BLE_50 +struct bt_mesh_adv_inst * bt_mesh_get_adv_insts_set(void); +int bt_mesh_adv_inst_init(enum bt_mesh_adv_inst_type inst_type, uint8_t inst_id); +int bt_mesh_adv_inst_deinit(enum bt_mesh_adv_inst_type inst_type); +#endif /* CONFIG_BLE_MESH_USE_BLE_50 */ + +#if CONFIG_BLE_MESH_SUPPORT_MULTI_ADV +void bt_mesh_adv_inst_supported_adv_type_add(enum bt_mesh_adv_inst_type inst_type, + enum bt_mesh_adv_type adv_type); + +void bt_mesh_adv_inst_supported_adv_type_rm(enum bt_mesh_adv_inst_type inst_type, + enum bt_mesh_adv_type adv_type); + +void bt_mesh_adv_inst_supported_adv_type_clear(enum bt_mesh_adv_inst_type inst_type, + enum bt_mesh_adv_type adv_type); +#endif + +#if CONFIG_BLE_MESH_RELAY_ADV_BUF +void bt_mesh_relay_adv_init(void); +bool bt_mesh_ignore_relay_packet(uint32_t timestamp); +struct net_buf *bt_mesh_relay_adv_create(enum bt_mesh_adv_type type, int32_t timeout); + +static inline void bt_mesh_relay_adv_send(struct net_buf *buf, uint8_t xmit, + uint16_t src, uint16_t dst, + const struct bt_mesh_send_cb *cb, + void *cb_data) +{ + bt_mesh_generic_adv_send(buf, xmit, cb, cb_data, src, dst, false); +}; + +uint16_t bt_mesh_get_stored_relay_count(void); + +#if CONFIG_BLE_MESH_DEINIT +void bt_mesh_relay_adv_deinit(void); +#endif +#endif /* CONFIG_BLE_MESH_RELAY_ADV_BUF */ + +#if CONFIG_BLE_MESH_FRIEND +struct bt_mesh_adv *bt_mesh_frnd_adv_buf_get(int id); +struct net_buf_pool *bt_mesh_frnd_adv_pool_get(void); +void bt_mesh_frnd_adv_init(void); +#if CONFIG_BLE_MESH_DEINIT +void bt_mesh_frnd_adv_deinit(void); +#endif /* CONFIG_BLE_MESH_DEINIT */ +#endif /* CONFIG_BLE_MESH_FRIEND */ + +void bt_mesh_adv_task_init(void adv_thread(void *p)); +void bt_mesh_adv_common_init(void); + +#if CONFIG_BLE_MESH_DEINIT +void bt_mesh_adv_task_deinit(void); +void bt_mesh_adv_common_deinit(void); +#endif + +#if CONFIG_BLE_MESH_USE_BLE_50 +bool bt_mesh_is_adv_inst_used(uint8_t adv_inst_id); +bool ble_mesh_adv_task_wait(uint32_t wait_bits, TickType_t timeout, uint32_t *notify); +int ble_mesh_adv_task_wakeup(uint32_t evt); +#else +bool ble_mesh_adv_task_wait(uint32_t timeout); +#endif + +#if CONFIG_BLE_MESH_SUPPORT_BLE_ADV +int bt_mesh_start_ble_advertising(const struct bt_mesh_ble_adv_param *param, + const struct bt_mesh_ble_adv_data *data, uint8_t *index); + +int bt_mesh_stop_ble_advertising(uint8_t index); +#endif /* CONFIG_BLE_MESH_SUPPORT_BLE_ADV */ + +#ifdef __cplusplus +} +#endif + +#endif /* _ADV_COMMON_H_ */ diff --git a/components/bt/esp_ble_mesh/core/ble_adv.c b/components/bt/esp_ble_mesh/core/ble_adv.c new file mode 100644 index 00000000000..ec99efa09c1 --- /dev/null +++ b/components/bt/esp_ble_mesh/core/ble_adv.c @@ -0,0 +1,323 @@ +/* Bluetooth Mesh */ + +/* + * SPDX-FileCopyrightText: 2017 Intel Corporation + * SPDX-FileContributor: 2018-2024 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include + +#include "ble_adv.h" +#include "mesh/common.h" +#include "mesh/buf.h" + +#if CONFIG_BLE_MESH_SUPPORT_BLE_ADV + +static struct bt_mesh_adv_queue ble_adv_queue; +#define BLE_MESH_BLE_ADV_QUEUE_SIZE (CONFIG_BLE_MESH_BLE_ADV_BUF_COUNT + 1) +/* length + advertising data + length + scan response data */ +NET_BUF_POOL_DEFINE(ble_adv_buf_pool, CONFIG_BLE_MESH_BLE_ADV_BUF_COUNT, + ((BLE_MESH_ADV_DATA_SIZE + 3) << 1), BLE_MESH_ADV_USER_DATA_SIZE, NULL); + +static struct bt_mesh_adv ble_adv_pool[CONFIG_BLE_MESH_BLE_ADV_BUF_COUNT]; + +static struct bt_mesh_ble_adv_tx ble_adv_tx[CONFIG_BLE_MESH_BLE_ADV_BUF_COUNT]; + +#define SEND_BLE_ADV_INFINITE 0xFFFF + +static void bt_mesh_ble_task_post(bt_mesh_msg_t *msg, uint32_t timeout, bool front); + +static struct bt_mesh_adv *ble_adv_alloc(int id) +{ + return &ble_adv_pool[id]; +} + +static void bt_mesh_ble_task_post(bt_mesh_msg_t *msg, uint32_t timeout, bool front) +{ + BT_DBG("%s", __func__); + + if (ble_adv_queue.q.handle == NULL) { + BT_ERR("Invalid adv queue"); + return; + } + + if (front) { + if (xQueueSendToFront(ble_adv_queue.q.handle, msg, timeout) != pdTRUE) { + BT_ERR("Failed to send item to adv queue front"); + bt_mesh_unref_buf(msg); + } + } else { + if (xQueueSend(ble_adv_queue.q.handle, msg, timeout) != pdTRUE) { + BT_ERR("Failed to send item to adv queue back"); + bt_mesh_unref_buf(msg); + } + } +} + +static struct net_buf *bt_mesh_ble_adv_create(enum bt_mesh_adv_type type, int32_t timeout) +{ + return bt_mesh_adv_create_from_pool(type, timeout); +} + +inline void bt_mesh_ble_adv_send(struct net_buf *buf, const struct bt_mesh_send_cb *cb, + void *cb_data, bool front) +{ + bt_mesh_generic_adv_send(buf, 0, cb, cb_data, BLE_MESH_ADDR_UNASSIGNED, BLE_MESH_ADDR_UNASSIGNED, front); +} + +static void ble_adv_tx_reset(struct bt_mesh_ble_adv_tx *tx, bool unref) +{ + if (tx->buf == NULL) { + return; + } + + if (bt_mesh_atomic_test_bit(tx->flags, TIMER_INIT)) { + k_delayed_work_free(&tx->resend); + } + bt_mesh_atomic_set(tx->flags, 0); + memset(&tx->param, 0, sizeof(tx->param)); + bt_mesh_atomic_set(&BLE_MESH_ADV_BUSY(tx->buf), 0); + if (unref) { + net_buf_unref(tx->buf); + } + tx->buf = NULL; +} + +static void ble_adv_send_start(uint16_t duration, int err, void *cb_data) +{ + struct bt_mesh_ble_adv_tx *tx = cb_data; + + BT_DBG("%s, duration %d, err %d", __func__, duration, err); + + /* If failed to send BLE adv packet, and param->count is not 0 + * which means the timer has been initialized, here we need to + * free the timer. + */ + if (err) { + ble_adv_tx_reset(tx, true); + } +} + +static void ble_adv_send_end(int err, void *cb_data) +{ + struct bt_mesh_ble_adv_tx *tx = cb_data; + + BT_DBG("%s, err %d", __func__, err); + + if (err) { + ble_adv_tx_reset(tx, true); + return; + } + + if (tx->param.count) { + if (tx->param.period) { + k_delayed_work_submit(&tx->resend, tx->param.period); + } else { + k_work_submit(&tx->resend.work); + } + } else { + ble_adv_tx_reset(tx, true); + } +} + +static struct bt_mesh_send_cb ble_adv_send_cb = { + .start = ble_adv_send_start, + .end = ble_adv_send_end, +}; + +static void ble_adv_resend(struct k_work *work) +{ + struct bt_mesh_ble_adv_tx *tx = CONTAINER_OF(work, struct bt_mesh_ble_adv_tx, resend.work); + bool front = false; + + if (tx->buf == NULL) { + /* The advertising has been cancelled */ + return; + } + + front = (tx->param.priority == BLE_MESH_BLE_ADV_PRIO_HIGH) ? true : false; + bt_mesh_ble_adv_send(tx->buf, &ble_adv_send_cb, tx, front); + + if (tx->param.count == SEND_BLE_ADV_INFINITE) { + /* Send the BLE advertising packet infinitely */ + return; + } + + if (tx->param.count > 0U) { + tx->param.count--; + } +} + +int bt_mesh_start_ble_advertising(const struct bt_mesh_ble_adv_param *param, + const struct bt_mesh_ble_adv_data *data, uint8_t *index) +{ + struct bt_mesh_ble_adv_tx *tx = NULL; + struct net_buf *buf = NULL; + bool front = false; + + if (param == NULL || index == NULL) { + BT_ERR("%s, Invalid parameter", __func__); + return -EINVAL; + } + + if (param->adv_type != BLE_MESH_ADV_DIRECT_IND && + (param->interval < 0x20 || param->interval > 0x4000)) { + BT_ERR("Invalid adv interval 0x%04x", param->interval); + return -EINVAL; + } + + if (param->adv_type > BLE_MESH_ADV_DIRECT_IND_LOW_DUTY) { + BT_ERR("Invalid adv type 0x%02x", param->adv_type); + return -EINVAL; + } + + if (param->own_addr_type > BLE_MESH_ADDR_RANDOM_ID) { + BT_ERR("Invalid own addr type 0x%02x", param->own_addr_type); + return -EINVAL; + } + + if ((param->own_addr_type == BLE_MESH_ADDR_PUBLIC_ID || + param->own_addr_type == BLE_MESH_ADDR_RANDOM_ID || + param->adv_type == BLE_MESH_ADV_DIRECT_IND || + param->adv_type == BLE_MESH_ADV_DIRECT_IND_LOW_DUTY) && + param->peer_addr_type > BLE_MESH_ADDR_RANDOM) { + BT_ERR("Invalid peer addr type 0x%02x", param->peer_addr_type); + return -EINVAL; + } + + if (data && (data->adv_data_len > 31 || data->scan_rsp_data_len > 31)) { + BT_ERR("Invalid adv data length (adv %d, scan rsp %d)", + data->adv_data_len, data->scan_rsp_data_len); + return -EINVAL; + } + + if (param->priority > BLE_MESH_BLE_ADV_PRIO_HIGH) { + BT_ERR("Invalid adv priority %d", param->priority); + return -EINVAL; + } + + if (param->duration < ADV_SCAN_INT(param->interval)) { + BT_ERR("Too small duration %dms", param->duration); + return -EINVAL; + } + + buf = bt_mesh_ble_adv_create(BLE_MESH_ADV_BLE, K_NO_WAIT); + if (!buf) { + BT_ERR("No empty ble adv buffer"); + return -ENOBUFS; + } + + /* Set advertising data and scan response data */ + memset(buf->data, 0, buf->size); + if (data) { + net_buf_add_u8(buf, data->adv_data_len); + if (data->adv_data_len) { + net_buf_add_mem(buf, data->adv_data, data->adv_data_len); + } + net_buf_add_u8(buf, data->scan_rsp_data_len); + if (data->scan_rsp_data_len) { + net_buf_add_mem(buf, data->scan_rsp_data, data->scan_rsp_data_len); + } + } + + *index = net_buf_id(buf); + tx = &ble_adv_tx[*index]; + tx->buf = buf; + memcpy(&tx->param, param, sizeof(tx->param)); + + front = (tx->param.priority == BLE_MESH_BLE_ADV_PRIO_HIGH) ? true : false; + bt_mesh_ble_adv_send(buf, &ble_adv_send_cb, tx, front); + if (param->count) { + if (k_delayed_work_init(&tx->resend, ble_adv_resend)) { + /* If failed to create a timer, the BLE adv packet will be + * sent only once. Just give a warning here, and since the + * BLE adv packet can be sent, return 0 here. + */ + BT_WARN("Send BLE adv packet only once"); + tx->param.count = 0; + net_buf_unref(buf); + return 0; + } + bt_mesh_atomic_set_bit(tx->flags, TIMER_INIT); + } else { + /* Send the BLE advertising packet only once */ + net_buf_unref(buf); + } + + return 0; +} + +int bt_mesh_stop_ble_advertising(uint8_t index) +{ + struct bt_mesh_ble_adv_tx *tx = NULL; + bool unref = true; + + if (index >= ARRAY_SIZE(ble_adv_tx)) { + BT_ERR("Invalid adv index %d", index); + return -EINVAL; + } + + tx = &ble_adv_tx[index]; + + if (tx->buf == NULL) { + BT_WARN("Already stopped, index %d", index); + return 0; + } + + /* busy 1, ref 1; busy 1, ref 2; + * busy 0, ref 0; busy 0, ref 1; + */ + + if (bt_mesh_atomic_get(&BLE_MESH_ADV_BUSY(tx->buf)) && + tx->buf->ref == 1U) { + unref = false; + } + ble_adv_tx_reset(tx, unref); + + return 0; +} + +void bt_mesh_ble_adv_init(void) +{ + bt_mesh_adv_queue_init(&ble_adv_queue, CONFIG_BLE_MESH_BLE_ADV_BUF_COUNT, bt_mesh_ble_task_post); + bt_mesh_adv_type_init(BLE_MESH_ADV_BLE, &ble_adv_queue, &ble_adv_buf_pool, ble_adv_alloc); +#if CONFIG_BLE_MESH_USE_BLE_50 +#if CONFIG_BLE_MESH_SEPARATE_BLE_ADV_INSTANCE + bt_mesh_adv_inst_init(BLE_MESH_BLE_ADV_INS, CONFIG_BLE_MESH_BLE_ADV_INST_ID); + bt_mesh_adv_inst_supported_adv_type_add(BLE_MESH_BLE_ADV_INS, BLE_MESH_ADV_BLE); +#else +#if CONFIG_BLE_MESH_SUPPORT_MULTI_ADV + bt_mesh_adv_inst_supported_adv_type_add(BLE_MESH_ADV_INS, BLE_MESH_ADV_BLE); +#endif +#endif /* CONFIG_BLE_MESH_SEPARATE_BLE_ADV_INSTANCE */ +#endif /* CONFIG_BLE_MESH_USE_BLE_50 */ +} + +#if CONFIG_BLE_MESH_DEINIT +void bt_mesh_ble_adv_deinit(void) +{ + for (int i = 0; i < ARRAY_SIZE(ble_adv_tx); i++) { + struct bt_mesh_ble_adv_tx *tx = &ble_adv_tx[i]; + ble_adv_tx_reset(tx, false); + } + bt_mesh_unref_buf_from_pool(&ble_adv_buf_pool); + memset(ble_adv_pool, 0, sizeof(ble_adv_pool)); + + bt_mesh_adv_queue_deinit(&ble_adv_queue); + bt_mesh_adv_type_deinit(BLE_MESH_ADV_BLE); +#if CONFIG_BLE_MESH_USE_BLE_50 +#if CONFIG_BLE_MESH_SEPARATE_BLE_ADV_INSTANCE + bt_mesh_adv_inst_deinit(BLE_MESH_BLE_ADV_INS); + bt_mesh_adv_inst_supported_adv_type_rm(BLE_MESH_BLE_ADV_INS, BLE_MESH_ADV_BLE); +#else +#if CONFIG_BLE_MESH_SUPPORT_MULTI_ADV + bt_mesh_adv_inst_supported_adv_type_rm(BLE_MESH_ADV_INS, BLE_MESH_ADV_BLE); +#endif +#endif /* CONFIG_BLE_MESH_SEPARATE_BLE_ADV_INSTANCE */ +#endif /* CONFIG_BLE_MESH_USE_BLE_50 */ +} +#endif /* CONFIG_BLE_MESH_DEINIT */ +#endif /* CONFIG_BLE_MESH_SUPPORT_BLE_ADV */ diff --git a/components/bt/esp_ble_mesh/core/ble_adv.h b/components/bt/esp_ble_mesh/core/ble_adv.h new file mode 100644 index 00000000000..733320d6087 --- /dev/null +++ b/components/bt/esp_ble_mesh/core/ble_adv.h @@ -0,0 +1,54 @@ +/* Bluetooth Mesh */ + +/* + * SPDX-FileCopyrightText: 2017 Intel Corporation + * SPDX-FileContributor: 2018-2024 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef _BLE_ADV_H_ +#define _BLE_ADV_H_ + +#include "mesh/atomic.h" +#include "mesh/access.h" +#include "mesh/adapter.h" +#include "mesh/utils.h" +#include "adv_common.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#if CONFIG_BLE_MESH_SUPPORT_BLE_ADV + +enum { + TIMER_INIT, /* Resend timer is initialized */ + NUM_FLAGS, +}; + +struct bt_mesh_ble_adv_tx { + struct bt_mesh_ble_adv_param param; + struct net_buf *buf; + struct k_delayed_work resend; + BLE_MESH_ATOMIC_DEFINE(flags, NUM_FLAGS); +}; + +int bt_mesh_start_ble_advertising(const struct bt_mesh_ble_adv_param *param, + const struct bt_mesh_ble_adv_data *data, uint8_t *index); + +int bt_mesh_stop_ble_advertising(uint8_t index); + +void bt_mesh_ble_adv_init(void); + +#if CONFIG_BLE_MESH_DEINIT +void bt_mesh_ble_adv_deinit(void); +#endif + +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* _BLE_ADV_H_ */ diff --git a/components/bt/esp_ble_mesh/core/bluedroid_host/adapter.c b/components/bt/esp_ble_mesh/core/bluedroid_host/adapter.c index 5664c9b6ccf..89dcd9ef901 100644 --- a/components/bt/esp_ble_mesh/core/bluedroid_host/adapter.c +++ b/components/bt/esp_ble_mesh/core/bluedroid_host/adapter.c @@ -109,7 +109,9 @@ static struct bt_mesh_prov_conn_cb *bt_mesh_gattc_conn_cb; static tBTA_GATTC_IF bt_mesh_gattc_if; #endif -#if CONFIG_BLE_MESH_USE_BLE_50 && CONFIG_BLE_MESH_SUPPORT_BLE_ADV +#if CONFIG_BLE_MESH_USE_BLE_50 && \ + CONFIG_BLE_MESH_SUPPORT_BLE_ADV && \ + (!CONFIG_BLE_MESH_SUPPORT_MULTI_ADV) static inline void bt_mesh_set_ble_adv_running(); static inline void bt_mesh_unset_ble_adv_running(); @@ -334,9 +336,12 @@ void ble_mesh_5_gap_callback(tBTA_DM_BLE_5_GAP_EVENT event, if (!bt_mesh_is_adv_inst_used(params->adv_term.adv_handle)) { goto transfer_to_user; } +#if CONFIG_BLE_MESH_SUPPORT_MULTI_ADV + ble_mesh_adv_task_wakeup(ADV_TASK_ADV_INST_EVT(params->adv_term.adv_handle)); +#else /* CONFIG_BLE_MESH_SUPPORT_MULTI_ADV */ if (params->adv_term.status == 0x43 || /* Limit reached */ params->adv_term.status == 0x3C) { /* Advertising timeout */ - ble_mesh_adv_task_wakeup(params->adv_term.adv_handle); + ble_mesh_adv_task_wakeup(ADV_TASK_MESH_ADV_INST_EVT); } #if CONFIG_BLE_MESH_SUPPORT_BLE_ADV /** @@ -359,9 +364,10 @@ void ble_mesh_5_gap_callback(tBTA_DM_BLE_5_GAP_EVENT event, * could lead to resource contention issues. */ bt_mesh_unset_ble_adv_running(); - ble_mesh_adv_task_wakeup(params->adv_term.adv_handle); + ble_mesh_adv_task_wakeup(ADV_TASK_MESH_ADV_INST_EVT); } #endif /* CONFIG_BLE_MESH_SUPPORT_BLE_ADV */ +#endif /* CONFIG_BLE_MESH_SUPPORT_MULTI_ADV */ break; case BTA_DM_BLE_5_GAP_EXT_ADV_REPORT_EVT: if (!bt_mesh_scan_result_process(¶ms->ext_adv_report)) { @@ -821,7 +827,7 @@ int bt_le_adv_start(const struct bt_mesh_adv_param *param, #if CONFIG_BLE_MESH_SUPPORT_BLE_ADV #if CONFIG_BLE_MESH_USE_BLE_50 - +#if !CONFIG_BLE_MESH_SUPPORT_MULTI_ADV static bool _ble_adv_running_flag; static inline void bt_mesh_set_ble_adv_running() @@ -838,6 +844,7 @@ static inline bool bt_mesh_is_ble_adv_running() { return _ble_adv_running_flag == true; } +#endif /* !CONFIG_BLE_MESH_SUPPORT_MULTI_ADV */ int bt_mesh_ble_ext_adv_start(const uint8_t inst_id, const struct bt_mesh_ble_adv_param *param, @@ -903,7 +910,9 @@ int bt_mesh_ble_ext_adv_start(const uint8_t inst_id, BTA_DmBleGapExtAdvEnable(true, 1, &ext_adv); +#if !CONFIG_BLE_MESH_SUPPORT_MULTI_ADV bt_mesh_set_ble_adv_running(); +#endif return 0; } diff --git a/components/bt/esp_ble_mesh/core/ext_adv.c b/components/bt/esp_ble_mesh/core/ext_adv.c new file mode 100644 index 00000000000..3a2e4af2d08 --- /dev/null +++ b/components/bt/esp_ble_mesh/core/ext_adv.c @@ -0,0 +1,409 @@ +/* Bluetooth Mesh */ + +/* + * SPDX-FileCopyrightText: 2017 Intel Corporation + * SPDX-FileContributor: 2018-2024 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include + +#include "mesh/kernel.h" +#include "mesh.h" +#include "mesh/hci.h" +#include "mesh/common.h" +#include "mesh/ffs.h" +#include "ext_adv.h" +#include "beacon.h" +#include "prov_common.h" +#include "foundation.h" +#include "proxy_server.h" +#include "proxy_client.h" +#include "prov_pvnr.h" +#include "mesh/adapter.h" + +#include "adv_common.h" +#include "ble_adv.h" + +static struct bt_mesh_adv_queue *adv_queue; + +static struct bt_mesh_adv_inst *adv_insts; + +static inline void adv_send_start(uint16_t duration, int err, + const struct bt_mesh_send_cb *cb, + void *cb_data) +{ + if (cb && cb->start) { + cb->start(duration, err, cb_data); + } +} + +static inline void adv_send_end(int err, const struct bt_mesh_send_cb *cb, + void *cb_data) +{ + if (cb && cb->end) { + cb->end(err, cb_data); + } +} + +static inline int adv_send(struct bt_mesh_adv_inst *inst, uint16_t *adv_duration) +{ + struct net_buf *buf = inst->sending_buf; + const struct bt_mesh_send_cb *cb = BLE_MESH_ADV(buf)->cb; + void *cb_data = BLE_MESH_ADV(buf)->cb_data; + struct bt_mesh_adv_param param = {0}; + uint16_t duration = 0U, adv_int = 0U; + struct bt_mesh_adv_data ad = {0}; + int err = 0; + + BT_DBG("type %u len %u: %s", BLE_MESH_ADV(buf)->type, + buf->len, bt_hex(buf->data, buf->len)); + + switch (BLE_MESH_ADV(buf)->type) { + case BLE_MESH_ADV_PROV: + case BLE_MESH_ADV_DATA: +#if CONFIG_BLE_MESH_RELAY_ADV_BUF + case BLE_MESH_ADV_RELAY_DATA: +#endif + case BLE_MESH_ADV_BEACON: + case BLE_MESH_ADV_URI: { + adv_int = MAX(ADV_ITVL_MIN, + BLE_MESH_TRANSMIT_INT(BLE_MESH_ADV(buf)->xmit)); + duration = (BLE_MESH_TRANSMIT_COUNT(BLE_MESH_ADV(buf)->xmit) + 1) * + (adv_int + 10); + + BT_DBG("count %u interval %ums duration %ums", + BLE_MESH_TRANSMIT_COUNT(BLE_MESH_ADV(buf)->xmit) + 1, adv_int, + duration); + + ad.type = adv_type[BLE_MESH_ADV(buf)->type]; + ad.data_len = buf->len; + ad.data = buf->data; + + param.options = 0U; + param.interval_min = ADV_SCAN_UNIT(adv_int); + param.interval_max = param.interval_min; + + param.adv_duration = duration; + param.adv_count = BLE_MESH_TRANSMIT_COUNT(BLE_MESH_ADV(buf)->xmit) + 1; + + param.primary_phy = BLE_MESH_ADV_PHY_1M; + param.secondary_phy = BLE_MESH_ADV_PHY_1M; + + bt_mesh_adv_buf_ref_debug(__func__, buf, 4U, BLE_MESH_BUF_REF_SMALL); + + err = bt_le_ext_adv_start(inst->id, ¶m, &ad, 1, NULL, 0); + } + break; +#if CONFIG_BLE_MESH_SUPPORT_BLE_ADV + case BLE_MESH_ADV_BLE: + struct bt_mesh_ble_adv_data data = {0}; + struct bt_mesh_ble_adv_tx *tx = cb_data; + + if (tx == NULL) { + BT_ERR("Invalid adv user data"); + net_buf_unref(buf); + return -EINVAL; + } + + BT_DBG("interval %dms, duration %dms, period %dms, count %d", + ADV_SCAN_INT(tx->param.interval), tx->param.duration, + tx->param.period, tx->param.count); + + data.adv_data_len = tx->buf->data[0]; + if (data.adv_data_len) { + memcpy(data.adv_data, tx->buf->data + 1, data.adv_data_len); + } + data.scan_rsp_data_len = tx->buf->data[data.adv_data_len + 1]; + if (data.scan_rsp_data_len) { + memcpy(data.scan_rsp_data, tx->buf->data + data.adv_data_len + 2, data.scan_rsp_data_len); + } + duration = tx->param.duration; + + bt_mesh_adv_buf_ref_debug(__func__, buf, 3U, BLE_MESH_BUF_REF_SMALL); + + err = bt_mesh_ble_ext_adv_start(inst->id, &tx->param, &data); + break; +#endif + default: + BT_ERR("Error Type"); + break; + } + + adv_send_start(duration, err, cb, cb_data); + if (err) { + BT_ERR("Start advertising failed: err %d", err); + return err; + } + + *adv_duration = duration; + BT_DBG("Advertising started. %u ms", duration); + return 0; +} + +static inline int find_valid_msg_from_queue(bt_mesh_queue_t *msg_queue, bt_mesh_msg_t *msg) +{ + while(uxQueueMessagesWaiting(msg_queue->handle)) { + xQueueReceive(msg_queue->handle, msg, K_WAIT(K_FOREVER)); + + /* In the previous adv task design, only + * the *buf of messages pushed to the queue + * by adv_update would be empty, but in the + * new design, there is a new processing method + * for adv_update's messages, + * so *buf here cannot be empty. */ + assert(msg->arg); + + /* If the message is canceled for advertising, + * then continue to retrieve the next message + * from that queue. */ + if (!bt_mesh_atomic_cas(&BLE_MESH_ADV_BUSY(BLE_MESH_MSG_NET_BUF(msg)), 1, 0)) { + bt_mesh_adv_buf_ref_debug(__func__, BLE_MESH_MSG_NET_BUF(msg), 1U, BLE_MESH_BUF_REF_EQUAL); + /* Cancel the adv task's reference to this data packet. + * tips: The reference of buffer by adv_task occurs + * when the buffer is pushed into the queue. + */ + net_buf_unref(BLE_MESH_MSG_NET_BUF(msg)); + /* Avoid reading the last message in the queue, which could lead + * to pointing to an invalid buffer due to the absence of other + * messages in the queue. */ + msg->arg = NULL; + continue; + } + +#if CONFIG_BLE_MESH_RELAY_ADV_BUF + /* If the relay message should be ignored, + * then continue to retrieve the next message + * from that queue. */ + if (msg->relay && bt_mesh_ignore_relay_packet(msg->timestamp)) { + /* If the interval between "current time - msg.timestamp" is bigger than + * BLE_MESH_RELAY_TIME_INTERVAL, this relay packet will not be sent. + */ + BT_DBG("Ignore relay packet"); + net_buf_unref(BLE_MESH_MSG_NET_BUF(msg)); + msg->arg = NULL; + continue; + } +#endif + break; + } + + if (msg->arg == NULL) { + return -EINVAL; + } + + return 0; +} + +static inline int active_idle_adv_instance(uint32_t *update_evts, uint16_t *min_duration) +{ + uint32_t evts = 0; + uint16_t duration = K_FOREVER; + uint16_t cur_min_duration = K_FOREVER; + enum bt_mesh_adv_type adv_type = 0; + struct bt_mesh_adv_inst *instance = NULL; + bt_mesh_queue_t *msg_queue = NULL; + bt_mesh_msg_t msg = {0}; + uint32_t spt_mask = 0; + +#if (CONFIG_BLE_MESH_NODE && CONFIG_BLE_MESH_PB_GATT) || \ + CONFIG_BLE_MESH_GATT_PROXY_SERVER + if (!adv_insts[BLE_MESH_ADV_PROXY_INS].busy) { + BT_DBG("Mesh Proxy Advertising start"); + duration = bt_mesh_proxy_server_adv_start(); + if (duration < cur_min_duration) { + cur_min_duration = duration; + } + adv_insts[BLE_MESH_ADV_PROXY_INS].busy = true; + evts |= ADV_TASK_ADV_INST_EVT(adv_insts[BLE_MESH_ADV_PROXY_INS].id); + } +#endif + + for (int i = BLE_MESH_ADV_INS; i < BLE_MESH_ADV_INS_TYPES_NUM; i++) { + instance = &adv_insts[i]; + if (instance->busy +#if (CONFIG_BLE_MESH_NODE && CONFIG_BLE_MESH_PB_GATT) || \ + CONFIG_BLE_MESH_GATT_PROXY_SERVER + || unlikely(instance->id == CONFIG_BLE_MESH_PROXY_ADV_INST_ID) +#endif + ) { + continue; + } + + spt_mask = instance->spt_mask; + adv_type = 0; + + while(spt_mask) { + adv_type = find_lsb_set(spt_mask) - 1; + spt_mask &= ~BIT(adv_type); + msg_queue = &(bt_mesh_adv_types_mgnt_get(adv_type)->adv_q->q); + + /* When there is no new message in the queue, *buf (aka: msg.arg) + * will be empty. */ + if (find_valid_msg_from_queue(msg_queue, &msg)) { + BT_DBG("no valid message for instance %d", instance->id); + continue; + } + + instance->sending_buf = (struct net_buf *)msg.arg; + if (adv_send(instance, &duration)) { + BT_ERR("adv start failed"); + net_buf_unref(instance->sending_buf); + instance->sending_buf = NULL; + /* When this adv instance fails to broadcast, it could be + * due to some persistent issues, such as incorrect adv + * parameter settings, or it could be due to some temporary + * issues, such as memory allocation failure. Therefore, it + * is advisable to skip subsequent queue reads for this instance + * and attempt to broadcast subsequent data again next time, + * rather than disabling the adv instance. */ + break; + } + + if (duration < cur_min_duration) { + cur_min_duration = duration; + } + + instance->busy = true; + evts |= ADV_TASK_ADV_INST_EVT(adv_insts[i].id); + + /* Must be nullified to avoid affecting the next adv + * instance's judgment on whether the message queue + * is empty. */ + msg.arg = NULL; + break; + } + } + + *min_duration = cur_min_duration; + *update_evts |= evts; + + return 0; +} + +static uint32_t received_adv_evts_handle(uint32_t recv_evts) +{ + uint32_t evt = 0; + + if (!recv_evts) { + return 0; + } + + for (int i = 0; recv_evts && i < BLE_MESH_ADV_INS_TYPES_NUM; i++) { + evt = ADV_TASK_ADV_INST_EVT(adv_insts[i].id); + if (recv_evts & evt) { + recv_evts &= ~evt; +#if (CONFIG_BLE_MESH_NODE && CONFIG_BLE_MESH_PB_GATT) || \ +CONFIG_BLE_MESH_GATT_PROXY_SERVER + if (unlikely(i == BLE_MESH_ADV_PROXY_INS)) { + BT_DBG("Mesh Proxy Advertising auto stop"); + } else +#endif + { + /* adv_send_end maybe*/ + adv_send_end(0, BLE_MESH_ADV(adv_insts[i].sending_buf)->cb, BLE_MESH_ADV(adv_insts[i].sending_buf)->cb_data); + bt_mesh_adv_buf_ref_debug(__func__, adv_insts[i].sending_buf, 4U, BLE_MESH_BUF_REF_SMALL); + net_buf_unref(adv_insts[i].sending_buf); + adv_insts[i].sending_buf = NULL; + } + adv_insts[i].busy = false; + } + } + + return recv_evts; +} + +static void adv_thread(void *p) +{ + uint16_t adv_duration = K_FOREVER; + uint32_t recv_evts = 0; + uint32_t wait_evts = 0; + + BT_DBG("%s, starts", __func__); + + while (1) { + adv_duration = K_FOREVER; + wait_evts |= ADV_TASK_PKT_SEND_EVT; + + active_idle_adv_instance(&wait_evts, &adv_duration); + + ble_mesh_adv_task_wait(wait_evts, adv_duration, &recv_evts); + + wait_evts &= ~recv_evts; + +#if (CONFIG_BLE_MESH_NODE && CONFIG_BLE_MESH_PB_GATT) || \ + CONFIG_BLE_MESH_GATT_PROXY_SERVER + if (recv_evts & ADV_TASK_PROXY_ADV_UPD_EVT) { + adv_insts[BLE_MESH_ADV_PROXY_INS].busy = false; + recv_evts &= ~ADV_TASK_PROXY_ADV_UPD_EVT; + } +#endif + + /** + * `recv_evts == ADV_TASK_PKT_SEND_EVT` indicates that new packets + * have been placed into the queue, and the advertising instances started + * previous have not yet stopped. + */ + if (recv_evts == ADV_TASK_PKT_SEND_EVT) { + continue; + } + + recv_evts = received_adv_evts_handle(recv_evts); + + if (recv_evts) { + BT_ERR("Remain evts %08x to handle", recv_evts); + } + } +} + +void bt_mesh_adv_update(void) +{ +#if (CONFIG_BLE_MESH_NODE && CONFIG_BLE_MESH_PB_GATT) || \ + CONFIG_BLE_MESH_GATT_PROXY_SERVER + BT_WARN("Mesh Proxy Advertising stopped manually"); + bt_mesh_proxy_server_adv_stop(); + if (adv_insts[BLE_MESH_ADV_PROXY_INS].busy) { + ble_mesh_adv_task_wakeup(ADV_TASK_PROXY_ADV_UPD_EVT); + } +#endif +} + +void bt_mesh_adv_init(void) +{ + bt_mesh_adv_common_init(); + + adv_insts = bt_mesh_get_adv_insts_set(); + adv_queue = bt_mesh_adv_queue_get(); + +#if CONFIG_BLE_MESH_RELAY_ADV_BUF + bt_mesh_relay_adv_init(); +#endif + +#if CONFIG_BLE_MESH_SUPPORT_BLE_ADV + bt_mesh_ble_adv_init(); +#endif + + bt_mesh_adv_task_init(adv_thread); +} + +#if CONFIG_BLE_MESH_DEINIT +void bt_mesh_adv_deinit(void) +{ + bt_mesh_adv_task_deinit(); + + bt_mesh_adv_common_deinit(); + + adv_insts = NULL; + +#if CONFIG_BLE_MESH_RELAY_ADV_BUF + bt_mesh_relay_adv_deinit(); +#endif + +#if CONFIG_BLE_MESH_SUPPORT_BLE_ADV + bt_mesh_ble_adv_deinit(); +#endif +} +#endif /* CONFIG_BLE_MESH_DEINIT */ diff --git a/components/bt/esp_ble_mesh/core/ext_adv.h b/components/bt/esp_ble_mesh/core/ext_adv.h new file mode 100644 index 00000000000..3004db27cdf --- /dev/null +++ b/components/bt/esp_ble_mesh/core/ext_adv.h @@ -0,0 +1,39 @@ +/* Bluetooth Mesh */ + +/* + * SPDX-FileCopyrightText: 2017 Intel Corporation + * SPDX-FileContributor: 2024 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef _EXT_ADV_H_ +#define _EXT_ADV_H_ + +#include "mesh/atomic.h" +#include "mesh/access.h" +#include "mesh/adapter.h" +#include "mesh/queue.h" +#include "adv_common.h" + +#ifdef __cplusplus +extern "C" { +#endif + +static inline void bt_mesh_adv_send(struct net_buf *buf, uint8_t xmit, + const struct bt_mesh_send_cb *cb, + void *cb_data) +{ + bt_mesh_generic_adv_send(buf, xmit, cb, cb_data, BLE_MESH_ADDR_UNASSIGNED, BLE_MESH_ADDR_UNASSIGNED, false); +} + +void bt_mesh_adv_update(void); + +void bt_mesh_adv_init(void); +void bt_mesh_adv_deinit(void); + +#ifdef __cplusplus +} +#endif + +#endif /* _EXT_ADV_H_ */ diff --git a/components/bt/esp_ble_mesh/core/friend.c b/components/bt/esp_ble_mesh/core/friend.c index aa9607492b2..99e41cd099d 100644 --- a/components/bt/esp_ble_mesh/core/friend.c +++ b/components/bt/esp_ble_mesh/core/friend.c @@ -27,14 +27,6 @@ #ifdef CONFIG_BLE_MESH_FRIEND -/* We reserve one extra buffer for each friendship, since we need to be able - * to resend the last sent PDU, which sits separately outside of the queue. - */ -#define FRIEND_BUF_COUNT ((CONFIG_BLE_MESH_FRIEND_QUEUE_SIZE + 1) * \ - CONFIG_BLE_MESH_FRIEND_LPN_COUNT) - -#define FRIEND_ADV(buf) CONTAINER_OF(BLE_MESH_ADV(buf), struct friend_adv, adv) - /* PDUs from Friend to the LPN should only be transmitted once with the * smallest possible interval (20ms). * @@ -57,14 +49,6 @@ struct friend_pdu_info { uint32_t iv_index; }; -NET_BUF_POOL_FIXED_DEFINE(friend_buf_pool, FRIEND_BUF_COUNT, - BLE_MESH_ADV_DATA_SIZE, NULL); - -static struct friend_adv { - struct bt_mesh_adv adv; - uint16_t app_idx; -} adv_pool[FRIEND_BUF_COUNT]; - enum { BLE_MESH_FRIENDSHIP_TERMINATE_ESTABLISH_FAIL, BLE_MESH_FRIENDSHIP_TERMINATE_POLL_TIMEOUT, @@ -83,12 +67,6 @@ static struct bt_mesh_subnet *friend_subnet_get(uint16_t net_idx) return bt_mesh_subnet_get(net_idx); } -static struct bt_mesh_adv *adv_alloc(int id) -{ - adv_pool[id].app_idx = BLE_MESH_KEY_UNUSED; - return &adv_pool[id].adv; -} - static bool is_lpn_unicast(struct bt_mesh_friend *frnd, uint16_t addr) { if (frnd->lpn == BLE_MESH_ADDR_UNASSIGNED) { @@ -368,8 +346,7 @@ static struct net_buf *create_friend_pdu(struct bt_mesh_friend *frnd, { struct net_buf *buf = NULL; - buf = bt_mesh_adv_create_from_pool(&friend_buf_pool, adv_alloc, - BLE_MESH_ADV_DATA, K_NO_WAIT); + buf = bt_mesh_adv_create_from_pool(BLE_MESH_ADV_FRIEND, K_NO_WAIT); if (!buf) { return NULL; } @@ -1323,6 +1300,8 @@ int bt_mesh_friend_init(void) } } + bt_mesh_frnd_adv_init(); + friend_init = true; return 0; @@ -1349,8 +1328,7 @@ int bt_mesh_friend_deinit(void) k_delayed_work_free(&frnd->clear.timer); } - bt_mesh_unref_buf_from_pool(&friend_buf_pool); - memset(adv_pool, 0, sizeof(adv_pool)); + bt_mesh_frnd_adv_deinit(); friend_init = false; diff --git a/components/bt/esp_ble_mesh/core/include/mesh/access.h b/components/bt/esp_ble_mesh/core/include/mesh/access.h index 9d013baa0d4..fac499764d5 100644 --- a/components/bt/esp_ble_mesh/core/include/mesh/access.h +++ b/components/bt/esp_ble_mesh/core/include/mesh/access.h @@ -348,7 +348,7 @@ struct bt_mesh_model_op { * @return Mesh transmit value that can be used e.g. for the default * values of the configuration model data. */ -#define BLE_MESH_TRANSMIT(count, int_ms) ((count) | ((((int_ms) / 10) - 1) << 3)) +#define BLE_MESH_TRANSMIT(count, int_ms) ((uint8_t)(count) | ((((int_ms) / 10) - 1) << 3)) /** @def BLE_MESH_TRANSMIT_COUNT * diff --git a/components/bt/esp_ble_mesh/core/include/mesh/adapter.h b/components/bt/esp_ble_mesh/core/include/mesh/adapter.h index cbc59ce5130..f02c9f5b3bc 100644 --- a/components/bt/esp_ble_mesh/core/include/mesh/adapter.h +++ b/components/bt/esp_ble_mesh/core/include/mesh/adapter.h @@ -487,15 +487,24 @@ struct bt_mesh_adv_param { #endif }; -#if CONFIG_BLE_MESH_USE_BLE_50 +#define ADV_TASK_ADV_INST_EVT(inst_id) BIT(inst_id) + enum bt_mesh_adv_inst_type { - BLE_MESH_ADV_PROXY_INS, BLE_MESH_ADV_INS, - BLE_MESH_EXT_ADV_INS, +#if CONFIG_BLE_MESH_SUPPORT_MULTI_ADV +#if (CONFIG_BLE_MESH_NODE && CONFIG_BLE_MESH_PB_GATT) || \ + CONFIG_BLE_MESH_GATT_PROXY_SERVER + BLE_MESH_ADV_PROXY_INS, +#endif +#if CONFIG_BLE_MESH_SEPARATE_RELAY_ADV_INSTANCE + BLE_MESH_RELAY_ADV_INS, +#endif +#if CONFIG_BLE_MESH_SEPARATE_BLE_ADV_INSTANCE BLE_MESH_BLE_ADV_INS, - BLE_MESH_ADV_INS_TYPE_NUMS, +#endif +#endif /* CONFIG_BLE_MESH_SUPPORT_MULTI_ADV */ + BLE_MESH_ADV_INS_TYPES_NUM, }; -#endif /* CONFIG_BLE_MESH_USE_BLE_50 */ #if CONFIG_BLE_MESH_SUPPORT_BLE_ADV enum bt_mesh_ble_adv_priority { diff --git a/components/bt/esp_ble_mesh/core/net.c b/components/bt/esp_ble_mesh/core/net.c index d28a99c25f3..4f54c85419c 100644 --- a/components/bt/esp_ble_mesh/core/net.c +++ b/components/bt/esp_ble_mesh/core/net.c @@ -1682,7 +1682,7 @@ static void bt_mesh_net_relay(struct net_buf_simple *sbuf, if (bt_mesh_get_stored_relay_count() >= BLE_MESH_MAX_STORED_RELAY_COUNT) { xmit = BLE_MESH_TRANSMIT(0, 20); } - buf = bt_mesh_relay_adv_create(BLE_MESH_ADV_DATA, K_NO_WAIT); + buf = bt_mesh_relay_adv_create(BLE_MESH_ADV_RELAY_DATA, K_NO_WAIT); #endif if (!buf) { diff --git a/components/bt/esp_ble_mesh/core/nimble_host/adapter.c b/components/bt/esp_ble_mesh/core/nimble_host/adapter.c index 4816f29af0d..7fed0d0bdb4 100644 --- a/components/bt/esp_ble_mesh/core/nimble_host/adapter.c +++ b/components/bt/esp_ble_mesh/core/nimble_host/adapter.c @@ -86,7 +86,9 @@ static bool g_gatts_svcs_add = false; #endif #endif /* CONFIG_BLE_MESH_NODE */ -#if CONFIG_BLE_MESH_USE_BLE_50 && CONFIG_BLE_MESH_SUPPORT_BLE_ADV +#if CONFIG_BLE_MESH_USE_BLE_50 && \ + CONFIG_BLE_MESH_SUPPORT_BLE_ADV && \ + (!CONFIG_BLE_MESH_SUPPORT_MULTI_ADV) static inline void bt_mesh_set_ble_adv_running(); static inline void bt_mesh_unset_ble_adv_running(); @@ -930,10 +932,14 @@ static int gap_event_cb(struct ble_gap_event *event, void *arg) case BLE_GAP_EVENT_ADV_COMPLETE: BT_DBG("advertise complete; reason=%d", event->adv_complete.reason); - /* Limit Reached (0x43) and Advertising Timeout (0x3C) will cause BLE_HS_ETIMEOUT to be set. */ #if CONFIG_BLE_MESH_USE_BLE_50 +#if CONFIG_BLE_MESH_SUPPORT_MULTI_ADV + ble_mesh_adv_task_wakeup(ADV_TASK_ADV_INST_EVT(event->adv_complete.instance)); +#else /* CONFIG_BLE_MESH_SUPPORT_MULTI_ADV */ + assert(CONFIG_BLE_MESH_ADV_INST_ID == event->adv_complete.instance); + /* Limit Reached (0x43) and Advertising Timeout (0x3C) will cause BLE_HS_ETIMEOUT to be set. */ if (event->adv_complete.reason == BLE_HS_ETIMEOUT) { - ble_mesh_adv_task_wakeup(event->adv_complete.instance); + ble_mesh_adv_task_wakeup(ADV_TASK_ADV_INST_EVT(event->adv_complete.instance)); } #if CONFIG_BLE_MESH_SUPPORT_BLE_ADV /** @@ -956,9 +962,10 @@ static int gap_event_cb(struct ble_gap_event *event, void *arg) * could lead to resource contention issues. */ bt_mesh_unset_ble_adv_running(); - ble_mesh_adv_task_wakeup(event->adv_complete.instance); + ble_mesh_adv_task_wakeup(ADV_TASK_ADV_INST_EVT(event->adv_complete.instance)); } #endif /* CONFIG_BLE_MESH_SUPPORT_BLE_ADV */ +#endif /* CONFIG_BLE_MESH_SUPPORT_MULTI_ADV */ #endif /* CONFIG_BLE_MESH_USE_BLE_50 */ return 0; @@ -1053,9 +1060,13 @@ static int gap_event_cb(struct ble_gap_event *event, void *arg) case BLE_GAP_EVENT_ADV_COMPLETE: BT_DBG("Provisioner advertise complete; reason=%d", event->adv_complete.reason); +#if CONFIG_BLE_MESH_SUPPORT_MULTI_ADV + ble_mesh_adv_task_wakeup(ADV_TASK_ADV_INST_EVT(event->adv_complete.instance)); +#else /* CONFIG_BLE_MESH_SUPPORT_MULTI_ADV */ + assert(CONFIG_BLE_MESH_ADV_INST_ID == event->adv_complete.instance); /* Limit Reached (0x43) and Advertising Timeout (0x3C) will cause BLE_HS_ETIMEOUT to be set. */ if (event->adv_complete.reason == BLE_HS_ETIMEOUT) { - ble_mesh_adv_task_wakeup(event->adv_complete.instance); + ble_mesh_adv_task_wakeup(ADV_TASK_ADV_INST_EVT(CONFIG_BLE_MESH_ADV_INST_ID)); } #if CONFIG_BLE_MESH_SUPPORT_BLE_ADV /** @@ -1078,9 +1089,10 @@ static int gap_event_cb(struct ble_gap_event *event, void *arg) * could lead to resource contention issues. */ bt_mesh_unset_ble_adv_running(); - ble_mesh_adv_task_wakeup(event->adv_complete.instance); + ble_mesh_adv_task_wakeup(ADV_TASK_ADV_INST_EVT(CONFIG_BLE_MESH_ADV_INST_ID)); } #endif /* CONFIG_BLE_MESH_SUPPORT_BLE_ADV */ +#endif /* CONFIG_BLE_MESH_SUPPORT_MULTI_ADV */ break; } #endif /* CONFIG_BLE_MESH_USE_BLE_50 */ @@ -1211,8 +1223,6 @@ int bt_le_ext_adv_start(const uint8_t inst_id, interval >>= 1; interval += (bt_mesh_get_rand() % (interval + 1)); - adv_params->high_duty_directed = true; - BT_INFO("%u->%u", param->interval_min, interval); } #endif @@ -1376,7 +1386,14 @@ int bt_le_adv_start(const struct bt_mesh_adv_param *param, #if CONFIG_BLE_MESH_SUPPORT_BLE_ADV #if CONFIG_BLE_MESH_USE_BLE_50 - +#if !CONFIG_BLE_MESH_SUPPORT_MULTI_ADV +/** + * The current flag is only used to distinguish between BLE ADV + * and proxy ADV in the same adv instance to handle the adv + * completed events. + * + * This flag is not needed in the case of multiple adv instances. + */ static bool _ble_adv_running_flag; static inline void bt_mesh_set_ble_adv_running() @@ -1393,6 +1410,7 @@ static inline bool bt_mesh_is_ble_adv_running() { return _ble_adv_running_flag == true; } +#endif /* BLE_MESH_SUPPORT_MULTI_ADV */ int bt_mesh_ble_ext_adv_start(const uint8_t inst_id, const struct bt_mesh_ble_adv_param *param, @@ -1507,7 +1525,9 @@ int bt_mesh_ble_ext_adv_start(const uint8_t inst_id, return err; } +#if !CONFIG_BLE_MESH_SUPPORT_MULTI_ADV bt_mesh_set_ble_adv_running(); +#endif return 0; } diff --git a/components/bt/esp_ble_mesh/core/proxy_server.c b/components/bt/esp_ble_mesh/core/proxy_server.c index ece9723ce75..ac95c24cee4 100644 --- a/components/bt/esp_ble_mesh/core/proxy_server.c +++ b/components/bt/esp_ble_mesh/core/proxy_server.c @@ -1043,7 +1043,6 @@ int bt_mesh_proxy_server_prov_enable(void) } } - return 0; } @@ -1749,6 +1748,7 @@ static int32_t gatt_proxy_advertise(struct bt_mesh_subnet *sub) && sub->private_node_id == BLE_MESH_PRIVATE_NODE_IDENTITY_STOPPED #endif ) { + /* advertising node identity forever */ if (bt_mesh_gatt_proxy_get() == BLE_MESH_GATT_PROXY_ENABLED) { net_id_adv(sub); } @@ -1864,13 +1864,14 @@ static int32_t solic_adv_private_net_id(void) int32_t bt_mesh_proxy_server_adv_start(void) { + BT_DBG("proxy server start"); + if (gatt_svc == MESH_GATT_NONE) { return K_FOREVER; } #if CONFIG_BLE_MESH_USE_BLE_50 if (proxy_adv_inst == BLE_MESH_ADV_INS_UNUSED) { - BT_ERR("Proxy adv inst is not initialized!"); return K_FOREVER; } #endif @@ -1931,23 +1932,22 @@ int32_t bt_mesh_proxy_server_adv_start(void) } #endif /* GATT_PROXY */ + /* used to indicate proxy advertising could be stopped */ return K_FOREVER; } -void bt_mesh_proxy_server_adv_stop(void) +int bt_mesh_proxy_server_adv_stop(void) { int err = 0; - BT_DBG("adv_enabled %u", proxy_adv_enabled); - if (!proxy_adv_enabled) { - return; + return -EALREADY; } #if CONFIG_BLE_MESH_USE_BLE_50 if (proxy_adv_inst == BLE_MESH_ADV_INS_UNUSED) { BT_ERR("Proxy adv inst is not initialized!"); - return; + return -EINVAL; } err = bt_le_ext_adv_stop(proxy_adv_inst); @@ -1956,9 +1956,11 @@ void bt_mesh_proxy_server_adv_stop(void) #endif if (err) { BT_ERR("Failed to stop advertising (err %d)", err); - } else { - proxy_adv_enabled = false; + return -EINVAL; } + + proxy_adv_enabled = false; + return 0; } static struct bt_mesh_conn_cb conn_callbacks = { @@ -1971,7 +1973,11 @@ int bt_mesh_proxy_server_init(void) int i; #if CONFIG_BLE_MESH_USE_BLE_50 - proxy_adv_inst = bt_mesh_get_proxy_inst(); +#if CONFIG_BLE_MESH_SUPPORT_MULTI_ADV + proxy_adv_inst = CONFIG_BLE_MESH_PROXY_ADV_INST_ID; +#else /* CONFIG_BLE_MESH_SUPPORT_MULTI_ADV */ + proxy_adv_inst = CONFIG_BLE_MESH_ADV_INST_ID; +#endif #endif #if CONFIG_BLE_MESH_GATT_PROXY_SERVER diff --git a/components/bt/esp_ble_mesh/core/proxy_server.h b/components/bt/esp_ble_mesh/core/proxy_server.h index 88eed8a7e96..6cebe965da3 100644 --- a/components/bt/esp_ble_mesh/core/proxy_server.h +++ b/components/bt/esp_ble_mesh/core/proxy_server.h @@ -95,7 +95,7 @@ void bt_mesh_proxy_server_beacon_send(struct bt_mesh_subnet *sub); struct net_buf_simple *bt_mesh_proxy_server_get_buf(void); int32_t bt_mesh_proxy_server_adv_start(void); -void bt_mesh_proxy_server_adv_stop(void); +int bt_mesh_proxy_server_adv_stop(void); void bt_mesh_proxy_server_update_net_id_rand(void); void bt_mesh_proxy_server_update_net_id_rand_stop(void);