mirror of
https://github.com/espressif/esp-idf.git
synced 2026-10-01 18:50:34 +03:00
feat(nimble): Migrate to nimble-1.10.0
This commit is contained in:
Submodule components/bt/host/nimble/nimble updated: 973e7d4279...f361449c87
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2017-2025 Espressif Systems (Shanghai) CO LTD
|
||||
* SPDX-FileCopyrightText: 2017-2026 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
@@ -273,9 +273,14 @@ void esp_hid_cod_minor_print(uint8_t cod_min, FILE *fp);
|
||||
|
||||
/**
|
||||
* @brief Convert BLE disconnect reason to string
|
||||
* @param reason : The value of the reason
|
||||
*
|
||||
* @return: a pointer to the string or NULL
|
||||
* Accepts Bluedroid `esp_gatt_conn_reason_t` values (raw HCI for most
|
||||
* cases) and NimBLE `BLE_HS_HCI_ERR()` values (`0x200 + HCI status`).
|
||||
*
|
||||
* @param transport : HID transport (string map is BLE-only)
|
||||
* @param reason : Disconnect reason from the host stack
|
||||
*
|
||||
* @return: a pointer to the string (never NULL)
|
||||
*/
|
||||
const char *esp_hid_disconnect_reason_str(esp_hid_transport_t transport, int reason);
|
||||
|
||||
|
||||
@@ -14,6 +14,9 @@
|
||||
#if (CONFIG_GATTS_ENABLE || CONFIG_GATTC_ENABLE)
|
||||
#include "esp_gatt_defs.h"
|
||||
#endif
|
||||
#if CONFIG_BT_NIMBLE_ENABLED
|
||||
#include "host/ble_hs.h"
|
||||
#endif
|
||||
static const char *TAG = "hid_parser";
|
||||
|
||||
typedef struct {
|
||||
@@ -524,22 +527,57 @@ void esp_hid_cod_minor_print(uint8_t cod_min, FILE *fp)
|
||||
}
|
||||
}
|
||||
|
||||
/* Core HCI disconnect statuses (Vol 1 Part F). Shared by Bluedroid GATT
|
||||
* conn reasons and NimBLE BLE_HS_HCI_ERR(hci_status).
|
||||
*/
|
||||
static const char *ble_hci_disconn_reason_str(int hci_reason)
|
||||
{
|
||||
switch (hci_reason) {
|
||||
case 0x05: return "AUTH_FAIL";
|
||||
case 0x06: return "PINKEY_MISSING";
|
||||
case 0x08: return "TIMEOUT";
|
||||
case 0x13: return "TERMINATE_PEER_USER";
|
||||
case 0x14: return "TERMINATE_PEER_RESOURCES";
|
||||
case 0x15: return "TERMINATE_PEER_POWER_OFF";
|
||||
case 0x16: return "TERMINATE_LOCAL_HOST";
|
||||
case 0x1f: return "UNSPECIFIED";
|
||||
case 0x22: return "LMP_TIMEOUT";
|
||||
case 0x28: return "INSTANT_PASSED";
|
||||
case 0x3b: return "UNACCEPTABLE_CONN_PARAMS";
|
||||
case 0x3d: return "MIC_FAILURE";
|
||||
case 0x3e: return "FAIL_ESTABLISH";
|
||||
default: return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
const char *esp_hid_disconnect_reason_str(esp_hid_transport_t transport, int reason)
|
||||
{
|
||||
if (transport == ESP_HID_TRANSPORT_BLE) {
|
||||
#if (CONFIG_GATTS_ENABLE || CONFIG_GATTC_ENABLE)
|
||||
switch ((esp_gatt_conn_reason_t)reason) {
|
||||
case ESP_GATT_CONN_L2C_FAILURE: return "L2C_FAILURE";
|
||||
case ESP_GATT_CONN_TIMEOUT: return "TIMEOUT";
|
||||
case ESP_GATT_CONN_TERMINATE_PEER_USER: return "TERMINATE_PEER_USER";
|
||||
case ESP_GATT_CONN_TERMINATE_LOCAL_HOST: return "TERMINATE_LOCAL_HOST";
|
||||
case ESP_GATT_CONN_LMP_TIMEOUT: return "LMP_TIMEOUT";
|
||||
case ESP_GATT_CONN_FAIL_ESTABLISH: return "FAIL_ESTABLISH";
|
||||
case ESP_GATT_CONN_CONN_CANCEL: return "CONN_CANCEL";
|
||||
case ESP_GATT_CONN_NONE: return "NONE";
|
||||
default: break;
|
||||
}
|
||||
#endif /* CONFIG_GATTS_ENABLE || CONFIG_GATTC_ENABLE */
|
||||
const char *str;
|
||||
|
||||
if (transport != ESP_HID_TRANSPORT_BLE) {
|
||||
return s_unknown_str;
|
||||
}
|
||||
return s_unknown_str;
|
||||
|
||||
#if CONFIG_BT_NIMBLE_ENABLED
|
||||
/* NimBLE GAP posts BLE_HS_HCI_ERR(hci) = 0x200 + hci. Do not fall through:
|
||||
* HCI 0x01 would collide with Bluedroid ESP_GATT_CONN_L2C_FAILURE.
|
||||
*/
|
||||
if (reason > BLE_HS_ERR_HCI_BASE && reason < BLE_HS_ERR_L2C_BASE) {
|
||||
str = ble_hci_disconn_reason_str(reason - BLE_HS_ERR_HCI_BASE);
|
||||
return str ? str : s_unknown_str;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if (CONFIG_GATTS_ENABLE || CONFIG_GATTC_ENABLE)
|
||||
switch ((esp_gatt_conn_reason_t)reason) {
|
||||
case ESP_GATT_CONN_L2C_FAILURE: return "L2C_FAILURE";
|
||||
case ESP_GATT_CONN_CONN_CANCEL: return "CONN_CANCEL";
|
||||
case ESP_GATT_CONN_NONE: return "NONE";
|
||||
default:
|
||||
break;
|
||||
}
|
||||
#endif /* CONFIG_GATTS_ENABLE || CONFIG_GATTC_ENABLE */
|
||||
|
||||
str = ble_hci_disconn_reason_str(reason);
|
||||
return str ? str : s_unknown_str;
|
||||
}
|
||||
|
||||
@@ -520,6 +520,13 @@ void app_main(void)
|
||||
}
|
||||
ESP_ERROR_CHECK( ret );
|
||||
|
||||
#if !SOC_MPI_SUPPORTED
|
||||
/* Software 3072-bit modular exponentiation needs ~4.2 kB of contiguous
|
||||
* internal heap. Start it before Wi-Fi and the BLE host claim their pools,
|
||||
* otherwise the allocation fails with PSA_ERROR_INSUFFICIENT_MEMORY. */
|
||||
blufi_dh_pregen_start();
|
||||
#endif
|
||||
|
||||
initialise_wifi();
|
||||
|
||||
#if CONFIG_BT_CONTROLLER_ENABLED || !CONFIG_BT_NIMBLE_ENABLED
|
||||
@@ -537,7 +544,6 @@ void app_main(void)
|
||||
}
|
||||
|
||||
#if !SOC_MPI_SUPPORTED
|
||||
blufi_dh_pregen_start();
|
||||
blufi_dh_pregen_wait();
|
||||
esp_blufi_adv_start();
|
||||
#endif
|
||||
|
||||
@@ -47,7 +47,7 @@
|
||||
#define BLUFI_DEC_DOMAIN_STR "blufi_dec"
|
||||
|
||||
#if !SOC_MPI_SUPPORTED
|
||||
#define BLUFI_DH_PREGEN_STACK_SIZE 4096
|
||||
#define BLUFI_DH_PREGEN_STACK_SIZE 6144
|
||||
#define BLUFI_DH_PREGEN_PRIO (tskIDLE_PRIORITY + 1)
|
||||
#define BLUFI_DH_PREGEN_WAIT_MS 30000
|
||||
#define BLUFI_DH_HEAVY_CRYPTO_WDT_MS 30000
|
||||
@@ -125,11 +125,15 @@ static void blufi_cleanup_negotiation(bool abort_enc, bool abort_dec)
|
||||
* with BLE advertising so only key agreement remains on the critical path
|
||||
* when the phone sends its DH parameters.
|
||||
*/
|
||||
#define BLUFI_PREGEN_DONE_BIT BIT0
|
||||
|
||||
static psa_key_id_t s_pregen_private_key;
|
||||
static uint8_t s_pregen_public_key[DH_SELF_PUB_KEY_LEN];
|
||||
static size_t s_pregen_public_key_len;
|
||||
static SemaphoreHandle_t s_pregen_done;
|
||||
static bool s_pregen_ok;
|
||||
static bool s_pregen_busy;
|
||||
static EventGroupHandle_t s_pregen_evt;
|
||||
static SemaphoreHandle_t s_pregen_req;
|
||||
static TaskHandle_t s_pregen_task_hdl;
|
||||
static void (*s_pregen_complete_cb)(void);
|
||||
|
||||
@@ -143,12 +147,8 @@ static void blufi_wdt_set_timeout(uint32_t timeout_ms)
|
||||
esp_task_wdt_reconfigure(&cfg);
|
||||
}
|
||||
|
||||
static void blufi_dh_pregen_task(void *arg)
|
||||
static void blufi_dh_pregen_generate(void)
|
||||
{
|
||||
(void)arg;
|
||||
|
||||
blufi_wdt_set_timeout(BLUFI_DH_HEAVY_CRYPTO_WDT_MS);
|
||||
|
||||
psa_key_attributes_t attr = psa_key_attributes_init();
|
||||
psa_set_key_type(&attr, PSA_KEY_TYPE_DH_KEY_PAIR(PSA_DH_FAMILY_RFC7919));
|
||||
psa_set_key_bits(&attr, 3072);
|
||||
@@ -170,44 +170,88 @@ static void blufi_dh_pregen_task(void *arg)
|
||||
}
|
||||
|
||||
BLUFI_INFO("DH keypair pre-generation %s", s_pregen_ok ? "done" : "FAILED");
|
||||
|
||||
blufi_wdt_set_timeout(CONFIG_ESP_TASK_WDT_TIMEOUT_S * 1000);
|
||||
|
||||
xSemaphoreGive(s_pregen_done);
|
||||
|
||||
if (s_pregen_complete_cb) {
|
||||
void (*cb)(void) = s_pregen_complete_cb;
|
||||
s_pregen_complete_cb = NULL;
|
||||
cb();
|
||||
}
|
||||
|
||||
vTaskSuspend(NULL);
|
||||
}
|
||||
|
||||
static void blufi_dh_pregen_start_impl(void (*done_cb)(void))
|
||||
/*
|
||||
* The worker outlives every connection. Creating it per keypair would mean
|
||||
* asking for BLUFI_DH_PREGEN_STACK_SIZE of contiguous internal heap at the
|
||||
* worst possible moment - right after a disconnect, with Wi-Fi and the BLE host
|
||||
* fully up - which is where xTaskCreate() fails.
|
||||
*/
|
||||
static void blufi_dh_pregen_task(void *arg)
|
||||
{
|
||||
if (s_pregen_done != NULL) {
|
||||
return;
|
||||
(void)arg;
|
||||
|
||||
while (true) {
|
||||
xSemaphoreTake(s_pregen_req, portMAX_DELAY);
|
||||
|
||||
blufi_wdt_set_timeout(BLUFI_DH_HEAVY_CRYPTO_WDT_MS);
|
||||
blufi_dh_pregen_generate();
|
||||
blufi_wdt_set_timeout(CONFIG_ESP_TASK_WDT_TIMEOUT_S * 1000);
|
||||
|
||||
s_pregen_busy = false;
|
||||
xEventGroupSetBits(s_pregen_evt, BLUFI_PREGEN_DONE_BIT);
|
||||
|
||||
if (s_pregen_complete_cb) {
|
||||
void (*cb)(void) = s_pregen_complete_cb;
|
||||
s_pregen_complete_cb = NULL;
|
||||
cb();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static bool blufi_dh_pregen_worker_ensure(void)
|
||||
{
|
||||
if (s_pregen_task_hdl != NULL) {
|
||||
return true;
|
||||
}
|
||||
|
||||
s_pregen_private_key = 0;
|
||||
s_pregen_public_key_len = 0;
|
||||
s_pregen_ok = false;
|
||||
s_pregen_task_hdl = NULL;
|
||||
s_pregen_complete_cb = done_cb;
|
||||
s_pregen_done = xSemaphoreCreateBinary();
|
||||
if (s_pregen_done == NULL) {
|
||||
BLUFI_ERROR("Failed to create pre-gen semaphore");
|
||||
return;
|
||||
if (s_pregen_evt == NULL) {
|
||||
s_pregen_evt = xEventGroupCreate();
|
||||
}
|
||||
if (s_pregen_req == NULL) {
|
||||
s_pregen_req = xSemaphoreCreateBinary();
|
||||
}
|
||||
if (s_pregen_evt == NULL || s_pregen_req == NULL) {
|
||||
BLUFI_ERROR("Failed to create pre-gen sync objects");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (xTaskCreate(blufi_dh_pregen_task, "blufi_pregen",
|
||||
BLUFI_DH_PREGEN_STACK_SIZE, NULL,
|
||||
BLUFI_DH_PREGEN_PRIO, &s_pregen_task_hdl) != pdPASS) {
|
||||
BLUFI_ERROR("Failed to create pre-gen task");
|
||||
vSemaphoreDelete(s_pregen_done);
|
||||
s_pregen_done = NULL;
|
||||
s_pregen_task_hdl = NULL;
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static void blufi_dh_pregen_start_impl(void (*done_cb)(void))
|
||||
{
|
||||
if (!blufi_dh_pregen_worker_ensure()) {
|
||||
/* Advertise anyway; negotiation falls back to inline key generation. */
|
||||
if (done_cb) {
|
||||
done_cb();
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
/* A keypair is already banked, or one is on its way. */
|
||||
if (s_pregen_busy || (s_pregen_ok && s_pregen_private_key != 0)) {
|
||||
if (done_cb) {
|
||||
done_cb();
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
s_pregen_public_key_len = 0;
|
||||
s_pregen_ok = false;
|
||||
s_pregen_complete_cb = done_cb;
|
||||
s_pregen_busy = true;
|
||||
xEventGroupClearBits(s_pregen_evt, BLUFI_PREGEN_DONE_BIT);
|
||||
xSemaphoreGive(s_pregen_req);
|
||||
}
|
||||
|
||||
void blufi_dh_pregen_start(void)
|
||||
@@ -222,29 +266,30 @@ void blufi_dh_pregen_start_with_cb(void (*done_cb)(void))
|
||||
|
||||
void blufi_dh_pregen_wait(void)
|
||||
{
|
||||
if (s_pregen_done == NULL) {
|
||||
if (s_pregen_evt == NULL) {
|
||||
return;
|
||||
}
|
||||
xSemaphoreTake(s_pregen_done, portMAX_DELAY);
|
||||
xSemaphoreGive(s_pregen_done);
|
||||
xEventGroupWaitBits(s_pregen_evt, BLUFI_PREGEN_DONE_BIT,
|
||||
pdFALSE, pdTRUE, portMAX_DELAY);
|
||||
}
|
||||
|
||||
static void blufi_dh_pregen_cleanup(void)
|
||||
/**
|
||||
* @brief Hand the banked keypair to the caller, which takes ownership of it
|
||||
*
|
||||
* @return The private key id, or 0 when no usable keypair is banked
|
||||
*/
|
||||
static psa_key_id_t blufi_dh_pregen_take(void)
|
||||
{
|
||||
if (s_pregen_done != NULL) {
|
||||
xSemaphoreTake(s_pregen_done, portMAX_DELAY);
|
||||
vSemaphoreDelete(s_pregen_done);
|
||||
s_pregen_done = NULL;
|
||||
}
|
||||
if (s_pregen_task_hdl != NULL) {
|
||||
vTaskDelete(s_pregen_task_hdl);
|
||||
s_pregen_task_hdl = NULL;
|
||||
}
|
||||
if (s_pregen_private_key != 0) {
|
||||
psa_destroy_key(s_pregen_private_key);
|
||||
s_pregen_private_key = 0;
|
||||
if (!s_pregen_ok || s_pregen_private_key == 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
psa_key_id_t key = s_pregen_private_key;
|
||||
s_pregen_private_key = 0;
|
||||
s_pregen_ok = false;
|
||||
xEventGroupClearBits(s_pregen_evt, BLUFI_PREGEN_DONE_BIT);
|
||||
|
||||
return key;
|
||||
}
|
||||
#endif /* !SOC_MPI_SUPPORTED */
|
||||
|
||||
@@ -384,19 +429,27 @@ void blufi_dh_negotiate_data_handler(uint8_t *data, int len, uint8_t **output_da
|
||||
* heap before key agreement, and widen the task WDT window. */
|
||||
bool used_pregen = false;
|
||||
|
||||
if (s_pregen_done != NULL &&
|
||||
xSemaphoreTake(s_pregen_done, pdMS_TO_TICKS(BLUFI_DH_PREGEN_WAIT_MS)) == pdTRUE) {
|
||||
xSemaphoreGive(s_pregen_done);
|
||||
if (s_pregen_ok && s_pregen_private_key != 0) {
|
||||
private_key = s_pregen_private_key;
|
||||
s_pregen_private_key = 0;
|
||||
memcpy(blufi_sec->self_public_key, s_pregen_public_key, s_pregen_public_key_len);
|
||||
public_key_len = s_pregen_public_key_len;
|
||||
if (s_pregen_evt != NULL &&
|
||||
(xEventGroupWaitBits(s_pregen_evt, BLUFI_PREGEN_DONE_BIT, pdFALSE, pdTRUE,
|
||||
pdMS_TO_TICKS(BLUFI_DH_PREGEN_WAIT_MS)) & BLUFI_PREGEN_DONE_BIT)) {
|
||||
size_t pregen_len = s_pregen_public_key_len;
|
||||
private_key = blufi_dh_pregen_take();
|
||||
if (private_key != 0) {
|
||||
memcpy(blufi_sec->self_public_key, s_pregen_public_key, pregen_len);
|
||||
public_key_len = pregen_len;
|
||||
used_pregen = true;
|
||||
BLUFI_INFO("Using pre-generated DH keypair");
|
||||
}
|
||||
}
|
||||
|
||||
/* Release the DH parameter buffer before any further modular
|
||||
* exponentiation. Both the inline keypair generation and the key
|
||||
* agreement below need a single ~4.2 kB contiguous internal
|
||||
* allocation, so nothing reclaimable may be held across them. */
|
||||
uint8_t peer_pub[DH_SELF_PUB_KEY_LEN];
|
||||
memcpy(peer_pub, param, pub_len);
|
||||
blufi_cleanup_dh_param();
|
||||
|
||||
if (!used_pregen) {
|
||||
BLUFI_INFO("Pre-gen unavailable, generating DH keypair inline");
|
||||
blufi_wdt_set_timeout(BLUFI_DH_HEAVY_CRYPTO_WDT_MS);
|
||||
@@ -412,7 +465,6 @@ void blufi_dh_negotiate_data_handler(uint8_t *data, int len, uint8_t **output_da
|
||||
BLUFI_ERROR("%s psa_generate_key failed %d\n", __func__, status);
|
||||
blufi_wdt_set_timeout(CONFIG_ESP_TASK_WDT_TIMEOUT_S * 1000);
|
||||
btc_blufi_report_error(ESP_BLUFI_DH_MALLOC_ERROR);
|
||||
blufi_cleanup_dh_param();
|
||||
return;
|
||||
}
|
||||
psa_reset_key_attributes(&keygen_attr);
|
||||
@@ -424,20 +476,10 @@ void blufi_dh_negotiate_data_handler(uint8_t *data, int len, uint8_t **output_da
|
||||
blufi_wdt_set_timeout(CONFIG_ESP_TASK_WDT_TIMEOUT_S * 1000);
|
||||
psa_destroy_key(private_key);
|
||||
btc_blufi_report_error(ESP_BLUFI_DH_MALLOC_ERROR);
|
||||
blufi_cleanup_dh_param();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t peer_pub[DH_SELF_PUB_KEY_LEN];
|
||||
memcpy(peer_pub, param, pub_len);
|
||||
blufi_cleanup_dh_param();
|
||||
|
||||
if (s_pregen_task_hdl != NULL) {
|
||||
vTaskDelete(s_pregen_task_hdl);
|
||||
s_pregen_task_hdl = NULL;
|
||||
}
|
||||
|
||||
blufi_wdt_set_timeout(BLUFI_DH_HEAVY_CRYPTO_WDT_MS);
|
||||
status = psa_raw_key_agreement(alg, private_key, peer_pub, pub_len,
|
||||
blufi_sec->share_key, SHARE_KEY_LEN,
|
||||
@@ -738,9 +780,9 @@ void blufi_security_deinit(void)
|
||||
return;
|
||||
}
|
||||
|
||||
#if !SOC_MPI_SUPPORTED
|
||||
blufi_dh_pregen_cleanup();
|
||||
#endif
|
||||
/* The pre-generation worker and any keypair it has banked deliberately
|
||||
* survive the disconnect: the next connection reuses them, and its task
|
||||
* stack could not be reallocated once Wi-Fi and the BLE host are up. */
|
||||
|
||||
/* Clean up all resources */
|
||||
blufi_cleanup_negotiation(true, true);
|
||||
|
||||
@@ -18,3 +18,7 @@ CONFIG_BT_NIMBLE_ROLE_OBSERVER=n
|
||||
CONFIG_BT_NIMBLE_50_FEATURE_SUPPORT=n
|
||||
CONFIG_BT_NIMBLE_SECURITY_ENABLE=n
|
||||
CONFIG_BT_NIMBLE_CRYPTO_STACK_MBEDTLS=n
|
||||
# ESP32-C2 has no hardware MPI, so the 3072-bit BLUFI Diffie-Hellman runs in
|
||||
# software and needs ~4.2 kB of contiguous internal heap. BLUFI only exchanges
|
||||
# small packets, so the 320-byte msys_2 pool is trimmed to leave that headroom.
|
||||
CONFIG_BT_NIMBLE_MSYS_2_BLOCK_COUNT=8
|
||||
|
||||
@@ -22,7 +22,9 @@
|
||||
#endif
|
||||
|
||||
static const char *tag = "NimBLE_CTS_CENT";
|
||||
#if CONFIG_EXAMPLE_CI_ID && CONFIG_EXAMPLE_CI_PIPELINE_ID
|
||||
static char remote_device_name[32];
|
||||
#endif
|
||||
static int ble_cts_cent_gap_event(struct ble_gap_event *event, void *arg);
|
||||
|
||||
#if CONFIG_EXAMPLE_CI_ID && CONFIG_EXAMPLE_CI_PIPELINE_ID
|
||||
|
||||
@@ -21,7 +21,9 @@
|
||||
#endif
|
||||
|
||||
static const char *tag = "NimBLE_HTP_CENT";
|
||||
#if CONFIG_EXAMPLE_CI_ID && CONFIG_EXAMPLE_CI_PIPELINE_ID
|
||||
static char remote_device_name[32];
|
||||
#endif
|
||||
static int ble_htp_cent_gap_event(struct ble_gap_event *event, void *arg);
|
||||
|
||||
void ble_store_config_init(void);
|
||||
|
||||
Reference in New Issue
Block a user