From a86bb375f7f23f2983f03b054f0c348f129de333 Mon Sep 17 00:00:00 2001 From: luoxu Date: Thu, 30 May 2024 16:44:12 +0800 Subject: [PATCH] feat(ble_mesh): Support BLE 5.0 for BLE Mesh --- components/bt/common/btc/core/btc_task.c | 4 +- components/bt/esp_ble_mesh/Kconfig.in | 15 +- .../api/core/esp_ble_mesh_ble_api.c | 26 +- .../api/core/esp_ble_mesh_common_api.c | 2 +- .../api/core/include/esp_ble_mesh_ble_api.h | 88 ++- .../bt/esp_ble_mesh/api/esp_ble_mesh_defs.h | 25 +- .../bt/esp_ble_mesh/btc/btc_ble_mesh_ble.c | 49 +- .../bt/esp_ble_mesh/btc/btc_ble_mesh_prov.c | 2 + .../btc/include/btc_ble_mesh_ble.h | 39 +- .../btc/include/btc_ble_mesh_prov.h | 2 +- .../esp_ble_mesh/common/include/mesh/utils.h | 2 +- components/bt/esp_ble_mesh/core/adv.c | 98 ++- components/bt/esp_ble_mesh/core/adv.h | 20 +- .../core/bluedroid_host/adapter.c | 560 ++++++++++++- .../esp_ble_mesh/core/include/mesh/access.h | 2 +- .../esp_ble_mesh/core/include/mesh/adapter.h | 104 ++- components/bt/esp_ble_mesh/core/net.c | 60 +- components/bt/esp_ble_mesh/core/net.h | 14 +- .../esp_ble_mesh/core/nimble_host/adapter.c | 736 +++++++++++++++++- .../bt/esp_ble_mesh/core/proxy_client.c | 2 +- .../bt/esp_ble_mesh/core/proxy_server.c | 68 +- .../bt/esp_ble_mesh/core/proxy_server.h | 1 + components/bt/esp_ble_mesh/core/scan.c | 173 ++-- components/bt/esp_ble_mesh/core/scan.h | 8 +- .../host/bluedroid/bta/include/bta/bta_api.h | 24 +- .../btc/profile/std/gap/btc_gap_ble.c | 2 +- docs/doxygen/Doxyfile | 1 + .../api-reference/bluetooth/esp-ble-mesh.rst | 3 + .../example_init/ble_mesh_example_init.c | 18 +- 29 files changed, 1961 insertions(+), 187 deletions(-) diff --git a/components/bt/common/btc/core/btc_task.c b/components/bt/common/btc/core/btc_task.c index 3729c3dc8d..c3a0bd2bee 100644 --- a/components/bt/common/btc/core/btc_task.c +++ b/components/bt/common/btc/core/btc_task.c @@ -254,9 +254,9 @@ static const btc_func_t profile_tab[BTC_PID_NUM] = { #if CONFIG_BLE_MESH_MBT_SRV [BTC_PID_MBT_SERVER] = {btc_ble_mesh_mbt_server_call_handler, btc_ble_mesh_mbt_server_cb_handler }, #endif /* CONFIG_BLE_MESH_MBT_SRV */ -#if CONFIG_BLE_MESH_BLE_COEX_SUPPORT +#if CONFIG_BLE_MESH_BLE_COEX_SUPPORT || CONFIG_BLE_MESH_USE_BLE_50 [BTC_PID_BLE_MESH_BLE_COEX] = {btc_ble_mesh_ble_call_handler, btc_ble_mesh_ble_cb_handler }, -#endif /* CONFIG_BLE_MESH_BLE_COEX_SUPPORT */ +#endif /* CONFIG_BLE_MESH_BLE_COEX_SUPPORT || CONFIG_BLE_MESH_USE_BLE_50 */ #endif /* #if CONFIG_BLE_MESH */ }; diff --git a/components/bt/esp_ble_mesh/Kconfig.in b/components/bt/esp_ble_mesh/Kconfig.in index 47c6fad2c0..d9c7fb8521 100644 --- a/components/bt/esp_ble_mesh/Kconfig.in +++ b/components/bt/esp_ble_mesh/Kconfig.in @@ -21,13 +21,25 @@ if BLE_MESH for mesh packets. And this could help avoid collision of advertising packets. + menuconfig BLE_MESH_USE_BLE_50 + bool "Support using BLE 5.0 APIs for BLE Mesh" + depends on BLE_MESH_EXPERIMENTAL + depends on IDF_TARGET_ESP32C3 || IDF_TARGET_ESP32S3 + select BT_NIMBLE_50_FEATURE_SUPPORT if BT_NIMBLE_ENABLED + select BT_NIMBLE_EXT_ADV if BT_NIMBLE_ENABLED + select BT_BLE_50_FEATURES_SUPPORTED if BT_BLUEDROID_ENABLED + select BT_LE_50_FEATURE_SUPPORT if IDF_TARGET_ESP32C6 || IDF_TARGET_ESP32H2 + default n + help + This option to enable BLE Mesh using some BLE 5.0 APIs. + config BLE_MESH_USE_DUPLICATE_SCAN bool "Support Duplicate Scan in BLE Mesh" select BTDM_BLE_SCAN_DUPL if IDF_TARGET_ESP32 select BTDM_BLE_MESH_SCAN_DUPL_EN if IDF_TARGET_ESP32 select BT_CTRL_BLE_SCAN_DUPL if IDF_TARGET_ESP32C3 || IDF_TARGET_ESP32S3 select BT_CTRL_BLE_MESH_SCAN_DUPL_EN if IDF_TARGET_ESP32C3 || IDF_TARGET_ESP32S3 - select BT_LE_SCAN_DUPL if IDF_TARGET_ESP32C6 || IDF_TARGET_ESP32H2 + select BT_LE_SCAN_DUPL if IDF_TARGET_ESP32C6 || IDF_TARGET_ESP32H2 || IDF_TARGET_ESP32C61 || IDF_TARGET_ESP32C5 select BT_NIMBLE_VS_SUPPORT if BT_NIMBLE_ENABLED default y help @@ -1646,5 +1658,6 @@ if BLE_MESH Make BLE Mesh Experimental features visible. Experimental features list: - CONFIG_BLE_MESH_NOT_RELAY_REPLAY_MSG + - CONFIG_BLE_MESH_USE_BLE_50 endif # BLE_MESH diff --git a/components/bt/esp_ble_mesh/api/core/esp_ble_mesh_ble_api.c b/components/bt/esp_ble_mesh/api/core/esp_ble_mesh_ble_api.c index 559528e8ad..fcba1f4b51 100644 --- a/components/bt/esp_ble_mesh/api/core/esp_ble_mesh_ble_api.c +++ b/components/bt/esp_ble_mesh/api/core/esp_ble_mesh_ble_api.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 */ @@ -12,14 +12,14 @@ #include "btc_ble_mesh_ble.h" #include "esp_ble_mesh_ble_api.h" -#if CONFIG_BLE_MESH_BLE_COEX_SUPPORT +#if (CONFIG_BLE_MESH_BLE_COEX_SUPPORT || CONFIG_BLE_MESH_USE_BLE_50) esp_err_t esp_ble_mesh_register_ble_callback(esp_ble_mesh_ble_cb_t callback) { ESP_BLE_HOST_STATUS_CHECK(ESP_BLE_HOST_STATUS_ENABLED); return (btc_profile_cb_set(BTC_PID_BLE_MESH_BLE_COEX, callback) == 0 ? ESP_OK : ESP_FAIL); } -#endif /* CONFIG_BLE_MESH_BLE_COEX_SUPPORT */ +#endif /* (CONFIG_BLE_MESH_BLE_COEX_SUPPORT || CONFIG_BLE_MESH_USE_BLE_50) */ #if CONFIG_BLE_MESH_SUPPORT_BLE_ADV esp_err_t esp_ble_mesh_start_ble_advertising(const esp_ble_mesh_ble_adv_param_t *param, @@ -100,3 +100,23 @@ esp_err_t esp_ble_mesh_stop_ble_scanning(void) == BT_STATUS_SUCCESS ? ESP_OK : ESP_FAIL); } #endif /* CONFIG_BLE_MESH_SUPPORT_BLE_SCAN */ + +esp_err_t esp_ble_mesh_scan_params_update(esp_ble_mesh_scan_param_t *scan_param) +{ + btc_ble_mesh_ble_args_t arg = {0}; + btc_msg_t msg = {0}; + + if (!scan_param) { + return ESP_FAIL; + } + + msg.sig = BTC_SIG_API_CALL; + msg.pid = BTC_PID_BLE_MESH_BLE_COEX; + msg.act = BTC_BLE_MESH_ACT_UPDATE_SCAN_PARAMS; + + arg.scan_params.scan_interval = scan_param->scan_interval; + arg.scan_params.uncoded_scan_window = scan_param->uncoded_scan_window; + + return (btc_transfer_context(&msg, &arg, sizeof(btc_ble_mesh_ble_args_t), NULL, NULL) + == BT_STATUS_SUCCESS ? ESP_OK : ESP_FAIL); +} diff --git a/components/bt/esp_ble_mesh/api/core/esp_ble_mesh_common_api.c b/components/bt/esp_ble_mesh/api/core/esp_ble_mesh_common_api.c index 8212878608..eaa1868133 100644 --- a/components/bt/esp_ble_mesh/api/core/esp_ble_mesh_common_api.c +++ b/components/bt/esp_ble_mesh/api/core/esp_ble_mesh_common_api.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 */ diff --git a/components/bt/esp_ble_mesh/api/core/include/esp_ble_mesh_ble_api.h b/components/bt/esp_ble_mesh/api/core/include/esp_ble_mesh_ble_api.h index 6818ba18ae..83d7e62760 100644 --- a/components/bt/esp_ble_mesh/api/core/include/esp_ble_mesh_ble_api.h +++ b/components/bt/esp_ble_mesh/api/core/include/esp_ble_mesh_ble_api.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 */ @@ -9,6 +9,10 @@ #include "esp_ble_mesh_defs.h" +#if CONFIG_BLE_MESH_USE_BLE_50 && CONFIG_BT_NIMBLE_ENABLED +#include "host/ble_gap.h" +#endif + #ifdef __cplusplus extern "C" { #endif @@ -20,9 +24,38 @@ typedef enum { ESP_BLE_MESH_START_BLE_SCANNING_COMP_EVT, /*!< Start BLE scanning completion event */ ESP_BLE_MESH_STOP_BLE_SCANNING_COMP_EVT, /*!< Stop BLE scanning completion event */ ESP_BLE_MESH_SCAN_BLE_ADVERTISING_PKT_EVT, /*!< Scanning BLE advertising packets event */ + ESP_BLE_MESH_SCAN_PARAMS_UPDATE_COMP_EVT, /*!< Scan parameters update completion event */ +#if CONFIG_BLE_MESH_USE_BLE_50 && CONFIG_BT_NIMBLE_ENABLED + ESP_BLE_MESH_NIMBLE_GAP_EVENT_EVT, /*!< NIMBLE GAP event */ +#endif /* CONFIG_BLE_MESH_USE_BLE_50 && CONFIG_BT_NIMBLE_ENABLED */ ESP_BLE_MESH_BLE_EVT_MAX, } esp_ble_mesh_ble_cb_event_t; +/** Context of BLE advertising report. */ +typedef struct { + uint8_t addr[6]; /*!< Device address */ + uint8_t addr_type; /*!< Device address type */ +#if CONFIG_BLE_MESH_USE_BLE_50 + uint8_t adv_type __attribute__((deprecated("`event_type` should be used to determine the advertising type"))); /*!< advertising type */ +#else + uint8_t adv_type; /*!< Advertising type */ +#endif + uint8_t *data; /*!< Advertising data */ + uint16_t length; /*!< Advertising data length */ + int8_t rssi; /*!< RSSI of the advertising packet */ +#if CONFIG_BLE_MESH_USE_BLE_50 + uint8_t event_type; /*!< Extended advertising event type */ + uint8_t primary_phy; /*!< Extended advertising primary PHY */ + uint8_t secondary_phy; /*!< Extended advertising secondary PHY */ + uint8_t sid; /*!< Extended advertising set ID */ + uint8_t tx_power; /*!< Extended advertising TX power */ + uint8_t dir_addr_type; /*!< Direct address type */ + uint8_t dir_addr[6]; /*!< Direct address */ + uint8_t data_status; /*!< Data type */ + uint16_t per_adv_interval; /*!< Periodic advertising interval */ +#endif /* CONFIG_BLE_MESH_USE_BLE_50 */ +} esp_ble_mesh_ble_adv_rpt_t; + /** BLE operation callback parameters */ typedef union { /** @@ -52,16 +85,24 @@ typedef union { int err_code; /*!< Indicate the result of stopping BLE scanning */ } stop_ble_scan_comp; /*!< Event parameters of ESP_BLE_MESH_STOP_BLE_SCANNING_COMP_EVT */ /** - * @brief ESP_BLE_MESH_SCAN_BLE_ADVERTISING_PKT_EVT + * @brief Event parameters of ESP_BLE_MESH_SCAN_BLE_ADVERTISING_PKT_EVT */ - struct { - uint8_t addr[6]; /*!< Device address */ - uint8_t addr_type; /*!< Device address type */ - uint8_t adv_type; /*!< Advertising data type */ - uint8_t *data; /*!< Advertising data */ - uint16_t length; /*!< Advertising data length */ - int8_t rssi; /*!< RSSI of the advertising packet */ - } scan_ble_adv_pkt; /*!< Event parameters of ESP_BLE_MESH_SCAN_BLE_ADVERTISING_PKT_EVT */ + esp_ble_mesh_ble_adv_rpt_t scan_ble_adv_pkt; + /** + * @brief Event parameter of ESP_BLE_MESH_SCAN_PARAMS_UPDATE_COMP_EVT + */ + struct ble_mesh_scan_params_update_comp_param { + int err_code; /*!< Indicates the result of updating scan parameters */ + } scan_params_update_comp; /*!< Event parameter of ESP_BLE_MESH_SCAN_PARAMS_UPDATE_COMP_EVT */ +#if CONFIG_BLE_MESH_USE_BLE_50 && CONFIG_BT_NIMBLE_ENABLED + /** + * @brief Event parameters of ESP_BLE_MESH_NIMBLE_GAP_EVENT_EVT + */ + struct ble_mesh_nimble_gap_event_evt_param { + struct ble_gap_event event; /*!< GAP event parameters for NimBLE Host */ + void *arg; /*!< User parameters */ + } nimble_gap_evt; /*!< Event parameters of ESP_BLE_MESH_NIMBLE_GAP_EVENT_EVT */ +#endif /* CONFIG_BLE_MESH_USE_BLE_50 && CONFIG_BT_NIMBLE_ENABLED */ } esp_ble_mesh_ble_cb_param_t; /** @@ -175,6 +216,33 @@ esp_err_t esp_ble_mesh_start_ble_scanning(esp_ble_mesh_ble_scan_param_t *param); */ esp_err_t esp_ble_mesh_stop_ble_scanning(void); +/** + * @brief Update BLE Mesh scan parameters. + * + * @note + * 1. This function shall be used after ESP BLE Mesh is initialized! + * Parameters `scan_interval` and `uncoded_scan_window` must both + * be multiples of 8. + * + * 2. If the config BLE_MESH_USE_BLE_50 is enabled, within the scan_interval: + * - If uncoded_scan_window is not zero, the scan_interval is divided into + * two parts: + * - uncoded_scan_window: Used for performing uncoded scanning. + * - (scan_interval - uncoded_scan_window): The remaining time is + * used for coded scanning (coded_scan). + * - If uncoded_scan_window is set to 0, it means the entire scan_interval + * is used for coded scanning. + * - If uncoded_scan_window is equal to scan_interval, it means the entire + * scan_interval is used for uncoded scanning. + * + * @param[in] scan_param: Scan parameters + * + * @return + * - ESP_OK: Success + * - ESP_FAIL: Invalid parameters or unable transfer this command to the stack +*/ +esp_err_t esp_ble_mesh_scan_params_update(esp_ble_mesh_scan_param_t *scan_param); + #ifdef __cplusplus } #endif diff --git a/components/bt/esp_ble_mesh/api/esp_ble_mesh_defs.h b/components/bt/esp_ble_mesh/api/esp_ble_mesh_defs.h index efbf2df5b7..188d6db22d 100644 --- a/components/bt/esp_ble_mesh/api/esp_ble_mesh_defs.h +++ b/components/bt/esp_ble_mesh/api/esp_ble_mesh_defs.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2017-2023 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2017-2024 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -415,6 +415,29 @@ typedef struct { bool erase_flash; /*!< Indicate if erasing flash when deinit mesh stack */ } esp_ble_mesh_deinit_param_t; +/** Scan parameters */ +typedef struct { + /** + * Scan interval. + * + * Range: 0x0004 to 0x4000. + * + * Time = N * 0.625 ms. Time Range: 2.5 ms to 10.24 s + */ + uint16_t scan_interval; + + /** + * Uncoded Scan window. + * + * Time scanned on uncoded PHY within a scan interval. + * + * Range: 0x0004 to 0x4000. + * + * Time = N * 0.625 ms. Time Range: 2.5 ms to 10.24 s + */ + uint16_t uncoded_scan_window; +} esp_ble_mesh_scan_param_t; + /** Format of Unicast Address Range */ typedef struct { uint16_t len_present:1, /*!< Indicate the presence or absence of the RangeLength field */ diff --git a/components/bt/esp_ble_mesh/btc/btc_ble_mesh_ble.c b/components/bt/esp_ble_mesh/btc/btc_ble_mesh_ble.c index ead6c2cc02..2769960029 100644 --- a/components/bt/esp_ble_mesh/btc/btc_ble_mesh_ble.c +++ b/components/bt/esp_ble_mesh/btc/btc_ble_mesh_ble.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2020-2021 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2020-2024 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -13,8 +13,7 @@ #include "mesh/adapter.h" #include "esp_ble_mesh_ble_api.h" -#if CONFIG_BLE_MESH_BLE_COEX_SUPPORT - +#if (CONFIG_BLE_MESH_BLE_COEX_SUPPORT || CONFIG_BLE_MESH_USE_BLE_50) static void btc_ble_mesh_ble_copy_req_data(btc_msg_t *msg, void *p_dst, void *p_src) { #if CONFIG_BLE_MESH_SUPPORT_BLE_SCAN @@ -29,6 +28,7 @@ static void btc_ble_mesh_ble_copy_req_data(btc_msg_t *msg, void *p_dst, void *p_ switch (msg->act) { case ESP_BLE_MESH_SCAN_BLE_ADVERTISING_PKT_EVT: if (p_src_data->scan_ble_adv_pkt.data && p_src_data->scan_ble_adv_pkt.length) { + memcpy(&p_dst_data->scan_ble_adv_pkt, &p_src_data->scan_ble_adv_pkt, sizeof(p_src_data->scan_ble_adv_pkt)); p_dst_data->scan_ble_adv_pkt.length = p_src_data->scan_ble_adv_pkt.length; p_dst_data->scan_ble_adv_pkt.data = bt_mesh_calloc(p_src_data->scan_ble_adv_pkt.length); if (p_dst_data->scan_ble_adv_pkt.data) { @@ -86,26 +86,34 @@ static void btc_ble_mesh_ble_callback(esp_ble_mesh_ble_cb_param_t *cb_params, ui btc_ble_mesh_ble_copy_req_data, btc_ble_mesh_ble_free_req_data); } -#if CONFIG_BLE_MESH_SUPPORT_BLE_SCAN -void bt_mesh_ble_scan_cb_evt_to_btc(const bt_mesh_addr_t *addr, - uint8_t adv_type, uint8_t data[], - uint16_t length, int8_t rssi) +#if CONFIG_BT_NIMBLE_ENABLED && CONFIG_BLE_MESH_USE_BLE_50 +void bt_mesh_ble_nimble_evt_to_btc(struct ble_gap_event *event, void *arg) { esp_ble_mesh_ble_cb_param_t param = {0}; - if (addr == NULL) { + if (event == NULL) { BT_ERR("%s, Invalid parameter", __func__); return; } - memcpy(param.scan_ble_adv_pkt.addr, addr->val, sizeof(addr->val)); - param.scan_ble_adv_pkt.addr_type = addr->type; - if (data && length) { - param.scan_ble_adv_pkt.data = data; - param.scan_ble_adv_pkt.length = length; + memcpy(¶m.nimble_gap_evt.event, event, sizeof(struct ble_gap_event)); + param.nimble_gap_evt.arg = arg; + + btc_ble_mesh_ble_callback(¶m, ESP_BLE_MESH_NIMBLE_GAP_EVENT_EVT); +} +#endif /* CONFIG_BT_NIMBLE_ENABLED && CONFIG_BLE_MESH_USE_BLE_50 */ + +#if CONFIG_BLE_MESH_SUPPORT_BLE_SCAN +void bt_mesh_ble_scan_cb_evt_to_btc(bt_mesh_ble_adv_report_t *adv_report) +{ + esp_ble_mesh_ble_cb_param_t param = {0}; + + if (adv_report == NULL) { + BT_ERR("%s, Invalid parameter", __func__); + return; } - param.scan_ble_adv_pkt.adv_type = adv_type; - param.scan_ble_adv_pkt.rssi = rssi; + + memcpy(¶m.scan_ble_adv_pkt, adv_report, sizeof(bt_mesh_ble_adv_report_t)); btc_ble_mesh_ble_callback(¶m, ESP_BLE_MESH_SCAN_BLE_ADVERTISING_PKT_EVT); } @@ -157,6 +165,14 @@ void btc_ble_mesh_ble_call_handler(btc_msg_t *msg) btc_ble_mesh_ble_callback(¶m, ESP_BLE_MESH_STOP_BLE_SCANNING_COMP_EVT); break; #endif /* CONFIG_BLE_MESH_SUPPORT_BLE_SCAN */ + case BTC_BLE_MESH_ACT_UPDATE_SCAN_PARAMS: + struct bt_mesh_scan_param scan_param = { + .interval = arg->scan_params.scan_interval, + .window = arg->scan_params.uncoded_scan_window, + }; + param.scan_params_update_comp.err_code = bt_mesh_scan_param_update(&scan_param); + btc_ble_mesh_ble_callback(¶m, ESP_BLE_MESH_SCAN_PARAMS_UPDATE_COMP_EVT); + break; default: return; } @@ -191,5 +207,4 @@ void btc_ble_mesh_ble_cb_handler(btc_msg_t *msg) btc_ble_mesh_ble_free_req_data(msg); } - -#endif /* CONFIG_BLE_MESH_BLE_COEX_SUPPORT */ +#endif /* (CONFIG_BLE_MESH_BLE_COEX_SUPPORT || CONFIG_BLE_MESH_USE_BLE_50) */ diff --git a/components/bt/esp_ble_mesh/btc/btc_ble_mesh_prov.c b/components/bt/esp_ble_mesh/btc/btc_ble_mesh_prov.c index f6cdb426f1..e878250012 100644 --- a/components/bt/esp_ble_mesh/btc/btc_ble_mesh_prov.c +++ b/components/bt/esp_ble_mesh/btc/btc_ble_mesh_prov.c @@ -30,6 +30,7 @@ #endif /* CONFIG_BLE_MESH_V11_SUPPORT */ #include "adv.h" +#include "scan.h" #include "mesh/kernel.h" #include "mesh/proxy.h" #include "mesh.h" @@ -2948,6 +2949,7 @@ void btc_ble_mesh_model_call_handler(btc_msg_t *msg) .ctx.send_tag = arg->model_send.ctx->send_tag, .msg_timeout = arg->model_send.msg_timeout, }; + err = bt_mesh_client_send_msg(¶m, buf, arg->model_send.need_rsp, btc_ble_mesh_client_model_timeout_cb); bt_mesh_free_buf(buf); diff --git a/components/bt/esp_ble_mesh/btc/include/btc_ble_mesh_ble.h b/components/bt/esp_ble_mesh/btc/include/btc_ble_mesh_ble.h index 8c63002a2a..e5d21df0d0 100644 --- a/components/bt/esp_ble_mesh/btc/include/btc_ble_mesh_ble.h +++ b/components/bt/esp_ble_mesh/btc/include/btc_ble_mesh_ble.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2020-2021 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2020-2024 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -16,6 +16,30 @@ extern "C" { #endif +typedef struct { + uint8_t addr[6]; /*!< Device address */ + uint8_t addr_type; /*!< Device address type */ +#if CONFIG_BLE_MESH_USE_BLE_50 + uint8_t adv_type __attribute__((deprecated("`event_type` should be used to determine the advertising type"))); /*!< advertising type */ +#else + uint8_t adv_type; /*!< Advertising type */ +#endif + uint8_t *data; /*!< Advertising data */ + uint16_t length; /*!< Advertising data length */ + int8_t rssi; /*!< RSSI of the advertising packet */ +#if CONFIG_BLE_MESH_USE_BLE_50 + uint8_t event_type; /*!< Extended advertising event type */ + uint8_t primary_phy; /*!< Extended advertising primary PHY */ + uint8_t secondary_phy; /*!< Extended advertising secondary PHY */ + uint8_t sid; /*!< Extended advertising set ID */ + uint8_t tx_power; /*!< Extended advertising TX power */ + uint8_t dir_addr_type; /*!< Direct address type */ + uint8_t dir_addr[6]; /*!< Direct address */ + uint8_t data_status; /*!< Data type */ + uint16_t per_adv_interval; /*!< Periodic advertising interval */ +#endif /* CONFIG_BLE_MESH_USE_BLE_50 */ +} bt_mesh_ble_adv_report_t; + typedef union { struct { esp_ble_mesh_ble_adv_param_t param; @@ -30,6 +54,10 @@ typedef union { struct { /* RFU */ } stop_ble_scan; + struct ble_mesh_scan_params { + uint16_t scan_interval; + uint16_t uncoded_scan_window; + } scan_params; } btc_ble_mesh_ble_args_t; typedef enum { @@ -37,11 +65,14 @@ typedef enum { BTC_BLE_MESH_ACT_STOP_BLE_ADV, BTC_BLE_MESH_ACT_START_BLE_SCAN, BTC_BLE_MESH_ACT_STOP_BLE_SCAN, + BTC_BLE_MESH_ACT_UPDATE_SCAN_PARAMS, } btc_ble_mesh_ble_act_t; -void bt_mesh_ble_scan_cb_evt_to_btc(const bt_mesh_addr_t *addr, - uint8_t adv_type, uint8_t data[], - uint16_t length, int8_t rssi); +void bt_mesh_ble_scan_cb_evt_to_btc(bt_mesh_ble_adv_report_t *adv_report); + +#if CONFIG_BT_NIMBLE_ENABLED && CONFIG_BLE_MESH_USE_BLE_50 +void bt_mesh_ble_nimble_evt_to_btc(struct ble_gap_event *event, void *arg); +#endif /* CONFIG_BT_NIMBLE_ENABLED && CONFIG_BLE_MESH_USE_BLE_50 */ void btc_ble_mesh_ble_call_handler(btc_msg_t *msg); diff --git a/components/bt/esp_ble_mesh/btc/include/btc_ble_mesh_prov.h b/components/bt/esp_ble_mesh/btc/include/btc_ble_mesh_prov.h index f27779270f..741a6b313d 100644 --- a/components/bt/esp_ble_mesh/btc/include/btc_ble_mesh_prov.h +++ b/components/bt/esp_ble_mesh/btc/include/btc_ble_mesh_prov.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 */ diff --git a/components/bt/esp_ble_mesh/common/include/mesh/utils.h b/components/bt/esp_ble_mesh/common/include/mesh/utils.h index 98243483c8..967fed2e0c 100644 --- a/components/bt/esp_ble_mesh/common/include/mesh/utils.h +++ b/components/bt/esp_ble_mesh/common/include/mesh/utils.h @@ -200,7 +200,7 @@ extern "C" { * { MY_PWM0 , MY_PWM1 } * * @param LEN The length of the sequence. Must be an integer literal less - * than 255. + * than 255 (ref: utils_loops.h). * @param F A macro function that accepts at least two arguments: * F(i, ...). @p F is called repeatedly in the expansion. * Its first argument @p i is the index in the sequence, and diff --git a/components/bt/esp_ble_mesh/core/adv.c b/components/bt/esp_ble_mesh/core/adv.c index 79932a0582..70341bbfa4 100644 --- a/components/bt/esp_ble_mesh/core/adv.c +++ b/components/bt/esp_ble_mesh/core/adv.c @@ -45,6 +45,14 @@ static const uint8_t adv_type[] = { [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); @@ -122,11 +130,51 @@ struct bt_mesh_adv_task { 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) @@ -155,8 +203,16 @@ uint16_t bt_mesh_pdu_duration(uint8_t xmit) 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}; @@ -187,6 +243,11 @@ static inline int adv_send(struct net_buf *buf) param.interval_min = ADV_SCAN_UNIT(adv_int); param.interval_max = param.interval_min; +#if CONFIG_BLE_MESH_USE_BLE_50 + param.adv_duration = duration; + param.adv_count = BLE_MESH_TRANSMIT_COUNT(BLE_MESH_ADV(buf)->xmit) + 1; +#endif + #if CONFIG_BLE_MESH_PROXY_SOLIC_PDU_TX if (BLE_MESH_ADV(buf)->type == BLE_MESH_ADV_PROXY_SOLIC) { bt_mesh_adv_buf_ref_debug(__func__, buf, 3U, BLE_MESH_BUF_REF_SMALL); @@ -195,12 +256,24 @@ static inline int adv_send(struct net_buf *buf) BLE_MESH_ADV_DATA_BYTES(BLE_MESH_DATA_UUID16_ALL, 0x59, 0x18), BLE_MESH_ADV_DATA(BLE_MESH_DATA_SVC_DATA16, buf->data, buf->len), }; - err = bt_le_adv_start(¶m, solic_ad, 3, NULL, 0); +#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); +#else /* CONFIG_BLE_MESH_USE_BLE_50 */ + err = bt_le_adv_start(¶m, &ad, 3, NULL, 0); +#endif /* CONFIG_BLE_MESH_USE_BLE_50 */ } else #endif { bt_mesh_adv_buf_ref_debug(__func__, buf, 4U, BLE_MESH_BUF_REF_SMALL); +#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); +#else /* CONFIG_BLE_MESH_USE_BLE_50 */ err = bt_le_adv_start(¶m, &ad, 1, NULL, 0); +#endif /* CONFIG_BLE_MESH_USE_BLE_50 */ } #if CONFIG_BLE_MESH_SUPPORT_BLE_ADV } else { @@ -229,7 +302,11 @@ 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); +#else /* CONFIG_BLE_MESH_USE_BLE_50 */ err = bt_mesh_ble_adv_start(&tx->param, &data); +#endif /* CONFIG_BLE_MESH_USE_BLE_50 */ } #endif /* CONFIG_BLE_MESH_SUPPORT_BLE_ADV */ @@ -242,9 +319,19 @@ 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)) { + BT_WARN("Advertising didn't finish on time"); + bt_le_ext_adv_stop(adv_ins->id); + } +#else /* CONFIG_BLE_MESH_USE_BLE_50 */ k_sleep(K_MSEC(duration)); +#endif /* CONFIG_BLE_MESH_USE_BLE_50 */ +#if !CONFIG_BLE_MESH_USE_BLE_50 err = bt_le_adv_stop(); +#endif + adv_send_end(err, cb, cb_data); if (err) { BT_ERR("Stop advertising failed: err %d", err); @@ -255,11 +342,6 @@ static inline int adv_send(struct net_buf *buf) return 0; } -static inline TickType_t K_WAIT(int32_t val) -{ - return (val == K_FOREVER) ? portMAX_DELAY : (val / portTICK_PERIOD_MS); -} - static void adv_thread(void *p) { #if CONFIG_BLE_MESH_RELAY_ADV_BUF @@ -679,6 +761,10 @@ void bt_mesh_adv_deinit(void) 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 && \ diff --git a/components/bt/esp_ble_mesh/core/adv.h b/components/bt/esp_ble_mesh/core/adv.h index 33224d78b1..d2fb7baca3 100644 --- a/components/bt/esp_ble_mesh/core/adv.h +++ b/components/bt/esp_ble_mesh/core/adv.h @@ -2,7 +2,7 @@ /* * SPDX-FileCopyrightText: 2017 Intel Corporation - * SPDX-FileContributor: 2018-2021 Espressif Systems (Shanghai) CO LTD + * SPDX-FileContributor: 2018-2024 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -13,6 +13,7 @@ #include "mesh/atomic.h" #include "mesh/access.h" #include "mesh/adapter.h" +#include "mesh/utils.h" #ifdef __cplusplus extern "C" { @@ -67,6 +68,19 @@ typedef enum { 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); @@ -81,6 +95,10 @@ 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, 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 f16456d6dd..d72b83b263 100644 --- a/components/bt/esp_ble_mesh/core/bluedroid_host/adapter.c +++ b/components/bt/esp_ble_mesh/core/bluedroid_host/adapter.c @@ -29,8 +29,10 @@ #include "mesh/adapter.h" #include "mesh/common.h" #include "prov_pvnr.h" +#include "scan.h" #include "net.h" #include "beacon.h" +#include "btc_ble_mesh_ble.h" #if CONFIG_BLE_MESH_V11_SUPPORT #include "mesh_v1.1/utils.h" @@ -60,7 +62,10 @@ static uint8_t bt_mesh_private_key[32]; /* Scan related functions */ static bt_mesh_scan_cb_t *bt_mesh_scan_dev_found_cb; + +#if !CONFIG_BLE_MESH_USE_BLE_50 static void bt_mesh_scan_result_callback(tBTA_DM_SEARCH_EVT event, tBTA_DM_SEARCH *p_data); +#endif #if (CONFIG_BLE_MESH_NODE && CONFIG_BLE_MESH_PB_GATT) || \ CONFIG_BLE_MESH_GATT_PROXY_SERVER || \ @@ -104,6 +109,14 @@ 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 +static inline void bt_mesh_set_ble_adv_running(); + +static inline void bt_mesh_unset_ble_adv_running(); + +static inline bool bt_mesh_is_ble_adv_running(); +#endif + int bt_mesh_host_init(void) { return 0; @@ -138,11 +151,18 @@ void bt_mesh_hci_init(void) const uint8_t *p = controller_get_interface()->get_ble_supported_states(); uint64_t states_fh = 0, states_sh = 0; - STREAM_TO_UINT32(states_fh, p); - STREAM_TO_UINT32(states_sh, p); + + /* macro STREAM_TO_UINT32 expansion */ + states_fh = (((uint32_t)(*(p))) + ((((uint32_t)(*((p) + 1)))) << 8) + ((((uint32_t)(*((p) + 2)))) << 16) + ((((uint32_t)(*((p) + 3)))) << 24)); + (p) += 4; + + states_sh = (((uint32_t)(*(p))) + ((((uint32_t)(*((p) + 1)))) << 8) + ((((uint32_t)(*((p) + 2)))) << 16) + ((((uint32_t)(*((p) + 3)))) << 24)); + (p) += 4; + bt_mesh_dev.le.states = (states_sh << 32) | states_fh; } +#if !CONFIG_BLE_MESH_USE_BLE_50 static void bt_mesh_scan_results_change_2_bta(tBTM_INQ_RESULTS *p_inq, uint8_t *p_eir, tBTA_DM_SEARCH_CBACK *p_scan_cback) { @@ -185,6 +205,189 @@ static void bt_mesh_scan_results_cb(tBTM_INQ_RESULTS *p_inq, uint8_t *p_eir) { bt_mesh_scan_results_change_2_bta(p_inq, p_eir, bt_mesh_scan_result_callback); } +#endif + +#if CONFIG_BLE_MESH_USE_BLE_50 +extern void btc_ble_5_gap_callback(tBTA_DM_BLE_5_GAP_EVENT event, + tBTA_DM_BLE_5_GAP_CB_PARAMS *params); + +void bt_mesh_ble_ext_adv_report(tBTM_BLE_EXT_ADV_REPORT *ext_adv_report) +{ +#if CONFIG_BLE_MESH_SUPPORT_BLE_SCAN + bt_mesh_ble_adv_report_t adv_rpt = {0}; + + if (bt_mesh_ble_scan_state_get()) { + memcpy(adv_rpt.addr, ext_adv_report->addr, BLE_MESH_ADDR_LEN); + memcpy(adv_rpt.dir_addr, ext_adv_report->dir_addr, BLE_MESH_ADDR_LEN); + + adv_rpt.addr_type = ext_adv_report->addr_type; + adv_rpt.data = ext_adv_report->adv_data; + adv_rpt.length = ext_adv_report->adv_data_len; + adv_rpt.rssi = ext_adv_report->rssi; + adv_rpt.event_type = ext_adv_report->event_type; + adv_rpt.primary_phy = ext_adv_report->primary_phy; + adv_rpt.secondary_phy = ext_adv_report->secondry_phy; + adv_rpt.sid = ext_adv_report->sid; + adv_rpt.tx_power = ext_adv_report->tx_power; + adv_rpt.dir_addr_type = ext_adv_report->dir_addr_type; + adv_rpt.data_status = ext_adv_report->data_status; + adv_rpt.per_adv_interval = ext_adv_report->per_adv_interval; + + bt_mesh_ble_scan_cb_evt_to_btc(&adv_rpt); + } +#endif /* CONFIG_BLE_MESH_SUPPORT_BLE_SCAN */ +} + +static bool bt_mesh_scan_result_process(tBTM_BLE_EXT_ADV_REPORT *ext_adv_report) +{ + struct bt_mesh_adv_report adv_rpt = {0}; + + assert(ext_adv_report); + + adv_rpt.addr.type = ext_adv_report->addr_type; + memcpy(adv_rpt.addr.val, ext_adv_report->addr, BLE_MESH_ADDR_LEN); + adv_rpt.primary_phy = ext_adv_report->primary_phy; + adv_rpt.secondary_phy = ext_adv_report->secondry_phy; + adv_rpt.rssi = ext_adv_report->rssi; + + if (!(ext_adv_report->event_type & BTM_BLE_ADV_LEGACY_MASK)) { + return false; + } + + if (!bt_mesh_atomic_test_bit(bt_mesh_dev.flags, BLE_MESH_DEV_SCANNING)) { + return false; + } + + BT_DBG("Recv adv report type %04x", ext_adv_report->event_type); + + switch (ext_adv_report->event_type) { + case BLE_MESH_ADV_IND: + case BLE_MESH_ADV_DIRECT_IND: + case BLE_MESH_ADV_SCAN_IND: + case BLE_MESH_ADV_NONCONN_IND: + case BLE_MESH_ADV_SCAN_RSP: + adv_rpt.adv_type = ext_adv_report->event_type; + break; + default: + return false; + break; + } + + if (bt_mesh_scan_dev_found_cb) { + net_buf_simple_init_with_data(&adv_rpt.adv_data, ext_adv_report->adv_data, ext_adv_report->adv_data_len); + bt_mesh_scan_dev_found_cb(&adv_rpt); + if (adv_rpt.adv_data.len != ext_adv_report->adv_data_len) { + /* The advertising data has been processed by Mesh Protocol */ + return true; + } + } + return false; +} + +void ble_mesh_5_gap_callback(tBTA_DM_BLE_5_GAP_EVENT event, + tBTA_DM_BLE_5_GAP_CB_PARAMS *params) +{ + BT_DBG("recv event %d", event); + + switch (event) { + case BTA_DM_BLE_5_GAP_EXT_ADV_SET_PARAMS_COMPLETE_EVT: + if (!bt_mesh_is_adv_inst_used(params->set_params.instance)) { + goto transfer_to_user; + } + if (params->set_params.status != BTM_SUCCESS) { + BT_ERR("BTA_DM_BLE_5_GAP_EXT_ADV_SET_PARAMS_COMPLETE_EVT Failed"); + } + break; + case BTA_DM_BLE_5_GAP_EXT_ADV_DATA_SET_COMPLETE_EVT: + if (!bt_mesh_is_adv_inst_used(params->adv_data_set.instance)) { + goto transfer_to_user; + } + if (params->adv_data_set.status != BTM_SUCCESS) { + BT_ERR("BTA_DM_BLE_5_GAP_EXT_ADV_DATA_SET_COMPLETE_EVT Failed"); + } + break; + case BTA_DM_BLE_5_GAP_EXT_SCAN_RSP_DATA_SET_COMPLETE_EVT: + if (!bt_mesh_is_adv_inst_used(params->scan_rsp_data_set.instance)) { + goto transfer_to_user; + } + if (params->scan_rsp_data_set.status != BTM_SUCCESS) { + BT_ERR("BTA_DM_BLE_5_GAP_EXT_SCAN_RSP_DATA_SET_COMPLETE_EVT Failed"); + } + break; + case BTA_DM_BLE_5_GAP_EXT_ADV_START_COMPLETE_EVT: + if (!bt_mesh_is_adv_inst_used(params->adv_start.instance[0])) { + goto transfer_to_user; + } + if (params->adv_start.status != BTM_SUCCESS) { + BT_ERR("BTA_DM_BLE_5_GAP_EXT_ADV_START_COMPLETE_EVT Failed"); + } + break; + case BTA_DM_BLE_5_GAP_EXT_ADV_STOP_COMPLETE_EVT: + if (!bt_mesh_is_adv_inst_used(params->adv_start.instance[0])) { + goto transfer_to_user; + } + if (params->adv_start.status != BTM_SUCCESS) { + BT_ERR("BTA_DM_BLE_5_GAP_EXT_ADV_STOP_COMPLETE_EVT Failed"); + } + break; + case BTA_DM_BLE_5_GAP_ADV_TERMINATED_EVT: + if (!bt_mesh_is_adv_inst_used(params->adv_term.adv_handle)) { + goto transfer_to_user; + } + 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); + } +#if CONFIG_BLE_MESH_SUPPORT_BLE_ADV + /** + * This judgment is to distinguish between the termination + * events of BLE connectable broadcasting and proxy connectable + * adv under the same instance ID, that is, when the status is 0. + * + * Since the host task and adv task are currently operated in + * series, there is no need to consider competition issues between + * tasks. + * + * @attention: once multiple adv instances are used, the adv task + * and host will be asynchronous, and it is necessary to consider + * the issue of resource competition. + */ + if (bt_mesh_is_ble_adv_running() && + params->adv_term.status == 0x00) { + /* The unset operation must be performed before waking up the + * adv task; performing the unset after waking up the adv task + * could lead to resource contention issues. + */ + bt_mesh_unset_ble_adv_running(); + ble_mesh_adv_task_wakeup(params->adv_term.adv_handle); + } +#endif /* CONFIG_BLE_MESH_SUPPORT_BLE_ADV */ + break; + case BTA_DM_BLE_5_GAP_EXT_ADV_REPORT_EVT: + if (!bt_mesh_scan_result_process(¶ms->ext_adv_report)) { + bt_mesh_ble_ext_adv_report(¶ms->ext_adv_report); + } + break; + case BTA_DM_BLE_5_GAP_EXT_SCAN_START_COMPLETE_EVT: + if (params->scan_start.status != BTM_SUCCESS) { + BT_ERR("BTA_DM_BLE_5_GAP_EXT_SCAN_START_COMPLETE_EVT Failed"); + } + break; + case BTA_DM_BLE_5_GAP_EXT_SCAN_STOP_COMPLETE_EVT: + if (params->scan_stop.status != BTM_SUCCESS) { + BT_ERR("BTM_BLE_5_GAP_EXT_SCAN_START_COMPLETE_EVT Failed"); + } + break; + default: + goto transfer_to_user; + } + + return; + +transfer_to_user: + btc_ble_5_gap_callback(event, params); +} +#endif static bool valid_adv_param(const struct bt_mesh_adv_param *param) { @@ -205,7 +408,12 @@ static bool valid_adv_param(const struct bt_mesh_adv_param *param) return true; } +#if CONFIG_BLE_MESH_USE_BLE_50 +static int set_adv_data(uint16_t hci_op, const uint8_t inst_id, + const struct bt_mesh_adv_data *ad, size_t ad_len) +#else static int set_adv_data(uint16_t hci_op, const struct bt_mesh_adv_data *ad, size_t ad_len) +#endif { struct bt_mesh_hci_cp_set_adv_data param = {0}; int i; @@ -227,16 +435,22 @@ static int set_adv_data(uint16_t hci_op, const struct bt_mesh_adv_data *ad, size param.len += ad[i].data_len; } +#if CONFIG_BLE_MESH_USE_BLE_50 + BTA_DmBleGapConfigExtAdvDataRaw(hci_op == BLE_MESH_HCI_OP_SET_SCAN_RSP_DATA, + inst_id, param.len, param.data); +#else /* Set adv data and scan rsp data. */ if (hci_op == BLE_MESH_HCI_OP_SET_ADV_DATA) { BLE_MESH_BTM_CHECK_STATUS(BTM_BleWriteAdvDataRaw(param.data, param.len)); } else if (hci_op == BLE_MESH_HCI_OP_SET_SCAN_RSP_DATA) { BLE_MESH_BTM_CHECK_STATUS(BTM_BleWriteScanRspRaw(param.data, param.len)); } +#endif return 0; } +#if !CONFIG_BLE_MESH_USE_BLE_50 static void start_adv_completed_cb(uint8_t status) { #if BLE_MESH_DEV @@ -245,6 +459,7 @@ static void start_adv_completed_cb(uint8_t status) } #endif } +#endif static bool valid_scan_param(const struct bt_mesh_scan_param *param) { @@ -276,15 +491,54 @@ static bool valid_scan_param(const struct bt_mesh_scan_param *param) static int start_le_scan(uint8_t scan_type, uint16_t interval, uint16_t window, uint8_t filter_dup, uint8_t scan_fil_policy) { +#if !CONFIG_BLE_MESH_USE_BLE_50 uint8_t addr_type_own = BLE_MESH_ADDR_PUBLIC; /* Currently only support Public Address */ tGATT_IF client_if = 0xFF; /* Default GATT interface id */ +#endif +#if CONFIG_BLE_MESH_USE_BLE_50 + tBTA_DM_BLE_EXT_SCAN_PARAMS ext_scan_params = {0}; + + if (interval == 0 || + interval < window) { + BT_ERR("invalid scan param itvl %d win %d", interval, window); + return EINVAL; + } + + ext_scan_params.own_addr_type = BLE_MESH_ADDR_PUBLIC; + ext_scan_params.filter_policy = scan_fil_policy; + ext_scan_params.scan_duplicate = filter_dup; + + if (window == 0) { + ext_scan_params.cfg_mask = BTM_BLE_GAP_EXT_SCAN_CODE_MASK; + } else if (interval > window) { + ext_scan_params.cfg_mask = BTM_BLE_GAP_EXT_SCAN_UNCODE_MASK | BTM_BLE_GAP_EXT_SCAN_CODE_MASK; + } else { + // interval == window + ext_scan_params.cfg_mask = BTM_BLE_GAP_EXT_SCAN_UNCODE_MASK; + } + + ext_scan_params.uncoded_cfg.scan_type = scan_type; + ext_scan_params.uncoded_cfg.scan_interval = interval; + ext_scan_params.uncoded_cfg.scan_window = window; + + ext_scan_params.coded_cfg.scan_type = scan_type; + ext_scan_params.coded_cfg.scan_interval = interval; + ext_scan_params.coded_cfg.scan_window = interval - window; + + BTA_DmBleGapSetExtScanParams(&ext_scan_params); + + BTM_BleGapRegisterCallback(ble_mesh_5_gap_callback); + + BTA_DmBleGapExtScan(true, 0, 0); +#else /* CONFIG_BLE_MESH_USE_BLE_50 */ BLE_MESH_BTM_CHECK_STATUS( BTM_BleSetScanFilterParams(client_if, interval, window, scan_type, addr_type_own, filter_dup, scan_fil_policy, NULL)); /* BLE Mesh scan permanently, so no duration of scan here */ BLE_MESH_BTM_CHECK_STATUS(BTM_BleScan(true, 0, bt_mesh_scan_results_cb, NULL, NULL)); +#endif /* CONFIG_BLE_MESH_USE_BLE_50 */ #if BLE_MESH_DEV if (scan_type == BLE_MESH_SCAN_ACTIVE) { @@ -297,22 +551,32 @@ static int start_le_scan(uint8_t scan_type, uint16_t interval, uint16_t window, return 0; } +#if !CONFIG_BLE_MESH_USE_BLE_50 static void bt_mesh_scan_result_callback(tBTA_DM_SEARCH_EVT event, tBTA_DM_SEARCH *p_data) { - struct net_buf_simple buf = {0}; - bt_mesh_addr_t addr = {0}; + struct bt_mesh_adv_report adv_rpt = {0}; BT_DBG("%s, event %d", __func__, event); if (event == BTA_DM_INQ_RES_EVT) { /* TODO: How to process scan response here? PS: p_data->inq_res.scan_rsp_len */ - addr.type = p_data->inq_res.ble_addr_type; - memcpy(addr.val, p_data->inq_res.bd_addr, BLE_MESH_ADDR_LEN); - net_buf_simple_init_with_data(&buf, p_data->inq_res.p_eir, p_data->inq_res.adv_data_len); + adv_rpt.addr.type = p_data->inq_res.ble_addr_type; + adv_rpt.rssi = p_data->inq_res.rssi; + adv_rpt.adv_type = p_data->inq_res.ble_evt_type; + + memcpy(adv_rpt.addr.val, p_data->inq_res.bd_addr, BLE_MESH_ADDR_LEN); + + net_buf_simple_init_with_data(&adv_rpt.adv_data, p_data->inq_res.p_eir, p_data->inq_res.adv_data_len); if (bt_mesh_scan_dev_found_cb) { - bt_mesh_scan_dev_found_cb(&addr, p_data->inq_res.rssi, p_data->inq_res.ble_evt_type, &buf, p_data->inq_res.scan_rsp_len); + bt_mesh_scan_dev_found_cb(&adv_rpt); + + if (p_data->inq_res.scan_rsp_len) { + adv_rpt.adv_type = BLE_MESH_ADV_SCAN_RSP; + net_buf_simple_init_with_data(&adv_rpt.adv_data, p_data->inq_res.p_eir + p_data->inq_res.adv_data_len, p_data->inq_res.scan_rsp_len); + bt_mesh_scan_dev_found_cb(&adv_rpt); + } } } else if (event == BTA_DM_INQ_CMPL_EVT) { BT_INFO("Scan completed, number of scan response %d", p_data->inq_cmpl.num_resps); @@ -320,7 +584,132 @@ static void bt_mesh_scan_result_callback(tBTA_DM_SEARCH_EVT event, tBTA_DM_SEARC BT_WARN("Unexpected scan result event %d", event); } } +#endif +#if CONFIG_BLE_MESH_USE_BLE_50 +int bt_le_ext_adv_start(const uint8_t inst_id, + const struct bt_mesh_adv_param *param, + const struct bt_mesh_adv_data *ad, size_t ad_len, + const struct bt_mesh_adv_data *sd, size_t sd_len) +{ + tBTA_DM_BLE_GAP_EXT_ADV_PARAMS ext_adv_params = {0}; + tBTA_DM_BLE_EXT_ADV ext_adv = {0}; + uint16_t interval = 0U; + int err = 0; + + assert(param); + +#if BLE_MESH_DEV + if (bt_mesh_atomic_test_bit(bt_mesh_dev.flags, BLE_MESH_DEV_ADVERTISING)) { + return -EALREADY; + } +#endif + + if (!valid_adv_param(param)) { + BT_ERR("Invalid adv parameters"); + return -EINVAL; + } + + memset(&ext_adv_params, 0, sizeof(tBTA_DM_BLE_GAP_EXT_ADV_PARAMS)); + + if (param->options & BLE_MESH_ADV_OPT_CONNECTABLE) { + ext_adv_params.type = BTA_DM_BLE_GAP_SET_EXT_ADV_PROP_LEGACY_IND; + } else if (sd != NULL) { + ext_adv_params.type = BTA_DM_BLE_GAP_SET_EXT_ADV_PROP_LEGACY_SCAN; + } else { + if (param->primary_phy == BLE_MESH_ADV_PHY_1M && + param->secondary_phy == BLE_MESH_ADV_PHY_1M) { + ext_adv_params.type = BTA_DM_BLE_GAP_SET_EXT_ADV_PROP_LEGACY_NONCONN; + } else { + BT_ERR("Unsupported PHY: pri %d sec %d",param->primary_phy, param->secondary_phy); + return -EINVAL; + } + } + +#if CONFIG_BLE_MESH_PRB_SRV + /* NOTE: When a Mesh Private beacon is advertised, the Mesh Private beacon shall + * use a resolvable private address or a non-resolvable private address in the + * AdvA field of the advertising PDU. + */ + if (ad->type == BLE_MESH_DATA_MESH_BEACON && ad->data[0] == BEACON_TYPE_PRIVATE) { + ext_adv_params.own_addr_type = BLE_MESH_ADDR_RANDOM; + } else { + ext_adv_params.own_addr_type = BLE_MESH_ADDR_PUBLIC; + } +#else + ext_adv_params.own_addr_type = BLE_MESH_ADDR_PUBLIC; +#endif + + ext_adv_params.sid = inst_id; + ext_adv_params.max_skip = 0; + ext_adv_params.tx_power = 0x7F; + ext_adv_params.scan_req_notif = false; + ext_adv_params.primary_phy = param->primary_phy; + ext_adv_params.secondary_phy = param->secondary_phy; + ext_adv_params.filter_policy = BLE_MESH_AP_SCAN_CONN_ALL; + ext_adv_params.channel_map = BLE_MESH_ADV_CHNL_37 | BLE_MESH_ADV_CHNL_38 | BLE_MESH_ADV_CHNL_39; + + interval = param->interval_min; + +#if CONFIG_BLE_MESH_RANDOM_ADV_INTERVAL + /* If non-connectable mesh packets are transmitted with an adv interval + * not smaller than 10ms, then we will use a random adv interval between + * [interval / 2, interval] for them. + */ + if (adv_type == BLE_MESH_ADV_NONCONN_IND && interval >= 16) { + interval >>= 1; + interval += (bt_mesh_get_rand() % (interval + 1)); + + BT_INFO("%u->%u", param->interval_min, interval); + } +#endif + + ext_adv_params.interval_min = interval; + ext_adv_params.interval_max = interval; + + /* Check if we can start adv using BTM_BleSetAdvParamsStartAdvCheck */ + BTA_DmBleGapExtAdvSetParams(inst_id, &ext_adv_params); + + err = set_adv_data(BLE_MESH_HCI_OP_SET_ADV_DATA, inst_id, ad, ad_len); + if (err) { + BT_ERR("Failed to set adv data, err %d", err); + return err; + } + + /* + * We need to set SCAN_RSP when enabling advertising type that allows + * for Scan Requests. + * + * If sd was not provided but we enable connectable undirected + * advertising sd needs to be cleared from values set by previous calls. + * Clearing sd is done by calling set_adv_data() with NULL data and zero len. + * So following condition check is unusual but correct. + */ + if (sd && (param->options & BLE_MESH_ADV_OPT_CONNECTABLE)) { + err = set_adv_data(BLE_MESH_HCI_OP_SET_SCAN_RSP_DATA, inst_id, sd, sd_len); + if (err) { + BT_ERR("Failed to set scan rsp data err %d", err); + return err; + } + } + + ext_adv.instance = inst_id; + ext_adv.duration = param->adv_duration / 10; + ext_adv.max_events = param->adv_count; + + BTA_DmBleGapExtAdvEnable(true, 1, &ext_adv); + +#if BLE_MESH_DEV + bt_mesh_atomic_set_bit(bt_mesh_dev.flags, BLE_MESH_DEV_ADVERTISING); + + if (!(param->options & BLE_MESH_ADV_OPT_ONE_TIME)) { + bt_mesh_atomic_set_bit(bt_mesh_dev.flags, BLE_MESH_DEV_KEEP_ADVERTISING); + } +#endif + + return 0; +} +#else /* CONFIG_BLE_MESH_USE_BLE_50 */ /* APIs functions */ int bt_le_adv_start(const struct bt_mesh_adv_param *param, const struct bt_mesh_adv_data *ad, size_t ad_len, @@ -348,7 +737,7 @@ int bt_le_adv_start(const struct bt_mesh_adv_param *param, err = set_adv_data(BLE_MESH_HCI_OP_SET_ADV_DATA, ad, ad_len); if (err) { - BT_ERR("Failed to set adv data"); + BT_ERR("Failed to set adv data, err %d", err); return err; } @@ -364,7 +753,7 @@ int bt_le_adv_start(const struct bt_mesh_adv_param *param, if (sd && (param->options & BLE_MESH_ADV_OPT_CONNECTABLE)) { err = set_adv_data(BLE_MESH_HCI_OP_SET_SCAN_RSP_DATA, sd, sd_len); if (err) { - BT_ERR("Failed to set scan rsp data"); + BT_ERR("Failed to set scan rsp data, err %d", err); return err; } } @@ -427,8 +816,97 @@ int bt_le_adv_start(const struct bt_mesh_adv_param *param, return 0; } +#endif /* CONFIG_BLE_MESH_USE_BLE_50 */ #if CONFIG_BLE_MESH_SUPPORT_BLE_ADV +#if CONFIG_BLE_MESH_USE_BLE_50 + +static bool _ble_adv_running_flag; + +static inline void bt_mesh_set_ble_adv_running() +{ + _ble_adv_running_flag = true; +} + +static inline void bt_mesh_unset_ble_adv_running() +{ + _ble_adv_running_flag = false; +} + +static inline bool bt_mesh_is_ble_adv_running() +{ + return _ble_adv_running_flag == true; +} + +int bt_mesh_ble_ext_adv_start(const uint8_t inst_id, + const struct bt_mesh_ble_adv_param *param, + const struct bt_mesh_ble_adv_data *data) +{ + tBTA_DM_BLE_GAP_EXT_ADV_PARAMS ext_adv_params = {0}; + tBTA_DM_BLE_EXT_ADV ext_adv = {0}; + struct bt_mesh_hci_cp_set_adv_data set = {0}; + + if (data && param->adv_type != BLE_MESH_ADV_DIRECT_IND && + param->adv_type != BLE_MESH_ADV_DIRECT_IND_LOW_DUTY) { + if (data->adv_data_len) { + set.len = data->adv_data_len; + memcpy(set.data, data->adv_data, data->adv_data_len); + BTA_DmBleGapConfigExtAdvDataRaw(false, inst_id, set.len, set.data); + } + if (data->scan_rsp_data_len && param->adv_type != BLE_MESH_ADV_NONCONN_IND) { + set.len = data->scan_rsp_data_len; + memcpy(set.data, data->scan_rsp_data, data->scan_rsp_data_len); + BTA_DmBleGapConfigExtAdvDataRaw(true, inst_id, set.len, set.data); + } + } + + switch (param->adv_type) { + case BLE_MESH_ADV_IND: + case BLE_MESH_ADV_DIRECT_IND: + case BLE_MESH_ADV_SCAN_IND: + case BLE_MESH_ADV_NONCONN_IND: + case BLE_MESH_ADV_SCAN_RSP: + ext_adv_params.type = param->adv_type; + break; + default: + BT_ERR("Unsupported adv type %d", param->adv_type); + return -EINVAL; + } + + ext_adv_params.max_skip = 0; + ext_adv_params.tx_power = 0x7F; + ext_adv_params.sid = inst_id; + ext_adv_params.scan_req_notif = false; + ext_adv_params.own_addr_type = param->own_addr_type; + ext_adv_params.interval_min = param->interval; + ext_adv_params.interval_max = param->interval; + ext_adv_params.primary_phy = BLE_MESH_ADV_PHY_1M; + ext_adv_params.secondary_phy = BLE_MESH_ADV_PHY_1M; + ext_adv_params.filter_policy = BLE_MESH_AP_SCAN_CONN_ALL; + ext_adv_params.channel_map = BLE_MESH_ADV_CHNL_37 | BLE_MESH_ADV_CHNL_38 | BLE_MESH_ADV_CHNL_39; + + 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) { + ext_adv_params.peer_addr_type = param->peer_addr_type; + memcpy(ext_adv_params.peer_addr, param->peer_addr, BLE_MESH_ADDR_LEN); + } + + ext_adv.instance = inst_id; + ext_adv.duration = param->duration; + ext_adv.max_events = param->count; + + /* Check if we can start adv using BTM_BleSetAdvParamsStartAdvCheck */ + BTA_DmBleGapExtAdvSetParams(inst_id, &ext_adv_params); + + BTA_DmBleGapExtAdvEnable(true, 1, &ext_adv); + + bt_mesh_set_ble_adv_running(); + + return 0; +} +#else /* CONFIG_BLE_MESH_USE_BLE_50 */ int bt_mesh_ble_adv_start(const struct bt_mesh_ble_adv_param *param, const struct bt_mesh_ble_adv_data *data) { @@ -470,8 +948,32 @@ int bt_mesh_ble_adv_start(const struct bt_mesh_ble_adv_param *param, return 0; } +#endif /* CONFIG_BLE_MESH_USE_BLE_50 */ #endif /* CONFIG_BLE_MESH_SUPPORT_BLE_ADV */ +#if CONFIG_BLE_MESH_USE_BLE_50 +int bt_le_ext_adv_stop(uint8_t inst_id) +{ + tBTA_DM_BLE_EXT_ADV ext_adv = {0}; + +#if BLE_MESH_DEV + bt_mesh_atomic_clear_bit(bt_mesh_dev.flags, BLE_MESH_DEV_KEEP_ADVERTISING); + if (!bt_mesh_atomic_test_bit(bt_mesh_dev.flags, BLE_MESH_DEV_ADVERTISING)) { + return 0; + } +#endif + + ext_adv.instance = inst_id; + + BTA_DmBleGapExtAdvEnable(false, 1, &ext_adv); + +#if BLE_MESH_DEV + bt_mesh_atomic_clear_bit(bt_mesh_dev.flags, BLE_MESH_DEV_ADVERTISING); +#endif + + return 0; +} +#else /* CONFIG_BLE_MESH_USE_BLE_50 */ int bt_le_adv_stop(void) { #if BLE_MESH_DEV @@ -489,6 +991,7 @@ int bt_le_adv_stop(void) return 0; } +#endif /* CONFIG_BLE_MESH_USE_BLE_50 */ int bt_le_scan_start(const struct bt_mesh_scan_param *param, bt_mesh_scan_cb_t cb) { @@ -530,7 +1033,11 @@ int bt_le_scan_stop(void) return -EALREADY; } +#if CONFIG_BLE_MESH_USE_BLE_50 + BTA_DmBleGapExtScan(false, 0 ,0); +#else /* CONFIG_BLE_MESH_USE_BLE_50 */ BLE_MESH_BTM_CHECK_STATUS(BTM_BleScan(false, 0, NULL, NULL, NULL)); +#endif /* CONFIG_BLE_MESH_USE_BLE_50 */ bt_mesh_atomic_clear_bit(bt_mesh_dev.flags, BLE_MESH_DEV_SCANNING); bt_mesh_scan_dev_found_cb = NULL; @@ -1198,6 +1705,9 @@ uint16_t bt_mesh_gattc_get_service_uuid(struct bt_mesh_conn *conn) int bt_mesh_gattc_conn_create(const bt_mesh_addr_t *addr, uint16_t service_uuid) { +#if CONFIG_BLE_MESH_USE_BLE_50 + tBTA_DM_BLE_CONN_PARAMS conn_1m_param = {0}; +#endif uint8_t zero[6] = {0}; int i; @@ -1240,21 +1750,47 @@ int bt_mesh_gattc_conn_create(const bt_mesh_addr_t *addr, uint16_t service_uuid) } if (bt_mesh_atomic_test_bit(bt_mesh_dev.flags, BLE_MESH_DEV_SCANNING)) { +#if CONFIG_BLE_MESH_USE_BLE_50 + BTA_DmBleGapExtScan(false, 0 ,0); +#else BLE_MESH_BTM_CHECK_STATUS(BTM_BleScan(false, 0, NULL, NULL, NULL)); +#endif bt_mesh_atomic_clear_bit(bt_mesh_dev.flags, BLE_MESH_DEV_SCANNING); } BT_DBG("Create conn with %s", bt_hex(addr->val, BLE_MESH_ADDR_LEN)); +#if CONFIG_BLE_MESH_USE_BLE_50 + /* Min_interval: 15ms 0x18, 0x18, 0x00, 0x64 + * Max_interval: 15ms + * Slave_latency: 0x0 + * Supervision_timeout: 1s + */ + conn_1m_param.scan_interval = 0x0020; + conn_1m_param.scan_window = 0x0020; + conn_1m_param.interval_min = 0x18; + conn_1m_param.interval_max = 0x18; + conn_1m_param.latency = 0; + conn_1m_param.supervision_timeout = 0x64; + conn_1m_param.min_ce_len = 0; + conn_1m_param.max_ce_len = 0; + + BTA_DmBleGapPreferExtConnectParamsSet(bt_mesh_gattc_info[i].addr.val, 0x01, &conn_1m_param ,NULL, NULL); + + BTA_GATTC_Open(bt_mesh_gattc_if, bt_mesh_gattc_info[i].addr.val, + bt_mesh_gattc_info[i].addr.type, true, BTA_GATT_TRANSPORT_LE, TRUE); +#else /* Min_interval: 15ms * Max_interval: 15ms * Slave_latency: 0x0 * Supervision_timeout: 1s */ + BTA_DmSetBlePrefConnParams(bt_mesh_gattc_info[i].addr.val, 0x18, 0x18, 0x00, 0x64); BTA_GATTC_Open(bt_mesh_gattc_if, bt_mesh_gattc_info[i].addr.val, bt_mesh_gattc_info[i].addr.type, true, BTA_GATT_TRANSPORT_LE, FALSE); +#endif return 0; } @@ -1655,11 +2191,15 @@ static void bt_mesh_bta_gattc_cb(tBTA_GATTC_EVT event, tBTA_GATTC *p_data) * use BTM_BleScan() to re-enable scan. */ if (!bt_mesh_atomic_test_bit(bt_mesh_dev.flags, BLE_MESH_DEV_SCANNING)) { +#if CONFIG_BLE_MESH_USE_BLE_50 + BTA_DmBleGapExtScan(true, 0 ,0); +#else tBTM_STATUS status = BTM_BleScan(true, 0, bt_mesh_scan_results_cb, NULL, NULL); if (status != BTM_SUCCESS && status != BTM_CMD_STARTED) { BT_ERR("Invalid scan status %d", status); break; } +#endif bt_mesh_atomic_set_bit(bt_mesh_dev.flags, BLE_MESH_DEV_SCANNING); } break; 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 8673103651..9d013baa0d 100644 --- a/components/bt/esp_ble_mesh/core/include/mesh/access.h +++ b/components/bt/esp_ble_mesh/core/include/mesh/access.h @@ -4,7 +4,7 @@ /* * SPDX-FileCopyrightText: 2017 Intel Corporation - * SPDX-FileContributor: 2018-2023 Espressif Systems (Shanghai) CO LTD + * SPDX-FileContributor: 2018-2024 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ 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 1cb239a3ca..4f28c0d684 100644 --- a/components/bt/esp_ble_mesh/core/include/mesh/adapter.h +++ b/components/bt/esp_ble_mesh/core/include/mesh/adapter.h @@ -1,7 +1,7 @@ /* * SPDX-FileCopyrightText: 2017 Nordic Semiconductor ASA * SPDX-FileCopyrightText: 2015-2017 Intel Corporation - * SPDX-FileContributor: 2018-2021 Espressif Systems (Shanghai) CO LTD + * SPDX-FileContributor: 2018-2024 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -33,6 +33,18 @@ extern "C" { #define BLE_MESH_GATT_DEF_MTU_SIZE 23 +#if CONFIG_BLE_MESH_USE_BLE_50 +#define BLE_MESH_ADV_PHY_UNASSIGNED 0 +#define BLE_MESH_ADV_PHY_1M 1 +#define BLE_MESH_ADV_PHY_2M 2 +#define BLE_MESH_ADV_PHY_CODED 3 +#define BLE_MESH_ADV_PHY_OPTION_NO_PREFER 0 +#define BLE_MESH_ADV_PHY_OPTION_PREFER_S2 1 +#define BLE_MESH_ADV_PHY_OPTION_PREFER_S8 2 +#define BLE_MESH_ADV_PHY_OPTION_REQUIRE_S2 3 +#define BLE_MESH_ADV_PHY_OPTION_REQUIRE_S8 4 +#endif + /* BD ADDR types */ #define BLE_MESH_ADDR_PUBLIC 0x00 #define BLE_MESH_ADDR_RANDOM 0x01 @@ -43,11 +55,22 @@ extern "C" { #define BLE_MESH_ADDR_LEN 0x06 /* Advertising types */ +#if !CONFIG_BLE_MESH_USE_BLE_50 #define BLE_MESH_ADV_IND 0x00 #define BLE_MESH_ADV_DIRECT_IND 0x01 #define BLE_MESH_ADV_SCAN_IND 0x02 #define BLE_MESH_ADV_NONCONN_IND 0x03 #define BLE_MESH_ADV_DIRECT_IND_LOW_DUTY 0x04 +#define BLE_MESH_ADV_SCAN_RSP 0x04 +#else +/* Bluetooth Core Spec 6.0, Vol 4, Part E, 7.7.65.13 */ +#define BLE_MESH_ADV_IND (0x13) +#define BLE_MESH_ADV_DIRECT_IND (0x15) +#define BLE_MESH_ADV_SCAN_IND (0x12) +#define BLE_MESH_ADV_NONCONN_IND (0x10) +#define BLE_MESH_ADV_DIRECT_IND_LOW_DUTY (0x1b) +#define BLE_MESH_ADV_SCAN_RSP (0x1b) +#endif /* advertising channel map */ #define BLE_MESH_ADV_CHNL_37 BIT(0) @@ -400,8 +423,32 @@ struct bt_mesh_adv_param { /** Maximum Advertising Interval (N * 0.625) */ uint16_t interval_max; + +#if CONFIG_BLE_MESH_USE_BLE_50 + /** Maximum Advertising Duration (N * 0.625) */ + uint16_t adv_duration; + + /** Advertising Packages Number */ + uint16_t adv_count; + + /** Advertising Primary PHY */ + uint8_t primary_phy; + + /** Advertising Secondary PHY */ + uint8_t secondary_phy; +#endif }; +#if CONFIG_BLE_MESH_USE_BLE_50 +enum bt_mesh_adv_inst_type { + BLE_MESH_ADV_PROXY_INS, + BLE_MESH_ADV_INS, + BLE_MESH_EXT_ADV_INS, + BLE_MESH_BLE_ADV_INS, + BLE_MESH_ADV_INS_TYPE_NUMS, +}; +#endif /* CONFIG_BLE_MESH_USE_BLE_50 */ + #if CONFIG_BLE_MESH_SUPPORT_BLE_ADV enum bt_mesh_ble_adv_priority { BLE_MESH_BLE_ADV_PRIO_LOW, @@ -441,7 +488,7 @@ struct bt_mesh_scan_param { /** Scan interval (N * 0.625 ms) */ uint16_t interval; - /** Scan window (N * 0.625 ms) */ + /** Uncoded phy Scan window (N * 0.625 ms) */ uint16_t window; /** BLE scan filter policy */ @@ -453,21 +500,38 @@ struct bt_mesh_conn { bt_mesh_atomic_t ref; }; +/* BLE Mesh advertising report */ +struct bt_mesh_adv_report { + /* Advertiser LE address and type. */ + bt_mesh_addr_t addr; + + /* Strength of advertiser signal. */ + int8_t rssi; + + /* Type of advertising response from advertiser. */ + uint8_t adv_type; + + /* Buffer containing advertiser data. */ + struct net_buf_simple adv_data; + +#if CONFIG_BLE_MESH_USE_BLE_50 + /* Primary advertising PHY */ + uint8_t primary_phy; + + /* Secondary advertising PHY */ + uint8_t secondary_phy; +#endif /* CONFIG_BLE_MESH_USE_BLE_50 */ +}; + /** @typedef bt_mesh_scan_cb_t * @brief Callback type for reporting LE scan results. * * A function of this type is given to the bt_le_scan_start() function * and will be called for any discovered LE device. * - * @param addr Advertiser LE address and type. - * @param rssi Strength of advertiser signal. - * @param adv_type Type of advertising response from advertiser. - * @param data Buffer containing advertiser data. - * @param scan_rsp_len Scan Response data length. + * @param adv_rpt: BLE Mesh advertising report. */ -typedef void bt_mesh_scan_cb_t(const bt_mesh_addr_t *addr, int8_t rssi, - uint8_t adv_type, struct net_buf_simple *buf, - uint8_t scan_rsp_len); +typedef void bt_mesh_scan_cb_t(struct bt_mesh_adv_report *adv_rpt); /* @typedef bt_mesh_dh_key_cb_t * @brief Callback type for DH Key calculation. @@ -553,7 +617,7 @@ struct bt_mesh_gatt_attr { * @param len Length of data to read * @param offset Offset to start reading from * - * @return Number fo bytes read, or in case of an error + * @return Number of bytes read, or in case of an error * BLE_MESH_GATT_ERR() with a specific ATT error code. */ ssize_t (*read)(struct bt_mesh_conn *conn, @@ -684,6 +748,21 @@ struct bt_mesh_gatt_attr { int bt_mesh_host_init(void); int bt_mesh_host_deinit(void); +#if CONFIG_BLE_MESH_USE_BLE_50 +int bt_le_ext_adv_start(const uint8_t inst_id, + const struct bt_mesh_adv_param *param, + const struct bt_mesh_adv_data *ad, size_t ad_len, + const struct bt_mesh_adv_data *sd, size_t sd_len); + +#if CONFIG_BLE_MESH_SUPPORT_BLE_ADV +int bt_mesh_ble_ext_adv_start(const uint8_t inst_id, + const struct bt_mesh_ble_adv_param *param, + const struct bt_mesh_ble_adv_data *adv_data); +#endif /* CONFIG_BLE_MESH_SUPPORT_BLE_ADV */ + +int bt_le_ext_adv_stop(uint8_t inst_id); + +#else /* CONFIG_BLE_MESH_USE_BLE_50 */ int bt_le_adv_start(const struct bt_mesh_adv_param *param, const struct bt_mesh_adv_data *ad, size_t ad_len, const struct bt_mesh_adv_data *sd, size_t sd_len); @@ -691,9 +770,10 @@ int bt_le_adv_start(const struct bt_mesh_adv_param *param, #if CONFIG_BLE_MESH_SUPPORT_BLE_ADV int bt_mesh_ble_adv_start(const struct bt_mesh_ble_adv_param *param, const struct bt_mesh_ble_adv_data *data); -#endif +#endif /* CONFIG_BLE_MESH_SUPPORT_BLE_ADV */ int bt_le_adv_stop(void); +#endif /* CONFIG_BLE_MESH_USE_BLE_50 */ int bt_le_scan_start(const struct bt_mesh_scan_param *param, bt_mesh_scan_cb_t cb); diff --git a/components/bt/esp_ble_mesh/core/net.c b/components/bt/esp_ble_mesh/core/net.c index 15d099cc5c..43f0af2487 100644 --- a/components/bt/esp_ble_mesh/core/net.c +++ b/components/bt/esp_ble_mesh/core/net.c @@ -13,6 +13,7 @@ #include "crypto.h" #include "adv.h" +#include "net.h" #include "scan.h" #include "mesh.h" #include "lpn.h" @@ -1123,6 +1124,15 @@ int bt_mesh_net_send(struct bt_mesh_net_tx *tx, struct net_buf *buf, tx->ctx->send_cred != BLE_MESH_FRIENDSHIP_CRED) { if (bt_mesh_proxy_server_relay(&buf->b, tx->ctx->addr) && BLE_MESH_ADDR_IS_UNICAST(tx->ctx->addr)) { + /** + * When a message is sent to a proxy client, the message + * can be sent via GATT only, eliminating the need for + * an ADV bearer. + */ + if (bt_mesh_proxy_server_find_client_by_addr(tx->ctx->addr)) { + bearer &= ~BLE_MESH_ADV_BEARER; + } + /* Notify completion if this only went * through the Mesh Proxy. */ @@ -1892,24 +1902,26 @@ static bool ignore_net_msg(uint16_t src, uint16_t dst) return false; } -void bt_mesh_net_recv(struct net_buf_simple *data, int8_t rssi, - enum bt_mesh_net_if net_if) +void bt_mesh_generic_net_recv(struct net_buf_simple *data, + struct bt_mesh_net_rx *rx, + enum bt_mesh_net_if net_if) { NET_BUF_SIMPLE_DEFINE(buf, 29); - struct bt_mesh_net_rx rx = { .ctx.recv_rssi = rssi }; struct net_buf_simple_state state = {0}; - BT_DBG("rssi %d net_if %u", rssi, net_if); + assert(rx); + + BT_DBG("rssi %d net_if %u", rx->ctx.recv_rssi, net_if); if (!ready_to_recv()) { return; } - if (bt_mesh_net_decode(data, net_if, &rx, &buf)) { + if (bt_mesh_net_decode(data, net_if, rx, &buf)) { return; } - if (ignore_net_msg(rx.ctx.addr, rx.ctx.recv_dst)) { + if (ignore_net_msg(rx->ctx.addr, rx->ctx.recv_dst)) { return; } @@ -1919,26 +1931,26 @@ void bt_mesh_net_recv(struct net_buf_simple *data, int8_t rssi, BT_BQB(BLE_MESH_BQB_TEST_LOG_LEVEL_PRIMARY_ID_NODE | \ BLE_MESH_BQB_TEST_LOG_LEVEL_SUB_ID_NET, "\nNetRecv: ctl: %d, src: %d, dst: %d, ttl: %d, data: 0x%s", - rx.ctl, rx.ctx.addr, rx.ctx.recv_dst, rx.ctx.recv_ttl, + rx->ctl, rx->ctx.addr, rx->ctx.recv_dst, rx->ctx.recv_ttl, bt_hex(buf.data + BLE_MESH_NET_HDR_LEN, buf.len - BLE_MESH_NET_HDR_LEN)); /* If trying to handle a message with DST set to all-directed-forwarding-nodes, * we need to make sure the directed forwarding functionality is enabled in the * corresponding subnet. */ - rx.local_match = (bt_mesh_fixed_group_match(rx.ctx.recv_dst) || - bt_mesh_fixed_direct_match(rx.sub, rx.ctx.recv_dst) || - bt_mesh_elem_find(rx.ctx.recv_dst)); + rx->local_match = (bt_mesh_fixed_group_match(rx->ctx.recv_dst) || + bt_mesh_fixed_direct_match(rx->sub, rx->ctx.recv_dst) || + bt_mesh_elem_find(rx->ctx.recv_dst)); if (IS_ENABLED(CONFIG_BLE_MESH_GATT_PROXY_SERVER) && #if CONFIG_BLE_MESH_PRB_SRV bt_mesh_private_gatt_proxy_state_get() != BLE_MESH_PRIVATE_GATT_PROXY_ENABLED && #endif net_if == BLE_MESH_NET_IF_PROXY) { - bt_mesh_proxy_server_addr_add(data, rx.ctx.addr); + bt_mesh_proxy_server_addr_add(data, rx->ctx.addr); if (bt_mesh_gatt_proxy_get() == BLE_MESH_GATT_PROXY_DISABLED && - !rx.local_match) { + !rx->local_match) { BT_INFO("Proxy is disabled; ignoring message"); return; } @@ -1951,11 +1963,11 @@ void bt_mesh_net_recv(struct net_buf_simple *data, int8_t rssi, * tag the Network PDU with the immutable-credentials tag. */ #if CONFIG_BLE_MESH_DF_SRV - if (rx.sub->directed_proxy == BLE_MESH_DIRECTED_PROXY_ENABLED && - rx.sub->use_directed == BLE_MESH_PROXY_USE_DIRECTED_ENABLED && - !bt_mesh_addr_in_uar(&rx.sub->proxy_client_uar, rx.ctx.addr) && - !bt_mesh_proxy_server_find_client_by_addr(rx.ctx.addr)) { - rx.ctx.recv_tag |= BLE_MESH_TAG_IMMUTABLE_CRED; + if (rx->sub->directed_proxy == BLE_MESH_DIRECTED_PROXY_ENABLED && + rx->sub->use_directed == BLE_MESH_PROXY_USE_DIRECTED_ENABLED && + !bt_mesh_addr_in_uar(&rx->sub->proxy_client_uar, rx->ctx.addr) && + !bt_mesh_proxy_server_find_client_by_addr(rx->ctx.addr)) { + rx->ctx.recv_tag |= BLE_MESH_TAG_IMMUTABLE_CRED; } #endif /* CONFIG_BLE_MESH_DF_SRV */ } @@ -1967,24 +1979,24 @@ void bt_mesh_net_recv(struct net_buf_simple *data, int8_t rssi, * credentials. Remove it from the message cache so that we accept * it again in the future. */ - if (bt_mesh_trans_recv(&buf, &rx) == -EAGAIN) { + if (bt_mesh_trans_recv(&buf, rx) == -EAGAIN) { BT_WARN("Removing rejected message from Network Message Cache"); - msg_cache[rx.msg_cache_idx].src = BLE_MESH_ADDR_UNASSIGNED; + msg_cache[rx->msg_cache_idx].src = BLE_MESH_ADDR_UNASSIGNED; /* Rewind the next index now that we're not using this entry */ - msg_cache_next = rx.msg_cache_idx; + msg_cache_next = rx->msg_cache_idx; } /* Relay if this was a group/virtual address, or if the destination * was neither a local element nor an LPN we're Friends for. */ - if (!BLE_MESH_ADDR_IS_UNICAST(rx.ctx.recv_dst) || - (!rx.local_match && !rx.friend_match + if (!BLE_MESH_ADDR_IS_UNICAST(rx->ctx.recv_dst) || + (!rx->local_match && !rx->friend_match #if CONFIG_BLE_MESH_NOT_RELAY_REPLAY_MSG - && !rx.replay_msg + && !rx->replay_msg #endif )) { net_buf_simple_restore(&buf, &state); - bt_mesh_net_relay(&buf, &rx); + bt_mesh_net_relay(&buf, rx); } } diff --git a/components/bt/esp_ble_mesh/core/net.h b/components/bt/esp_ble_mesh/core/net.h index 7da8c4a078..94e0781917 100644 --- a/components/bt/esp_ble_mesh/core/net.h +++ b/components/bt/esp_ble_mesh/core/net.h @@ -2,7 +2,7 @@ /* * SPDX-FileCopyrightText: 2017 Intel Corporation - * SPDX-FileContributor: 2018-2021 Espressif Systems (Shanghai) CO LTD + * SPDX-FileContributor: 2018-2024 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -465,8 +465,16 @@ int bt_mesh_net_resend(struct bt_mesh_subnet *sub, struct net_buf *buf, int bt_mesh_net_decode(struct net_buf_simple *data, enum bt_mesh_net_if net_if, struct bt_mesh_net_rx *rx, struct net_buf_simple *buf); -void bt_mesh_net_recv(struct net_buf_simple *data, int8_t rssi, - enum bt_mesh_net_if net_if); +void bt_mesh_generic_net_recv(struct net_buf_simple *data, + struct bt_mesh_net_rx *rx, + enum bt_mesh_net_if net_if); + +static inline void bt_mesh_net_recv(struct net_buf_simple *data, int8_t rssi, + enum bt_mesh_net_if net_if) +{ + struct bt_mesh_net_rx rx = { .ctx.recv_rssi = rssi }; + bt_mesh_generic_net_recv(data, &rx, net_if); +} bool bt_mesh_primary_subnet_exist(void); 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 fcad720059..2dd9777001 100644 --- a/components/bt/esp_ble_mesh/core/nimble_host/adapter.c +++ b/components/bt/esp_ble_mesh/core/nimble_host/adapter.c @@ -1,7 +1,7 @@ /* * SPDX-FileCopyrightText: 2017 Nordic Semiconductor ASA * SPDX-FileCopyrightText: 2015-2016 Intel Corporation - * SPDX-FileContributor: 2018-2023 Espressif Systems (Shanghai) CO LTD + * SPDX-FileContributor: 2018-2024 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -27,6 +27,8 @@ #include "mesh/hci.h" #include "mesh/common.h" #include "prov_pvnr.h" +#include "scan.h" +#include "btc_ble_mesh_ble.h" /** @def BT_UUID_MESH_PROV * @brief Mesh Provisioning Service @@ -69,7 +71,6 @@ static uint8_t bt_mesh_private_key[32]; /* Scan related functions */ static bt_mesh_scan_cb_t *bt_mesh_scan_dev_found_cb; - #if CONFIG_BLE_MESH_NODE /* the gatt database list to save the attribute table */ static sys_slist_t bt_mesh_gatts_db; @@ -79,10 +80,57 @@ static struct bt_mesh_conn bt_mesh_gatts_conn[BLE_MESH_MAX_CONN]; static struct bt_mesh_conn_cb *bt_mesh_gatts_conn_cb; static uint8_t bt_mesh_gatts_addr[6]; + +#if CONFIG_BLE_MESH_USE_BLE_50 +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 +static inline void bt_mesh_set_ble_adv_running(); + +static inline void bt_mesh_unset_ble_adv_running(); + +static inline bool bt_mesh_is_ble_adv_running(); +#endif + static bool g_host_init = false; +#if CONFIG_BLE_MESH_NODE && CONFIG_BLE_MESH_USE_BLE_50 + +#define BT_MESH_GATTS_CONN_UNUSED 0xFF + +static void bt_mesh_gatts_conn_init(void) +{ + int i; + for (i = 0; i < BLE_MESH_MAX_CONN; i++) { + bt_mesh_gatts_conn[i].handle = BT_MESH_GATTS_CONN_UNUSED; + } +} + +static int bt_mesh_find_free_conn_idx(void) +{ + int i; + for (i = 0; i < BLE_MESH_MAX_CONN; i++) { + if (bt_mesh_gatts_conn[i].handle == BT_MESH_GATTS_CONN_UNUSED) { + return i; + } + } + return -ENOMEM; +} + +static int bt_mesh_find_conn_idx(uint16_t conn_handle) +{ + int i; + for (i = 0; i < BLE_MESH_MAX_CONN; i++) { + if (bt_mesh_gatts_conn[i].handle == conn_handle) { + return i; + } + } + return -ENODEV; +} +#endif /* CONFIG_BLE_MESH_NODE && CONFIG_BLE_MESH_USE_BLE_50 */ + int bt_mesh_host_init(void) { int rc; @@ -145,7 +193,13 @@ void bt_mesh_hci_init(void) #endif } +#if CONFIG_BLE_MESH_USE_BLE_50 +static struct ble_gap_ext_disc_params uncoded_disc_params; +static struct ble_gap_ext_disc_params coded_disc_params; +#else static struct ble_gap_disc_params scan_param; +#endif + #if (CONFIG_BLE_MESH_PROVISIONER && CONFIG_BLE_MESH_PB_GATT) || \ CONFIG_BLE_MESH_GATT_PROXY_CLIENT static struct gattc_prov_info { @@ -350,7 +404,7 @@ static int svc_disced(uint16_t conn_handle, const struct ble_gatt_error *error, } uuid = &service->uuid; - uuid_length = (uint8_t) (uuid->u.type == BLE_UUID_TYPE_16 ? 2 : 16); + uuid_length = (uint8_t)(uuid->u.type == BLE_UUID_TYPE_16 ? 2 : 16); if (uuid_length != 2) { return 0; } @@ -398,9 +452,45 @@ static int svc_disced(uint16_t conn_handle, const struct ble_gatt_error *error, } #endif /* (CONFIG_BLE_MESH_PROVISIONER && CONFIG_BLE_MESH_PB_GATT) || CONFIG_BLE_MESH_GATT_PROXY_CLIENT */ -static int disc_cb(struct ble_gap_event *event, void *arg) +#if CONFIG_BLE_MESH_USE_BLE_50 +void bt_mesh_ble_ext_adv_report(struct ble_gap_ext_disc_desc *desc) { +#if CONFIG_BLE_MESH_SUPPORT_BLE_SCAN + bt_mesh_ble_adv_report_t adv_rpt = {0}; + if (bt_mesh_ble_scan_state_get()) { + memcpy(adv_rpt.addr, desc->addr.val, BLE_MESH_ADDR_LEN); + memcpy(adv_rpt.dir_addr, desc->direct_addr.val, BLE_MESH_ADDR_LEN); + + /* Here, only a shallow copy needs to be implemented; + * deep copying behavior occurs in btc_ble_mesh_ble_copy_req_data. */ + adv_rpt.data = desc->data; + + adv_rpt.event_type = desc->props; + adv_rpt.addr_type = desc->addr.type; + adv_rpt.length = desc->length_data; + adv_rpt.rssi = desc->rssi; + adv_rpt.primary_phy = desc->prim_phy; + adv_rpt.secondary_phy = desc->sec_phy; + adv_rpt.sid = desc->sid; + adv_rpt.tx_power = desc->tx_power; + adv_rpt.dir_addr_type = desc->direct_addr.type; + adv_rpt.data_status = desc->data_status; + adv_rpt.per_adv_interval = desc->periodic_adv_itvl; + + bt_mesh_ble_scan_cb_evt_to_btc(&adv_rpt); + } +#endif /* CONFIG_BLE_MESH_SUPPORT_BLE_SCAN */ +} +#endif + +int disc_cb(struct ble_gap_event *event, void *arg) +{ +#if CONFIG_BLE_MESH_USE_BLE_50 + struct ble_gap_ext_disc_desc *desc; +#else struct ble_gap_disc_desc *desc; +#endif + #if (CONFIG_BLE_MESH_PROVISIONER && CONFIG_BLE_MESH_PB_GATT) || \ CONFIG_BLE_MESH_GATT_PROXY_CLIENT int rc, i; @@ -412,21 +502,58 @@ static int disc_cb(struct ble_gap_event *event, void *arg) #endif switch (event->type) { - case BLE_GAP_EVENT_DISC: { - struct net_buf_simple buf = {0}; +#if CONFIG_BLE_MESH_USE_BLE_50 + case BLE_GAP_EVENT_EXT_DISC: { + struct bt_mesh_adv_report adv_rpt = {0}; - desc = &event->disc; - net_buf_simple_init_with_data(&buf, (void *)desc->data, desc->length_data); + desc = &event->ext_disc; + + memcpy(&adv_rpt.addr, &desc->addr, sizeof(bt_mesh_addr_t)); + adv_rpt.rssi = desc->rssi; + adv_rpt.adv_type = desc->props; + adv_rpt.primary_phy = desc->prim_phy; + adv_rpt.secondary_phy = desc->sec_phy; + + net_buf_simple_init_with_data(&adv_rpt.adv_data, (void *)desc->data, desc->length_data); if (bt_mesh_scan_dev_found_cb) { /* TODO: Support Scan Response data length for NimBLE host */ - bt_mesh_scan_dev_found_cb((bt_mesh_addr_t *)&desc->addr, desc->rssi, desc->event_type, &buf, 0); + if (desc->props & BLE_HCI_ADV_LEGACY_MASK) { + bt_mesh_scan_dev_found_cb(&adv_rpt); + } + } + + /* Mesh didn't process that data */ + if (adv_rpt.adv_data.len == desc->length_data) { + bt_mesh_ble_ext_adv_report(desc); + } + + break; + } +#else /* CONFIG_BLE_MESH_USE_BLE_50 */ + case BLE_GAP_EVENT_DISC: { + struct bt_mesh_adv_report adv_rpt = {0}; + + desc = &event->disc; + + adv_rpt.rssi = desc->rssi; + adv_rpt.adv_type = desc->event_type; + + memcpy(&adv_rpt.addr, &desc->addr, sizeof(bt_mesh_addr_t)); + + net_buf_simple_init_with_data(&adv_rpt.adv_data, (void *)desc->data, desc->length_data); + + if (bt_mesh_scan_dev_found_cb) { + /* TODO: Support Scan Response data length for NimBLE host */ + bt_mesh_scan_dev_found_cb(&adv_rpt); } break; } +#endif /* CONFIG_BLE_MESH_USE_BLE_50 */ #if (CONFIG_BLE_MESH_PROVISIONER && CONFIG_BLE_MESH_PB_GATT) || \ CONFIG_BLE_MESH_GATT_PROXY_CLIENT case BLE_GAP_EVENT_CONNECT: + /* @todo: process connect failed event */ if (event->connect.status == 0) { /* Connection successfully established. */ MODLOG_DFLT(INFO, "Connection established "); @@ -442,10 +569,21 @@ static int disc_cb(struct ble_gap_event *event, void *arg) break; } } + if (i == ARRAY_SIZE(bt_mesh_gattc_info)) { + goto transfer_to_user; + } + } else { + goto transfer_to_user; } } if (!bt_mesh_atomic_test_bit(bt_mesh_dev.flags, BLE_MESH_DEV_SCANNING)) { +#if CONFIG_BLE_MESH_USE_BLE_50 + rc = ble_gap_ext_disc(BLE_OWN_ADDR_PUBLIC, 0, 0, 0, 0, 0, + uncoded_disc_params.itvl ? &uncoded_disc_params : NULL, + coded_disc_params.itvl ? &coded_disc_params : NULL, disc_cb, NULL); +#else /* CONFIG_BLE_MESH_USE_BLE_50 */ rc = ble_gap_disc(BLE_OWN_ADDR_PUBLIC, BLE_HS_FOREVER, &scan_param, disc_cb, NULL); +#endif /* CONFIG_BLE_MESH_USE_BLE_50 */ if (rc != 0) { BT_ERR("Invalid scan status %d", rc); break; @@ -494,7 +632,13 @@ static int disc_cb(struct ble_gap_event *event, void *arg) bt_mesh_gattc_info[i].wr_desc_done = false; break; } + + if (i == ARRAY_SIZE(bt_mesh_gattc_info)) { + goto transfer_to_user; + } } + } else { + goto transfer_to_user; } break; case BLE_GAP_EVENT_MTU: @@ -521,6 +665,8 @@ static int disc_cb(struct ble_gap_event *event, void *arg) } /* Search Mesh Provisioning Service or Mesh Proxy Service */ ble_gattc_disc_all_svcs(bt_mesh_gattc_info[i].conn.handle, svc_disced, NULL); + } else { + goto transfer_to_user; } break; case BLE_GAP_EVENT_NOTIFY_RX: @@ -531,8 +677,8 @@ static int disc_cb(struct ble_gap_event *event, void *arg) } if (i == ARRAY_SIZE(bt_mesh_gattc_info)) { - BT_ERR("Conn handle 0x%04x not found", event->notify_rx.conn_handle); - return 0; + BT_DBG("Conn handle 0x%04x not blonges to Mesh", event->notify_rx.conn_handle); + goto transfer_to_user; } conn = &bt_mesh_gattc_info[i].conn; @@ -557,7 +703,7 @@ static int disc_cb(struct ble_gap_event *event, void *arg) if (bt_mesh_gattc_info[i].service_uuid == BLE_MESH_UUID_MESH_PROV_VAL) { if (bt_mesh_gattc_conn_cb != NULL && bt_mesh_gattc_conn_cb->prov_notify != NULL) { len = bt_mesh_gattc_conn_cb->prov_notify(&bt_mesh_gattc_info[i].conn, - notif_data, notif_len); + notif_data, notif_len); if (len < 0) { BT_ERR("prov_notify failed"); bt_mesh_gattc_disconnect(conn); @@ -568,7 +714,7 @@ static int disc_cb(struct ble_gap_event *event, void *arg) if (bt_mesh_gattc_conn_cb != NULL && bt_mesh_gattc_conn_cb->proxy_notify != NULL && bt_mesh_gattc_info[i].wr_desc_done) { len = bt_mesh_gattc_conn_cb->proxy_notify(&bt_mesh_gattc_info[i].conn, - notif_data, notif_len); + notif_data, notif_len); if (len < 0) { BT_ERR("proxy_notify failed"); bt_mesh_gattc_disconnect(conn); @@ -579,14 +725,53 @@ static int disc_cb(struct ble_gap_event *event, void *arg) break; #endif default: + goto transfer_to_user; break; } return 0; + +transfer_to_user: +#if CONFIG_BLE_MESH_USE_BLE_50 + bt_mesh_ble_nimble_evt_to_btc(event, arg); +#endif + return 0; } +#if CONFIG_BLE_MESH_USE_BLE_50 +/** + * @brief Get the gap callback function used by BLE Mesh + * + * @note The user must get the mesh gap event handler function + * through the bt_mesh_nimble_gap_cb_get function and pass + * it in as a callback function when using the api: + * ble_gap_ext_connect, ble_gap_ext_disc, ble_gap_connect, + * and ble_gap_disc. + * + * @return void* + */ +void *bt_mesh_nimble_gap_cb_get(void) +{ + return (void*)disc_cb; +} +#endif + static int start_le_scan(uint8_t scan_type, uint16_t interval, uint16_t window, uint8_t filter_dup) { +#if CONFIG_BLE_MESH_USE_BLE_50 + uncoded_disc_params.itvl = (window ? interval : 0); + uncoded_disc_params.window = window; + + coded_disc_params.itvl = ((interval > window) ? interval : 0); + coded_disc_params.window = ((interval > window) ? interval - window : 0); + + coded_disc_params.passive = (scan_type == BLE_MESH_SCAN_PASSIVE); + uncoded_disc_params.passive = (scan_type == BLE_MESH_SCAN_PASSIVE); + + ble_gap_ext_disc(BLE_OWN_ADDR_PUBLIC, 0, 0, filter_dup, 0, 0, + uncoded_disc_params.itvl ? &uncoded_disc_params : NULL, + coded_disc_params.itvl ? &coded_disc_params : NULL, disc_cb, NULL); +#else /* CONFIG_BLE_MESH_USE_BLE_50 */ scan_param.filter_duplicates = filter_dup; scan_param.itvl = interval; scan_param.window = window; @@ -597,6 +782,7 @@ static int start_le_scan(uint8_t scan_type, uint16_t interval, uint16_t window, scan_param.passive = 0; } ble_gap_disc(BLE_OWN_ADDR_PUBLIC, BLE_HS_FOREVER, &scan_param, disc_cb, NULL); +#endif /* CONFIG_BLE_MESH_USE_BLE_50 */ #if BLE_MESH_DEV if (scan_type == BLE_MESH_SCAN_ACTIVE) { @@ -649,11 +835,23 @@ static int gap_event_cb(struct ble_gap_event *event, void *arg) bt_mesh_atomic_test_and_clear_bit(bt_mesh_dev.flags, BLE_MESH_DEV_ADVERTISING); #endif if (bt_mesh_gatts_conn_cb != NULL && bt_mesh_gatts_conn_cb->connected != NULL) { - uint8_t index = BLE_MESH_GATT_GET_CONN_ID(event->connect.conn_handle); + int index = 0; +#if CONFIG_BLE_MESH_USE_BLE_50 + index = bt_mesh_find_free_conn_idx(); + if (index != -ENOMEM) { + bt_mesh_gatts_conn[index].handle = BLE_MESH_GATT_GET_CONN_ID(event->connect.conn_handle); + (bt_mesh_gatts_conn_cb->connected)(&bt_mesh_gatts_conn[index], 0); + } else { + BT_ERR("No space for new connection"); + ble_gap_terminate(event->connect.conn_handle, BLE_ERR_CONN_LIMIT); + } +#else /* CONFIG_BLE_MESH_USE_BLE_50 */ + index = BLE_MESH_GATT_GET_CONN_ID(event->connect.conn_handle); if (index < BLE_MESH_MAX_CONN) { bt_mesh_gatts_conn[index].handle = BLE_MESH_GATT_GET_CONN_ID(event->connect.conn_handle); (bt_mesh_gatts_conn_cb->connected)(&bt_mesh_gatts_conn[index], 0); } +#endif /* CONFIG_BLE_MESH_USE_BLE_50 */ memcpy(bt_mesh_gatts_addr, desc.peer_id_addr.val, BLE_MESH_ADDR_LEN); /* This is for EspBleMesh Android app. When it tries to connect with the * device at the first time and it fails due to some reason. And after @@ -673,11 +871,23 @@ static int gap_event_cb(struct ble_gap_event *event, void *arg) bt_mesh_atomic_test_and_clear_bit(bt_mesh_dev.flags, BLE_MESH_DEV_ADVERTISING); #endif if (bt_mesh_gatts_conn_cb != NULL && bt_mesh_gatts_conn_cb->disconnected != NULL) { - uint8_t index = BLE_MESH_GATT_GET_CONN_ID(event->disconnect.conn.conn_handle); + int index = 0; +#if CONFIG_BLE_MESH_USE_BLE_50 + index = bt_mesh_find_conn_idx(BLE_MESH_GATT_GET_CONN_ID(event->disconnect.conn.conn_handle)); + if (index != -ENODEV) { + bt_mesh_gatts_conn[index].handle = BLE_MESH_GATT_GET_CONN_ID(event->disconnect.conn.conn_handle); + (bt_mesh_gatts_conn_cb->disconnected)(&bt_mesh_gatts_conn[index], event->disconnect.reason); + } else { + BT_ERR("No device"); + } +#else /* CONFIG_BLE_MESH_USE_BLE_50 */ + index = BLE_MESH_GATT_GET_CONN_ID(event->disconnect.conn.conn_handle); if (index < BLE_MESH_MAX_CONN) { bt_mesh_gatts_conn[index].handle = BLE_MESH_GATT_GET_CONN_ID(event->disconnect.conn.conn_handle); (bt_mesh_gatts_conn_cb->disconnected)(&bt_mesh_gatts_conn[index], event->disconnect.reason); } +#endif /* CONFIG_BLE_MESH_USE_BLE_50 */ + bt_mesh_gatts_conn[index].handle = 0; memset(bt_mesh_gatts_addr, 0x0, BLE_MESH_ADDR_LEN); } @@ -693,8 +903,38 @@ static int gap_event_cb(struct ble_gap_event *event, void *arg) return 0; case BLE_GAP_EVENT_ADV_COMPLETE: - MODLOG_DFLT(INFO, "advertise complete; reason=%d", - event->adv_complete.reason); + 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 (event->adv_complete.reason == BLE_HS_ETIMEOUT) { + ble_mesh_adv_task_wakeup(event->adv_complete.instance); + } +#if CONFIG_BLE_MESH_SUPPORT_BLE_ADV + /** + * This judgment is to distinguish between the termination + * events of BLE connectable broadcasting and proxy connectable + * adv under the same instance ID, that is, when the status is 0. + * + * Since the host task and adv task are currently operated in + * series, there is no need to consider competition issues between + * tasks. + * + * @attention: once multiple adv instances are used, the adv task + * and host will be asynchronous, and it is necessary to consider + * the issue of resource competition. + */ + if (bt_mesh_is_ble_adv_running() && + event->adv_complete.reason == 0) { + /* The unset operation must be performed before waking up the + * adv task; performing the unset after waking up the adv task + * could lead to resource contention issues. + */ + bt_mesh_unset_ble_adv_running(); + ble_mesh_adv_task_wakeup(event->adv_complete.instance); + } +#endif /* CONFIG_BLE_MESH_SUPPORT_BLE_ADV */ +#endif /* CONFIG_BLE_MESH_USE_BLE_50 */ return 0; case BLE_GAP_EVENT_ENC_CHANGE: @@ -717,10 +957,20 @@ static int gap_event_cb(struct ble_gap_event *event, void *arg) event->subscribe.prev_indicate, event->subscribe.cur_indicate); struct bt_mesh_gatt_attr *attr = bt_mesh_gatts_find_attr_by_handle(event->subscribe.attr_handle + 1); - uint8_t index = BLE_MESH_GATT_GET_CONN_ID(event->subscribe.conn_handle); + int index = 0; uint16_t len = 0; uint16_t ccc_val = 0; +#if CONFIG_BLE_MESH_USE_BLE_50 + index = bt_mesh_find_conn_idx(BLE_MESH_GATT_GET_CONN_ID(event->subscribe.conn_handle)); + if (index == -ENODEV) { + BT_ERR("Couldn't find conn %d", event->subscribe.conn_handle); + return 0; + } +#else /* CONFIG_BLE_MESH_USE_BLE_50 */ + index = BLE_MESH_GATT_GET_CONN_ID(event->subscribe.conn_handle); +#endif /* CONFIG_BLE_MESH_USE_BLE_50 */ + if (event->subscribe.prev_notify != event->subscribe.cur_notify) { ccc_val = event->subscribe.cur_notify; } else if (event->subscribe.prev_indicate != event->subscribe.cur_indicate) { @@ -773,10 +1023,231 @@ static int gap_event_cb(struct ble_gap_event *event, void *arg) #else static int gap_event_cb(struct ble_gap_event *event, void *arg) { +#if CONFIG_BLE_MESH_USE_BLE_50 + switch (event->type) { + case BLE_GAP_EVENT_ADV_COMPLETE: + BT_DBG("Provisioner advertise complete; reason=%d", + event->adv_complete.reason); + /* 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); + } +#if CONFIG_BLE_MESH_SUPPORT_BLE_ADV + /** + * This judgment is to distinguish between the termination + * events of BLE connectable broadcasting and proxy connectable + * adv under the same instance ID, that is, when the status is 0. + * + * Since the host task and adv task are currently operated in + * series, there is no need to consider competition issues between + * tasks. + * + * @attention: once multiple adv instances are used, the adv task + * and host will be asynchronous, and it is necessary to consider + * the issue of resource competition. + */ + if (bt_mesh_is_ble_adv_running() && + event->adv_complete.reason == 0) { + /* The unset operation must be performed before waking up the + * adv task; performing the unset after waking up the adv task + * could lead to resource contention issues. + */ + bt_mesh_unset_ble_adv_running(); + ble_mesh_adv_task_wakeup(event->adv_complete.instance); + } +#endif /* CONFIG_BLE_MESH_SUPPORT_BLE_ADV */ + break; + } +#endif /* CONFIG_BLE_MESH_USE_BLE_50 */ return 0; } #endif /* CONFIG_BLE_MESH_NODE */ +#if CONFIG_BLE_MESH_USE_BLE_50 +int bt_le_ext_adv_start(const uint8_t inst_id, + const struct bt_mesh_adv_param *param, + const struct bt_mesh_adv_data *ad, size_t ad_len, + const struct bt_mesh_adv_data *sd, size_t sd_len) +{ + struct ble_gap_ext_adv_params adv_params = {0}; + struct os_mbuf *data = NULL; + struct os_mbuf *scan_rsp = NULL; + uint8_t *buf = NULL; + uint16_t interval = 0; + uint8_t buf_len = 0; + int err = 0; + + err = ble_gap_ext_adv_active(inst_id); + if (err) { + BT_ERR("adv inst(%d) is running %d", inst_id, err); + return -EINVAL; + } + +#if BLE_MESH_DEV + if (bt_mesh_atomic_test_bit(bt_mesh_dev.flags, BLE_MESH_DEV_ADVERTISING)) { + return -EALREADY; + } +#endif + buf = bt_mesh_calloc(ad_len * BLE_HS_ADV_MAX_SZ); + if (!buf) { + BT_ERR("ad buffer alloc failed"); + return -ENOMEM; + } + + err = set_ad(ad, ad_len, buf, &buf_len); + if (err) { + bt_mesh_free(buf); + BT_ERR("set_ad failed: err %d", err); + return err; + } + + data = os_msys_get_pkthdr(buf_len, 0); + if (!data) { + bt_mesh_free(buf); + BT_ERR("os buf get failed"); + return -ENOBUFS; + } + + err = os_mbuf_append(data, buf, buf_len); + if (err) { + bt_mesh_free(buf); + BT_ERR("Append ad data to os buf failed %d", err); + return -EINVAL; + } + + bt_mesh_free(buf); + + if (sd && (param->options & BLE_MESH_ADV_OPT_CONNECTABLE)) { + buf_len = 0; + + buf = bt_mesh_calloc(sd_len * BLE_HS_ADV_MAX_SZ); + if (!buf) { + BT_ERR("ad buffer alloc failed"); + return -ENOMEM; + } + + err = set_ad(sd, sd_len, buf, &buf_len); + if (err) { + bt_mesh_free(buf); + BT_ERR("set_ad failed: err %d", err); + return err; + } + + scan_rsp = os_msys_get_pkthdr(buf_len, 0); + if (!data) { + bt_mesh_free(buf); + BT_ERR("os buf get failed"); + return -ENOBUFS; + } + + err = os_mbuf_append(scan_rsp, buf, buf_len); + if (err) { + bt_mesh_free(buf); + BT_ERR("Append ad data to os buf failed %d", err); + return -EINVAL; + } + + bt_mesh_free(buf); + } + + memset(&adv_params, 0, sizeof adv_params); + + assert(param); + + if (param->options & BLE_MESH_ADV_OPT_CONNECTABLE) { + adv_params.connectable = true; + adv_params.scannable = true; + adv_params.legacy_pdu = true; + } else if (sd != NULL) { + adv_params.connectable = false; + adv_params.scannable = true; + adv_params.legacy_pdu = true; + } else { + if (param->primary_phy == BLE_MESH_ADV_PHY_1M && + param->secondary_phy == BLE_MESH_ADV_PHY_1M) { + adv_params.legacy_pdu = true; + } + } + + adv_params.sid = inst_id; + adv_params.primary_phy = param->primary_phy; + adv_params.secondary_phy = param->secondary_phy; + adv_params.tx_power = 0x7F; // tx power will be selected by controller + adv_params.own_addr_type = BLE_OWN_ADDR_PUBLIC; + + interval = param->interval_min; + +#if CONFIG_BLE_MESH_RANDOM_ADV_INTERVAL + /* If non-connectable mesh packets are transmitted with an adv interval + * not smaller than 10ms, then we will use a random adv interval between + * [interval / 2, interval] for them. + */ + if (adv_params.conn_mode == BLE_GAP_CONN_MODE_NON && + adv_params.disc_mode == BLE_GAP_DISC_MODE_NON && interval >= 16) { + interval >>= 1; + interval += (bt_mesh_get_rand() % (interval + 1)); + + adv_params->high_duty_directed = true; + + BT_INFO("%u->%u", param->interval_min, interval); + } +#endif + + adv_params.itvl_min = interval; + adv_params.itvl_max = interval; + + err = ble_gap_ext_adv_configure(inst_id, &adv_params, NULL, gap_event_cb, NULL); + if (err != 0) { + BT_ERR("Advertising config failed: err %d", err); + return err; + } + + err = ble_gap_ext_adv_set_data(inst_id, data); + if (err != 0) { + BT_ERR("Advertising set failed: err %d", err); + return err; + } + + if (scan_rsp) { + err = ble_gap_ext_adv_rsp_set_data(inst_id, scan_rsp); + if (err != 0) { + BT_ERR("scan rsp set failed: err %d", err); + return err; + } else { + BT_INFO("scan rsp set succeed\n"); + } + } + +again: + + if (param->adv_duration < 10 && + param->adv_duration != 0) { + BT_WARN("adv duration shall not be less than 10ms"); + } + + err = ble_gap_ext_adv_start(inst_id, param->adv_duration ? + 2 + param->adv_duration / 10 : 0, param->adv_count); + if (err) { + if (err == BLE_HS_EALREADY) { + ble_gap_ext_adv_stop(inst_id); + goto again; + } + + BT_ERR("Advertising start failed: err %d", err); + return err; + } + +#if BLE_MESH_DEV + bt_mesh_atomic_set_bit(bt_mesh_dev.flags, BLE_MESH_DEV_ADVERTISING); + + if (!(param->options & BLE_MESH_ADV_OPT_ONE_TIME)) { + bt_mesh_atomic_set_bit(bt_mesh_dev.flags, BLE_MESH_DEV_KEEP_ADVERTISING); + } +#endif + + return 0; +} +#else /* CONFIG_BLE_MESH_USE_BLE_50 */ /* APIs functions */ int bt_le_adv_start(const struct bt_mesh_adv_param *param, const struct bt_mesh_adv_data *ad, size_t ad_len, @@ -877,8 +1348,146 @@ again: return 0; } +#endif /* CONFIG_BLE_MESH_USE_BLE_50 */ #if CONFIG_BLE_MESH_SUPPORT_BLE_ADV +#if CONFIG_BLE_MESH_USE_BLE_50 + +static bool _ble_adv_running_flag; + +static inline void bt_mesh_set_ble_adv_running() +{ + _ble_adv_running_flag = true; +} + +static inline void bt_mesh_unset_ble_adv_running() +{ + _ble_adv_running_flag = false; +} + +static inline bool bt_mesh_is_ble_adv_running() +{ + return _ble_adv_running_flag == true; +} + +int bt_mesh_ble_ext_adv_start(const uint8_t inst_id, + const struct bt_mesh_ble_adv_param *param, + const struct bt_mesh_ble_adv_data *adv_data) +{ + struct ble_gap_ext_adv_params adv_params = {0}; + struct os_mbuf *data = NULL; + int err = 0; + + assert(param); + + switch (param->adv_type) { + case BLE_MESH_ADV_IND: + adv_params.connectable = true; + adv_params.scannable = true; + adv_params.legacy_pdu = true; + break; + case BLE_MESH_ADV_DIRECT_IND: + adv_params.connectable = true; + adv_params.scannable = false; + adv_params.directed = true; + adv_params.high_duty_directed = false; + adv_params.legacy_pdu = true; + break; + case BLE_MESH_ADV_SCAN_IND: + adv_params.connectable = false; + adv_params.scannable = true; + adv_params.directed = false; + adv_params.high_duty_directed = false; + adv_params.legacy_pdu = true; + break; + case BLE_MESH_ADV_NONCONN_IND: + adv_params.connectable = false; + adv_params.scannable = false; + adv_params.directed = false; + adv_params.high_duty_directed = false; + adv_params.legacy_pdu = true; + break; + case BLE_MESH_ADV_DIRECT_IND_LOW_DUTY: + adv_params.connectable = true; + adv_params.scannable = false; + adv_params.directed = true; + adv_params.high_duty_directed = true; + adv_params.legacy_pdu = true; + break; + } + + adv_params.itvl_min = param->interval; + adv_params.itvl_max = param->interval; + adv_params.channel_map = BLE_MESH_ADV_CHNL_37 | BLE_MESH_ADV_CHNL_38 | BLE_MESH_ADV_CHNL_39; + adv_params.filter_policy = BLE_MESH_AP_SCAN_CONN_ALL; + adv_params.primary_phy = BLE_MESH_ADV_PHY_1M; + adv_params.secondary_phy = BLE_MESH_ADV_PHY_1M; + + 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) { + adv_params.peer.type = param->peer_addr_type; + memcpy(adv_params.peer.val, param->peer_addr, BLE_MESH_ADDR_LEN); + } + + + if (ble_gap_ext_adv_configure(inst_id, &adv_params, NULL, + gap_event_cb, NULL)) { + BT_ERR("ble adv configure failed\n"); + return -EINVAL; + } + + if (adv_data && param->adv_type != BLE_MESH_ADV_DIRECT_IND && + param->adv_type != BLE_MESH_ADV_DIRECT_IND_LOW_DUTY) { + if (adv_data->adv_data_len) { + data = os_msys_get_pkthdr(adv_data->adv_data_len, 0); + if (!data) { + BT_ERR("Failed to alloc buffer for ble"); + return -ENOMEM; + } + + if (os_mbuf_append(data, adv_data->adv_data, adv_data->adv_data_len)) { + BT_ERR("Append data failed"); + return -EINVAL; + } + + err = ble_gap_ext_adv_set_data(inst_id, data); + if (err) { + BT_ERR("Failed to set advertising data, err %d", err); + return err; + } + } + if (adv_data->scan_rsp_data_len && param->adv_type != BLE_MESH_ADV_NONCONN_IND) { + data = os_msys_get_pkthdr(adv_data->scan_rsp_data_len, 0); + if (!data) { + BT_ERR("Failed to alloc buffer for ble"); + return -ENOMEM; + } + + if (os_mbuf_append(data, adv_data->scan_rsp_data, adv_data->scan_rsp_data_len)) { + BT_ERR("Append data failed"); + return -EINVAL; + } + err = ble_gap_ext_adv_rsp_set_data(inst_id, data); + if (err) { + BT_ERR("Failed to set scan rsp data, err %d", err); + return err; + } + } + } + + err = ble_gap_ext_adv_start(inst_id, 2 + param->duration / 10, param->count); + if (err) { + BT_ERR("Failed to start advertising, err %d", err); + return err; + } + + bt_mesh_set_ble_adv_running(); + + return 0; +} +#else /* CONFIG_BLE_MESH_USE_BLE_50 */ int bt_mesh_ble_adv_start(const struct bt_mesh_ble_adv_param *param, const struct bt_mesh_ble_adv_data *data) { @@ -949,8 +1558,27 @@ int bt_mesh_ble_adv_start(const struct bt_mesh_ble_adv_param *param, return 0; } +#endif /* CONFIG_BLE_MESH_USE_BLE_50 */ #endif /* CONFIG_BLE_MESH_SUPPORT_BLE_ADV */ +#if CONFIG_BLE_MESH_USE_BLE_50 +int bt_le_ext_adv_stop(uint8_t inst_id) +{ +#if BLE_MESH_DEV + bt_mesh_atomic_clear_bit(bt_mesh_dev.flags, BLE_MESH_DEV_KEEP_ADVERTISING); + if (!bt_mesh_atomic_test_bit(bt_mesh_dev.flags, BLE_MESH_DEV_ADVERTISING)) { + return 0; + } +#endif + ble_gap_ext_adv_stop(inst_id); + +#if BLE_MESH_DEV + bt_mesh_atomic_clear_bit(bt_mesh_dev.flags, BLE_MESH_DEV_ADVERTISING); +#endif + + return 0; +} +#else /* CONFIG_BLE_MESH_USE_BLE_50 */ int bt_le_adv_stop(void) { #if BLE_MESH_DEV @@ -967,6 +1595,7 @@ int bt_le_adv_stop(void) return 0; } +#endif /* CONFIG_BLE_MESH_USE_BLE_50 */ int bt_le_scan_start(const struct bt_mesh_scan_param *param, bt_mesh_scan_cb_t cb) { @@ -987,6 +1616,7 @@ int bt_le_scan_start(const struct bt_mesh_scan_param *param, bt_mesh_scan_cb_t c err = start_le_scan(param->type, param->interval, param->window, param->filter_dup); if (err) { + BT_ERR("Failed to start advertising, err %d", err); return err; } @@ -1554,6 +2184,7 @@ int bt_mesh_gattc_write_no_rsp(struct bt_mesh_conn *conn, om = ble_hs_mbuf_from_flat(data, len); if (om == NULL) { + BT_ERR("om buffer alloc failed"); return -1; } @@ -1622,9 +2253,19 @@ static int proxy_char_access_cb(uint16_t conn_handle, uint16_t attr_handle, { if (ctxt->op == BLE_GATT_ACCESS_OP_WRITE_CHR || ctxt->op == BLE_GATT_ACCESS_OP_WRITE_DSC) { struct bt_mesh_gatt_attr *attr = bt_mesh_gatts_find_attr_by_handle(attr_handle); - uint8_t index = BLE_MESH_GATT_GET_CONN_ID(conn_handle); + int index = 0; uint16_t len = 0; +#if CONFIG_BLE_MESH_USE_BLE_50 + index = bt_mesh_find_conn_idx(BLE_MESH_GATT_GET_CONN_ID(conn_handle)); + if (index == -ENODEV) { + BT_ERR("Unknown conn handle"); + return 0; + } +#else + index = BLE_MESH_GATT_GET_CONN_ID(conn_handle); +#endif + BT_DBG("write, handle %d, len %d, data %s", attr_handle, ctxt->om->om_len, bt_hex(ctxt->om->om_data, ctxt->om->om_len)); @@ -1713,6 +2354,58 @@ void gatt_register_cb(struct ble_gatt_register_ctxt *ctxt, } } +#if CONFIG_BLE_MESH_USE_BLE_50 +void bt_mesh_gatts_svcs_add(void) +{ + ble_hs_cfg.gatts_register_cb = gatt_register_cb; + +#if CONFIG_BLE_MESH_NODE + int rc = 0; + + ble_svc_gap_init(); + ble_svc_gatt_init(); + + rc = ble_gatts_count_cfg(svc_defs); + assert(rc == 0); + + rc = ble_gatts_add_svcs(svc_defs); + assert(rc == 0); + + g_gatts_svcs_add = true; +#endif +} + +void bt_mesh_gatt_init(void) +{ + ble_att_set_preferred_mtu(BLE_MESH_GATT_DEF_MTU_SIZE); + +#if CONFIG_BLE_MESH_NODE + static bool init = false; + + if (init == false) { + + __ASSERT(g_gatts_svcs_add, "func bt_mesh_gatts_svcs_add should be called before mesh init"); + + ble_gatts_svc_set_visibility(prov_svc_start_handle, 1); + ble_gatts_svc_set_visibility(proxy_svc_start_handle, 0); + +#if CONFIG_BLE_MESH_USE_BLE_50 + bt_mesh_gatts_conn_init(); +#endif /* CONFIG_BLE_MESH_USE_BLE_50 */ + init = true; + } +#endif /* CONFIG_BLE_MESH_NODE */ + +#if (CONFIG_BLE_MESH_PROVISIONER && CONFIG_BLE_MESH_PB_GATT) || \ + CONFIG_BLE_MESH_GATT_PROXY_CLIENT + for (int i = 0; i < ARRAY_SIZE(bt_mesh_gattc_info); i++) { + bt_mesh_gattc_info[i].conn.handle = 0xFFFF; + bt_mesh_gattc_info[i].mtu = BLE_ATT_MTU_DFLT; + bt_mesh_gattc_info[i].wr_desc_done = false; + } +#endif +} +#else void bt_mesh_gatt_init(void) { ble_att_set_preferred_mtu(BLE_ATT_MTU_DFLT); @@ -1751,6 +2444,7 @@ void bt_mesh_gatt_init(void) } #endif } +#endif /* CONFIG_BLE_MESH_USE_BLE_50 */ #if CONFIG_BLE_MESH_DEINIT void bt_mesh_gatt_deinit(void) @@ -1981,12 +2675,12 @@ int bt_mesh_update_exceptional_list(uint8_t sub_code, uint32_t type, void *info) if ((sub_code > BLE_MESH_EXCEP_LIST_SUB_CODE_CLEAN) || (sub_code < BLE_MESH_EXCEP_LIST_SUB_CODE_CLEAN && - type > BLE_MESH_EXCEP_LIST_TYPE_MESH_PROXY_ADV) || + type > BLE_MESH_EXCEP_LIST_TYPE_MAX) || (sub_code == BLE_MESH_EXCEP_LIST_SUB_CODE_CLEAN && !(type & BLE_MESH_EXCEP_LIST_CLEAN_ALL_LIST))) { BT_ERR("%s, Invalid parameter", __func__); return -EINVAL; - } + } if (type == BLE_MESH_EXCEP_LIST_TYPE_MESH_LINK_ID) { if (!info) { diff --git a/components/bt/esp_ble_mesh/core/proxy_client.c b/components/bt/esp_ble_mesh/core/proxy_client.c index 1719e4737d..9e9a7354a2 100644 --- a/components/bt/esp_ble_mesh/core/proxy_client.c +++ b/components/bt/esp_ble_mesh/core/proxy_client.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 */ diff --git a/components/bt/esp_ble_mesh/core/proxy_server.c b/components/bt/esp_ble_mesh/core/proxy_server.c index 532b23d823..65b5dcba63 100644 --- a/components/bt/esp_ble_mesh/core/proxy_server.c +++ b/components/bt/esp_ble_mesh/core/proxy_server.c @@ -2,7 +2,7 @@ /* * SPDX-FileCopyrightText: 2017 Intel Corporation - * SPDX-FileContributor: 2018-2021 Espressif Systems (Shanghai) CO LTD + * SPDX-FileContributor: 2018-2024 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -35,6 +35,10 @@ _Static_assert(!(IS_ENABLED(CONFIG_BLE_MESH_GATT_PROXY_SERVER) && IS_ENABLED(CON "Not support Proxy Server and Proxy Client simultaneously"); #endif +#if CONFIG_BLE_MESH_USE_BLE_50 +static uint8_t proxy_adv_inst = BLE_MESH_ADV_INS_UNUSED; +#endif + #define ADV_OPT (BLE_MESH_ADV_OPT_CONNECTABLE | BLE_MESH_ADV_OPT_ONE_TIME) #if CONFIG_BLE_MESH_GATT_PROXY_SERVER && \ @@ -52,12 +56,24 @@ static const struct bt_mesh_adv_param slow_adv_param = { .options = ADV_OPT, .interval_min = BLE_MESH_GAP_ADV_SLOW_INT_MIN, .interval_max = BLE_MESH_GAP_ADV_SLOW_INT_MAX, +#if CONFIG_BLE_MESH_USE_BLE_50 + .primary_phy = BLE_MESH_ADV_PHY_1M, + .secondary_phy = BLE_MESH_ADV_PHY_1M, + .adv_duration = 0, + .adv_count = 0, +#endif }; static const struct bt_mesh_adv_param fast_adv_param = { .options = ADV_OPT, .interval_min = BLE_MESH_GAP_ADV_FAST_INT_MIN_0, .interval_max = BLE_MESH_GAP_ADV_FAST_INT_MAX_0, +#if CONFIG_BLE_MESH_USE_BLE_50 + .primary_phy = BLE_MESH_ADV_PHY_1M, + .secondary_phy = BLE_MESH_ADV_PHY_1M, + .adv_duration = 0, + .adv_count = 0, +#endif }; static bool proxy_adv_enabled; @@ -1465,8 +1481,13 @@ static int node_id_adv(struct bt_mesh_subnet *sub) memcpy(proxy_svc_data + 3, tmp + 8, 8); proxy_sd_len = gatt_proxy_adv_create(&proxy_sd); - err = bt_le_adv_start(&fast_adv_param, node_id_ad, - ARRAY_SIZE(node_id_ad), &proxy_sd, proxy_sd_len); +#if CONFIG_BLE_MESH_USE_BLE_50 + err = bt_le_ext_adv_start(proxy_adv_inst, &fast_adv_param, node_id_ad, + ARRAY_SIZE(node_id_ad), &proxy_sd, proxy_sd_len); +#else + err = bt_le_adv_start(&fast_adv_param, node_id_ad, + ARRAY_SIZE(node_id_ad), &proxy_sd, proxy_sd_len); +#endif if (err) { BT_WARN("Failed to advertise using Node ID (err %d)", err); return err; @@ -1491,8 +1512,13 @@ static int net_id_adv(struct bt_mesh_subnet *sub) memcpy(proxy_svc_data + 3, sub->keys[sub->kr_flag].net_id, 8); proxy_sd_len = gatt_proxy_adv_create(&proxy_sd); - err = bt_le_adv_start(&slow_adv_param, net_id_ad, - ARRAY_SIZE(net_id_ad), &proxy_sd, proxy_sd_len); +#if CONFIG_BLE_MESH_USE_BLE_50 + err = bt_le_ext_adv_start(proxy_adv_inst, &slow_adv_param, net_id_ad, + ARRAY_SIZE(net_id_ad), &proxy_sd, proxy_sd_len); +#else + err = bt_le_adv_start(&slow_adv_param, net_id_ad, + ARRAY_SIZE(net_id_ad), &proxy_sd, proxy_sd_len); +#endif if (err) { BT_WARN("Failed to advertise using Network ID (err %d)", err); return err; @@ -1836,13 +1862,20 @@ int32_t bt_mesh_proxy_server_adv_start(void) 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 + #if CONFIG_BLE_MESH_PB_GATT if (prov_fast_adv) { prov_start_time = k_uptime_get_32(); } if (!bt_mesh_is_provisioned()) { - const struct bt_mesh_adv_param *param; + const struct bt_mesh_adv_param *param = NULL; struct bt_mesh_adv_data prov_sd[2]; size_t prov_sd_len; @@ -1854,8 +1887,14 @@ int32_t bt_mesh_proxy_server_adv_start(void) prov_sd_len = gatt_prov_adv_create(prov_sd); +#if CONFIG_BLE_MESH_USE_BLE_50 + if (bt_le_ext_adv_start(proxy_adv_inst, param, prov_ad, ARRAY_SIZE(prov_ad), + prov_sd, prov_sd_len) == 0) { +#else /* CONFIG_BLE_MESH_USE_BLE_50 */ if (bt_le_adv_start(param, prov_ad, ARRAY_SIZE(prov_ad), prov_sd, prov_sd_len) == 0) { +#endif /* CONFIG_BLE_MESH_USE_BLE_50 */ + proxy_adv_enabled = true; /* Advertise 60 seconds using fast interval */ @@ -1899,7 +1938,16 @@ void bt_mesh_proxy_server_adv_stop(void) return; } +#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; + } + + err = bt_le_ext_adv_stop(proxy_adv_inst); +#else err = bt_le_adv_stop(); +#endif if (err) { BT_ERR("Failed to stop advertising (err %d)", err); } else { @@ -1916,6 +1964,10 @@ int bt_mesh_proxy_server_init(void) { int i; +#if CONFIG_BLE_MESH_USE_BLE_50 + proxy_adv_inst = bt_mesh_get_proxy_inst(); +#endif + #if CONFIG_BLE_MESH_GATT_PROXY_SERVER bt_mesh_gatts_service_register(&proxy_svc); #endif @@ -1954,6 +2006,10 @@ int bt_mesh_proxy_server_deinit(void) { int i; +#if CONFIG_BLE_MESH_USE_BLE_50 + proxy_adv_inst = BLE_MESH_ADV_INS_UNUSED; +#endif + proxy_adv_enabled = false; gatt_svc = MESH_GATT_NONE; diff --git a/components/bt/esp_ble_mesh/core/proxy_server.h b/components/bt/esp_ble_mesh/core/proxy_server.h index b98728910d..88eed8a7e9 100644 --- a/components/bt/esp_ble_mesh/core/proxy_server.h +++ b/components/bt/esp_ble_mesh/core/proxy_server.h @@ -12,6 +12,7 @@ #include "net.h" #include "mesh/adapter.h" +#include "adv.h" #ifdef __cplusplus extern "C" { diff --git a/components/bt/esp_ble_mesh/core/scan.c b/components/bt/esp_ble_mesh/core/scan.c index 72b1ccb300..4e021a7cbb 100644 --- a/components/bt/esp_ble_mesh/core/scan.c +++ b/components/bt/esp_ble_mesh/core/scan.c @@ -41,6 +41,22 @@ #define PROXY_SVC_DATA_LEN_PRIVATE_NET_ID 0x11 #define PROXY_SVC_DATA_LEN_PRIVATE_NODE_ID 0x11 +static struct bt_mesh_scan_param scan_param = { +#if CONFIG_BLE_MESH_RPR_SRV_ACTIVE_SCAN + .type = BLE_MESH_SCAN_ACTIVE, +#else + .type = BLE_MESH_SCAN_PASSIVE, +#endif +#if CONFIG_BLE_MESH_USE_DUPLICATE_SCAN + .filter_dup = BLE_MESH_SCAN_FILTER_DUP_ENABLE, +#else + .filter_dup = BLE_MESH_SCAN_FILTER_DUP_DISABLE, +#endif + .interval = SCAN_INTERVAL, + .window = SCAN_WINDOW, + .scan_fil_policy = BLE_MESH_SP_ADV_ALL, +}; + #if (CONFIG_BLE_MESH_PROVISIONER || CONFIG_BLE_MESH_RPR_SRV) static const bt_mesh_addr_t *unprov_dev_addr; static uint8_t current_adv_type; @@ -336,13 +352,27 @@ int bt_mesh_stop_ble_scan(void) return 0; } +bool bt_mesh_ble_scan_state_get(void) +{ + return ble_scan_en; +} + static void inline callback_ble_adv_pkt(const bt_mesh_addr_t *addr, uint8_t adv_type, uint8_t data[], uint16_t length, int8_t rssi) { +#if !CONFIG_BLE_MESH_USE_BLE_50 + bt_mesh_ble_adv_report_t adv_rpt = {0}; if (ble_scan_en) { - bt_mesh_ble_scan_cb_evt_to_btc(addr, adv_type, data, length, rssi); + memcpy(adv_rpt.addr, addr->val, BD_ADDR_LEN); + adv_rpt.addr_type = addr->type; + adv_rpt.adv_type = adv_type; + adv_rpt.length = length; + adv_rpt.data = data; + adv_rpt.rssi = rssi; + bt_mesh_ble_scan_cb_evt_to_btc(&adv_rpt); } +#endif } #endif /* CONFIG_BLE_MESH_SUPPORT_BLE_SCAN */ @@ -364,11 +394,11 @@ static bool rpr_ext_scan_handle_adv_pkt(const bt_mesh_addr_t *addr, } #endif /* CONFIG_BLE_MESH_RPR_SRV */ -static void bt_mesh_scan_cb(const bt_mesh_addr_t *addr, - int8_t rssi, uint8_t adv_type, - struct net_buf_simple *buf, - uint8_t scan_rsp_len) +static void bt_mesh_scan_cb(struct bt_mesh_adv_report *adv_rpt) { + struct net_buf_simple_state buf_state = {0}; + struct net_buf_simple *buf = &adv_rpt->adv_data; + #if (CONFIG_BLE_MESH_PROVISIONER && CONFIG_BLE_MESH_PB_GATT) || \ CONFIG_BLE_MESH_GATT_PROXY_CLIENT || \ CONFIG_BLE_MESH_PROXY_SOLIC_PDU_RX @@ -379,20 +409,44 @@ static void bt_mesh_scan_cb(const bt_mesh_addr_t *addr, uint16_t adv_len = buf->len; #endif - if (adv_type != BLE_MESH_ADV_NONCONN_IND && adv_type != BLE_MESH_ADV_IND) { -#if CONFIG_BLE_MESH_SUPPORT_BLE_SCAN - callback_ble_adv_pkt(addr, adv_type, adv_data, adv_len, rssi); + net_buf_simple_save(buf, &buf_state); + + if (adv_rpt->adv_type != BLE_MESH_ADV_NONCONN_IND && + adv_rpt->adv_type != BLE_MESH_ADV_IND +#if CONFIG_BLE_MESH_RPR_SRV && CONFIG_BLE_MESH_RPR_SRV_ACTIVE_SCAN + && adv_rpt->adv_type != BLE_MESH_ADV_SCAN_RSP #endif + ) { +#if CONFIG_BLE_MESH_SUPPORT_BLE_SCAN + callback_ble_adv_pkt(&adv_rpt->addr, adv_rpt->adv_type, adv_data, adv_len, adv_rpt->rssi); +#endif + net_buf_simple_restore(buf, &buf_state); return; } BT_DBG("scan, len %u: %s", buf->len, bt_hex(buf->data, buf->len)); #if (CONFIG_BLE_MESH_PROVISIONER || CONFIG_BLE_MESH_RPR_SRV) - unprov_dev_addr = addr; - current_adv_type = adv_type; + unprov_dev_addr = &adv_rpt->addr; + current_adv_type = adv_rpt->adv_type; #endif +#if CONFIG_BLE_MESH_RPR_SRV && CONFIG_BLE_MESH_RPR_SRV_ACTIVE_SCAN + if (adv_rpt->adv_type == BLE_MESH_ADV_SCAN_RSP) { + /** + * scan response is only visible for remote provisioning extend scan. + */ + if (rpr_ext_scan_handle_adv_pkt(&adv_rpt->addr, adv_data, adv_len)) { + return; + } else { +#if CONFIG_BLE_MESH_SUPPORT_BLE_SCAN + callback_ble_adv_pkt(&adv_rpt->addr, adv_rpt->adv_type, adv_data, adv_len, adv_rpt->rssi); +#endif + net_buf_simple_restore(buf, &buf_state); + } + } +#endif /* CONFIG_BLE_MESH_RPR_SRV && CONFIG_BLE_MESH_RPR_SRV_ACTIVE_SCAN */ + while (buf->len > 1) { struct net_buf_simple_state state; uint8_t len, type; @@ -401,16 +455,18 @@ static void bt_mesh_scan_cb(const bt_mesh_addr_t *addr, /* Check for early termination */ if (len == 0U) { #if CONFIG_BLE_MESH_SUPPORT_BLE_SCAN - callback_ble_adv_pkt(addr, adv_type, adv_data, adv_len, rssi); + callback_ble_adv_pkt(&adv_rpt->addr, adv_rpt->adv_type, adv_data, adv_len, adv_rpt->rssi); #endif + net_buf_simple_restore(buf, &buf_state); return; } if (len > buf->len) { BT_DBG("AD malformed"); #if CONFIG_BLE_MESH_SUPPORT_BLE_SCAN - callback_ble_adv_pkt(addr, adv_type, adv_data, adv_len, rssi); + callback_ble_adv_pkt(&adv_rpt->addr, adv_rpt->adv_type, adv_data, adv_len, adv_rpt->rssi); #endif + net_buf_simple_restore(buf, &buf_state); return; } @@ -421,14 +477,17 @@ static void bt_mesh_scan_cb(const bt_mesh_addr_t *addr, buf->len = len - 1; if ((type == BLE_MESH_DATA_MESH_PROV || type == BLE_MESH_DATA_MESH_MESSAGE || - type == BLE_MESH_DATA_MESH_BEACON) && (adv_type != BLE_MESH_ADV_NONCONN_IND)) { - BT_DBG("Ignore mesh packet (type 0x%02x) with adv_type 0x%02x", type, adv_type); + type == BLE_MESH_DATA_MESH_BEACON) && (adv_rpt->adv_type != BLE_MESH_ADV_NONCONN_IND)) { + BT_DBG("Ignore mesh packet (type 0x%02x) with adv_type 0x%02x", type, adv_rpt->adv_type); return; } switch (type) { case BLE_MESH_DATA_MESH_MESSAGE: - bt_mesh_net_recv(buf, rssi, BLE_MESH_NET_IF_ADV); + struct bt_mesh_net_rx rx = { + .ctx.recv_rssi = adv_rpt->rssi, + }; + bt_mesh_generic_net_recv(buf, &rx, BLE_MESH_NET_IF_ADV); break; #if CONFIG_BLE_MESH_PB_ADV case BLE_MESH_DATA_MESH_PROV: @@ -441,7 +500,7 @@ static void bt_mesh_scan_cb(const bt_mesh_addr_t *addr, break; #endif /* CONFIG_BLE_MESH_PB_ADV */ case BLE_MESH_DATA_MESH_BEACON: - bt_mesh_beacon_recv(buf, rssi); + bt_mesh_beacon_recv(buf, adv_rpt->rssi); break; #if (CONFIG_BLE_MESH_PROVISIONER && CONFIG_BLE_MESH_PB_GATT) || \ CONFIG_BLE_MESH_GATT_PROXY_CLIENT || \ @@ -450,8 +509,9 @@ static void bt_mesh_scan_cb(const bt_mesh_addr_t *addr, if (!adv_flags_valid(buf)) { BT_DBG("Adv Flags mismatch, ignore this adv pkt"); #if CONFIG_BLE_MESH_SUPPORT_BLE_SCAN - callback_ble_adv_pkt(addr, adv_type, adv_data, adv_len, rssi); + callback_ble_adv_pkt(&adv_rpt->addr, adv_rpt->adv_type, adv_data, adv_len, adv_rpt->rssi); #endif + net_buf_simple_restore(buf, &buf_state); return; } break; @@ -459,7 +519,7 @@ static void bt_mesh_scan_cb(const bt_mesh_addr_t *addr, if (!adv_service_uuid_valid(buf, &uuid)) { BT_DBG("Adv Service UUID mismatch, ignore this adv pkt"); #if CONFIG_BLE_MESH_RPR_SRV - if (rpr_ext_scan_handle_adv_pkt(addr, adv_data, adv_len)) { + if (rpr_ext_scan_handle_adv_pkt(&adv_rpt->addr, adv_data, adv_len)) { /* If handled as extended scan report successfully, then not * notify to the application layer as normal BLE adv packet. */ @@ -467,18 +527,19 @@ static void bt_mesh_scan_cb(const bt_mesh_addr_t *addr, } #endif #if CONFIG_BLE_MESH_SUPPORT_BLE_SCAN - callback_ble_adv_pkt(addr, adv_type, adv_data, adv_len, rssi); + callback_ble_adv_pkt(&adv_rpt->addr, adv_rpt->adv_type, adv_data, adv_len, adv_rpt->rssi); #endif + net_buf_simple_restore(buf, &buf_state); return; } break; case BLE_MESH_DATA_SVC_DATA16: - handle_adv_service_data(buf, addr, uuid, rssi); + handle_adv_service_data(buf, &adv_rpt->addr, uuid, adv_rpt->rssi); break; #endif default: #if CONFIG_BLE_MESH_RPR_SRV - if (rpr_ext_scan_handle_adv_pkt(addr, adv_data, adv_len)) { + if (rpr_ext_scan_handle_adv_pkt(&adv_rpt->addr, adv_data, adv_len)) { /* If handled as extended scan report successfully, then not * notify to the application layer as normal BLE adv packet. */ @@ -486,44 +547,21 @@ static void bt_mesh_scan_cb(const bt_mesh_addr_t *addr, } #endif #if CONFIG_BLE_MESH_SUPPORT_BLE_SCAN - callback_ble_adv_pkt(addr, adv_type, adv_data, adv_len, rssi); + callback_ble_adv_pkt(&adv_rpt->addr, adv_rpt->adv_type, adv_data, adv_len, adv_rpt->rssi); #endif + net_buf_simple_restore(buf, &buf_state); return; } net_buf_simple_restore(buf, &state); net_buf_simple_pull(buf, len); } -#if CONFIG_BLE_MESH_RPR_SRV && CONFIG_BLE_MESH_RPR_SRV_ACTIVE_SCAN - if (scan_rsp_len != 0) { - /** - * scan response is only visible for remote provisioning extend scan. - */ - rpr_ext_scan_handle_adv_pkt(addr, adv_data + adv_len, scan_rsp_len); - } -#endif /* CONFIG_BLE_MESH_RPR_SRV && CONFIG_BLE_MESH_RPR_SRV_ACTIVE_SCAN */ } int bt_mesh_scan_enable(void) { int err = 0; - struct bt_mesh_scan_param scan_param = { -#if CONFIG_BLE_MESH_RPR_SRV_ACTIVE_SCAN - .type = BLE_MESH_SCAN_ACTIVE, -#else - .type = BLE_MESH_SCAN_PASSIVE, -#endif -#if CONFIG_BLE_MESH_USE_DUPLICATE_SCAN - .filter_dup = BLE_MESH_SCAN_FILTER_DUP_ENABLE, -#else - .filter_dup = BLE_MESH_SCAN_FILTER_DUP_DISABLE, -#endif - .interval = SCAN_INTERVAL, - .window = SCAN_WINDOW, - .scan_fil_policy = BLE_MESH_SP_ADV_ALL, - }; - err = bt_le_scan_start(&scan_param, bt_mesh_scan_cb); if (err && err != -EALREADY) { BT_ERR("starting scan failed (err %d)", err); @@ -546,6 +584,49 @@ int bt_mesh_scan_disable(void) return 0; } +int bt_mesh_scan_param_update(struct bt_mesh_scan_param *param) +{ + int err = 0; + + if (param == NULL || + param->interval == 0 || + param->interval < param->window) { + return -EINVAL; + } + + scan_param.interval = param->interval; + scan_param.window = param->window; + + err = bt_le_scan_stop(); + if (err) { + if (err == -EALREADY) { + BT_INFO("New scan parameters will take effect after scan starts"); + return 0; + } + BT_ERR("Failed to stop scan (err %d)", err); + return err; + } + + /** + * Since the user only needs to set the scan interval + * and scan window parameters, only the interval and + * window parameters in the `param` are correct. + * + * For the aforementioned reason, when updating the scan + * parameters, the other parameters also need to be set + * correctly, and these other parameters are saved in the + * `scan_param`. Therefore, `scan_param` must be used instead + * of `param` here. + */ + err = bt_le_scan_start(&scan_param, bt_mesh_scan_cb); + if (err && err != -EALREADY) { + BT_ERR("Failed to start scan (err %d)", err); + return err; + } + + return 0; +} + #if CONFIG_BLE_MESH_TEST_USE_WHITE_LIST int bt_mesh_scan_with_wl_enable(void) { diff --git a/components/bt/esp_ble_mesh/core/scan.h b/components/bt/esp_ble_mesh/core/scan.h index b7d0555c83..612751d3f2 100644 --- a/components/bt/esp_ble_mesh/core/scan.h +++ b/components/bt/esp_ble_mesh/core/scan.h @@ -2,7 +2,7 @@ /* * SPDX-FileCopyrightText: 2017 Intel Corporation - * SPDX-FileContributor: 2020-2021 Espressif Systems (Shanghai) CO LTD + * SPDX-FileContributor: 2020-2024 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -33,16 +33,22 @@ int bt_mesh_scan_enable(void); int bt_mesh_scan_disable(void); +int bt_mesh_scan_param_update(struct bt_mesh_scan_param *scan_param); + int bt_mesh_scan_with_wl_enable(void); struct bt_mesh_ble_scan_param { uint32_t duration; }; +#if CONFIG_BLE_MESH_SUPPORT_BLE_SCAN int bt_mesh_start_ble_scan(struct bt_mesh_ble_scan_param *param); int bt_mesh_stop_ble_scan(void); +bool bt_mesh_ble_scan_state_get(void); +#endif /* CONFIG_BLE_MESH_SUPPORT_BLE_SCAN */ + #ifdef __cplusplus } #endif diff --git a/components/bt/host/bluedroid/bta/include/bta/bta_api.h b/components/bt/host/bluedroid/bta/include/bta/bta_api.h index c0cabab2c7..62b0273f10 100644 --- a/components/bt/host/bluedroid/bta/include/bta/bta_api.h +++ b/components/bt/host/bluedroid/bta/include/bta/bta_api.h @@ -1512,18 +1512,18 @@ typedef UINT8 tBTA_DM_LINK_TYPE; #define BTA_DM_BLE_GAP_SET_EXT_ADV_PROP_INCLUDE_TX_PWR (1 << 6) #define BTA_DM_BLE_GAP_SET_EXT_ADV_PROP_MASK (0x7F) -#define BTA_DM_BLE_GAP_SET_EXT_ADV_PROP_LEGACY_IND (ESP_BLE_GAP_SET_EXT_ADV_PROP_LEGACY |\ - ESP_BLE_GAP_SET_EXT_ADV_PROP_CONNECTABLE |\ - ESP_BLE_GAP_SET_EXT_ADV_PROP_SCANNABLE) -#define BTA_DM_BLE_GAP_SET_EXT_ADV_PROP_LEGACY_LD_DIR (ESP_BLE_GAP_SET_EXT_ADV_PROP_LEGACY |\ - ESP_BLE_GAP_SET_EXT_ADV_PROP_CONNECTABLE |\ - ESP_BLE_GAP_SET_EXT_ADV_PROP_DIRECTED) -#define BTA_DM_BLE_GAP_SET_EXT_ADV_PROP_LEGACY_HD_DIR (ESP_BLE_GAP_SET_EXT_ADV_PROP_LEGACY |\ - ESP_BLE_GAP_SET_EXT_ADV_PROP_CONNECTABLE |\ - ESP_BLE_GAP_SET_EXT_ADV_PROP_HD_DIRECTED) -#define BTA_DM_BLE_GAP_SET_EXT_ADV_PROP_LEGACY_SCAN (ESP_BLE_GAP_SET_EXT_ADV_PROP_LEGACY |\ - ESP_BLE_GAP_SET_EXT_ADV_PROP_SCANNABLE) -#define BTA_DM_BLE_GAP_SET_EXT_ADV_PROP_LEGACY_NONCONN (ESP_BLE_GAP_SET_EXT_ADV_PROP_LEGACY) +#define BTA_DM_BLE_GAP_SET_EXT_ADV_PROP_LEGACY_IND (BTA_DM_BLE_GAP_SET_EXT_ADV_PROP_LEGACY |\ + BTA_DM_BLE_GAP_SET_EXT_ADV_PROP_CONNECTABLE |\ + BTA_DM_BLE_GAP_SET_EXT_ADV_PROP_SCANNABLE) +#define BTA_DM_BLE_GAP_SET_EXT_ADV_PROP_LEGACY_LD_DIR (BTA_DM_BLE_GAP_SET_EXT_ADV_PROP_LEGACY |\ + BTA_DM_BLE_GAP_SET_EXT_ADV_PROP_CONNECTABLE |\ + BTA_DM_BLE_GAP_SET_EXT_ADV_PROP_DIRECTED) +#define BTA_DM_BLE_GAP_SET_EXT_ADV_PROP_LEGACY_HD_DIR (BTA_DM_BLE_GAP_SET_EXT_ADV_PROP_LEGACY |\ + BTA_DM_BLE_GAP_SET_EXT_ADV_PROP_CONNECTABLE |\ + BTA_DM_BLE_GAP_SET_EXT_ADV_PROP_HD_DIRECTED) +#define BTA_DM_BLE_GAP_SET_EXT_ADV_PROP_LEGACY_SCAN (BTA_DM_BLE_GAP_SET_EXT_ADV_PROP_LEGACY |\ + BTA_DM_BLE_GAP_SET_EXT_ADV_PROP_SCANNABLE) +#define BTA_DM_BLE_GAP_SET_EXT_ADV_PROP_LEGACY_NONCONN (BTA_DM_BLE_GAP_SET_EXT_ADV_PROP_LEGACY) typedef UINT16 tBTA_DM_BLE_EXT_ADV_TYPE_MASK; diff --git a/components/bt/host/bluedroid/btc/profile/std/gap/btc_gap_ble.c b/components/bt/host/bluedroid/btc/profile/std/gap/btc_gap_ble.c index b486703346..ecbea5124c 100644 --- a/components/bt/host/bluedroid/btc/profile/std/gap/btc_gap_ble.c +++ b/components/bt/host/bluedroid/btc/profile/std/gap/btc_gap_ble.c @@ -958,7 +958,7 @@ static void btc_read_ble_rssi_cmpl_callback(void *p_data) } #if (BLE_50_FEATURE_SUPPORT == TRUE) -static void btc_ble_5_gap_callback(tBTA_DM_BLE_5_GAP_EVENT event, +void btc_ble_5_gap_callback(tBTA_DM_BLE_5_GAP_EVENT event, tBTA_DM_BLE_5_GAP_CB_PARAMS *params) { esp_ble_gap_cb_param_t param; diff --git a/docs/doxygen/Doxyfile b/docs/doxygen/Doxyfile index 8a6d91db27..1916b68d9f 100644 --- a/docs/doxygen/Doxyfile +++ b/docs/doxygen/Doxyfile @@ -29,6 +29,7 @@ INPUT = \ $(PROJECT_PATH)/components/bootloader_support/include/esp_flash_encrypt.h \ $(PROJECT_PATH)/components/esp_coex/include/esp_coexist.h \ $(PROJECT_PATH)/components/bt/common/api/include/api/esp_blufi_api.h \ + $(PROJECT_PATH)/components/bt/esp_ble_mesh/api/core/include/esp_ble_mesh_ble_api.h \ $(PROJECT_PATH)/components/bt/esp_ble_mesh/api/core/include/esp_ble_mesh_common_api.h \ $(PROJECT_PATH)/components/bt/esp_ble_mesh/api/core/include/esp_ble_mesh_local_data_operation_api.h \ $(PROJECT_PATH)/components/bt/esp_ble_mesh/api/core/include/esp_ble_mesh_low_power_api.h \ diff --git a/docs/en/api-reference/bluetooth/esp-ble-mesh.rst b/docs/en/api-reference/bluetooth/esp-ble-mesh.rst index bf03a8fe79..35de1143e5 100644 --- a/docs/en/api-reference/bluetooth/esp-ble-mesh.rst +++ b/docs/en/api-reference/bluetooth/esp-ble-mesh.rst @@ -71,6 +71,9 @@ Reading of Local Data Information .. include-build-file:: inc/esp_ble_mesh_local_data_operation_api.inc +Coexist with BLE + +.. include-build-file:: inc/esp_ble_mesh_ble_api.inc Low Power Operation (Updating) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/examples/bluetooth/esp_ble_mesh/common_components/example_init/ble_mesh_example_init.c b/examples/bluetooth/esp_ble_mesh/common_components/example_init/ble_mesh_example_init.c index 81600912b4..8a4674a871 100644 --- a/examples/bluetooth/esp_ble_mesh/common_components/example_init/ble_mesh_example_init.c +++ b/examples/bluetooth/esp_ble_mesh/common_components/example_init/ble_mesh_example_init.c @@ -1,6 +1,6 @@ /* * SPDX-FileCopyrightText: 2017 Intel Corporation - * SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2021-2024 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -155,6 +155,22 @@ esp_err_t bluetooth_init(void) /* XXX Need to have template for store */ ble_store_config_init(); +#if CONFIG_BLE_MESH_USE_BLE_50 + /** + * On the NimBLE host, once any of the discovery, + * advertising, or connection is enabled, it is + * no longer possible to register GATT services. + * + * Once the NimBLE host is started, it will call + * the registered sync callback. Since it is + * uncertain what the user will do in the sync + * callback, GATT services should be registered + * before starting the NimBLE. + */ + extern void bt_mesh_gatts_svcs_add(void); + bt_mesh_gatts_svcs_add(); +#endif /* CONFIG_BLE_MESH_USE_BLE_50 */ + nimble_port_freertos_init(mesh_host_task); xSemaphoreTake(mesh_sem, portMAX_DELAY);