Update bt fork to be based on v5.3

This commit is contained in:
jacqueline
2024-08-13 06:02:54 +00:00
committed by cooljqln
parent be9725c1c7
commit 5a02f34ed9
508 changed files with 42429 additions and 5168 deletions
+10 -1
View File
@@ -1,8 +1,17 @@
# Documentation: .gitlab/ci/README.md#manifest-file-to-control-the-buildtest-apps
components/bt/test_apps:
components/bt/test_apps/basic_unit_test:
disable:
- if: IDF_TARGET not in ["esp32", "esp32c3"]
reason: Sufficient to run the tests on one chip of each architecture
depends_components:
- bt
components/bt/test_apps/memory_release:
disable:
- if: IDF_TARGET not in ["esp32", "esp32c2"]
- if: CONFIG_NAME == "iram" and IDF_TARGET != "esp32c2"
- if: CONFIG_NAME == "psram" and SOC_SPIRAM_SUPPORTED != 1
reason: Sufficient to run the tests on one chip of each architecture
depends_components:
- bt
@@ -0,0 +1,9 @@
cmake_minimum_required(VERSION 3.16)
include($ENV{IDF_PATH}/tools/cmake/project.cmake)
set(COMPONENTS main)
list(PREPEND SDKCONFIG_DEFAULTS
"$ENV{IDF_PATH}/tools/test_apps/configs/sdkconfig.debug_helpers"
"sdkconfig.defaults")
project(bt_test)
@@ -0,0 +1,21 @@
| Supported Targets | ESP32 | ESP32-C3 |
| ----------------- | ----- | -------- |
# `bt` component unit tests
When adding new test cases, check if the `depends_components` list in `.build-test-rules.yml` needs to be updated to include additional components. The test app will only be built and tested when these components are modified.
To build and run this test app, using esp32c3 target for example:
```bash
idf.py set-target esp32c3
idf.py build flash monitor
```
To run tests using pytest:
```bash
idf.py set-target esp32c3
idf.py build
pytest --target=esp32c3
```
@@ -0,0 +1,6 @@
idf_component_register(SRCS "test_bt_main.c"
"test_bt_common.c"
"test_smp.c"
INCLUDE_DIRS "."
PRIV_REQUIRES unity bt
WHOLE_ARCHIVE)
@@ -0,0 +1,24 @@
/*
* SPDX-FileCopyrightText: 2021 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Unlicense OR CC0-1.0
*/
/*
Tests for the BT common things implementation
*/
#include <stdbool.h>
#include "unity.h"
#include "sdkconfig.h"
// btdm_controller_compile_version_check defined only for ESP32
#ifdef CONFIG_IDF_TARGET_ESP32
extern bool btdm_controller_compile_version_check(void);
TEST_CASE("bt_controller_git_commit_check", "[bt_common]")
{
TEST_ASSERT(btdm_controller_compile_version_check() == true);
}
#endif
@@ -0,0 +1,48 @@
/*
* SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#include "unity.h"
#include "unity_test_runner.h"
#include "esp_heap_caps.h"
#define TEST_MEMORY_LEAK_THRESHOLD_DEFAULT 0
static int leak_threshold = TEST_MEMORY_LEAK_THRESHOLD_DEFAULT;
void set_leak_threshold(int threshold)
{
leak_threshold = threshold;
}
static size_t before_free_8bit;
static size_t before_free_32bit;
static void check_leak(size_t before_free, size_t after_free, const char *type)
{
ssize_t delta = after_free - before_free;
printf("MALLOC_CAP_%s: Before %u bytes free, After %u bytes free (delta %d)\n", type, before_free, after_free, delta);
TEST_ASSERT_MESSAGE(delta >= leak_threshold, "memory leak");
}
void setUp(void)
{
before_free_8bit = heap_caps_get_free_size(MALLOC_CAP_8BIT);
before_free_32bit = heap_caps_get_free_size(MALLOC_CAP_32BIT);
}
void tearDown(void)
{
size_t after_free_8bit = heap_caps_get_free_size(MALLOC_CAP_8BIT);
size_t after_free_32bit = heap_caps_get_free_size(MALLOC_CAP_32BIT);
check_leak(before_free_8bit, after_free_8bit, "8BIT");
check_leak(before_free_32bit, after_free_32bit, "32BIT");
leak_threshold = TEST_MEMORY_LEAK_THRESHOLD_DEFAULT;
}
void app_main(void)
{
printf("Running bt component tests\n");
unity_run_menu();
}
@@ -0,0 +1,126 @@
/*
* SPDX-FileCopyrightText: 2021-2023 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Unlicense OR CC0-1.0
*/
/*
* Tests for the BLE SMP implementation
*/
#include <string.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "unity.h"
#include "esp_random.h"
#include "esp_bt_main.h"
#include "esp_bt_device.h"
#include "esp_gap_ble_api.h"
#define KEY_LENGTH_DWORDS_P256 8
typedef unsigned long DWORD;
typedef uint32_t UINT32;
typedef struct {
DWORD x[KEY_LENGTH_DWORDS_P256];
DWORD y[KEY_LENGTH_DWORDS_P256];
DWORD z[KEY_LENGTH_DWORDS_P256];
} Point;
typedef struct {
// curve's coefficients
DWORD a[KEY_LENGTH_DWORDS_P256];
DWORD b[KEY_LENGTH_DWORDS_P256];
//whether a is -3
int a_minus3;
// prime modulus
DWORD p[KEY_LENGTH_DWORDS_P256];
// Omega, p = 2^m -omega
DWORD omega[KEY_LENGTH_DWORDS_P256];
// base point, a point on E of order r
Point G;
} elliptic_curve_t;
extern void ECC_PointMult_Bin_NAF(Point *q, Point *p, DWORD *n, uint32_t keyLength);
extern bool ECC_CheckPointIsInElliCur_P256(Point *p);
extern void p_256_init_curve(UINT32 keyLength);
extern elliptic_curve_t curve_p256;
static void bt_rand(void *buf, size_t len)
{
if (!len) {
return;
}
// Reset the buf value to the fixed value.
memset(buf, 0x55, len);
for (int i = 0; i < (int)(len / sizeof(uint32_t)); i++) {
uint32_t rand = esp_random();
memcpy(buf + i * sizeof(uint32_t), &rand, sizeof(uint32_t));
}
return;
}
TEST_CASE("ble_smp_public_key_check", "[ble_smp]")
{
/* We wait init finish 200ms here */
vTaskDelay(200 / portTICK_PERIOD_MS);
Point public_key;
DWORD private_key[KEY_LENGTH_DWORDS_P256] = {[0 ... (KEY_LENGTH_DWORDS_P256 - 1)] = 0x12345678};
p_256_init_curve(KEY_LENGTH_DWORDS_P256);
ECC_PointMult_Bin_NAF(&public_key, &(curve_p256.G), private_key, KEY_LENGTH_DWORDS_P256);
/* Check Is the public key generated by the system on the given elliptic curve */
TEST_ASSERT(ECC_CheckPointIsInElliCur_P256(&public_key));
/* We simulate the attacker and set the y coordinate of the public key to 0. */
for (int i = 0; i < KEY_LENGTH_DWORDS_P256; i++) {
public_key.y[i] = 0x0;
}
/* At this point the public key should not be on the given elliptic curve. */
TEST_ASSERT(!ECC_CheckPointIsInElliCur_P256(&public_key));
/* Test whether the G point on the protocol is on a given elliptic curve */
TEST_ASSERT(ECC_CheckPointIsInElliCur_P256(&(curve_p256.G)));
/* test 100 times when the private key is generated by the random number. */
for (int j = 0; j < 100; j++) {
bt_rand(private_key, sizeof(DWORD)*KEY_LENGTH_DWORDS_P256);
ECC_PointMult_Bin_NAF(&public_key, &(curve_p256.G), private_key, KEY_LENGTH_DWORDS_P256);
/* Check Is the public key generated by the system on the given elliptic curve */
TEST_ASSERT(ECC_CheckPointIsInElliCur_P256(&public_key));
}
}
TEST_CASE("ble_smp_set_clear_static_passkey", "[ble_smp]")
{
/* We wait init finish 200ms here */
vTaskDelay(200 / portTICK_PERIOD_MS);
esp_ble_auth_req_t auth_req = ESP_LE_AUTH_BOND;
uint32_t passkey = 123456;
/* test len = 0 when type != ESP_BLE_SM_CLEAR_STATIC_PASSKEY */
TEST_ASSERT(esp_ble_gap_set_security_param(ESP_BLE_SM_AUTHEN_REQ_MODE, &auth_req, 0) == ESP_ERR_INVALID_ARG);
/* test function */
TEST_ASSERT(esp_ble_gap_set_security_param(ESP_BLE_SM_AUTHEN_REQ_MODE, &auth_req, sizeof(esp_ble_auth_req_t)) != ESP_ERR_INVALID_ARG);
/* test type >= ESP_BLE_SM_MAX_PARAM */
TEST_ASSERT(esp_ble_gap_set_security_param(ESP_BLE_SM_MAX_PARAM, &passkey, sizeof(uint32_t)) == ESP_ERR_INVALID_ARG);
/* test len < sizeof(uint32_t) when type is ESP_BLE_SM_SET_STATIC_PASSKEY */
TEST_ASSERT(esp_ble_gap_set_security_param(ESP_BLE_SM_SET_STATIC_PASSKEY, &passkey, sizeof(uint8_t)) != ESP_ERR_INVALID_ARG);
/* test value is NULL when type != ESP_BLE_SM_CLEAR_STATIC_PASSKEY */
TEST_ASSERT(esp_ble_gap_set_security_param(ESP_BLE_SM_SET_STATIC_PASSKEY, NULL, sizeof(uint8_t)) == ESP_ERR_INVALID_ARG);
/* test value is NULL and len is 0 when type != ESP_BLE_SM_CLEAR_STATIC_PASSKEY */
TEST_ASSERT(esp_ble_gap_set_security_param(ESP_BLE_SM_SET_STATIC_PASSKEY, NULL, 0) == ESP_ERR_INVALID_ARG);
/* test function */
TEST_ASSERT(esp_ble_gap_set_security_param(ESP_BLE_SM_SET_STATIC_PASSKEY, &passkey, sizeof(uint32_t)) != ESP_ERR_INVALID_ARG);
/* test function */
TEST_ASSERT(esp_ble_gap_set_security_param(ESP_BLE_SM_CLEAR_STATIC_PASSKEY, &passkey, sizeof(uint32_t)) != ESP_ERR_INVALID_ARG);
/* test function */
TEST_ASSERT(esp_ble_gap_set_security_param(ESP_BLE_SM_CLEAR_STATIC_PASSKEY, NULL, sizeof(uint32_t)) != ESP_ERR_INVALID_ARG);
/* test function */
TEST_ASSERT(esp_ble_gap_set_security_param(ESP_BLE_SM_CLEAR_STATIC_PASSKEY, NULL, 0) != ESP_ERR_INVALID_ARG);
}
@@ -0,0 +1,11 @@
# SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD
# SPDX-License-Identifier: CC0-1.0
import pytest
from pytest_embedded import Dut
@pytest.mark.generic
@pytest.mark.esp32
@pytest.mark.esp32c3
def test_bt(dut: Dut) -> None:
dut.run_all_single_board_cases()
@@ -0,0 +1,2 @@
CONFIG_BT_ENABLED=y
CONFIG_ESP_TASK_WDT_CHECK_IDLE_TASK_CPU0=n
@@ -0,0 +1,5 @@
# This is the project CMakeLists.txt file for the test subproject
cmake_minimum_required(VERSION 3.16)
include($ENV{IDF_PATH}/tools/cmake/project.cmake)
project(test_bt_memory_release)
@@ -0,0 +1,4 @@
| Supported Targets | ESP32 | ESP32-C2 |
| ----------------- | ----- | -------- |
This test app is used to test esp_bt_memory_release function
@@ -0,0 +1,3 @@
idf_component_register(SRCS "test_app_main.c"
INCLUDE_DIRS "."
PRIV_REQUIRES bt nvs_flash)
@@ -0,0 +1,131 @@
/*
* SPDX-FileCopyrightText: 2015-2024 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <stdio.h>
#include <unistd.h>
#include <assert.h>
#include "esp_log.h"
#include "nvs_flash.h"
#include "multi_heap.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "esp_bt.h"
#include "nimble/nimble_port.h"
#include "nimble/nimble_port_freertos.h"
#include "host/ble_hs.h"
#include "host/util/util.h"
#include "services/gap/ble_svc_gap.h"
#define FAIL() do { printf("FAILURE\n"); return; } while(0)
extern uint8_t _bt_bss_start;
extern uint8_t _bt_bss_end;
extern uint8_t _bt_controller_bss_start;
extern uint8_t _bt_controller_bss_end;
extern void ble_store_config_init(void);
static const char *tag = "MEM_RELEASE_APP";
static void nimble_host_on_reset(int reason)
{
ESP_LOGI(tag, "Resetting state; reason=%d", reason);
}
static void nimble_host_on_sync(void)
{
ESP_LOGI(tag, "NimBLE host synchronized");
}
static void nimble_host_task_fn(void *param)
{
ESP_LOGI(tag, "BLE Host Task Started");
/* This function will return only when nimble_port_stop() is executed */
nimble_port_run();
nimble_port_freertos_deinit();
}
static void bt_stack_init(void)
{
esp_err_t ret = nimble_port_init();
ESP_ERROR_CHECK(ret);
/* Initialize the NimBLE host configuration. */
ble_hs_cfg.reset_cb = nimble_host_on_reset;
ble_hs_cfg.sync_cb = nimble_host_on_sync;
ble_hs_cfg.store_status_cb = ble_store_util_status_rr;
/* Set the default device name. */
int rc = ble_svc_gap_device_name_set(tag);
assert(rc == 0);
/* XXX Need to have template for store */
ble_store_config_init();
nimble_port_freertos_init(nimble_host_task_fn);
}
static void bt_stack_deinit(void)
{
int rc = nimble_port_stop();
assert(rc == 0);
nimble_port_deinit();
ESP_LOGI(tag, "BLE Host Task Stopped");
}
void app_main(void)
{
esp_err_t ret = ESP_OK;
/* Initialize NVS — it is used to store PHY calibration data */
ret = nvs_flash_init();
if (ret == ESP_ERR_NVS_NO_FREE_PAGES || ret == ESP_ERR_NVS_NEW_VERSION_FOUND) {
ESP_ERROR_CHECK(nvs_flash_erase());
ret = nvs_flash_init();
}
ESP_ERROR_CHECK(ret);
/* initialize and then deinitialize bluetooth stack */
bt_stack_init();
vTaskDelay(pdMS_TO_TICKS(200));
bt_stack_deinit();
/* Get the size of heap located in external RAM */
const uint32_t free_before = heap_caps_get_free_size(MALLOC_CAP_DEFAULT);
ESP_LOGI(tag, "Free size in external RAM heap: %"PRIu32, free_before);
/* Make sure at least one of the Bluetooth BSS section that can be used as a heap */
const uint32_t heap_size = sizeof(multi_heap_info_t);
const uint32_t bt_bss_size = &_bt_bss_end - &_bt_bss_start;
const uint32_t bt_ctrl_bss_size = &_bt_controller_bss_end - &_bt_controller_bss_start;
ESP_LOGI(tag, "bt_bss_size %"PRIu32", bt_ctrl_bss_size %"PRIu32, bt_bss_size, bt_ctrl_bss_size);
if (bt_bss_size < heap_size && bt_ctrl_bss_size < heap_size)
{
ESP_LOGW(tag, "Bluetooth BSS sections are too small!");
FAIL();
}
/* Release the BSS sections to use them as heap */
ret = esp_bt_mem_release(ESP_BT_MODE_BTDM);
ESP_ERROR_CHECK(ret);
/* Check that we have more available memory in the external RAM heap */
const uint32_t free_after = heap_caps_get_free_size(MALLOC_CAP_DEFAULT);
ESP_LOGI(tag, "Free size in external RAM after releasing: %"PRIu32, free_after);
if (free_after <= free_before) {
FAIL();
}
ESP_LOGI(tag, "Free heap size increased by %"PRIu32" bytes", free_after - free_before);
ESP_LOGI(tag, "SUCCESS");
}
@@ -0,0 +1,15 @@
# SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD
# SPDX-License-Identifier: Apache-2.0
import pytest
from pytest_embedded import Dut
@pytest.mark.parametrize('config', [
pytest.param('default', marks=[pytest.mark.esp32, pytest.mark.esp32c2, pytest.mark.generic]),
pytest.param('iram', marks=[pytest.mark.esp32c2, pytest.mark.generic]),
pytest.param('psram', marks=[pytest.mark.esp32, pytest.mark.psram]),
], indirect=True)
def test_bt_memory_release(dut: Dut) -> None:
dut.expect_exact('BLE Host Task Started', timeout=6)
dut.expect_exact('BLE Host Task Stopped', timeout=8)
dut.expect_exact('SUCCESS', timeout=10)
@@ -0,0 +1,2 @@
CONFIG_ESP_SYSTEM_PMP_IDRAM_SPLIT=n
CONFIG_BT_RELEASE_IRAM=y
@@ -0,0 +1,2 @@
CONFIG_SPIRAM=y
CONFIG_SPIRAM_ALLOW_BSS_SEG_EXTERNAL_MEMORY=y
@@ -0,0 +1,2 @@
CONFIG_BT_ENABLED=y
CONFIG_BT_NIMBLE_ENABLED=y