Merge branch 'bugfix/fix_nimble_issue_310826_v6.1' into 'release/v6.1'

fix(nimble): Fix few nimble issues 31082026

See merge request espressif/esp-idf!52224
This commit is contained in:
Rahul Tank
2026-09-02 13:31:33 +05:30
245 changed files with 2028 additions and 1306 deletions
@@ -1,48 +1,69 @@
/* /*
* SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD * SPDX-FileCopyrightText: 2025-2026 Espressif Systems (Shanghai) CO LTD
* *
* SPDX-License-Identifier: Apache-2.0 * SPDX-License-Identifier: Apache-2.0
*/ */
#include "esp_tinycrypt_port.h" #include "esp_tinycrypt_port.h"
#include <string.h>
#include "esp_crypto_lock.h" #include "esp_crypto_lock.h"
#include "esp_private/esp_crypto_lock_internal.h" #include "esp_crypto_periph_clk.h"
#include <tinycrypt/ecc.h>
#if SOC_ECC_SUPPORTED #if SOC_ECC_SUPPORTED
#include "hal/ecc_hal.h" #include "hal/ecc_hal.h"
#include "hal/ecc_ll.h"
#endif /* SOC_ECC_SUPPORTED */ #endif /* SOC_ECC_SUPPORTED */
#define ECC_MAX_PARAM_BYTES 48
#if SOC_ECC_SUPPORTED #if SOC_ECC_SUPPORTED
static void esp_tinycrypt_acquire_ecc_hardware(void) static void uecc_vli_native_to_le(uint8_t *le, const uECC_word_t *native, uint16_t len)
{
uint8_t be[ECC_MAX_PARAM_BYTES];
uECC_vli_nativeToBytes(be, len, native);
for (uint16_t i = 0; i < len; i++) {
le[i] = be[len - 1 - i];
}
}
static void uecc_vli_le_to_native(uECC_word_t *native, const uint8_t *le, uint16_t len)
{
uint8_t be[ECC_MAX_PARAM_BYTES];
for (uint16_t i = 0; i < len; i++) {
be[i] = le[len - 1 - i];
}
uECC_vli_bytesToNative(native, be, len);
}
static void esp_tinycrypt_acquire_ecc_hardware(void)
{ {
esp_crypto_ecc_lock_acquire(); esp_crypto_ecc_lock_acquire();
esp_crypto_ecc_enable_periph_clk(true);
ECC_RCC_ATOMIC() {
ecc_ll_enable_bus_clock(true);
ecc_ll_power_up();
ecc_ll_reset_register();
}
} }
static void esp_tinycrypt_release_ecc_hardware(void) static void esp_tinycrypt_release_ecc_hardware(void)
{ {
ECC_RCC_ATOMIC() { esp_crypto_ecc_enable_periph_clk(false);
ecc_ll_enable_bus_clock(false);
ecc_ll_power_down();
}
esp_crypto_ecc_lock_release(); esp_crypto_ecc_lock_release();
} }
#endif /* SOC_ECC_SUPPORTED */
int esp_tinycrypt_verify_ecc_point(const uint8_t *pk_x, const uint8_t *pk_y, uint8_t length) int esp_tinycrypt_verify_ecc_point(const uint8_t *pk_x, const uint8_t *pk_y, uint8_t length)
{ {
#if SOC_ECC_SUPPORTED
int result; int result;
uint8_t px_le[ECC_MAX_PARAM_BYTES];
uint8_t py_le[ECC_MAX_PARAM_BYTES];
uecc_vli_native_to_le(px_le, (const uECC_word_t *)pk_x, length);
uecc_vli_native_to_le(py_le, (const uECC_word_t *)pk_y, length);
esp_tinycrypt_acquire_ecc_hardware(); esp_tinycrypt_acquire_ecc_hardware();
ecc_hal_write_verify_param(pk_x, pk_y, length); ecc_hal_write_verify_param(px_le, py_le, length);
ecc_hal_set_mode(ECC_MODE_VERIFY); ecc_hal_set_mode(ECC_MODE_VERIFY);
ecc_hal_start_calc(); ecc_hal_start_calc();
while (!ecc_hal_is_calc_finished()); while (!ecc_hal_is_calc_finished());
@@ -55,17 +76,40 @@ int esp_tinycrypt_verify_ecc_point(const uint8_t *pk_x, const uint8_t *pk_y, uin
} else { } else {
return -1; return -1;
} }
#else
(void)pk_x;
(void)pk_y;
(void)length;
return -1;
#endif /* SOC_ECC_SUPPORTED */
} }
int esp_tinycrypt_calc_ecc_mult(const uint8_t *p_x, const uint8_t *p_y, const uint8_t *scalar, int esp_tinycrypt_calc_ecc_mult(const uECC_word_t *point_x, const uECC_word_t *point_y,
uint8_t *r_x, uint8_t *r_y, uint8_t num_bytes, bool verify_first) const uECC_word_t *scalar, uECC_word_t *result_x,
uECC_word_t *result_y, uint8_t num_bytes, bool verify_first)
{ {
int ret = -1; #if SOC_ECC_SUPPORTED
int ret;
ecc_mode_t work_mode = verify_first ? ECC_MODE_VERIFY_THEN_POINT_MUL : ECC_MODE_POINT_MUL; ecc_mode_t work_mode = verify_first ? ECC_MODE_VERIFY_THEN_POINT_MUL : ECC_MODE_POINT_MUL;
uint8_t k_le[ECC_MAX_PARAM_BYTES];
uint8_t px_le[ECC_MAX_PARAM_BYTES];
uint8_t py_le[ECC_MAX_PARAM_BYTES];
uint8_t rx_le[ECC_MAX_PARAM_BYTES];
uint8_t ry_le[ECC_MAX_PARAM_BYTES];
memset(k_le, 0, sizeof(k_le));
memset(px_le, 0, sizeof(px_le));
memset(py_le, 0, sizeof(py_le));
memset(rx_le, 0, sizeof(rx_le));
memset(ry_le, 0, sizeof(ry_le));
uecc_vli_native_to_le(k_le, scalar, num_bytes);
uecc_vli_native_to_le(px_le, point_x, num_bytes);
uecc_vli_native_to_le(py_le, point_y, num_bytes);
esp_tinycrypt_acquire_ecc_hardware(); esp_tinycrypt_acquire_ecc_hardware();
ecc_hal_write_mul_param(scalar, p_x, p_y, num_bytes); ecc_hal_write_mul_param(k_le, px_le, py_le, num_bytes);
ecc_hal_set_mode(work_mode); ecc_hal_set_mode(work_mode);
/* /*
* Enable constant-time point multiplication operations for the ECC hardware accelerator, * Enable constant-time point multiplication operations for the ECC hardware accelerator,
@@ -78,10 +122,25 @@ int esp_tinycrypt_calc_ecc_mult(const uint8_t *p_x, const uint8_t *p_y, const ui
while (!ecc_hal_is_calc_finished()); while (!ecc_hal_is_calc_finished());
ret = ecc_hal_read_mul_result(r_x, r_y, num_bytes); ret = ecc_hal_read_mul_result(rx_le, ry_le, num_bytes);
esp_tinycrypt_release_ecc_hardware(); esp_tinycrypt_release_ecc_hardware();
return ret; if (ret != 0) {
} return -1;
}
uecc_vli_le_to_native(result_x, rx_le, num_bytes);
uecc_vli_le_to_native(result_y, ry_le, num_bytes);
return 0;
#else
(void)point_x;
(void)point_y;
(void)scalar;
(void)result_x;
(void)result_y;
(void)num_bytes;
(void)verify_first;
return -1;
#endif /* SOC_ECC_SUPPORTED */ #endif /* SOC_ECC_SUPPORTED */
}
@@ -1,15 +1,20 @@
/* /*
* SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD * SPDX-FileCopyrightText: 2025-2026 Espressif Systems (Shanghai) CO LTD
* *
* SPDX-License-Identifier: Apache-2.0 * SPDX-License-Identifier: Apache-2.0
*/ */
#pragma once
#include <stdint.h> #include <stdint.h>
#include <stdbool.h> #include <stdbool.h>
#include "soc/soc_caps.h" #include "soc/soc_caps.h"
#if SOC_ECC_SUPPORTED #if SOC_ECC_SUPPORTED
#include <tinycrypt/ecc.h>
int esp_tinycrypt_verify_ecc_point(const uint8_t *pk_x, const uint8_t *pk_y, uint8_t length); int esp_tinycrypt_verify_ecc_point(const uint8_t *pk_x, const uint8_t *pk_y, uint8_t length);
int esp_tinycrypt_calc_ecc_mult(const uint8_t *p_x, const uint8_t *p_y, const uint8_t *scalar, int esp_tinycrypt_calc_ecc_mult(const uECC_word_t *point_x, const uECC_word_t *point_y,
uint8_t *r_x, uint8_t *r_y, uint8_t num_bytes, bool verify_first); const uECC_word_t *scalar, uECC_word_t *result_x,
uECC_word_t *result_y, uint8_t num_bytes, bool verify_first);
#endif /* SOC_ECC_SUPPORTED */ #endif /* SOC_ECC_SUPPORTED */
+54 -38
View File
@@ -58,7 +58,6 @@
#include <tinycrypt/ecc.h> #include <tinycrypt/ecc.h>
#include <tinycrypt/ecc_platform_specific.h> #include <tinycrypt/ecc_platform_specific.h>
#include <assert.h>
#include <string.h> #include <string.h>
#include <stdio.h> #include <stdio.h>
@@ -699,7 +698,6 @@ void apply_z(uECC_word_t * X1, uECC_word_t * Y1, const uECC_word_t * const Z,
uECC_vli_modMult_fast(Y1, Y1, t1, curve); /* y1 * z^3 */ uECC_vli_modMult_fast(Y1, Y1, t1, curve); /* y1 * z^3 */
} }
#if !SOC_ECC_SUPPORTED || SOC_ESP_NIMBLE_CONTROLLER
/* P = (x1, y1) => 2P, (x2, y2) => P' */ /* P = (x1, y1) => 2P, (x2, y2) => P' */
static void XYcZ_initial_double(uECC_word_t * X1, uECC_word_t * Y1, static void XYcZ_initial_double(uECC_word_t * X1, uECC_word_t * Y1,
uECC_word_t * X2, uECC_word_t * Y2, uECC_word_t * X2, uECC_word_t * Y2,
@@ -765,7 +763,6 @@ static void XYcZ_addC(uECC_word_t * X1, uECC_word_t * Y1,
uECC_vli_set(X1, t7, num_words); uECC_vli_set(X1, t7, num_words);
} }
#endif /* !SOC_ECC_SUPPORTED */
void XYcZ_add(uECC_word_t * X1, uECC_word_t * Y1, void XYcZ_add(uECC_word_t * X1, uECC_word_t * Y1,
uECC_word_t * X2, uECC_word_t * Y2, uECC_word_t * X2, uECC_word_t * Y2,
@@ -798,20 +795,28 @@ void EccPoint_mult(uECC_word_t * result, const uECC_word_t * point,
const uECC_word_t * initial_Z, const uECC_word_t * initial_Z,
bitcount_t num_bits, uECC_Curve curve) bitcount_t num_bits, uECC_Curve curve)
{ {
#if SOC_ECC_SUPPORTED && !SOC_ESP_NIMBLE_CONTROLLER #if SOC_ECC_SUPPORTED
wordcount_t num_words = curve->num_words; wordcount_t num_words = curve->num_words;
/* Only p256r1 and p192r1 are supported currently. */ /*
assert(curve == uECC_secp256r1() * The ECC peripheral accepts canonical scalars only. Calls using the
* regularized software scalar use one additional bit and must stay on
* the software ladder.
*/
if (initial_Z == 0 && num_bits == curve->num_n_bits &&
(curve == uECC_secp256r1()
#if uECC_SUPPORTS_secp192r1 #if uECC_SUPPORTS_secp192r1
|| curve == uECC_secp192r1() || curve == uECC_secp192r1()
#endif /* #if uECC_SUPPORTS_secp192r1 */ #endif /* uECC_SUPPORTS_secp192r1 */
); )) {
if (esp_tinycrypt_calc_ecc_mult(point, point + num_words, scalar,
esp_tinycrypt_calc_ecc_mult((const uint8_t *)&point[0], (const uint8_t *)&point[num_words], result, result + num_words,
(uint8_t *)scalar, (uint8_t *)&result[0], (uint8_t *)&result[num_words], num_words * uECC_WORD_SIZE, false) == 0) {
num_words * uECC_WORD_SIZE, false); return;
#else }
}
#endif /* SOC_ECC_SUPPORTED */
{
/* R0 and R1 */ /* R0 and R1 */
uECC_word_t Rx[2][NUM_ECC_WORDS]; uECC_word_t Rx[2][NUM_ECC_WORDS];
uECC_word_t Ry[2][NUM_ECC_WORDS]; uECC_word_t Ry[2][NUM_ECC_WORDS];
@@ -850,7 +855,7 @@ void EccPoint_mult(uECC_word_t * result, const uECC_word_t * point,
uECC_vli_set(result, Rx[0], num_words); uECC_vli_set(result, Rx[0], num_words);
uECC_vli_set(result + num_words, Ry[0], num_words); uECC_vli_set(result + num_words, Ry[0], num_words);
#endif /* SOC_ECC_SUPPORTED */ }
} }
uECC_word_t regularize_k(const uECC_word_t * const k, uECC_word_t *k0, uECC_word_t regularize_k(const uECC_word_t * const k, uECC_word_t *k0,
@@ -886,22 +891,33 @@ uECC_word_t EccPoint_compute_public_key(uECC_word_t *result,
uECC_word_t *private_key, uECC_word_t *private_key,
uECC_Curve curve) uECC_Curve curve)
{ {
#if !SOC_ECC_SUPPORTED || SOC_ESP_NIMBLE_CONTROLLER #if SOC_ECC_SUPPORTED
/*
* The ECC peripheral requires a canonical scalar. regularize_k()
* produces k + n or k + 2n for the software constant-time ladder,
* which is mathematically equivalent but outside the HW input range.
*/
if (curve == uECC_secp256r1()
#if uECC_SUPPORTS_secp192r1
|| curve == uECC_secp192r1()
#endif /* uECC_SUPPORTS_secp192r1 */
) {
EccPoint_mult(result, curve->G, private_key, 0,
curve->num_n_bits, curve);
return !EccPoint_isZero(result, curve);
}
#endif /* SOC_ECC_SUPPORTED */
uECC_word_t tmp1[NUM_ECC_WORDS]; uECC_word_t tmp1[NUM_ECC_WORDS];
uECC_word_t tmp2[NUM_ECC_WORDS]; uECC_word_t tmp2[NUM_ECC_WORDS];
uECC_word_t *p2[2] = {tmp1, tmp2}; uECC_word_t *p2[2] = {tmp1, tmp2};
uECC_word_t carry; uECC_word_t carry;
#endif
#if SOC_ECC_SUPPORTED && !SOC_ESP_NIMBLE_CONTROLLER
EccPoint_mult(result, curve->G, private_key, 0, curve->num_n_bits, curve);
#else
/* Regularize the bitcount for the private key so that attackers cannot /* Regularize the bitcount for the private key so that attackers cannot
* use a side channel attack to learn the number of leading zeros. */ * use a side channel attack to learn the number of leading zeros. */
carry = regularize_k(private_key, tmp1, tmp2, curve); carry = regularize_k(private_key, tmp1, tmp2, curve);
EccPoint_mult(result, curve->G, p2[!carry], 0, curve->num_n_bits + 1, curve); EccPoint_mult(result, curve->G, p2[!carry], 0, curve->num_n_bits + 1, curve);
#endif
if (EccPoint_isZero(result, curve)) { if (EccPoint_isZero(result, curve)) {
return 0; return 0;
@@ -974,21 +990,20 @@ int uECC_valid_point(const uECC_word_t *point, uECC_Curve curve)
return -2; return -2;
} }
#if SOC_ECC_SUPPORTED && !SOC_ESP_NIMBLE_CONTROLLER #if SOC_ECC_SUPPORTED
if (curve != uECC_secp256r1() if (curve == uECC_secp256r1()
#if uECC_SUPPORTS_secp192r1 #if uECC_SUPPORTS_secp192r1
&& curve != uECC_secp192r1() || curve == uECC_secp192r1()
#endif /* uECC_SUPPORTS_secp192r1 */ #endif /* uECC_SUPPORTS_secp192r1 */
) { ) {
return -5; if (esp_tinycrypt_verify_ecc_point((const uint8_t *)&point[0],
} (const uint8_t *)&point[num_words],
num_words * uECC_WORD_SIZE) == 0) {
if (esp_tinycrypt_verify_ecc_point((const uint8_t *)&point[0], return 0;
(const uint8_t *)&point[num_words], }
num_words * uECC_WORD_SIZE)) { }
return -3; #endif /* SOC_ECC_SUPPORTED */
} {
#else
uECC_word_t tmp1[NUM_ECC_WORDS]; uECC_word_t tmp1[NUM_ECC_WORDS];
uECC_word_t tmp2[NUM_ECC_WORDS]; uECC_word_t tmp2[NUM_ECC_WORDS];
@@ -996,9 +1011,10 @@ int uECC_valid_point(const uECC_word_t *point, uECC_Curve curve)
curve->x_side(tmp2, point, curve); /* tmp2 = x^3 + ax + b */ curve->x_side(tmp2, point, curve); /* tmp2 = x^3 + ax + b */
/* Make sure that y^2 == x^3 + ax + b */ /* Make sure that y^2 == x^3 + ax + b */
if (uECC_vli_equal(tmp1, tmp2, num_words) != 0) if (uECC_vli_equal(tmp1, tmp2, num_words) != 0) {
return -3; return -3;
#endif /* SOC_ECC_SUPPORTED */ }
}
return 0; return 0;
} }
+5 -10
View File
@@ -147,11 +147,9 @@ int uECC_shared_secret(const uint8_t *public_key, const uint8_t *private_key,
uECC_word_t _private[NUM_ECC_WORDS]; uECC_word_t _private[NUM_ECC_WORDS];
uECC_word_t tmp[NUM_ECC_WORDS]; uECC_word_t tmp[NUM_ECC_WORDS];
#if !SOC_ECC_SUPPORTED || SOC_ESP_NIMBLE_CONTROLLER
uECC_word_t *p2[2] = {_private, tmp}; uECC_word_t *p2[2] = {_private, tmp};
uECC_word_t *initial_Z = 0; uECC_word_t *initial_Z = 0;
uECC_word_t carry; uECC_word_t carry;
#endif
wordcount_t num_words = curve->num_words; wordcount_t num_words = curve->num_words;
wordcount_t num_bytes = curve->num_bytes; wordcount_t num_bytes = curve->num_bytes;
int r; int r;
@@ -167,11 +165,11 @@ int uECC_shared_secret(const uint8_t *public_key, const uint8_t *private_key,
public_key + num_bytes, public_key + num_bytes,
num_bytes); num_bytes);
#if SOC_ECC_SUPPORTED && !SOC_ESP_NIMBLE_CONTROLLER /*
EccPoint_mult(_public, _public, _private, 0, curve->num_n_bits, curve); * Use the software ladder for ECDH. Its regularized scalar is unsuitable
#else * for the ECC peripheral, and EccPoint_mult() can otherwise silently fall
/* Regularize the bitcount for the private key so that attackers cannot use a * back to the software ladder with an unregularized scalar.
* side channel attack to learn the number of leading zeros. */ */
carry = regularize_k(_private, _private, tmp, curve); carry = regularize_k(_private, _private, tmp, curve);
/* If an RNG function was specified, try to get a random initial Z value to /* If an RNG function was specified, try to get a random initial Z value to
@@ -187,17 +185,14 @@ int uECC_shared_secret(const uint8_t *public_key, const uint8_t *private_key,
EccPoint_mult(_public, _public, p2[!carry], initial_Z, curve->num_n_bits + 1, EccPoint_mult(_public, _public, p2[!carry], initial_Z, curve->num_n_bits + 1,
curve); curve);
#endif
uECC_vli_nativeToBytes(secret, num_bytes, _public); uECC_vli_nativeToBytes(secret, num_bytes, _public);
r = !EccPoint_isZero(_public, curve); r = !EccPoint_isZero(_public, curve);
clear_and_out: clear_and_out:
/* erasing temporary buffer used to store secret: */ /* erasing temporary buffer used to store secret: */
#if !SOC_ECC_SUPPORTED || SOC_ESP_NIMBLE_CONTROLLER
memset(p2, 0, sizeof(p2)); memset(p2, 0, sizeof(p2));
__asm__ __volatile__("" :: "g"(p2) : "memory"); __asm__ __volatile__("" :: "g"(p2) : "memory");
#endif
memset(_public, 0, sizeof(_public)); memset(_public, 0, sizeof(_public));
__asm__ __volatile__("" :: "g"(_public) : "memory"); __asm__ __volatile__("" :: "g"(_public) : "memory");
memset(tmp, 0, sizeof(tmp)); memset(tmp, 0, sizeof(tmp));
@@ -101,10 +101,8 @@ int uECC_sign_with_k(const uint8_t *private_key, const uint8_t *message_hash,
uECC_word_t tmp[NUM_ECC_WORDS]; uECC_word_t tmp[NUM_ECC_WORDS];
uECC_word_t s[NUM_ECC_WORDS]; uECC_word_t s[NUM_ECC_WORDS];
#if !SOC_ECC_SUPPORTED || SOC_ESP_NIMBLE_CONTROLLER
uECC_word_t *k2[2] = {tmp, s}; uECC_word_t *k2[2] = {tmp, s};
uECC_word_t carry; uECC_word_t carry;
#endif
uECC_word_t p[NUM_ECC_WORDS * 2]; uECC_word_t p[NUM_ECC_WORDS * 2];
wordcount_t num_words = curve->num_words; wordcount_t num_words = curve->num_words;
wordcount_t num_n_words = BITS_TO_WORDS(curve->num_n_bits); wordcount_t num_n_words = BITS_TO_WORDS(curve->num_n_bits);
@@ -116,12 +114,8 @@ int uECC_sign_with_k(const uint8_t *private_key, const uint8_t *message_hash,
return 0; return 0;
} }
#if SOC_ECC_SUPPORTED && !SOC_ESP_NIMBLE_CONTROLLER
EccPoint_mult(p, curve->G, k, 0, num_n_bits, curve);
#else
carry = regularize_k(k, tmp, s, curve); carry = regularize_k(k, tmp, s, curve);
EccPoint_mult(p, curve->G, k2[!carry], 0, num_n_bits + 1, curve); EccPoint_mult(p, curve->G, k2[!carry], 0, num_n_bits + 1, curve);
#endif
if (uECC_vli_isZero(p, num_words)) { if (uECC_vli_isZero(p, num_words)) {
return 0; return 0;
} }
+4 -7
View File
@@ -575,7 +575,7 @@ config BT_CTRL_CHECK_CONNECT_IND_ACCESS_ADDRESS
config BT_CTRL_BLE_MIN_CONN_INTERVAL_ENABLE config BT_CTRL_BLE_MIN_CONN_INTERVAL_ENABLE
bool "Allow BLE connection interval below the spec minimum" bool "Allow BLE connection interval below the spec minimum"
default y default y
select BT_BLE_HOST_ALLOW_SUB_SPEC_MIN_CONN_INT if BT_BLUEDROID_ENABLED select BT_BLE_HOST_ALLOW_SUB_SPEC_MIN_CONN_INT if BT_BLUEDROID_ENABLED || BT_NIMBLE_ENABLED
help help
Enabling this option allows the BLE controller to use a connection interval Enabling this option allows the BLE controller to use a connection interval
smaller than the Bluetooth Core specification minimum of 7.5 ms. On smaller than the Bluetooth Core specification minimum of 7.5 ms. On
@@ -590,12 +590,9 @@ config BT_CTRL_BLE_MIN_CONN_INTERVAL_ENABLE
This option is enabled by default. Disable it to stay compliant with the BLE This option is enabled by default. Disable it to stay compliant with the BLE
specification (minimum connection interval 7.5 ms). specification (minimum connection interval 7.5 ms).
Host stack: When Bluedroid is the BLE host, enabling this option also selects Host stack: Enabling this option also selects
BT_BLE_HOST_ALLOW_SUB_SPEC_MIN_CONN_INT so the host accepts connection BT_BLE_HOST_ALLOW_SUB_SPEC_MIN_CONN_INT so the active BLE host accepts
intervals below the spec minimum. NimBLE host does not provide equivalent connection intervals below the spec minimum.
support yet; it is planned for a future release. Until then, use Bluedroid
if you need coordinated host and controller behavior for sub-minimum
intervals.
menu "Controller debug log Options (Experimental)" menu "Controller debug log Options (Experimental)"
config BT_CTRL_LE_LOG_EN config BT_CTRL_LE_LOG_EN
@@ -83,6 +83,7 @@ void app_main(void) {
rc = gap_init(); rc = gap_init();
if (rc != 0) { if (rc != 0) {
ESP_LOGE(TAG, "failed to initialize GAP service, error code: %d", rc); ESP_LOGE(TAG, "failed to initialize GAP service, error code: %d", rc);
nimble_port_deinit();
return; return;
} }
#endif #endif
@@ -35,6 +35,9 @@ static void start_advertising(void) {
/* Set device name */ /* Set device name */
name = ble_svc_gap_device_name(); name = ble_svc_gap_device_name();
if (name == NULL) {
name = DEVICE_NAME;
}
adv_fields.name = (uint8_t *)name; adv_fields.name = (uint8_t *)name;
adv_fields.name_len = strlen(name); adv_fields.name_len = strlen(name);
adv_fields.name_is_complete = 1; adv_fields.name_is_complete = 1;
@@ -87,6 +87,7 @@ void app_main(void) {
rc = gap_init(); rc = gap_init();
if (rc != 0) { if (rc != 0) {
ESP_LOGE(TAG, "failed to initialize GAP service, error code: %d", rc); ESP_LOGE(TAG, "failed to initialize GAP service, error code: %d", rc);
nimble_port_deinit();
return; return;
} }
#endif #endif
@@ -1,5 +1,5 @@
/* /*
* SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD * SPDX-FileCopyrightText: 2024-2026 Espressif Systems (Shanghai) CO LTD
* *
* SPDX-License-Identifier: Unlicense OR CC0-1.0 * SPDX-License-Identifier: Unlicense OR CC0-1.0
*/ */
@@ -64,6 +64,9 @@ static void start_advertising(void) {
/* Set device name */ /* Set device name */
name = ble_svc_gap_device_name(); name = ble_svc_gap_device_name();
if (name == NULL) {
name = DEVICE_NAME;
}
adv_fields.name = (uint8_t *)name; adv_fields.name = (uint8_t *)name;
adv_fields.name_len = strlen(name); adv_fields.name_len = strlen(name);
adv_fields.name_is_complete = 1; adv_fields.name_is_complete = 1;
@@ -160,26 +163,29 @@ static int gap_event_handler(struct ble_gap_event *event, void *arg) {
print_conn_desc(&desc); print_conn_desc(&desc);
led_on(); led_on();
/* Try to update connection parameters */ /* Try to update connection parameters.
* BT spec requires: supervision_timeout > (1+latency)*itvl/4
* Ensure the timeout satisfies this constraint when latency=3. */
uint16_t min_timeout = (uint16_t)(((1 + 3) * (uint32_t)desc.conn_itvl) / 4 + 1);
uint16_t supervision_timeout = (desc.supervision_timeout > min_timeout)
? desc.supervision_timeout : min_timeout;
struct ble_gap_upd_params params = {.itvl_min = desc.conn_itvl, struct ble_gap_upd_params params = {.itvl_min = desc.conn_itvl,
.itvl_max = desc.conn_itvl, .itvl_max = desc.conn_itvl,
.latency = 3, .latency = 3,
.supervision_timeout = .supervision_timeout = supervision_timeout};
desc.supervision_timeout};
rc = ble_gap_update_params(event->connect.conn_handle, &params); rc = ble_gap_update_params(event->connect.conn_handle, &params);
if (rc != 0) { if (rc != 0) {
ESP_LOGE( ESP_LOGE(
TAG, TAG,
"failed to update connection parameters, error code: %d", "failed to update connection parameters, error code: %d",
rc); rc);
return rc;
} }
} }
/* Connection failed, restart advertising */ /* Connection failed, restart advertising */
else { else {
start_advertising(); start_advertising();
} }
return rc; return 0;
/* Disconnect event */ /* Disconnect event */
case BLE_GAP_EVENT_DISCONNECT: case BLE_GAP_EVENT_DISCONNECT:
@@ -1,5 +1,5 @@
/* /*
* SPDX-FileCopyrightText: 2024-2025 Espressif Systems (Shanghai) CO LTD * SPDX-FileCopyrightText: 2024-2026 Espressif Systems (Shanghai) CO LTD
* *
* SPDX-License-Identifier: Unlicense OR CC0-1.0 * SPDX-License-Identifier: Unlicense OR CC0-1.0
*/ */
@@ -54,7 +54,7 @@ static void nimble_host_task(void *param) {
nimble_port_run(); nimble_port_run();
/* Clean up at exit */ /* Clean up at exit */
vTaskDelete(NULL); nimble_port_freertos_deinit();
} }
static void heart_rate_task(void *param) { static void heart_rate_task(void *param) {
@@ -114,6 +114,7 @@ void app_main(void) {
rc = gap_init(); rc = gap_init();
if (rc != 0) { if (rc != 0) {
ESP_LOGE(TAG, "failed to initialize GAP service, error code: %d", rc); ESP_LOGE(TAG, "failed to initialize GAP service, error code: %d", rc);
nimble_port_deinit();
return; return;
} }
#endif #endif
@@ -122,6 +123,7 @@ void app_main(void) {
rc = gatt_svc_init(); rc = gatt_svc_init();
if (rc != 0) { if (rc != 0) {
ESP_LOGE(TAG, "failed to initialize GATT server, error code: %d", rc); ESP_LOGE(TAG, "failed to initialize GATT server, error code: %d", rc);
nimble_port_deinit();
return; return;
} }
@@ -129,12 +131,7 @@ void app_main(void) {
nimble_host_config_init(); nimble_host_config_init();
/* Start NimBLE host task thread and return */ /* Start NimBLE host task thread and return */
rc = xTaskCreate(nimble_host_task, "NimBLE Host", 4 * 1024, NULL, nimble_port_freertos_init(nimble_host_task);
5, NULL);
if (rc != pdPASS) {
ESP_LOGE(TAG, "failed to create NimBLE host task");
return;
}
rc = xTaskCreate(heart_rate_task, "Heart Rate", 4 * 1024, NULL, 5, NULL); rc = xTaskCreate(heart_rate_task, "Heart Rate", 4 * 1024, NULL, 5, NULL);
if (rc != pdPASS) { if (rc != pdPASS) {
@@ -1,5 +1,5 @@
/* /*
* SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD * SPDX-FileCopyrightText: 2024-2026 Espressif Systems (Shanghai) CO LTD
* *
* SPDX-License-Identifier: Unlicense OR CC0-1.0 * SPDX-License-Identifier: Unlicense OR CC0-1.0
*/ */
@@ -64,6 +64,9 @@ static void start_advertising(void) {
/* Set device name */ /* Set device name */
name = ble_svc_gap_device_name(); name = ble_svc_gap_device_name();
if (name == NULL) {
name = DEVICE_NAME;
}
adv_fields.name = (uint8_t *)name; adv_fields.name = (uint8_t *)name;
adv_fields.name_len = strlen(name); adv_fields.name_len = strlen(name);
adv_fields.name_is_complete = 1; adv_fields.name_is_complete = 1;
@@ -159,26 +162,29 @@ static int gap_event_handler(struct ble_gap_event *event, void *arg) {
/* Print connection descriptor */ /* Print connection descriptor */
print_conn_desc(&desc); print_conn_desc(&desc);
/* Try to update connection parameters */ /* Try to update connection parameters.
* BT spec requires: supervision_timeout > (1+latency)*itvl/4
* Ensure the timeout satisfies this constraint when latency=3. */
uint16_t min_timeout = (uint16_t)(((1 + 3) * (uint32_t)desc.conn_itvl) / 4 + 1);
uint16_t supervision_timeout = (desc.supervision_timeout > min_timeout)
? desc.supervision_timeout : min_timeout;
struct ble_gap_upd_params params = {.itvl_min = desc.conn_itvl, struct ble_gap_upd_params params = {.itvl_min = desc.conn_itvl,
.itvl_max = desc.conn_itvl, .itvl_max = desc.conn_itvl,
.latency = 3, .latency = 3,
.supervision_timeout = .supervision_timeout = supervision_timeout};
desc.supervision_timeout};
rc = ble_gap_update_params(event->connect.conn_handle, &params); rc = ble_gap_update_params(event->connect.conn_handle, &params);
if (rc != 0) { if (rc != 0) {
ESP_LOGE( ESP_LOGE(
TAG, TAG,
"failed to update connection parameters, error code: %d", "failed to update connection parameters, error code: %d",
rc); rc);
return rc;
} }
} }
/* Connection failed, restart advertising */ /* Connection failed, restart advertising */
else { else {
start_advertising(); start_advertising();
} }
return rc; return 0;
/* Disconnect event */ /* Disconnect event */
case BLE_GAP_EVENT_DISCONNECT: case BLE_GAP_EVENT_DISCONNECT:
@@ -1,5 +1,5 @@
/* /*
* SPDX-FileCopyrightText: 2024-2025 Espressif Systems (Shanghai) CO LTD * SPDX-FileCopyrightText: 2024-2026 Espressif Systems (Shanghai) CO LTD
* *
* SPDX-License-Identifier: Unlicense OR CC0-1.0 * SPDX-License-Identifier: Unlicense OR CC0-1.0
*/ */
@@ -164,9 +164,11 @@ error:
/* Public functions */ /* Public functions */
void send_heart_rate_indication(void) { void send_heart_rate_indication(void) {
if (heart_rate_ind_status && heart_rate_chr_conn_handle_inited) { if (heart_rate_ind_status && heart_rate_chr_conn_handle_inited) {
ble_gatts_indicate(heart_rate_chr_conn_handle, int rc = ble_gatts_indicate(heart_rate_chr_conn_handle,
heart_rate_chr_val_handle); heart_rate_chr_val_handle);
ESP_LOGI(TAG, "heart rate indication sent!"); if (rc != 0) {
ESP_LOGE(TAG, "failed to send heart rate indication, error code: %d", rc);
}
} }
} }
@@ -230,9 +232,13 @@ void gatt_svr_subscribe_cb(struct ble_gap_event *event) {
/* Check attribute handle */ /* Check attribute handle */
if (event->subscribe.attr_handle == heart_rate_chr_val_handle) { if (event->subscribe.attr_handle == heart_rate_chr_val_handle) {
if (event->subscribe.conn_handle == BLE_HS_CONN_HANDLE_NONE) {
return;
}
/* Update heart rate subscription status */ /* Update heart rate subscription status */
heart_rate_chr_conn_handle = event->subscribe.conn_handle; heart_rate_chr_conn_handle = event->subscribe.conn_handle;
heart_rate_chr_conn_handle_inited = true; heart_rate_chr_conn_handle_inited = event->subscribe.cur_indicate;
heart_rate_ind_status = event->subscribe.cur_indicate; heart_rate_ind_status = event->subscribe.cur_indicate;
} }
} }
@@ -15,6 +15,7 @@
#include "host/ble_gap.h" #include "host/ble_gap.h"
/* Public function declarations */ /* Public function declarations */
void gatt_svr_reset_heart_rate_subscription(void);
void send_heart_rate_indication(void); void send_heart_rate_indication(void);
void gatt_svr_register_cb(struct ble_gatt_register_ctxt *ctxt, void *arg); void gatt_svr_register_cb(struct ble_gatt_register_ctxt *ctxt, void *arg);
int gatt_svr_subscribe_cb(struct ble_gap_event *event); int gatt_svr_subscribe_cb(struct ble_gap_event *event);
@@ -1,5 +1,5 @@
/* /*
* SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD * SPDX-FileCopyrightText: 2024-2026 Espressif Systems (Shanghai) CO LTD
* *
* SPDX-License-Identifier: Unlicense OR CC0-1.0 * SPDX-License-Identifier: Unlicense OR CC0-1.0
*/ */
@@ -59,7 +59,7 @@ static void nimble_host_task(void *param) {
nimble_port_run(); nimble_port_run();
/* Clean up at exit */ /* Clean up at exit */
vTaskDelete(NULL); nimble_port_freertos_deinit();
} }
static void heart_rate_task(void *param) { static void heart_rate_task(void *param) {
@@ -123,6 +123,7 @@ void app_main(void) {
rc = gap_init(); rc = gap_init();
if (rc != 0) { if (rc != 0) {
ESP_LOGE(TAG, "failed to initialize GAP service, error code: %d", rc); ESP_LOGE(TAG, "failed to initialize GAP service, error code: %d", rc);
nimble_port_deinit();
return; return;
} }
#endif #endif
@@ -131,6 +132,7 @@ void app_main(void) {
rc = gatt_svc_init(); rc = gatt_svc_init();
if (rc != 0) { if (rc != 0) {
ESP_LOGE(TAG, "failed to initialize GATT server, error code: %d", rc); ESP_LOGE(TAG, "failed to initialize GATT server, error code: %d", rc);
nimble_port_deinit();
return; return;
} }
@@ -138,7 +140,12 @@ void app_main(void) {
nimble_host_config_init(); nimble_host_config_init();
/* Start NimBLE host task thread and return */ /* Start NimBLE host task thread and return */
xTaskCreate(nimble_host_task, "NimBLE Host", 4*1024, NULL, 5, NULL); nimble_port_freertos_init(nimble_host_task);
xTaskCreate(heart_rate_task, "Heart Rate", 4*1024, NULL, 5, NULL);
rc = xTaskCreate(heart_rate_task, "Heart Rate", 4 * 1024, NULL, 5, NULL);
if (rc != pdPASS) {
ESP_LOGE(TAG, "failed to create heart rate task");
return;
}
return; return;
} }
@@ -1,5 +1,5 @@
/* /*
* SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD * SPDX-FileCopyrightText: 2024-2026 Espressif Systems (Shanghai) CO LTD
* *
* SPDX-License-Identifier: Unlicense OR CC0-1.0 * SPDX-License-Identifier: Unlicense OR CC0-1.0
*/ */
@@ -12,7 +12,6 @@
inline static void format_addr(char *addr_str, uint8_t addr[]); inline static void format_addr(char *addr_str, uint8_t addr[]);
static void print_conn_desc(struct ble_gap_conn_desc *desc); static void print_conn_desc(struct ble_gap_conn_desc *desc);
static void start_advertising(void); static void start_advertising(void);
static void set_random_addr(void);
static int gap_event_handler(struct ble_gap_event *event, void *arg); static int gap_event_handler(struct ble_gap_event *event, void *arg);
/* Private variables */ /* Private variables */
@@ -52,20 +51,6 @@ static void print_conn_desc(struct ble_gap_conn_desc *desc) {
desc->sec_state.bonded); desc->sec_state.bonded);
} }
static void set_random_addr(void) {
/* Local variables */
int rc = 0;
ble_addr_t addr;
/* Generate new non-resolvable private address */
rc = ble_hs_id_gen_rnd(0, &addr);
assert(rc == 0);
/* Set address */
rc = ble_hs_id_set_rnd(addr.val);
assert(rc == 0);
}
static void start_advertising(void) { static void start_advertising(void) {
/* Local variables */ /* Local variables */
int rc = 0; int rc = 0;
@@ -79,6 +64,9 @@ static void start_advertising(void) {
/* Set device name */ /* Set device name */
name = ble_svc_gap_device_name(); name = ble_svc_gap_device_name();
if (name == NULL) {
name = DEVICE_NAME;
}
adv_fields.name = (uint8_t *)name; adv_fields.name = (uint8_t *)name;
adv_fields.name_len = strlen(name); adv_fields.name_len = strlen(name);
adv_fields.name_is_complete = 1; adv_fields.name_is_complete = 1;
@@ -201,6 +189,9 @@ static int gap_event_handler(struct ble_gap_event *event, void *arg) {
ESP_LOGI(TAG, "disconnected from peer; reason=%d", ESP_LOGI(TAG, "disconnected from peer; reason=%d",
event->disconnect.reason); event->disconnect.reason);
/* Reset heart rate subscription state */
gatt_svr_reset_heart_rate_subscription();
/* Restart advertising */ /* Restart advertising */
start_advertising(); start_advertising();
return rc; return rc;
@@ -324,8 +315,9 @@ void adv_init(void) {
int rc = 0; int rc = 0;
char addr_str[18] = {0}; char addr_str[18] = {0};
/* Make sure we have proper BT identity address set */ /* Make sure we have proper BT identity address set.
set_random_addr(); * ble_hs_util_ensure_addr(1) safely generates a random address only if
* one is not already set, avoiding conflicts on re-sync events. */
rc = ble_hs_util_ensure_addr(1); rc = ble_hs_util_ensure_addr(1);
if (rc != 0) { if (rc != 0) {
ESP_LOGE(TAG, "device does not have any available bt address!"); ESP_LOGE(TAG, "device does not have any available bt address!");
@@ -1,5 +1,5 @@
/* /*
* SPDX-FileCopyrightText: 2024-2025 Espressif Systems (Shanghai) CO LTD * SPDX-FileCopyrightText: 2024-2026 Espressif Systems (Shanghai) CO LTD
* *
* SPDX-License-Identifier: Unlicense OR CC0-1.0 * SPDX-License-Identifier: Unlicense OR CC0-1.0
*/ */
@@ -24,7 +24,7 @@ static uint8_t heart_rate_chr_val[2] = {0};
static uint16_t heart_rate_chr_val_handle; static uint16_t heart_rate_chr_val_handle;
static const ble_uuid16_t heart_rate_chr_uuid = BLE_UUID16_INIT(0x2A37); static const ble_uuid16_t heart_rate_chr_uuid = BLE_UUID16_INIT(0x2A37);
static uint16_t heart_rate_chr_conn_handle = 0; static uint16_t heart_rate_chr_conn_handle = BLE_HS_CONN_HANDLE_NONE;
static bool heart_rate_chr_conn_handle_inited = false; static bool heart_rate_chr_conn_handle_inited = false;
static bool heart_rate_ind_status = false; static bool heart_rate_ind_status = false;
@@ -165,6 +165,12 @@ error:
} }
/* Public functions */ /* Public functions */
void gatt_svr_reset_heart_rate_subscription(void) {
heart_rate_chr_conn_handle_inited = false;
heart_rate_ind_status = false;
heart_rate_chr_conn_handle = BLE_HS_CONN_HANDLE_NONE;
}
void send_heart_rate_indication(void) { void send_heart_rate_indication(void) {
/* Check if connection handle is initialized */ /* Check if connection handle is initialized */
if (!heart_rate_chr_conn_handle_inited) { if (!heart_rate_chr_conn_handle_inited) {
@@ -230,10 +236,19 @@ void gatt_svr_register_cb(struct ble_gatt_register_ctxt *ctxt, void *arg) {
int gatt_svr_subscribe_cb(struct ble_gap_event *event) { int gatt_svr_subscribe_cb(struct ble_gap_event *event) {
/* Check attribute handle */ /* Check attribute handle */
if (event->subscribe.attr_handle == heart_rate_chr_val_handle) { if (event->subscribe.attr_handle == heart_rate_chr_val_handle) {
if (event->subscribe.conn_handle == BLE_HS_CONN_HANDLE_NONE) {
return 0;
}
if (!event->subscribe.cur_indicate) {
gatt_svr_reset_heart_rate_subscription();
return 0;
}
/* Update heart rate subscription status */ /* Update heart rate subscription status */
heart_rate_chr_conn_handle = event->subscribe.conn_handle; heart_rate_chr_conn_handle = event->subscribe.conn_handle;
heart_rate_chr_conn_handle_inited = true; heart_rate_chr_conn_handle_inited = true;
heart_rate_ind_status = event->subscribe.cur_indicate; heart_rate_ind_status = true;
/* Check security status */ /* Check security status */
if (!is_connection_encrypted(event->subscribe.conn_handle)) { if (!is_connection_encrypted(event->subscribe.conn_handle)) {
@@ -0,0 +1,11 @@
# Override some defaults so BT stack is enabled
# in this example
#
# BT config
#
CONFIG_BT_ENABLED=y
CONFIG_BT_BLUEDROID_ENABLED=n
CONFIG_BT_NIMBLE_ENABLED=y
CONFIG_BT_NIMBLE_NVS_PERSIST=y
CONFIG_BT_NIMBLE_SVC_GAP_APPEARANCE=960
@@ -0,0 +1,4 @@
# ESP32-only BTDM controller mode (classic BT + BLE SoC)
CONFIG_BTDM_CTRL_MODE_BLE_ONLY=y
CONFIG_BTDM_CTRL_MODE_BR_EDR_ONLY=n
CONFIG_BTDM_CTRL_MODE_BTDM=n
@@ -113,7 +113,7 @@ void ble_receive_apple_notification_source(uint8_t *message, uint16_t message_le
uint8_t CategoryID = message[2]; uint8_t CategoryID = message[2];
char *Cidstr = CategoryID_to_String(CategoryID); char *Cidstr = CategoryID_to_String(CategoryID);
uint8_t CategoryCount = message[3]; uint8_t CategoryCount = message[3];
uint32_t NotificationUID = (message[4]) | (message[5]<< 8) | (message[6]<< 16) | (message[7] << 24); uint32_t NotificationUID = ((uint32_t)message[4]) | ((uint32_t)message[5] << 8) | ((uint32_t)message[6] << 16) | ((uint32_t)message[7] << 24);
ESP_LOGI(NimBLE_ANCS_TAG, "EventID:%s EventFlags:0x%x CategoryID:%s CategoryCount:%d NotificationUID:%" PRIu32, EventIDS, EventFlags, Cidstr, CategoryCount, NotificationUID); ESP_LOGI(NimBLE_ANCS_TAG, "EventID:%s EventFlags:0x%x CategoryID:%s CategoryCount:%d NotificationUID:%" PRIu32, EventIDS, EventFlags, Cidstr, CategoryCount, NotificationUID);
} }
@@ -131,14 +131,18 @@ void ble_receive_apple_data_source(uint8_t *message, uint16_t message_len)
message_len); message_len);
return; return;
} }
uint32_t NotificationUID = (message[1]) | (message[2]<< 8) | (message[3]<< 16) | (message[4] << 24); uint32_t NotificationUID = ((uint32_t)message[1]) | ((uint32_t)message[2] << 8) | ((uint32_t)message[3] << 16) | ((uint32_t)message[4] << 24);
uint32_t remain_attr_len = message_len - 5; uint32_t remain_attr_len = message_len - 5;
uint8_t *attrs = &message[5]; uint8_t *attrs = &message[5];
ESP_LOGI(NimBLE_ANCS_TAG, "recevice Notification Attributes response Command_id %d NotificationUID %" PRIu32, Command_id, NotificationUID); ESP_LOGI(NimBLE_ANCS_TAG, "recevice Notification Attributes response Command_id %d NotificationUID %" PRIu32, Command_id, NotificationUID);
while(remain_attr_len > 0) { while(remain_attr_len > 0) {
if (remain_attr_len < 3) {
ESP_LOGE(NimBLE_ANCS_TAG, "incomplete attribute header");
break;
}
uint8_t AttributeID = attrs[0]; uint8_t AttributeID = attrs[0];
uint16_t len = attrs[1] | (attrs[2] << 8); uint16_t len = attrs[1] | (attrs[2] << 8);
if(len > (remain_attr_len -3)) { if(len > (remain_attr_len - 3)) {
ESP_LOGE(NimBLE_ANCS_TAG, "data error"); ESP_LOGE(NimBLE_ANCS_TAG, "data error");
break; break;
} }
+22 -2
View File
@@ -344,7 +344,7 @@ ext_ble_ancs_advertise(void)
params.connectable = 1; params.connectable = 1;
/* advertise using configured addr */ /* advertise using configured addr */
params.own_addr_type = BLE_OWN_ADDR_PUBLIC; params.own_addr_type = own_addr_type;
params.primary_phy = BLE_HCI_LE_PHY_1M; params.primary_phy = BLE_HCI_LE_PHY_1M;
params.secondary_phy = BLE_HCI_LE_PHY_2M; params.secondary_phy = BLE_HCI_LE_PHY_2M;
params.tx_power = 127; params.tx_power = 127;
@@ -413,11 +413,15 @@ ble_ancs_advertise(void)
fields.tx_pwr_lvl_is_present = 1; fields.tx_pwr_lvl_is_present = 1;
fields.tx_pwr_lvl = BLE_HS_ADV_TX_PWR_LVL_AUTO; fields.tx_pwr_lvl = BLE_HS_ADV_TX_PWR_LVL_AUTO;
#if CONFIG_BT_NIMBLE_GAP_SERVICE
name = ble_svc_gap_device_name(); name = ble_svc_gap_device_name();
fields.name = (uint8_t *)name; fields.name = (uint8_t *)name;
fields.name_len = strlen(name); fields.name_len = strlen(name);
fields.name_is_complete = 1; fields.name_is_complete = 1;
#endif
static const ble_uuid16_t adv_uuids16[] = { BLE_UUID16_INIT(0x1811) };
fields.uuids16 = adv_uuids16;
fields.num_uuids16 = 1; fields.num_uuids16 = 1;
fields.uuids16_is_complete = 1; fields.uuids16_is_complete = 1;
@@ -485,6 +489,7 @@ ble_ancs_gap_event(struct ble_gap_event *event, void *arg)
#else #else
ble_ancs_advertise(); ble_ancs_advertise();
#endif #endif
return 0;
} }
/** Initiate security - It will perform /** Initiate security - It will perform
@@ -544,7 +549,11 @@ ble_ancs_gap_event(struct ble_gap_event *event, void *arg)
assert(rc == 0); assert(rc == 0);
ble_ancs_print_conn_desc(&desc); ble_ancs_print_conn_desc(&desc);
MODLOG_DFLT(INFO, "\n"); MODLOG_DFLT(INFO, "\n");
rc = ble_gattc_disc_svc_by_uuid(event->connect.conn_handle, &APPLE_NC_UUID.u, if (event->enc_change.status != 0) {
MODLOG_DFLT(ERROR, "encryption failed; status=%d\n", event->enc_change.status);
return 0;
}
rc = ble_gattc_disc_svc_by_uuid(event->enc_change.conn_handle, &APPLE_NC_UUID.u,
ancs_service_discovered_cb, NULL); ancs_service_discovered_cb, NULL);
if (rc != 0) { if (rc != 0) {
return rc; return rc;
@@ -563,6 +572,10 @@ ble_ancs_gap_event(struct ble_gap_event *event, void *arg)
case BLE_GAP_EVENT_NOTIFY_RX: case BLE_GAP_EVENT_NOTIFY_RX:
/* Peer sent us a notification or indication. */ /* Peer sent us a notification or indication. */
if (event->notify_rx.attr_handle == notification_source_handle) { if (event->notify_rx.attr_handle == notification_source_handle) {
if (event->notify_rx.om == NULL || event->notify_rx.om->om_len < 8) {
MODLOG_DFLT(ERROR, "NOTIFY_RX: short or NULL notification source packet\n");
return 0;
}
ble_receive_apple_notification_source(event->notify_rx.om->om_data, event->notify_rx.om->om_len); ble_receive_apple_notification_source(event->notify_rx.om->om_data, event->notify_rx.om->om_len);
uint8_t *notificationUID = &event->notify_rx.om->om_data[4]; uint8_t *notificationUID = &event->notify_rx.om->om_data[4];
if (event->notify_rx.om->om_data[0] == EventIDNotificationAdded && if (event->notify_rx.om->om_data[0] == EventIDNotificationAdded &&
@@ -773,6 +786,13 @@ app_main(void)
/* XXX Need to have template for store */ /* XXX Need to have template for store */
ble_store_config_init(); ble_store_config_init();
ret = esp_timer_create(&periodic_timer_args, &periodic_timer);
if (ret != ESP_OK) {
ESP_LOGE(tag, "Failed to create periodic timer: %d", ret);
nimble_port_deinit();
return;
}
nimble_port_freertos_init(ble_ancs_host_task); nimble_port_freertos_init(ble_ancs_host_task);
} }
@@ -5,9 +5,6 @@
# BT config # BT config
# #
CONFIG_BT_ENABLED=y CONFIG_BT_ENABLED=y
CONFIG_BTDM_CTRL_MODE_BLE_ONLY=y
CONFIG_BTDM_CTRL_MODE_BR_EDR_ONLY=n
CONFIG_BTDM_CTRL_MODE_BTDM=n
CONFIG_BT_BLUEDROID_ENABLED=n CONFIG_BT_BLUEDROID_ENABLED=n
CONFIG_BT_NIMBLE_ENABLED=y CONFIG_BT_NIMBLE_ENABLED=y
CONFIG_BT_NIMBLE_NVS_PERSIST=y CONFIG_BT_NIMBLE_NVS_PERSIST=y
@@ -0,0 +1,4 @@
# ESP32-only BTDM controller mode (classic BT + BLE SoC)
CONFIG_BTDM_CTRL_MODE_BLE_ONLY=y
CONFIG_BTDM_CTRL_MODE_BR_EDR_ONLY=n
CONFIG_BTDM_CTRL_MODE_BTDM=n
@@ -31,7 +31,8 @@ gatt_svr_init(void)
#if MYNEWT_VAL(BLE_GATTS) #if MYNEWT_VAL(BLE_GATTS)
ble_svc_gatt_init(); ble_svc_gatt_init();
#endif #endif
#if MYNEWT_VAL(BLE_GATTS) && CONFIG_BT_NIMBLE_RAS_SERVICE
ble_svc_ras_init(); ble_svc_ras_init();
#endif
return 0; return 0;
} }
@@ -1,5 +1,5 @@
/* /*
* SPDX-FileCopyrightText: 2021-2025 Espressif Systems (Shanghai) CO LTD * SPDX-FileCopyrightText: 2021-2026 Espressif Systems (Shanghai) CO LTD
* SPDX-License-Identifier: Unlicense OR CC0-1.0 * SPDX-License-Identifier: Unlicense OR CC0-1.0
*/ */
@@ -79,6 +79,10 @@ int blecent_on_subscribe(uint16_t conn_handle,
param.cb_arg=NULL; param.cb_arg=NULL;
ble_cs_initiator_procedure_start(&param); ble_cs_initiator_procedure_start(&param);
} }
} else {
MODLOG_DFLT(ERROR, "Subscription failed; status=%d conn_handle=%d\n",
error->status, conn_handle);
ble_gap_terminate(conn_handle, BLE_ERR_REM_USER_CONN_TERM);
} }
return 0; return 0;
@@ -180,6 +184,7 @@ blecent_on_custom_read(uint16_t conn_handle,
rc = ble_chan_ras_subsribe_by_uuid(BLE_UUID16_DECLARE(BLE_UUID_RAS_REALTIME_RD_VAL), peer, conn_handle); rc = ble_chan_ras_subsribe_by_uuid(BLE_UUID16_DECLARE(BLE_UUID_RAS_REALTIME_RD_VAL), peer, conn_handle);
if (rc != 0) { if (rc != 0) {
MODLOG_DFLT(ERROR, "Error: Peer doesn't support the RAS on demand raging data or fail to subscribe \n"); MODLOG_DFLT(ERROR, "Error: Peer doesn't support the RAS on demand raging data or fail to subscribe \n");
ble_gap_terminate(peer->conn_handle, BLE_ERR_REM_USER_CONN_TERM);
return -1; return -1;
} else { } else {
MODLOG_DFLT(INFO, "Subscribed to the RAS Realtime Ranging Data characteristic\n"); MODLOG_DFLT(INFO, "Subscribed to the RAS Realtime Ranging Data characteristic\n");
@@ -189,6 +194,7 @@ blecent_on_custom_read(uint16_t conn_handle,
rc = ble_chan_ras_subsribe_by_uuid(BLE_UUID16_DECLARE(BLE_UUID_RAS_ONDEMAND_RD_VAL), peer, conn_handle); rc = ble_chan_ras_subsribe_by_uuid(BLE_UUID16_DECLARE(BLE_UUID_RAS_ONDEMAND_RD_VAL), peer, conn_handle);
if (rc != 0) { if (rc != 0) {
MODLOG_DFLT(ERROR, "Error: Peer doesn't support the RAS on demand ranging data or fail to subscribe \n"); MODLOG_DFLT(ERROR, "Error: Peer doesn't support the RAS on demand ranging data or fail to subscribe \n");
ble_gap_terminate(peer->conn_handle, BLE_ERR_REM_USER_CONN_TERM);
return -1; return -1;
} else { } else {
MODLOG_DFLT(INFO, "Subscribed to the RAS On Demand Ranging Data characteristic\n"); MODLOG_DFLT(INFO, "Subscribed to the RAS On Demand Ranging Data characteristic\n");
@@ -197,7 +203,11 @@ blecent_on_custom_read(uint16_t conn_handle,
ble_chan_ras_subscribe(peer, conn_handle); ble_chan_ras_subscribe(peer, conn_handle);
} else if (error->status == BLE_ATT_ERR_INSUFFICIENT_AUTHEN) { } else if (error->status == BLE_ATT_ERR_INSUFFICIENT_AUTHEN) {
MODLOG_DFLT(INFO, "Error: Insufficient authentication to read the characteristic\n"); MODLOG_DFLT(INFO, "Error: Insufficient authentication to read the characteristic\n");
ble_gap_terminate(peer->conn_handle, BLE_ERR_REM_USER_CONN_TERM);
return -1; return -1;
} else {
MODLOG_DFLT(ERROR, "Error: Failed to read RAS Features; status=%d\n", error->status);
ble_gap_terminate(peer->conn_handle, BLE_ERR_REM_USER_CONN_TERM);
} }
return 0; return 0;
} }
@@ -279,6 +289,7 @@ blecent_on_disc_complete(const struct peer *peer, int status, void *arg)
blecent_on_custom_read, (void *)peer); blecent_on_custom_read, (void *)peer);
if (rc != 0) { if (rc != 0) {
MODLOG_DFLT(ERROR, "2 Error: Failed to read the custom subscribable characteristic; ""rc=%d\n", rc); MODLOG_DFLT(ERROR, "2 Error: Failed to read the custom subscribable characteristic; ""rc=%d\n", rc);
ble_gap_terminate(peer->conn_handle, BLE_ERR_REM_USER_CONN_TERM);
} }
} }
@@ -289,7 +300,7 @@ static void
blecent_scan(void) blecent_scan(void)
{ {
uint8_t own_addr_type; uint8_t own_addr_type;
struct ble_gap_disc_params disc_params; struct ble_gap_disc_params disc_params = {0};
int rc; int rc;
/* Figure out address to use while advertising (no privacy for now) */ /* Figure out address to use while advertising (no privacy for now) */
@@ -351,15 +362,17 @@ blecent_connect_if_interesting(void *disc)
adv_data_len = d->length_data; adv_data_len = d->length_data;
#endif #endif
for (int i = 1; i < adv_data_len - 1; i++) { struct ble_hs_adv_fields adv_fields;
if (adv_data[i-1] == 0x03 && adv_data[i] == 0x5b && adv_data[i+1] == 0x18) { if (ble_hs_adv_parse_fields(&adv_fields, adv_data, adv_data_len) == 0) {
found = 1; for (int i = 0; i < adv_fields.num_uuids16; i++) {
MODLOG_DFLT(DEBUG, "Found 0x5b18 at index %d\n", i); if (adv_fields.uuids16[i].value == BLE_UUID_RANGING_SERVICE_VAL) {
break; found = 1;
break;
}
} }
} }
if (!found) { if (!found) {
MODLOG_DFLT(DEBUG, "0x5b18 not found in adv_data, skipping connect.\n"); MODLOG_DFLT(DEBUG, "Ranging Service UUID not found in adv_data, skipping connect.\n");
return; return;
} }
#if !(MYNEWT_VAL(BLE_HOST_ALLOW_CONNECT_WITH_SCAN)) #if !(MYNEWT_VAL(BLE_HOST_ALLOW_CONNECT_WITH_SCAN))
@@ -374,12 +387,18 @@ blecent_connect_if_interesting(void *disc)
rc = ble_hs_id_infer_auto(0, &own_addr_type); rc = ble_hs_id_infer_auto(0, &own_addr_type);
if (rc != 0) { if (rc != 0) {
MODLOG_DFLT(ERROR, "error determining address type; rc=%d\n", rc); MODLOG_DFLT(ERROR, "error determining address type; rc=%d\n", rc);
#if !(MYNEWT_VAL(BLE_HOST_ALLOW_CONNECT_WITH_SCAN))
blecent_scan();
#endif
return; return;
} }
rc = ble_gap_connect(own_addr_type, addr, 30000, NULL, rc = ble_gap_connect(own_addr_type, addr, 30000, NULL,
blecent_gap_event, NULL); blecent_gap_event, NULL);
if (rc != 0) { if (rc != 0) {
MODLOG_DFLT(ERROR, "Connection failed.\n"); MODLOG_DFLT(ERROR, "Connection failed.\n");
#if !(MYNEWT_VAL(BLE_HOST_ALLOW_CONNECT_WITH_SCAN))
blecent_scan();
#endif
return; return;
} }
} }
@@ -577,18 +596,19 @@ blecent_gap_event(struct ble_gap_event *event, void *arg)
rc = ble_gattc_write_no_rsp_flat(event->notify_rx.conn_handle, ble_svc_ras_cp_val_handle, &value, sizeof value); rc = ble_gattc_write_no_rsp_flat(event->notify_rx.conn_handle, ble_svc_ras_cp_val_handle, &value, sizeof value);
} else if( value[0] == RASCP_RSP_OPCODE_RSP_CODE) { } else if( value[0] == RASCP_RSP_OPCODE_RSP_CODE) {
MODLOG_DFLT(INFO, "Sucssefully completed the Ranging procedure\n"); MODLOG_DFLT(INFO, "Sucssefully completed the Ranging procedure\n");
vTaskDelay(1000 / portTICK_PERIOD_MS);
} }
} }
else if(ble_svc_ras_rd_val_handle == event->notify_rx.attr_handle){ else if(ble_svc_ras_rd_val_handle == event->notify_rx.attr_handle){
MODLOG_DFLT(INFO, "Received Ranging Data Ready Indication\n"); MODLOG_DFLT(INFO, "Received Ranging Data Ready Indication\n");
if (OS_MBUF_PKTLEN(event->notify_rx.om) < sizeof(uint16_t)) {
MODLOG_DFLT(ERROR, "Error: Invalid Ranging Data Ready Indication length\n");
return 0;
}
uint16_t ranging_counter; uint16_t ranging_counter;
os_mbuf_copydata(event->notify_rx.om, 0, sizeof(uint16_t), &ranging_counter); os_mbuf_copydata(event->notify_rx.om, 0, sizeof(uint16_t), &ranging_counter);
most_recent_peer_ranging_counter=ranging_counter; most_recent_peer_ranging_counter = ranging_counter;
most_recent_local_ranging_counter= ranging_counter;
if (most_recent_peer_ranging_counter!=most_recent_local_ranging_counter) { if (most_recent_peer_ranging_counter != most_recent_local_ranging_counter) {
MODLOG_DFLT(INFO, "Ranging counter mismatch : %" PRId32 " , %" PRId32, MODLOG_DFLT(INFO, "Ranging counter mismatch : %" PRId32 " , %" PRId32,
most_recent_peer_ranging_counter,most_recent_local_ranging_counter); most_recent_peer_ranging_counter,most_recent_local_ranging_counter);
return 0; return 0;
@@ -5,9 +5,6 @@
# BT config # BT config
# #
CONFIG_BT_ENABLED=y CONFIG_BT_ENABLED=y
CONFIG_BTDM_CTRL_MODE_BLE_ONLY=y
CONFIG_BTDM_CTRL_MODE_BR_EDR_ONLY=n
CONFIG_BTDM_CTRL_MODE_BTDM=n
CONFIG_BT_BLUEDROID_ENABLED=n CONFIG_BT_BLUEDROID_ENABLED=n
CONFIG_BT_CONTROLLER_DISABLED=y CONFIG_BT_CONTROLLER_DISABLED=y
CONFIG_BT_NIMBLE_60_FEATURE_SUPPORT=y CONFIG_BT_NIMBLE_60_FEATURE_SUPPORT=y
@@ -0,0 +1,4 @@
# ESP32-only BTDM controller mode (classic BT + BLE SoC)
CONFIG_BTDM_CTRL_MODE_BLE_ONLY=y
CONFIG_BTDM_CTRL_MODE_BR_EDR_ONLY=n
CONFIG_BTDM_CTRL_MODE_BTDM=n
@@ -31,7 +31,8 @@ custom_gatt_svr_init(void)
#if MYNEWT_VAL(BLE_GATTS) #if MYNEWT_VAL(BLE_GATTS)
ble_svc_gatt_init(); ble_svc_gatt_init();
#endif #endif
#if MYNEWT_VAL(BLE_GATTS) && CONFIG_BT_NIMBLE_RAS_SERVICE
ble_svc_ras_init(); ble_svc_ras_init();
#endif
return 0; return 0;
} }
@@ -71,13 +71,17 @@ void print_cs_event(const struct ble_cs_event *event)
MODLOG_DFLT(INFO, "subev_result.num_antenna_paths = %u\n", event->subev_result.num_antenna_paths); MODLOG_DFLT(INFO, "subev_result.num_antenna_paths = %u\n", event->subev_result.num_antenna_paths);
MODLOG_DFLT(INFO, "subev_result.num_steps_reported = %u\n", event->subev_result.num_steps_reported); MODLOG_DFLT(INFO, "subev_result.num_steps_reported = %u\n", event->subev_result.num_steps_reported);
for (int i = 0; i < event->subev_result.num_steps_reported; i++) { {
const struct cs_steps_data *step = &event->subev_result.steps[i]; const uint8_t *p = (const uint8_t *)event->subev_result.steps;
MODLOG_DFLT(INFO, "steps[%d]: mode=%u, channel=%u, data_len=%u, data=", i, step->mode, step->channel, step->data_len); for (int i = 0; i < event->subev_result.num_steps_reported; i++) {
for (int j = 0; j < step->data_len; j++) { const struct cs_steps_data *step = (const struct cs_steps_data *)p;
esp_rom_printf("%02x ", step->data[j]); MODLOG_DFLT(INFO, "steps[%d]: mode=%u, channel=%u, data_len=%u, data=", i, step->mode, step->channel, step->data_len);
for (int j = 0; j < step->data_len; j++) {
esp_rom_printf("%02x ", step->data[j]);
}
esp_rom_printf("\n");
p += sizeof(struct cs_steps_data) + step->data_len;
} }
esp_rom_printf("\n");
} }
break; break;
case BLE_CS_EVENT_SUBEVET_RESULT_CONTINUE: case BLE_CS_EVENT_SUBEVET_RESULT_CONTINUE:
@@ -89,13 +93,17 @@ void print_cs_event(const struct ble_cs_event *event)
MODLOG_DFLT(INFO, "subev_result_continue.num_antenna_paths = %u\n", event->subev_result_continue.num_antenna_paths); MODLOG_DFLT(INFO, "subev_result_continue.num_antenna_paths = %u\n", event->subev_result_continue.num_antenna_paths);
MODLOG_DFLT(INFO, "subev_result_continue.num_steps_reported = %u\n", event->subev_result_continue.num_steps_reported); MODLOG_DFLT(INFO, "subev_result_continue.num_steps_reported = %u\n", event->subev_result_continue.num_steps_reported);
for (int i = 0; i < event->subev_result_continue.num_steps_reported; i++) { {
const struct cs_steps_data *step = &event->subev_result_continue.steps[i]; const uint8_t *p = (const uint8_t *)event->subev_result_continue.steps;
MODLOG_DFLT(INFO, "steps[%d]: mode=%u, channel=%u, data_len=%u, data=", i, step->mode, step->channel, step->data_len); for (int i = 0; i < event->subev_result_continue.num_steps_reported; i++) {
for (int j = 0; j < step->data_len; j++) { const struct cs_steps_data *step = (const struct cs_steps_data *)p;
esp_rom_printf("%02x ", step->data[j]); MODLOG_DFLT(INFO, "steps[%d]: mode=%u, channel=%u, data_len=%u, data=", i, step->mode, step->channel, step->data_len);
for (int j = 0; j < step->data_len; j++) {
esp_rom_printf("%02x ", step->data[j]);
}
esp_rom_printf("\n");
p += sizeof(struct cs_steps_data) + step->data_len;
} }
esp_rom_printf("\n");
} }
break; break;
@@ -124,6 +132,7 @@ static int blecs_gap_event(struct ble_cs_event *event, void *arg)
if (idx==1) { if (idx==1) {
most_recent_local_ranging_counter=event->subev_result.procedure_counter; most_recent_local_ranging_counter=event->subev_result.procedure_counter;
} }
ble_gatts_store_ranging_data(ranging_subevent);
MODLOG_DFLT(INFO, "LE CS Subevent Result , status: Partial, procedure counter %d\n", event->subev_result.procedure_counter); MODLOG_DFLT(INFO, "LE CS Subevent Result , status: Partial, procedure counter %d\n", event->subev_result.procedure_counter);
} else { } else {
MODLOG_DFLT(INFO, "LE CS Subevent Result , status: Unknown\n"); MODLOG_DFLT(INFO, "LE CS Subevent Result , status: Unknown\n");
@@ -135,16 +144,19 @@ static int blecs_gap_event(struct ble_cs_event *event, void *arg)
MODLOG_DFLT(INFO, "LE CS Subevent Result Continue , status: Aborted\n"); MODLOG_DFLT(INFO, "LE CS Subevent Result Continue , status: Aborted\n");
} else if ( event->subev_result_continue.procedure_done_status == BLE_HCI_LE_CS_SUBEVENT_DONE_STATUS_COMPLETE) { } else if ( event->subev_result_continue.procedure_done_status == BLE_HCI_LE_CS_SUBEVENT_DONE_STATUS_COMPLETE) {
MODLOG_DFLT(INFO, "LE CS Subevent Result Continue , status: Complete\n"); MODLOG_DFLT(INFO, "LE CS Subevent Result Continue , status: Complete\n");
ranging_subevent.type = BLE_CS_EVENT_SUBEVET_RESULT_CONTINUE;
ranging_subevent.subev_result_continue = event->subev_result_continue;
/* To /* To
* Get total number of CS procedure from CS enable event and then accordigly indicate to most recent ranging counter * Get total number of CS procedure from CS enable event and then accordigly indicate to most recent ranging counter
Currently we are considering only one CS procedure Currently we are considering only one CS procedure
*/ */
ind ++; ind ++;
if (ind==1) { if (ind==1) {
ble_gatts_store_ranging_data(ranging_subevent); struct ble_cs_event continue_event;
continue_event.type = BLE_CS_EVENT_SUBEVET_RESULT_CONTINUE;
continue_event.subev_result_continue = event->subev_result_continue;
ble_gatts_store_ranging_data(continue_event);
ble_gatts_indicate_ranging_data_ready(most_recent_local_ranging_counter); ble_gatts_indicate_ranging_data_ready(most_recent_local_ranging_counter);
idx = 0;
ind = 0;
} }
} }
@@ -226,6 +238,9 @@ ext_bleprph_advertise(void)
/* start advertising */ /* start advertising */
rc = ble_gap_ext_adv_start(instance, 0, 0); rc = ble_gap_ext_adv_start(instance, 0, 0);
if (rc != 0) {
MODLOG_DFLT(ERROR, "error starting extended advertisement; rc=%d\n", rc);
}
} }
#else #else
/** /**
@@ -266,9 +281,10 @@ bleprph_advertise(void)
fields.name_len = strlen(name); fields.name_len = strlen(name);
fields.name_is_complete = 1; fields.name_is_complete = 1;
#endif #endif
fields.uuids16 = (ble_uuid16_t[]) { static const ble_uuid16_t uuids16[] = {
BLE_UUID16_INIT(BLE_UUID_RANGING_SERVICE_VAL) BLE_UUID16_INIT(BLE_UUID_RANGING_SERVICE_VAL)
}; };
fields.uuids16 = uuids16;
fields.num_uuids16 = 1; fields.num_uuids16 = 1;
fields.uuids16_is_complete = 1; fields.uuids16_is_complete = 1;
rc = ble_gap_adv_set_fields(&fields); rc = ble_gap_adv_set_fields(&fields);
@@ -335,6 +351,9 @@ bleprph_gap_event(struct ble_gap_event *event, void *arg)
MODLOG_DFLT(INFO, "disconnect; reason=%d ", event->disconnect.reason); MODLOG_DFLT(INFO, "disconnect; reason=%d ", event->disconnect.reason);
bleprph_print_conn_desc(&event->disconnect.conn); bleprph_print_conn_desc(&event->disconnect.conn);
MODLOG_DFLT(INFO, "\n"); MODLOG_DFLT(INFO, "\n");
idx = 0;
ind = 0;
most_recent_local_ranging_counter = -1;
/* Connection terminated; resume advertising. */ /* Connection terminated; resume advertising. */
#if CONFIG_EXAMPLE_EXTENDED_ADV #if CONFIG_EXAMPLE_EXTENDED_ADV
ext_bleprph_advertise(); ext_bleprph_advertise();
@@ -381,7 +400,6 @@ bleprph_gap_event(struct ble_gap_event *event, void *arg)
event->notify_tx.indication); event->notify_tx.indication);
if (event->notify_tx.status == BLE_HS_EDONE) { if (event->notify_tx.status == BLE_HS_EDONE) {
vTaskDelay(4000 / portTICK_PERIOD_MS);
ble_gatts_indicate_control_point_response(event->notify_tx.attr_handle,most_recent_local_ranging_counter); ble_gatts_indicate_control_point_response(event->notify_tx.attr_handle,most_recent_local_ranging_counter);
} }
return 0; return 0;
@@ -409,6 +427,9 @@ static void
bleprph_on_reset(int reason) bleprph_on_reset(int reason)
{ {
MODLOG_DFLT(ERROR, "Resetting state; reason=%d\n", reason); MODLOG_DFLT(ERROR, "Resetting state; reason=%d\n", reason);
idx = 0;
ind = 0;
most_recent_local_ranging_counter = -1;
} }
static void static void
@@ -5,9 +5,6 @@
# BT config # BT config
# #
CONFIG_BT_ENABLED=y CONFIG_BT_ENABLED=y
CONFIG_BTDM_CTRL_MODE_BLE_ONLY=y
CONFIG_BTDM_CTRL_MODE_BR_EDR_ONLY=n
CONFIG_BTDM_CTRL_MODE_BTDM=n
CONFIG_BT_BLUEDROID_ENABLED=n CONFIG_BT_BLUEDROID_ENABLED=n
CONFIG_BT_CONTROLLER_DISABLED=y CONFIG_BT_CONTROLLER_DISABLED=y
CONFIG_BT_NIMBLE_60_FEATURE_SUPPORT=y CONFIG_BT_NIMBLE_60_FEATURE_SUPPORT=y
@@ -0,0 +1,4 @@
# ESP32-only BTDM controller mode (classic BT + BLE SoC)
CONFIG_BTDM_CTRL_MODE_BLE_ONLY=y
CONFIG_BTDM_CTRL_MODE_BR_EDR_ONLY=n
CONFIG_BTDM_CTRL_MODE_BTDM=n
@@ -19,6 +19,11 @@
static const char *TAG = "CTE_ADV_EXAMPLE"; static const char *TAG = "CTE_ADV_EXAMPLE";
static uint8_t s_periodic_adv_raw_data[] = {0x0D, BLE_HS_ADV_TYPE_COMP_NAME, 'C','T','E',' ','P','e','r','i','o','d','i','c'}; static uint8_t s_periodic_adv_raw_data[] = {0x0D, BLE_HS_ADV_TYPE_COMP_NAME, 'C','T','E',' ','P','e','r','i','o','d','i','c'};
#if !(MYNEWT_VAL(BLE_EXT_ADV) && MYNEWT_VAL(BLE_PERIODIC_ADV) && MYNEWT_VAL(BLE_AOA_AOD))
#error "This example requires NimBLE Extended Advertising, Periodic Advertising, and CTE (AoA/AoD). " \
"Use a supported target from README.md (e.g. esp32h2, esp32c5, esp32c61) and run idf.py set-target before build."
#endif
/** /**
* @brief Configure and start periodic advertising with CTE * @brief Configure and start periodic advertising with CTE
*/ */
@@ -49,10 +54,9 @@ static void start_periodic_adv_cte(uint8_t own_addr_type)
assert(rc == 0); assert(rc == 0);
/* Configure advertising data */ /* Configure advertising data */
struct ble_hs_adv_fields adv_fields = { struct ble_hs_adv_fields adv_fields = {0};
.name = (const uint8_t *)"CTE_Periodic_Adv", adv_fields.name = (const uint8_t *)"CTE_Periodic_Adv";
.name_len = strlen((char *)adv_fields.name) adv_fields.name_len = strlen("CTE_Periodic_Adv");
};
struct os_mbuf *data = os_msys_get_pkthdr(BLE_HS_ADV_MAX_FIELD_SZ, 0); struct os_mbuf *data = os_msys_get_pkthdr(BLE_HS_ADV_MAX_FIELD_SZ, 0);
assert(data); assert(data);
@@ -193,7 +197,12 @@ void app_main(void)
ESP_LOGI(TAG, "%s", direction_finding_logo); ESP_LOGI(TAG, "%s", direction_finding_logo);
#if defined(CONFIG_EXAMPLE_ADV_DIRECTION_FINDING_AOD) #if defined(CONFIG_EXAMPLE_ADV_DIRECTION_FINDING_AOD)
ESP_LOGI(TAG, "DIRECTION_FINDING Example Periodic Adv AOD Mode"); ESP_LOGI(TAG, "DIRECTION_FINDING Example Periodic Adv AOD Mode");
ble_direction_finding_antenna_init(antenna_use_gpio,CONFIG_EXAMPLE_ANT_GPIO_BIT_COUNT); rc = ble_direction_finding_antenna_init(antenna_use_gpio, CONFIG_EXAMPLE_ANT_GPIO_BIT_COUNT);
if (rc != 0) {
ESP_LOGE(TAG, "Antenna init failed; rc=%d", rc);
nimble_port_deinit();
return;
}
#elif defined(CONFIG_EXAMPLE_ADV_DIRECTION_FINDING_AOA) #elif defined(CONFIG_EXAMPLE_ADV_DIRECTION_FINDING_AOA)
ESP_LOGI(TAG, "DIRECTION_FINDING Example Periodic Adv AOA Mode"); ESP_LOGI(TAG, "DIRECTION_FINDING Example Periodic Adv AOA Mode");
#endif #endif
@@ -1,7 +1,11 @@
# This file was generated using idf.py save-defconfig. It can be edited manually. # Minimal NimBLE config for periodic advertising with CTE (requires BLE 5.0).
# Espressif IoT Development Framework (ESP-IDF) 5.5.0 Project Minimal Configuration
# #
# Supported targets: ESP32-H2, ESP32-C5, ESP32-C61, etc. (see README.md).
# Run: idf.py set-target <chip> before building.
CONFIG_BT_ENABLED=y CONFIG_BT_ENABLED=y
CONFIG_BT_NIMBLE_ENABLED=y CONFIG_BT_NIMBLE_ENABLED=y
CONFIG_BT_NIMBLE_AOA_AOD=y CONFIG_BT_NIMBLE_50_FEATURE_SUPPORT=y
CONFIG_BT_NIMBLE_EXT_ADV=y CONFIG_BT_NIMBLE_EXT_ADV=y
CONFIG_BT_NIMBLE_ENABLE_PERIODIC_ADV=y
CONFIG_BT_NIMBLE_AOA_AOD=y
@@ -1,5 +1,6 @@
# This file was generated using idf.py save-defconfig. It can be edited manually.
# Espressif IoT Development Framework (ESP-IDF) 5.5.0 Project Minimal Configuration
#
CONFIG_IDF_TARGET="esp32h2" CONFIG_IDF_TARGET="esp32h2"
CONFIG_BT_NIMBLE_SECURITY_ENABLE=n CONFIG_BT_NIMBLE_SECURITY_ENABLE=n
CONFIG_BT_NIMBLE_50_FEATURE_SUPPORT=y
CONFIG_BT_NIMBLE_EXT_ADV=y
CONFIG_BT_NIMBLE_ENABLE_PERIODIC_ADV=y
CONFIG_BT_NIMBLE_AOA_AOD=y
@@ -173,7 +173,7 @@ static int periodic_sync_gap_event(struct ble_gap_event *event, void *arg)
memcpy(dev_name, &adv_data[index + 2], name_len); memcpy(dev_name, &adv_data[index + 2], name_len);
dev_name[name_len] = '\0'; dev_name[name_len] = '\0';
if (strcmp(dev_name, CONFIG_SYNC_TARGET_DEVNAME) == 0) { if (strcmp(dev_name, CONFIG_EXAMPLE_SYNC_TARGET_DEVNAME) == 0) {
should_sync = true; should_sync = true;
break; break;
} }
@@ -184,7 +184,7 @@ static int periodic_sync_gap_event(struct ble_gap_event *event, void *arg)
#else #else
#error "Please select EXAMPLE_SYNC_BY_SID or EXAMPLE_SYNC_BY_NAME in menuconfig" #error "Please select EXAMPLE_SYNC_BY_SID or EXAMPLE_SYNC_BY_NAME in menuconfig"
#endif #endif
if (should_sync) { if (should_sync && disc->periodic_adv_itvl != 0) {
ble_addr_t addr; ble_addr_t addr;
memcpy(&addr, &disc->addr, sizeof(ble_addr_t)); memcpy(&addr, &disc->addr, sizeof(ble_addr_t));
@@ -249,6 +249,7 @@ static int periodic_sync_gap_event(struct ble_gap_event *event, void *arg)
static void periodic_sync_on_reset(int reason) static void periodic_sync_on_reset(int reason)
{ {
ESP_LOGE(TAG, "Resetting state; reason=%d", reason); ESP_LOGE(TAG, "Resetting state; reason=%d", reason);
is_synced = 0;
} }
static void periodic_sync_on_sync(void) static void periodic_sync_on_sync(void)
@@ -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 * SPDX-License-Identifier: Apache-2.0
*/ */
@@ -206,28 +206,17 @@ ext_ble_cts_cent_should_connect(const struct ble_gap_ext_disc_desc *disc)
{ {
int offset = 0; int offset = 0;
int ad_struct_len = 0; int ad_struct_len = 0;
uint8_t test_addr[6]; uint8_t test_addr[6] = {0};
uint32_t peer_addr[6]; if (!(disc->props & BLE_HCI_ADV_CONN_MASK)) {
memset(peer_addr, 0x0, sizeof peer_addr);
if (disc->legacy_event_type != BLE_HCI_ADV_RPT_EVTYPE_ADV_IND &&
disc->legacy_event_type != BLE_HCI_ADV_RPT_EVTYPE_DIR_IND) {
return 0; return 0;
} }
if (strlen(CONFIG_EXAMPLE_PEER_ADDR) && (strncmp(CONFIG_EXAMPLE_PEER_ADDR, "ADDR_ANY", strlen("ADDR_ANY")) != 0)) { if (strlen(CONFIG_EXAMPLE_PEER_ADDR) && (strncmp(CONFIG_EXAMPLE_PEER_ADDR, "ADDR_ANY", strlen("ADDR_ANY")) != 0)) {
ESP_LOGI(tag, "Peer address from menuconfig: %s", CONFIG_EXAMPLE_PEER_ADDR); ESP_LOGI(tag, "Peer address from menuconfig: %s", CONFIG_EXAMPLE_PEER_ADDR);
/* Convert string to address */ /* Convert string to address */
sscanf(CONFIG_EXAMPLE_PEER_ADDR, "%lx:%lx:%lx:%lx:%lx:%lx", if (peer_addr_parse(CONFIG_EXAMPLE_PEER_ADDR, test_addr) != 6) {
&peer_addr[5], &peer_addr[4], &peer_addr[3], return 0;
&peer_addr[2], &peer_addr[1], &peer_addr[0]);
/* Conversion */
for(int i=0; i<6; i++) {
test_addr[i] = (uint8_t )peer_addr[i];
} }
if (memcmp(test_addr, disc->addr.val, sizeof(disc->addr.val)) != 0) { if (memcmp(test_addr, disc->addr.val, sizeof(disc->addr.val)) != 0) {
return 0; return 0;
} }
@@ -236,17 +225,24 @@ ext_ble_cts_cent_should_connect(const struct ble_gap_ext_disc_desc *disc)
/* The device has to advertise support for the CTS /* The device has to advertise support for the CTS
* service (0x1805). * service (0x1805).
*/ */
do { while (offset < disc->length_data) {
if (offset + 1 >= disc->length_data) {
break;
}
ad_struct_len = disc->data[offset]; ad_struct_len = disc->data[offset];
if (!ad_struct_len) { if (!ad_struct_len) {
break; break;
} }
if (offset + ad_struct_len >= disc->length_data) {
break;
}
/* Search if cts UUID is advertised */ /* Search if cts UUID is advertised */
if (disc->data[offset + 1] == 0x03) { if (disc->data[offset + 1] == 0x03) {
int temp = 2; int temp = 2;
while (temp < ad_struct_len) { while (temp < ad_struct_len && (offset + temp + 1) < disc->length_data) {
if(disc->data[offset + temp] == 0x05 && if(disc->data[offset + temp] == 0x05 &&
disc->data[offset + temp + 1] == 0x18) { disc->data[offset + temp + 1] == 0x18) {
return 1; return 1;
@@ -255,7 +251,7 @@ ext_ble_cts_cent_should_connect(const struct ble_gap_ext_disc_desc *disc)
} }
} }
offset += ad_struct_len + 1; offset += ad_struct_len + 1;
} while ( offset < disc->length_data ); }
return 0; return 0;
} }
@@ -267,11 +263,7 @@ ble_cts_cent_should_connect(const struct ble_gap_disc_desc *disc)
struct ble_hs_adv_fields fields; struct ble_hs_adv_fields fields;
int rc; int rc;
int i; int i;
uint8_t test_addr[6]; uint8_t test_addr[6] = {0};
uint32_t peer_addr[6];
memset(peer_addr, 0x0, sizeof peer_addr);
/* The device has to be advertising connectability. */ /* The device has to be advertising connectability. */
if (disc->event_type != BLE_HCI_ADV_RPT_EVTYPE_ADV_IND && if (disc->event_type != BLE_HCI_ADV_RPT_EVTYPE_ADV_IND &&
disc->event_type != BLE_HCI_ADV_RPT_EVTYPE_DIR_IND) { disc->event_type != BLE_HCI_ADV_RPT_EVTYPE_DIR_IND) {
@@ -287,15 +279,9 @@ ble_cts_cent_should_connect(const struct ble_gap_disc_desc *disc)
if (strlen(CONFIG_EXAMPLE_PEER_ADDR) && (strncmp(CONFIG_EXAMPLE_PEER_ADDR, "ADDR_ANY", strlen("ADDR_ANY")) != 0)) { if (strlen(CONFIG_EXAMPLE_PEER_ADDR) && (strncmp(CONFIG_EXAMPLE_PEER_ADDR, "ADDR_ANY", strlen("ADDR_ANY")) != 0)) {
ESP_LOGI(tag, "Peer address from menuconfig: %s", CONFIG_EXAMPLE_PEER_ADDR); ESP_LOGI(tag, "Peer address from menuconfig: %s", CONFIG_EXAMPLE_PEER_ADDR);
/* Convert string to address */ /* Convert string to address */
sscanf(CONFIG_EXAMPLE_PEER_ADDR, "%lx:%lx:%lx:%lx:%lx:%lx", if (peer_addr_parse(CONFIG_EXAMPLE_PEER_ADDR, test_addr) != 6) {
&peer_addr[5], &peer_addr[4], &peer_addr[3], return 0;
&peer_addr[2], &peer_addr[1], &peer_addr[0]); }
/* Conversion */
for (int i=0; i<6; i++) {
test_addr[i] = (uint8_t )peer_addr[i];
}
if (memcmp(test_addr, disc->addr.val, sizeof(disc->addr.val)) != 0) { if (memcmp(test_addr, disc->addr.val, sizeof(disc->addr.val)) != 0) {
return 0; return 0;
} }
@@ -350,6 +336,9 @@ ble_cts_cent_connect_if_interesting(void *disc)
rc = ble_hs_id_infer_auto(0, &own_addr_type); rc = ble_hs_id_infer_auto(0, &own_addr_type);
if (rc != 0) { if (rc != 0) {
MODLOG_DFLT(ERROR, "error determining address type; rc=%d\n", rc); MODLOG_DFLT(ERROR, "error determining address type; rc=%d\n", rc);
#if !(MYNEWT_VAL(BLE_HOST_ALLOW_CONNECT_WITH_SCAN))
ble_cts_cent_scan();
#endif
return; return;
} }
@@ -367,6 +356,9 @@ ble_cts_cent_connect_if_interesting(void *disc)
MODLOG_DFLT(ERROR, "Error: Failed to connect to device; addr_type=%d " MODLOG_DFLT(ERROR, "Error: Failed to connect to device; addr_type=%d "
"addr=%s; rc=%d\n", "addr=%s; rc=%d\n",
addr->type, addr_str(addr->val), rc); addr->type, addr_str(addr->val), rc);
#if !(MYNEWT_VAL(BLE_HOST_ALLOW_CONNECT_WITH_SCAN))
ble_cts_cent_scan();
#endif
return; return;
} }
} }
@@ -389,11 +381,13 @@ static int
ble_cts_cent_gap_event(struct ble_gap_event *event, void *arg) ble_cts_cent_gap_event(struct ble_gap_event *event, void *arg)
{ {
struct ble_gap_conn_desc desc; struct ble_gap_conn_desc desc;
struct ble_hs_adv_fields fields;
int rc; int rc;
switch (event->type) { switch (event->type) {
case BLE_GAP_EVENT_DISC: case BLE_GAP_EVENT_DISC:
#if !CONFIG_EXAMPLE_EXTENDED_ADV
{
struct ble_hs_adv_fields fields;
rc = ble_hs_adv_parse_fields(&fields, event->disc.data, rc = ble_hs_adv_parse_fields(&fields, event->disc.data,
event->disc.length_data); event->disc.length_data);
if (rc != 0) { if (rc != 0) {
@@ -405,6 +399,8 @@ ble_cts_cent_gap_event(struct ble_gap_event *event, void *arg)
/* Try to connect to the advertiser if it looks interesting. */ /* Try to connect to the advertiser if it looks interesting. */
ble_cts_cent_connect_if_interesting(&event->disc); ble_cts_cent_connect_if_interesting(&event->disc);
}
#endif
return 0; return 0;
case BLE_GAP_EVENT_CONNECT: case BLE_GAP_EVENT_CONNECT:
@@ -621,11 +617,14 @@ app_main(void)
/* Initialize data structures to track connected peers. */ /* Initialize data structures to track connected peers. */
#if MYNEWT_VAL(BLE_INCL_SVC_DISCOVERY) || MYNEWT_VAL(BLE_GATT_CACHING_INCLUDE_SERVICES) #if MYNEWT_VAL(BLE_INCL_SVC_DISCOVERY) || MYNEWT_VAL(BLE_GATT_CACHING_INCLUDE_SERVICES)
rc = peer_init(MYNEWT_VAL(BLE_MAX_CONNECTIONS), 64, 64, 64, 64); rc = peer_init(MYNEWT_VAL(BLE_MAX_CONNECTIONS), 64, 64, 64, 64);
assert(rc == 0);
#else #else
rc = peer_init(MYNEWT_VAL(BLE_MAX_CONNECTIONS), 64, 64, 64); rc = peer_init(MYNEWT_VAL(BLE_MAX_CONNECTIONS), 64, 64, 64);
assert(rc == 0);
#endif #endif
if (rc != 0) {
ESP_LOGE(tag, "Failed to init peer tracking; rc=%d", rc);
nimble_port_deinit();
return;
}
#if CONFIG_BT_NIMBLE_GAP_SERVICE #if CONFIG_BT_NIMBLE_GAP_SERVICE
/* Set the default device name. */ /* Set the default device name. */
@@ -5,8 +5,5 @@
# BT config # BT config
# #
CONFIG_BT_ENABLED=y CONFIG_BT_ENABLED=y
CONFIG_BTDM_CTRL_MODE_BLE_ONLY=y
CONFIG_BTDM_CTRL_MODE_BR_EDR_ONLY=n
CONFIG_BTDM_CTRL_MODE_BTDM=n
CONFIG_BT_BLUEDROID_ENABLED=n CONFIG_BT_BLUEDROID_ENABLED=n
CONFIG_BT_NIMBLE_ENABLED=y CONFIG_BT_NIMBLE_ENABLED=y
@@ -5,9 +5,6 @@
# BT config # BT config
# #
CONFIG_BT_ENABLED=y CONFIG_BT_ENABLED=y
CONFIG_BTDM_CTRL_MODE_BLE_ONLY=y
CONFIG_BTDM_CTRL_MODE_BR_EDR_ONLY=n
CONFIG_BTDM_CTRL_MODE_BTDM=n
CONFIG_BT_BLUEDROID_ENABLED=n CONFIG_BT_BLUEDROID_ENABLED=n
CONFIG_BT_NIMBLE_ENABLED=y CONFIG_BT_NIMBLE_ENABLED=y
@@ -0,0 +1,4 @@
# ESP32-only BTDM controller mode (classic BT + BLE SoC)
CONFIG_BTDM_CTRL_MODE_BLE_ONLY=y
CONFIG_BTDM_CTRL_MODE_BR_EDR_ONLY=n
CONFIG_BTDM_CTRL_MODE_BTDM=n
@@ -0,0 +1,4 @@
# ESP32-only BTDM controller mode (classic BT + BLE SoC)
CONFIG_BTDM_CTRL_MODE_BLE_ONLY=y
CONFIG_BTDM_CTRL_MODE_BR_EDR_ONLY=n
CONFIG_BTDM_CTRL_MODE_BTDM=n
@@ -5,9 +5,6 @@
# BT config # BT config
# #
CONFIG_BT_ENABLED=y CONFIG_BT_ENABLED=y
CONFIG_BTDM_CTRL_MODE_BLE_ONLY=y
CONFIG_BTDM_CTRL_MODE_BR_EDR_ONLY=n
CONFIG_BTDM_CTRL_MODE_BTDM=n
CONFIG_BT_BLUEDROID_ENABLED=n CONFIG_BT_BLUEDROID_ENABLED=n
CONFIG_BT_NIMBLE_ENABLED=y CONFIG_BT_NIMBLE_ENABLED=y
CONFIG_BT_NIMBLE_MAX_CONNECTIONS=1 CONFIG_BT_NIMBLE_MAX_CONNECTIONS=1
@@ -68,7 +65,6 @@ CONFIG_ESP_WIFI_ENABLED=n
# Application # Application
CONFIG_APP_COMPILE_TIME_DATE=n CONFIG_APP_COMPILE_TIME_DATE=n
CONFIG_ESP_COEX_SW_COEXIST_ENABLE=n CONFIG_ESP_COEX_SW_COEXIST_ENABLE=n
CONFIG_ESP_ERR_TO_NAME_LOOKUP=n CONFIG_ESP_ERR_TO_NAME_LOOKUP=n
CONFIG_SPI_MASTER_ISR_IN_IRAM=n CONFIG_SPI_MASTER_ISR_IN_IRAM=n
@@ -82,7 +78,6 @@ CONFIG_SPI_FLASH_ENABLE_ENCRYPTED_READ_WRITE=n
#Uncomment below, if security needs to be disabled #Uncomment below, if security needs to be disabled
#CONFIG_BT_NIMBLE_SECURITY_ENABLE=n #CONFIG_BT_NIMBLE_SECURITY_ENABLE=n
#Uncomment below, if logging needs to be disabled #Uncomment below, if logging needs to be disabled
#CONFIG_LOG_DEFAULT_LEVEL_NONE=y #CONFIG_LOG_DEFAULT_LEVEL_NONE=y
#CONFIG_LOG_DEFAULT_LEVEL=0 #CONFIG_LOG_DEFAULT_LEVEL=0
@@ -0,0 +1,4 @@
# ESP32-only BTDM controller mode (classic BT + BLE SoC)
CONFIG_BTDM_CTRL_MODE_BLE_ONLY=y
CONFIG_BTDM_CTRL_MODE_BR_EDR_ONLY=n
CONFIG_BTDM_CTRL_MODE_BTDM=n
@@ -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 * SPDX-License-Identifier: Apache-2.0
*/ */
@@ -71,9 +71,8 @@ int fetch_current_time(struct ble_svc_cts_curr_time *ctime) {
ctime->et_256.d_d_t.d_t.seconds = timeinfo.tm_sec; ctime->et_256.d_d_t.d_t.seconds = timeinfo.tm_sec;
/* day of week */ /* day of week */
/* time gives day range of [0, 6], current_time_sevice /* tm_wday: 0=Sunday..6=Saturday; CTS: 1=Monday..7=Sunday */
has day range of [1,7] */ ctime->et_256.d_d_t.day_of_week = (timeinfo.tm_wday == 0) ? 7 : timeinfo.tm_wday;
ctime->et_256.d_d_t.day_of_week = timeinfo.tm_wday + 1;
/* fractions_256 */ /* fractions_256 */
ctime->et_256.fractions_256 = (((uint64_t)tv_now.tv_usec * 256L )/ 1000000L); ctime->et_256.fractions_256 = (((uint64_t)tv_now.tv_usec * 256L )/ 1000000L);
@@ -108,7 +107,9 @@ int set_current_time(struct ble_svc_cts_curr_time ctime) {
timeinfo.tm_hour = ctime.et_256.d_d_t.d_t.hours; timeinfo.tm_hour = ctime.et_256.d_d_t.d_t.hours;
timeinfo.tm_min = ctime.et_256.d_d_t.d_t.minutes; timeinfo.tm_min = ctime.et_256.d_d_t.d_t.minutes;
timeinfo.tm_sec = ctime.et_256.d_d_t.d_t.seconds; timeinfo.tm_sec = ctime.et_256.d_d_t.d_t.seconds;
timeinfo.tm_wday = ctime.et_256.d_d_t.day_of_week - 1; /* CTS day_of_week: 1=Monday..7=Sunday; tm_wday: 0=Sunday..6=Saturday */
timeinfo.tm_wday = (ctime.et_256.d_d_t.day_of_week == 7) ? 0 : ctime.et_256.d_d_t.day_of_week;
timeinfo.tm_isdst = -1;
now = mktime(&timeinfo); now = mktime(&timeinfo);
if (now == (time_t)-1) { if (now == (time_t)-1) {
ESP_LOGE(TAG, "Failed to convert current time"); ESP_LOGE(TAG, "Failed to convert current time");
@@ -137,6 +138,7 @@ int set_local_time_info(struct ble_svc_cts_local_time_info info) {
local_info.timezone = info.timezone; local_info.timezone = info.timezone;
local_info.dst_offset = info.dst_offset; local_info.dst_offset = info.dst_offset;
gettimeofday(&last_updated, NULL); gettimeofday(&last_updated, NULL);
adjust_reason = (CHANGE_OF_DST_MASK | CHANGE_OF_TIME_ZONE_MASK);
return 0; return 0;
} }
int fetch_reference_time_info(struct ble_svc_cts_reference_time_info *info) { int fetch_reference_time_info(struct ble_svc_cts_reference_time_info *info) {
@@ -160,8 +162,6 @@ int fetch_reference_time_info(struct ble_svc_cts_reference_time_info *info) {
hours_since_update = (tv_now.tv_sec % 86400L) / 3600; hours_since_update = (tv_now.tv_sec % 86400L) / 3600;
info->hours_since_update = hours_since_update; info->hours_since_update = hours_since_update;
} }
adjust_reason = (CHANGE_OF_DST_MASK | CHANGE_OF_TIME_ZONE_MASK);
return 0; return 0;
} }
int int
@@ -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 * SPDX-License-Identifier: Apache-2.0
*/ */
@@ -79,8 +79,8 @@ ext_ble_cts_prph_advertise(void)
/* enable connectable advertising */ /* enable connectable advertising */
params.connectable = 1; params.connectable = 1;
/* advertise using random addr */ /* advertise using configured addr */
params.own_addr_type = BLE_OWN_ADDR_PUBLIC; params.own_addr_type = ble_cts_prph_addr_type;
params.primary_phy = BLE_HCI_LE_PHY_1M; params.primary_phy = BLE_HCI_LE_PHY_1M;
params.secondary_phy = BLE_HCI_LE_PHY_2M; params.secondary_phy = BLE_HCI_LE_PHY_2M;
@@ -148,9 +148,10 @@ ble_cts_prph_advertise(void)
fields.name_len = strlen(device_name); fields.name_len = strlen(device_name);
fields.name_is_complete = 1; fields.name_is_complete = 1;
fields.uuids16 = (ble_uuid16_t[]) { static const ble_uuid16_t adv_uuids16[] = {
BLE_UUID16_INIT(BLE_SVC_CTS_UUID16) BLE_UUID16_INIT(BLE_SVC_CTS_UUID16)
}; };
fields.uuids16 = adv_uuids16;
fields.num_uuids16 = 1; fields.num_uuids16 = 1;
fields.uuids16_is_complete = 1; fields.uuids16_is_complete = 1;
@@ -5,8 +5,5 @@
# BT config # BT config
# #
CONFIG_BT_ENABLED=y CONFIG_BT_ENABLED=y
CONFIG_BTDM_CTRL_MODE_BLE_ONLY=y
CONFIG_BTDM_CTRL_MODE_BR_EDR_ONLY=n
CONFIG_BTDM_CTRL_MODE_BTDM=n
CONFIG_BT_BLUEDROID_ENABLED=n CONFIG_BT_BLUEDROID_ENABLED=n
CONFIG_BT_NIMBLE_ENABLED=y CONFIG_BT_NIMBLE_ENABLED=y
@@ -5,9 +5,6 @@
# BT config # BT config
# #
CONFIG_BT_ENABLED=y CONFIG_BT_ENABLED=y
CONFIG_BTDM_CTRL_MODE_BLE_ONLY=y
CONFIG_BTDM_CTRL_MODE_BR_EDR_ONLY=n
CONFIG_BTDM_CTRL_MODE_BTDM=n
CONFIG_BT_BLUEDROID_ENABLED=n CONFIG_BT_BLUEDROID_ENABLED=n
CONFIG_BT_NIMBLE_ENABLED=y CONFIG_BT_NIMBLE_ENABLED=y
@@ -0,0 +1,4 @@
# ESP32-only BTDM controller mode (classic BT + BLE SoC)
CONFIG_BTDM_CTRL_MODE_BLE_ONLY=y
CONFIG_BTDM_CTRL_MODE_BR_EDR_ONLY=n
CONFIG_BTDM_CTRL_MODE_BTDM=n
@@ -0,0 +1,4 @@
# ESP32-only BTDM controller mode (classic BT + BLE SoC)
CONFIG_BTDM_CTRL_MODE_BLE_ONLY=y
CONFIG_BTDM_CTRL_MODE_BR_EDR_ONLY=n
CONFIG_BTDM_CTRL_MODE_BTDM=n
@@ -5,9 +5,6 @@
# BT config # BT config
# #
CONFIG_BT_ENABLED=y CONFIG_BT_ENABLED=y
CONFIG_BTDM_CTRL_MODE_BLE_ONLY=y
CONFIG_BTDM_CTRL_MODE_BR_EDR_ONLY=n
CONFIG_BTDM_CTRL_MODE_BTDM=n
CONFIG_BT_BLUEDROID_ENABLED=n CONFIG_BT_BLUEDROID_ENABLED=n
CONFIG_BT_NIMBLE_ENABLED=y CONFIG_BT_NIMBLE_ENABLED=y
CONFIG_BT_NIMBLE_MAX_CONNECTIONS=1 CONFIG_BT_NIMBLE_MAX_CONNECTIONS=1
@@ -36,7 +33,6 @@ CONFIG_BT_NIMBLE_SPS_SERVICE=n
CONFIG_BT_NIMBLE_HR_SERVICE=n CONFIG_BT_NIMBLE_HR_SERVICE=n
CONFIG_BT_NIMBLE_DIS_SERVICE=n CONFIG_BT_NIMBLE_DIS_SERVICE=n
CONFIG_BT_ALARM_MAX_NUM=15 CONFIG_BT_ALARM_MAX_NUM=15
CONFIG_BT_NIMBLE_ATT_PREFERRED_MTU=23 CONFIG_BT_NIMBLE_ATT_PREFERRED_MTU=23
@@ -80,7 +76,6 @@ CONFIG_ESP_WIFI_ENABLED=n
# Application # Application
CONFIG_APP_COMPILE_TIME_DATE=n CONFIG_APP_COMPILE_TIME_DATE=n
CONFIG_ESP_COEX_SW_COEXIST_ENABLE=n CONFIG_ESP_COEX_SW_COEXIST_ENABLE=n
CONFIG_ESP_ERR_TO_NAME_LOOKUP=n CONFIG_ESP_ERR_TO_NAME_LOOKUP=n
CONFIG_SPI_MASTER_ISR_IN_IRAM=n CONFIG_SPI_MASTER_ISR_IN_IRAM=n
@@ -94,7 +89,6 @@ CONFIG_SPI_FLASH_ENABLE_ENCRYPTED_READ_WRITE=n
#Uncomment below, if security needs to be disabled #Uncomment below, if security needs to be disabled
#CONFIG_BT_NIMBLE_SECURITY_ENABLE=n #CONFIG_BT_NIMBLE_SECURITY_ENABLE=n
#Uncomment below, if logging needs to be disabled #Uncomment below, if logging needs to be disabled
#CONFIG_LOG_DEFAULT_LEVEL_NONE=y #CONFIG_LOG_DEFAULT_LEVEL_NONE=y
#CONFIG_LOG_DEFAULT_LEVEL=0 #CONFIG_LOG_DEFAULT_LEVEL=0
@@ -0,0 +1,4 @@
# ESP32-only BTDM controller mode (classic BT + BLE SoC)
CONFIG_BTDM_CTRL_MODE_BLE_ONLY=y
CONFIG_BTDM_CTRL_MODE_BR_EDR_ONLY=n
CONFIG_BTDM_CTRL_MODE_BTDM=n
@@ -141,9 +141,11 @@ gatt_svc_access(uint16_t conn_handle, uint16_t attr_handle,
sizeof(gatt_svr_chr_val), sizeof(gatt_svr_chr_val),
sizeof(gatt_svr_chr_val), sizeof(gatt_svr_chr_val),
&gatt_svr_chr_val, NULL); &gatt_svr_chr_val, NULL);
ble_gatts_chr_updated(attr_handle); if (rc == 0) {
MODLOG_DFLT(INFO, "Notification/Indication scheduled for " ble_gatts_chr_updated(attr_handle);
"all subscribed peers.\n"); MODLOG_DFLT(INFO, "Notification/Indication scheduled for "
"all subscribed peers.\n");
}
return rc; return rc;
} }
goto unknown; goto unknown;
@@ -160,7 +162,7 @@ gatt_svc_access(uint16_t conn_handle, uint16_t attr_handle,
if (ble_uuid_cmp(uuid, &gatt_svr_dsc_uuid.u) == 0) { if (ble_uuid_cmp(uuid, &gatt_svr_dsc_uuid.u) == 0) {
rc = os_mbuf_append(ctxt->om, rc = os_mbuf_append(ctxt->om,
&gatt_svr_dsc_val, &gatt_svr_dsc_val,
sizeof(gatt_svr_chr_val)); sizeof(gatt_svr_dsc_val));
return rc == 0 ? 0 : BLE_ATT_ERR_INSUFFICIENT_RES; return rc == 0 ? 0 : BLE_ATT_ERR_INSUFFICIENT_RES;
} }
goto unknown; goto unknown;
@@ -1,5 +1,5 @@
/* /*
* SPDX-FileCopyrightText: 2021-2025 Espressif Systems (Shanghai) CO LTD * SPDX-FileCopyrightText: 2021-2026 Espressif Systems (Shanghai) CO LTD
* *
* SPDX-License-Identifier: Unlicense OR CC0-1.0 * SPDX-License-Identifier: Unlicense OR CC0-1.0
*/ */
@@ -90,9 +90,11 @@ dynamic_service_advertise(void)
fields.name_len = strlen(name); fields.name_len = strlen(name);
fields.name_is_complete = 1; fields.name_is_complete = 1;
fields.uuids16 = (ble_uuid16_t[]) { /* Must be static: ble_gap_adv_set_fields stores the pointer, not the data.
BLE_UUID16_INIT(GATT_SVR_SVC_ALERT_UUID) * A stack compound literal becomes dangling after this function returns,
}; * causing corruption when BLE_NIMBLE_ENABLE_CONN_REATTEMPT re-uses it. */
static const ble_uuid16_t adv_uuids16[] = { BLE_UUID16_INIT(GATT_SVR_SVC_ALERT_UUID) };
fields.uuids16 = adv_uuids16;
fields.num_uuids16 = 1; fields.num_uuids16 = 1;
fields.uuids16_is_complete = 1; fields.uuids16_is_complete = 1;
@@ -143,8 +145,11 @@ dynamic_service_gap_event(struct ble_gap_event *event, void *arg)
event->connect.status); event->connect.status);
if (event->connect.status == 0) { if (event->connect.status == 0) {
rc = ble_gap_conn_find(event->connect.conn_handle, &desc); rc = ble_gap_conn_find(event->connect.conn_handle, &desc);
assert(rc == 0); if (rc != 0) {
dynamic_service_print_conn_desc(&desc); MODLOG_DFLT(ERROR, "Failed to find connection; rc=%d\n", rc);
} else {
dynamic_service_print_conn_desc(&desc);
}
} }
MODLOG_DFLT(INFO, "\n"); MODLOG_DFLT(INFO, "\n");
@@ -282,11 +287,19 @@ app_main(void)
#if MYNEWT_VAL(BLE_GATTS) #if MYNEWT_VAL(BLE_GATTS)
rc = gatt_svr_init(); rc = gatt_svr_init();
assert(rc == 0); if (rc != 0) {
MODLOG_DFLT(ERROR, "Failed to init GATT server; rc=%d\n", rc);
nimble_port_deinit();
return;
}
/* Set the default device name. */ /* Set the default device name. */
rc = ble_svc_gap_device_name_set("ble-dynamic-service"); rc = ble_svc_gap_device_name_set("ble-dynamic-service");
assert(rc == 0); if (rc != 0) {
MODLOG_DFLT(ERROR, "Failed to set device name; rc=%d\n", rc);
nimble_port_deinit();
return;
}
#endif #endif
nimble_port_freertos_init(dynamic_service_host_task); nimble_port_freertos_init(dynamic_service_host_task);
@@ -5,9 +5,6 @@
# BT config # BT config
# #
CONFIG_BT_ENABLED=y CONFIG_BT_ENABLED=y
CONFIG_BTDM_CTRL_MODE_BLE_ONLY=y
CONFIG_BTDM_CTRL_MODE_BR_EDR_ONLY=n
CONFIG_BTDM_CTRL_MODE_BTDM=n
CONFIG_BT_BLUEDROID_ENABLED=n CONFIG_BT_BLUEDROID_ENABLED=n
CONFIG_BT_NIMBLE_ENABLED=y CONFIG_BT_NIMBLE_ENABLED=y
CONFIG_BT_NIMBLE_DYNAMIC_SERVICE=y CONFIG_BT_NIMBLE_DYNAMIC_SERVICE=y
@@ -5,9 +5,6 @@
# BT config # BT config
# #
CONFIG_BT_ENABLED=y CONFIG_BT_ENABLED=y
CONFIG_BTDM_CTRL_MODE_BLE_ONLY=y
CONFIG_BTDM_CTRL_MODE_BR_EDR_ONLY=n
CONFIG_BTDM_CTRL_MODE_BTDM=n
CONFIG_BT_BLUEDROID_ENABLED=n CONFIG_BT_BLUEDROID_ENABLED=n
CONFIG_BT_NIMBLE_ENABLED=y CONFIG_BT_NIMBLE_ENABLED=y
CONFIG_BT_NIMBLE_DYNAMIC_SERVICE=y CONFIG_BT_NIMBLE_DYNAMIC_SERVICE=y
@@ -0,0 +1,4 @@
# ESP32-only BTDM controller mode (classic BT + BLE SoC)
CONFIG_BTDM_CTRL_MODE_BLE_ONLY=y
CONFIG_BTDM_CTRL_MODE_BR_EDR_ONLY=n
CONFIG_BTDM_CTRL_MODE_BTDM=n
@@ -0,0 +1,4 @@
# ESP32-only BTDM controller mode (classic BT + BLE SoC)
CONFIG_BTDM_CTRL_MODE_BLE_ONLY=y
CONFIG_BTDM_CTRL_MODE_BR_EDR_ONLY=n
CONFIG_BTDM_CTRL_MODE_BTDM=n
@@ -5,9 +5,6 @@
# BT config # BT config
# #
CONFIG_BT_ENABLED=y CONFIG_BT_ENABLED=y
CONFIG_BTDM_CTRL_MODE_BLE_ONLY=y
CONFIG_BTDM_CTRL_MODE_BR_EDR_ONLY=n
CONFIG_BTDM_CTRL_MODE_BTDM=n
CONFIG_BT_BLUEDROID_ENABLED=n CONFIG_BT_BLUEDROID_ENABLED=n
CONFIG_BT_NIMBLE_ENABLED=y CONFIG_BT_NIMBLE_ENABLED=y
CONFIG_BT_NIMBLE_DYNAMIC_SERVICE=y CONFIG_BT_NIMBLE_DYNAMIC_SERVICE=y
@@ -38,7 +35,6 @@ CONFIG_BT_NIMBLE_SPS_SERVICE=n
CONFIG_BT_NIMBLE_HR_SERVICE=n CONFIG_BT_NIMBLE_HR_SERVICE=n
CONFIG_BT_NIMBLE_DIS_SERVICE=n CONFIG_BT_NIMBLE_DIS_SERVICE=n
CONFIG_BT_ALARM_MAX_NUM=15 CONFIG_BT_ALARM_MAX_NUM=15
CONFIG_BT_NIMBLE_ATT_PREFERRED_MTU=23 CONFIG_BT_NIMBLE_ATT_PREFERRED_MTU=23
@@ -82,7 +78,6 @@ CONFIG_ESP_WIFI_ENABLED=n
# Application # Application
CONFIG_APP_COMPILE_TIME_DATE=n CONFIG_APP_COMPILE_TIME_DATE=n
CONFIG_ESP_COEX_SW_COEXIST_ENABLE=n CONFIG_ESP_COEX_SW_COEXIST_ENABLE=n
CONFIG_ESP_ERR_TO_NAME_LOOKUP=n CONFIG_ESP_ERR_TO_NAME_LOOKUP=n
CONFIG_SPI_MASTER_ISR_IN_IRAM=n CONFIG_SPI_MASTER_ISR_IN_IRAM=n
@@ -96,7 +91,6 @@ CONFIG_SPI_FLASH_ENABLE_ENCRYPTED_READ_WRITE=n
#Uncomment below, if security needs to be disabled #Uncomment below, if security needs to be disabled
#CONFIG_BT_NIMBLE_SECURITY_ENABLE=n #CONFIG_BT_NIMBLE_SECURITY_ENABLE=n
#Uncomment below, if logging needs to be disabled #Uncomment below, if logging needs to be disabled
#CONFIG_LOG_DEFAULT_LEVEL_NONE=y #CONFIG_LOG_DEFAULT_LEVEL_NONE=y
#CONFIG_LOG_DEFAULT_LEVEL=0 #CONFIG_LOG_DEFAULT_LEVEL=0
@@ -0,0 +1,4 @@
# ESP32-only BTDM controller mode (classic BT + BLE SoC)
CONFIG_BTDM_CTRL_MODE_BLE_ONLY=y
CONFIG_BTDM_CTRL_MODE_BR_EDR_ONLY=n
CONFIG_BTDM_CTRL_MODE_BTDM=n
@@ -78,6 +78,7 @@ enc_adv_data_cent_on_read(uint16_t conn_handle,
{ {
int rc; int rc;
struct ble_store_value_ead value_ead = {0}; struct ble_store_value_ead value_ead = {0};
struct ble_gap_conn_desc desc;
struct peer *p; struct peer *p;
MODLOG_DFLT(INFO, "Read complete; status=%d conn_handle=%d", error->status, MODLOG_DFLT(INFO, "Read complete; status=%d conn_handle=%d", error->status,
@@ -119,6 +120,10 @@ enc_adv_data_cent_on_read(uint16_t conn_handle,
print_bytes(value_ead.km.iv, BLE_EAD_IV_SIZE); print_bytes(value_ead.km.iv, BLE_EAD_IV_SIZE);
memcpy(&value_ead.peer_addr.val, &p->peer_addr, PEER_ADDR_VAL_SIZE); memcpy(&value_ead.peer_addr.val, &p->peer_addr, PEER_ADDR_VAL_SIZE);
rc = ble_gap_conn_find(conn_handle, &desc);
if (rc == 0) {
value_ead.peer_addr.type = desc.peer_id_addr.type;
}
rc = ble_store_write_ead(&value_ead); rc = ble_store_write_ead(&value_ead);
if (rc == 0) { if (rc == 0) {
@@ -184,6 +189,8 @@ enc_adv_data_cent_on_disc_complete(const struct peer *peer, int status, void *ar
if (!enc_adv_data_check_km_exist(peer->peer_addr)) { if (!enc_adv_data_check_km_exist(peer->peer_addr)) {
/* Now perform GATT read procedures against the peer */ /* Now perform GATT read procedures against the peer */
enc_adv_data_cent_read(peer); enc_adv_data_cent_read(peer);
} else {
ble_gap_terminate(peer->conn_handle, BLE_ERR_REM_USER_CONN_TERM);
} }
} }
#endif #endif
@@ -289,7 +296,17 @@ enc_adv_data_cent_decrypt(uint8_t length_data, const uint8_t *data, const uint8_
return 0; return 0;
} }
uint8_t actual_dec_len = enc_payload_len - (BLE_EAD_RANDOMIZER_SIZE + BLE_EAD_MIC_SIZE);
if (actual_dec_len == 0) {
free(enc_data);
return 0;
}
dec_data_len = temp[0]; dec_data_len = temp[0];
if ((uint16_t)dec_data_len + 1 > actual_dec_len) {
MODLOG_DFLT(ERROR, "Decrypted length field exceeds payload");
free(enc_data);
return 0;
}
MODLOG_DFLT(INFO, "Data after decryption:"); MODLOG_DFLT(INFO, "Data after decryption:");
for (int i = 0; i < dec_data_len + 1; i++) { for (int i = 0; i < dec_data_len + 1; i++) {
@@ -318,27 +335,14 @@ enc_adv_data_cent_ext_should_connect(const struct ble_gap_ext_disc_desc *disc)
{ {
int offset = 0; int offset = 0;
int ad_struct_len = 0; int ad_struct_len = 0;
uint8_t test_addr[6]; uint8_t test_addr[6] = {0};
uint32_t peer_addr[6]; if (!(disc->props & BLE_HCI_ADV_CONN_MASK)) {
memset(peer_addr, 0x0, sizeof peer_addr);
if (disc->legacy_event_type != BLE_HCI_ADV_RPT_EVTYPE_ADV_IND &&
disc->legacy_event_type != BLE_HCI_ADV_RPT_EVTYPE_DIR_IND) {
return 0; return 0;
} }
if (strlen(CONFIG_EXAMPLE_PEER_ADDR) && (strncmp(CONFIG_EXAMPLE_PEER_ADDR, "ADDR_ANY", strlen ("ADDR_ANY")) != 0)) { if (strlen(CONFIG_EXAMPLE_PEER_ADDR) && (strncmp(CONFIG_EXAMPLE_PEER_ADDR, "ADDR_ANY", strlen ("ADDR_ANY")) != 0)) {
ESP_LOGI(tag, "Peer address from menuconfig: %s", CONFIG_EXAMPLE_PEER_ADDR); ESP_LOGI(tag, "Peer address from menuconfig: %s", CONFIG_EXAMPLE_PEER_ADDR);
/* Convert string to address */ /* Convert string to address */
sscanf(CONFIG_EXAMPLE_PEER_ADDR, "%lx:%lx:%lx:%lx:%lx:%lx", peer_addr_parse(CONFIG_EXAMPLE_PEER_ADDR, test_addr);
&peer_addr[5], &peer_addr[4], &peer_addr[3],
&peer_addr[2], &peer_addr[1], &peer_addr[0]);
/* Conversion */
for(int i=0; i<6; i++) {
test_addr[i] = (uint8_t )peer_addr[i];
}
if (memcmp(test_addr, disc->addr.val, sizeof(disc->addr.val)) != 0) { if (memcmp(test_addr, disc->addr.val, sizeof(disc->addr.val)) != 0) {
return 0; return 0;
} }
@@ -367,6 +371,7 @@ enc_adv_data_cent_ext_should_connect(const struct ble_gap_ext_disc_desc *disc)
MODLOG_DFLT(INFO, "Adding peer addr : %s", addr_str(&disc->addr.val)); MODLOG_DFLT(INFO, "Adding peer addr : %s", addr_str(&disc->addr.val));
memcpy(&kmp[counter].peer_addr, &disc->addr.val, PEER_ADDR_VAL_SIZE); memcpy(&kmp[counter].peer_addr, &disc->addr.val, PEER_ADDR_VAL_SIZE);
kmp[counter].key_material_exist = false;
counter++; counter++;
if (counter > CONFIG_BT_NIMBLE_MAX_CONNECTIONS) { if (counter > CONFIG_BT_NIMBLE_MAX_CONNECTIONS) {
@@ -394,11 +399,7 @@ enc_adv_data_cent_should_connect(const struct ble_gap_disc_desc *disc)
struct ble_hs_adv_fields fields; struct ble_hs_adv_fields fields;
int rc; int rc;
int i; int i;
uint8_t test_addr[6]; uint8_t test_addr[6] = {0};
uint32_t peer_addr[6];
memset(peer_addr, 0x0, sizeof peer_addr);
if (disc->event_type != BLE_HCI_ADV_RPT_EVTYPE_ADV_IND && if (disc->event_type != BLE_HCI_ADV_RPT_EVTYPE_ADV_IND &&
disc->event_type != BLE_HCI_ADV_RPT_EVTYPE_DIR_IND) { disc->event_type != BLE_HCI_ADV_RPT_EVTYPE_DIR_IND) {
return 0; return 0;
@@ -412,15 +413,7 @@ enc_adv_data_cent_should_connect(const struct ble_gap_disc_desc *disc)
if (strlen(CONFIG_EXAMPLE_PEER_ADDR) && (strncmp(CONFIG_EXAMPLE_PEER_ADDR, "ADDR_ANY", strlen ("ADDR_ANY")) != 0)) { if (strlen(CONFIG_EXAMPLE_PEER_ADDR) && (strncmp(CONFIG_EXAMPLE_PEER_ADDR, "ADDR_ANY", strlen ("ADDR_ANY")) != 0)) {
MODLOG_DFLT(INFO, "Peer address from menuconfig: %s", CONFIG_EXAMPLE_PEER_ADDR); MODLOG_DFLT(INFO, "Peer address from menuconfig: %s", CONFIG_EXAMPLE_PEER_ADDR);
/* Convert string to address */ /* Convert string to address */
sscanf(CONFIG_EXAMPLE_PEER_ADDR, "%lx:%lx:%lx:%lx:%lx:%lx", peer_addr_parse(CONFIG_EXAMPLE_PEER_ADDR, test_addr);
&peer_addr[5], &peer_addr[4], &peer_addr[3],
&peer_addr[2], &peer_addr[1], &peer_addr[0]);
/* Conversion */
for (int i=0; i<6; i++) {
test_addr[i] = (uint8_t )peer_addr[i];
}
if (memcmp(test_addr, disc->addr.val, sizeof(disc->addr.val)) != 0) { if (memcmp(test_addr, disc->addr.val, sizeof(disc->addr.val)) != 0) {
return 0; return 0;
} }
@@ -440,6 +433,7 @@ enc_adv_data_cent_should_connect(const struct ble_gap_disc_desc *disc)
MODLOG_DFLT(INFO, "Adding peer addr : %s", addr_str(&disc->addr.val)); MODLOG_DFLT(INFO, "Adding peer addr : %s", addr_str(&disc->addr.val));
memcpy(&kmp[counter].peer_addr, &disc->addr.val, PEER_ADDR_VAL_SIZE); memcpy(&kmp[counter].peer_addr, &disc->addr.val, PEER_ADDR_VAL_SIZE);
kmp[counter].key_material_exist = false;
counter++; counter++;
if (counter > CONFIG_BT_NIMBLE_MAX_CONNECTIONS) { if (counter > CONFIG_BT_NIMBLE_MAX_CONNECTIONS) {
@@ -494,6 +488,9 @@ enc_adv_data_cent_connect_if_interesting(void *disc)
rc = ble_hs_id_infer_auto(0, &own_addr_type); rc = ble_hs_id_infer_auto(0, &own_addr_type);
if (rc != 0) { if (rc != 0) {
MODLOG_DFLT(ERROR, "error determining address type; rc=%d\n", rc); MODLOG_DFLT(ERROR, "error determining address type; rc=%d\n", rc);
#if !(MYNEWT_VAL(BLE_HOST_ALLOW_CONNECT_WITH_SCAN))
enc_adv_data_cent_scan();
#endif
return; return;
} }
@@ -512,6 +509,9 @@ enc_adv_data_cent_connect_if_interesting(void *disc)
MODLOG_DFLT(ERROR, "Error: Failed to connect to device; addr_type=%d " MODLOG_DFLT(ERROR, "Error: Failed to connect to device; addr_type=%d "
"addr=%s; rc=%d\n", "addr=%s; rc=%d\n",
addr->type, addr_str(addr->val), rc); addr->type, addr_str(addr->val), rc);
#if !(MYNEWT_VAL(BLE_HOST_ALLOW_CONNECT_WITH_SCAN))
enc_adv_data_cent_scan();
#endif
return; return;
} }
} }
@@ -579,12 +579,15 @@ enc_adv_data_cent_gap_event(struct ble_gap_event *event, void *arg)
rc = peer_add(event->connect.conn_handle); rc = peer_add(event->connect.conn_handle);
if (rc != 0) { if (rc != 0) {
MODLOG_DFLT(ERROR, "Failed to add peer; rc=%d\n", rc); MODLOG_DFLT(ERROR, "Failed to add peer; rc=%d\n", rc);
ble_gap_terminate(event->connect.conn_handle, BLE_ERR_REM_USER_CONN_TERM);
return 0; return 0;
} }
rc = peer_set_addr(event->connect.conn_handle, desc.peer_id_addr.val); rc = peer_set_addr(event->connect.conn_handle, desc.peer_id_addr.val);
if (rc != 0) { if (rc != 0) {
MODLOG_DFLT(ERROR, "Failed to set peer addr; rc=%d\n", rc); MODLOG_DFLT(ERROR, "Failed to set peer addr; rc=%d\n", rc);
peer_delete(event->connect.conn_handle);
ble_gap_terminate(event->connect.conn_handle, BLE_ERR_REM_USER_CONN_TERM);
return 0; return 0;
} }
@@ -751,11 +754,14 @@ app_main(void)
/* Initialize data structures to track connected peers. */ /* Initialize data structures to track connected peers. */
#if MYNEWT_VAL(BLE_INCL_SVC_DISCOVERY) || MYNEWT_VAL(BLE_GATT_CACHING_INCLUDE_SERVICES) #if MYNEWT_VAL(BLE_INCL_SVC_DISCOVERY) || MYNEWT_VAL(BLE_GATT_CACHING_INCLUDE_SERVICES)
rc = peer_init(MYNEWT_VAL(BLE_MAX_CONNECTIONS), 64, 64, 64, 64); rc = peer_init(MYNEWT_VAL(BLE_MAX_CONNECTIONS), 64, 64, 64, 64);
assert(rc == 0);
#else #else
rc = peer_init(MYNEWT_VAL(BLE_MAX_CONNECTIONS), 64, 64, 64); rc = peer_init(MYNEWT_VAL(BLE_MAX_CONNECTIONS), 64, 64, 64);
assert(rc == 0);
#endif #endif
if (rc != 0) {
ESP_LOGE(tag, "Failed to init peer tracking; rc=%d", rc);
nimble_port_deinit();
return;
}
#if CONFIG_BT_NIMBLE_GAP_SERVICE #if CONFIG_BT_NIMBLE_GAP_SERVICE
/* Set the default device name. */ /* Set the default device name. */
@@ -5,9 +5,6 @@
# BT config # BT config
# #
CONFIG_BT_ENABLED=y CONFIG_BT_ENABLED=y
CONFIG_BTDM_CTRL_MODE_BLE_ONLY=y
CONFIG_BTDM_CTRL_MODE_BR_EDR_ONLY=n
CONFIG_BTDM_CTRL_MODE_BTDM=n
CONFIG_BT_BLUEDROID_ENABLED=n CONFIG_BT_BLUEDROID_ENABLED=n
CONFIG_BT_NIMBLE_ENABLED=y CONFIG_BT_NIMBLE_ENABLED=y
CONFIG_BT_NIMBLE_EXT_ADV=n CONFIG_BT_NIMBLE_EXT_ADV=n
@@ -5,9 +5,6 @@
# BT config # BT config
# #
CONFIG_BT_ENABLED=y CONFIG_BT_ENABLED=y
CONFIG_BTDM_CTRL_MODE_BLE_ONLY=y
CONFIG_BTDM_CTRL_MODE_BR_EDR_ONLY=n
CONFIG_BTDM_CTRL_MODE_BTDM=n
CONFIG_BT_BLUEDROID_ENABLED=n CONFIG_BT_BLUEDROID_ENABLED=n
CONFIG_BT_NIMBLE_ENABLED=y CONFIG_BT_NIMBLE_ENABLED=y
CONFIG_BT_NIMBLE_EXT_ADV=n CONFIG_BT_NIMBLE_EXT_ADV=n
@@ -0,0 +1,4 @@
# ESP32-only BTDM controller mode (classic BT + BLE SoC)
CONFIG_BTDM_CTRL_MODE_BLE_ONLY=y
CONFIG_BTDM_CTRL_MODE_BR_EDR_ONLY=n
CONFIG_BTDM_CTRL_MODE_BTDM=n
@@ -0,0 +1,4 @@
# ESP32-only BTDM controller mode (classic BT + BLE SoC)
CONFIG_BTDM_CTRL_MODE_BLE_ONLY=y
CONFIG_BTDM_CTRL_MODE_BR_EDR_ONLY=n
CONFIG_BTDM_CTRL_MODE_BTDM=n
@@ -5,9 +5,6 @@
# BT config # BT config
# #
CONFIG_BT_ENABLED=y CONFIG_BT_ENABLED=y
CONFIG_BTDM_CTRL_MODE_BLE_ONLY=y
CONFIG_BTDM_CTRL_MODE_BR_EDR_ONLY=n
CONFIG_BTDM_CTRL_MODE_BTDM=n
CONFIG_BT_BLUEDROID_ENABLED=n CONFIG_BT_BLUEDROID_ENABLED=n
CONFIG_BT_NIMBLE_ENABLED=y CONFIG_BT_NIMBLE_ENABLED=y
CONFIG_BT_NIMBLE_EXT_ADV=n CONFIG_BT_NIMBLE_EXT_ADV=n
@@ -70,7 +67,6 @@ CONFIG_ESP_WIFI_ENABLED=n
# Application # Application
CONFIG_APP_COMPILE_TIME_DATE=n CONFIG_APP_COMPILE_TIME_DATE=n
CONFIG_ESP_COEX_SW_COEXIST_ENABLE=n CONFIG_ESP_COEX_SW_COEXIST_ENABLE=n
CONFIG_ESP_ERR_TO_NAME_LOOKUP=n CONFIG_ESP_ERR_TO_NAME_LOOKUP=n
CONFIG_SPI_MASTER_ISR_IN_IRAM=n CONFIG_SPI_MASTER_ISR_IN_IRAM=n
@@ -84,7 +80,6 @@ CONFIG_SPI_FLASH_ENABLE_ENCRYPTED_READ_WRITE=n
#Uncomment below, if security needs to be disabled #Uncomment below, if security needs to be disabled
#CONFIG_BT_NIMBLE_SECURITY_ENABLE=n #CONFIG_BT_NIMBLE_SECURITY_ENABLE=n
#Uncomment below, if logging needs to be disabled #Uncomment below, if logging needs to be disabled
#CONFIG_LOG_DEFAULT_LEVEL_NONE=y #CONFIG_LOG_DEFAULT_LEVEL_NONE=y
#CONFIG_LOG_DEFAULT_LEVEL=0 #CONFIG_LOG_DEFAULT_LEVEL=0
@@ -0,0 +1,4 @@
# ESP32-only BTDM controller mode (classic BT + BLE SoC)
CONFIG_BTDM_CTRL_MODE_BLE_ONLY=y
CONFIG_BTDM_CTRL_MODE_BR_EDR_ONLY=n
CONFIG_BTDM_CTRL_MODE_BTDM=n
@@ -1,5 +1,5 @@
/* /*
* SPDX-FileCopyrightText: 2021-2023 Espressif Systems (Shanghai) CO LTD * SPDX-FileCopyrightText: 2021-2026 Espressif Systems (Shanghai) CO LTD
* *
* SPDX-License-Identifier: Unlicense OR CC0-1.0 * SPDX-License-Identifier: Unlicense OR CC0-1.0
*/ */
@@ -150,9 +150,11 @@ gatt_svc_access(uint16_t conn_handle, uint16_t attr_handle,
sizeof(gatt_svr_chr_val), sizeof(gatt_svr_chr_val),
sizeof(gatt_svr_chr_val), sizeof(gatt_svr_chr_val),
&gatt_svr_chr_val, NULL); &gatt_svr_chr_val, NULL);
ble_gatts_chr_updated(attr_handle); if (rc == 0) {
MODLOG_DFLT(INFO, "Notification/Indication scheduled for " ble_gatts_chr_updated(attr_handle);
"all subscribed peers.\n"); MODLOG_DFLT(INFO, "Notification/Indication scheduled for "
"all subscribed peers.\n");
}
return rc; return rc;
} }
goto unknown; goto unknown;
@@ -169,7 +171,7 @@ gatt_svc_access(uint16_t conn_handle, uint16_t attr_handle,
if (ble_uuid_cmp(uuid, &gatt_svr_dsc_uuid.u) == 0) { if (ble_uuid_cmp(uuid, &gatt_svr_dsc_uuid.u) == 0) {
rc = os_mbuf_append(ctxt->om, rc = os_mbuf_append(ctxt->om,
&gatt_svr_dsc_val, &gatt_svr_dsc_val,
sizeof(gatt_svr_chr_val)); sizeof(gatt_svr_dsc_val));
return rc == 0 ? 0 : BLE_ATT_ERR_INSUFFICIENT_RES; return rc == 0 ? 0 : BLE_ATT_ERR_INSUFFICIENT_RES;
} }
goto unknown; goto unknown;
@@ -140,8 +140,8 @@ enc_adv_data_prph_ext_advertise(void)
/* enable connectable advertising */ /* enable connectable advertising */
params.connectable = 1; params.connectable = 1;
/* advertise using random addr */ /* advertise using configured addr */
params.own_addr_type = BLE_OWN_ADDR_PUBLIC; params.own_addr_type = own_addr_type;
params.primary_phy = BLE_HCI_LE_PHY_1M; params.primary_phy = BLE_HCI_LE_PHY_1M;
params.secondary_phy = BLE_HCI_LE_PHY_2M; params.secondary_phy = BLE_HCI_LE_PHY_2M;
@@ -163,6 +163,10 @@ enc_adv_data_prph_ext_advertise(void)
/* get mbuf with adv data */ /* get mbuf with adv data */
temp = malloc(sizeof(ext_adv_pattern) + 2 + encrypted_adv_data_len); temp = malloc(sizeof(ext_adv_pattern) + 2 + encrypted_adv_data_len);
if (temp == NULL) {
MODLOG_DFLT(ERROR, "Failed to allocate temp buffer for ext adv data");
return;
}
memcpy(temp, ext_adv_pattern, sizeof(ext_adv_pattern)); memcpy(temp, ext_adv_pattern, sizeof(ext_adv_pattern));
temp[sizeof(ext_adv_pattern)] = 1 + encrypted_adv_data_len; temp[sizeof(ext_adv_pattern)] = 1 + encrypted_adv_data_len;
temp[sizeof(ext_adv_pattern) + 1] = BLE_GAP_ENC_ADV_DATA; temp[sizeof(ext_adv_pattern) + 1] = BLE_GAP_ENC_ADV_DATA;
@@ -194,8 +198,11 @@ enc_adv_data_prph_advertise(void)
struct ble_hs_adv_fields fields; struct ble_hs_adv_fields fields;
int rc; int rc;
const unsigned encrypted_adv_data_len = BLE_EAD_ENCRYPTED_PAYLOAD_SIZE(sizeof(unencrypted_adv_pattern)); static const ble_uuid16_t adv_uuids16[] = {
uint8_t encrypted_adv_data[encrypted_adv_data_len]; BLE_UUID16_INIT(0x2C01) /** For the central to recognise this device */
};
static uint8_t encrypted_adv_data[BLE_EAD_ENCRYPTED_PAYLOAD_SIZE(sizeof(unencrypted_adv_pattern))];
const unsigned encrypted_adv_data_len = sizeof(encrypted_adv_data);
memset(encrypted_adv_data, 0, encrypted_adv_data_len); memset(encrypted_adv_data, 0, encrypted_adv_data_len);
/* First check if any instance is already active */ /* First check if any instance is already active */
@@ -207,8 +214,6 @@ enc_adv_data_prph_advertise(void)
memset (&params, 0, sizeof(params)); memset (&params, 0, sizeof(params));
memset (&fields, 0, sizeof(fields)); memset (&fields, 0, sizeof(fields));
own_addr_type = BLE_OWN_ADDR_PUBLIC;
/* enable connectable advertising */ /* enable connectable advertising */
params.conn_mode = BLE_GAP_CONN_MODE_UND; params.conn_mode = BLE_GAP_CONN_MODE_UND;
params.disc_mode = BLE_GAP_DISC_MODE_GEN; params.disc_mode = BLE_GAP_DISC_MODE_GEN;
@@ -222,9 +227,7 @@ enc_adv_data_prph_advertise(void)
fields.name_len = 3; fields.name_len = 3;
fields.name_is_complete = 1; fields.name_is_complete = 1;
fields.uuids16 = (ble_uuid16_t[]) { fields.uuids16 = adv_uuids16;
BLE_UUID16_INIT(0x2C01) /** For the central to recognise this device */
};
fields.num_uuids16 = 1; fields.num_uuids16 = 1;
fields.uuids16_is_complete = 1; fields.uuids16_is_complete = 1;
@@ -397,17 +400,22 @@ enc_adv_data_prph_on_reset(int reason)
static void static void
ble_app_set_addr(void) ble_app_set_addr(void)
{ {
ble_addr_t addr; ble_addr_t addr = {0};
int rc; int rc;
/* generate new non-resolvable private address */ /* generate new non-resolvable private address */
rc = ble_hs_id_gen_rnd(0, &addr); rc = ble_hs_id_gen_rnd(0, &addr);
assert(rc == 0); if (rc != 0) {
MODLOG_DFLT(ERROR, "Failed to generate random address; rc=%d\n", rc);
return;
}
/* set generated address */ /* set generated address */
rc = ble_hs_id_set_rnd(addr.val); rc = ble_hs_id_set_rnd(addr.val);
if (rc != 0) {
assert(rc == 0); MODLOG_DFLT(ERROR, "Failed to set random address; rc=%d\n", rc);
return;
}
} }
#endif #endif
@@ -5,10 +5,7 @@
# BT config # BT config
# #
CONFIG_BT_ENABLED=y CONFIG_BT_ENABLED=y
CONFIG_BTDM_CTRL_MODE_BLE_ONLY=y
CONFIG_BTDM_CTRL_MODE_BR_EDR_ONLY=n
CONFIG_BTDM_CTRL_MODE_BTDM=n
CONFIG_BT_BLUEDROID_ENABLED=n CONFIG_BT_BLUEDROID_ENABLED=n
CONFIG_BT_NIMBLE_ENABLED=y CONFIG_BT_NIMBLE_ENABLED=y
CONFIG_BT_NIMBLE_HCI_EVT_BUF_SIZE=70 CONFIG_BT_NIMBLE_TRANSPORT_EVT_SIZE=70
CONFIG_BT_NIMBLE_EXT_ADV=n CONFIG_BT_NIMBLE_EXT_ADV=n
@@ -5,9 +5,6 @@
# BT config # BT config
# #
CONFIG_BT_ENABLED=y CONFIG_BT_ENABLED=y
CONFIG_BTDM_CTRL_MODE_BLE_ONLY=y
CONFIG_BTDM_CTRL_MODE_BR_EDR_ONLY=n
CONFIG_BTDM_CTRL_MODE_BTDM=n
CONFIG_BT_BLUEDROID_ENABLED=n CONFIG_BT_BLUEDROID_ENABLED=n
CONFIG_BT_NIMBLE_ENABLED=y CONFIG_BT_NIMBLE_ENABLED=y
CONFIG_BT_NIMBLE_TRANSPORT_EVT_SIZE=70 CONFIG_BT_NIMBLE_TRANSPORT_EVT_SIZE=70
@@ -0,0 +1,4 @@
# ESP32-only BTDM controller mode (classic BT + BLE SoC)
CONFIG_BTDM_CTRL_MODE_BLE_ONLY=y
CONFIG_BTDM_CTRL_MODE_BR_EDR_ONLY=n
CONFIG_BTDM_CTRL_MODE_BTDM=n
@@ -0,0 +1,4 @@
# ESP32-only BTDM controller mode (classic BT + BLE SoC)
CONFIG_BTDM_CTRL_MODE_BLE_ONLY=y
CONFIG_BTDM_CTRL_MODE_BR_EDR_ONLY=n
CONFIG_BTDM_CTRL_MODE_BTDM=n
@@ -5,9 +5,6 @@
# BT config # BT config
# #
CONFIG_BT_ENABLED=y CONFIG_BT_ENABLED=y
CONFIG_BTDM_CTRL_MODE_BLE_ONLY=y
CONFIG_BTDM_CTRL_MODE_BR_EDR_ONLY=n
CONFIG_BTDM_CTRL_MODE_BTDM=n
CONFIG_BT_BLUEDROID_ENABLED=n CONFIG_BT_BLUEDROID_ENABLED=n
CONFIG_BT_NIMBLE_ENABLED=y CONFIG_BT_NIMBLE_ENABLED=y
CONFIG_BT_NIMBLE_EXT_ADV=n CONFIG_BT_NIMBLE_EXT_ADV=n
@@ -39,7 +36,6 @@ CONFIG_BT_NIMBLE_SPS_SERVICE=n
CONFIG_BT_NIMBLE_HR_SERVICE=n CONFIG_BT_NIMBLE_HR_SERVICE=n
CONFIG_BT_NIMBLE_DIS_SERVICE=n CONFIG_BT_NIMBLE_DIS_SERVICE=n
CONFIG_BT_ALARM_MAX_NUM=15 CONFIG_BT_ALARM_MAX_NUM=15
CONFIG_BT_NIMBLE_ATT_PREFERRED_MTU=23 CONFIG_BT_NIMBLE_ATT_PREFERRED_MTU=23
@@ -83,7 +79,6 @@ CONFIG_ESP_WIFI_ENABLED=n
# Application # Application
CONFIG_APP_COMPILE_TIME_DATE=n CONFIG_APP_COMPILE_TIME_DATE=n
CONFIG_ESP_COEX_SW_COEXIST_ENABLE=n CONFIG_ESP_COEX_SW_COEXIST_ENABLE=n
CONFIG_ESP_ERR_TO_NAME_LOOKUP=n CONFIG_ESP_ERR_TO_NAME_LOOKUP=n
CONFIG_SPI_MASTER_ISR_IN_IRAM=n CONFIG_SPI_MASTER_ISR_IN_IRAM=n
@@ -97,7 +92,6 @@ CONFIG_SPI_FLASH_ENABLE_ENCRYPTED_READ_WRITE=n
#Uncomment below, if security needs to be disabled #Uncomment below, if security needs to be disabled
#CONFIG_BT_NIMBLE_SECURITY_ENABLE=n #CONFIG_BT_NIMBLE_SECURITY_ENABLE=n
#Uncomment below, if logging needs to be disabled #Uncomment below, if logging needs to be disabled
#CONFIG_LOG_DEFAULT_LEVEL_NONE=y #CONFIG_LOG_DEFAULT_LEVEL_NONE=y
#CONFIG_LOG_DEFAULT_LEVEL=0 #CONFIG_LOG_DEFAULT_LEVEL=0
@@ -0,0 +1,4 @@
# ESP32-only BTDM controller mode (classic BT + BLE SoC)
CONFIG_BTDM_CTRL_MODE_BLE_ONLY=y
CONFIG_BTDM_CTRL_MODE_BR_EDR_ONLY=n
CONFIG_BTDM_CTRL_MODE_BTDM=n
@@ -17,16 +17,16 @@ static uint8_t own_addr_type;
static int blecoex_gap_event(struct ble_gap_event *event, void *arg); static int blecoex_gap_event(struct ble_gap_event *event, void *arg);
void ble_coex_advertise(void); void ble_coex_advertise(void);
void ble_coex_scan(void); void ble_coex_scan(void);
static bool client_connect = 0; static uint8_t client_connect = 0;
static int gatt_svr_access_cb(uint16_t conn_handle, uint16_t attr_handle, static int gatt_svr_access_cb(uint16_t conn_handle, uint16_t attr_handle,
struct ble_gatt_access_ctxt *ctxt, void *arg) { struct ble_gatt_access_ctxt *ctxt, void *arg) {
int rc = 0; int rc = 0;
if (ctxt->op == BLE_GATT_ACCESS_OP_READ_CHR) { if (ctxt->op == BLE_GATT_ACCESS_OP_READ_CHR) {
static uint8_t data[1] = {42}; // Example value static uint8_t data[1] = {42}; // Example value
os_mbuf_append(ctxt->om, data, sizeof(data)); rc = os_mbuf_append(ctxt->om, data, sizeof(data));
if (rc != 0) { if (rc != 0) {
return rc; return BLE_ATT_ERR_INSUFFICIENT_RES;
} }
} else if (ctxt->op == BLE_GATT_ACCESS_OP_READ_DSC) { } else if (ctxt->op == BLE_GATT_ACCESS_OP_READ_DSC) {
static uint8_t dsc_data[1] = {0x01}; // Example descriptor value static uint8_t dsc_data[1] = {0x01}; // Example descriptor value
@@ -192,6 +192,10 @@ blecent_on_write(uint16_t conn_handle,
uint8_t value[2]; uint8_t value[2];
int rc; int rc;
const struct peer *peer = peer_find(conn_handle); const struct peer *peer = peer_find(conn_handle);
if (peer == NULL) {
MODLOG_DFLT(ERROR, "Peer not found for conn_handle=%d\n", conn_handle);
return ble_gap_terminate(conn_handle, BLE_ERR_REM_USER_CONN_TERM);
}
dsc = peer_dsc_find_uuid(peer, dsc = peer_dsc_find_uuid(peer,
BLE_UUID16_DECLARE(BLECOEX_SVC_ALERT_UUID), BLE_UUID16_DECLARE(BLECOEX_SVC_ALERT_UUID),
@@ -216,7 +220,7 @@ blecent_on_write(uint16_t conn_handle,
return 0; return 0;
err: err:
/* Terminate the connection. */ /* Terminate the connection. */
return ble_gap_terminate(peer->conn_handle, BLE_ERR_REM_USER_CONN_TERM); return ble_gap_terminate(conn_handle, BLE_ERR_REM_USER_CONN_TERM);
} }
@@ -241,6 +245,10 @@ blecent_on_read(uint16_t conn_handle,
uint8_t value[2]; uint8_t value[2];
int rc; int rc;
const struct peer *peer = peer_find(conn_handle); const struct peer *peer = peer_find(conn_handle);
if (peer == NULL) {
MODLOG_DFLT(ERROR, "Peer not found for conn_handle=%d\n", conn_handle);
return ble_gap_terminate(conn_handle, BLE_ERR_REM_USER_CONN_TERM);
}
chr = peer_chr_find_uuid(peer, chr = peer_chr_find_uuid(peer,
BLE_UUID16_DECLARE(BLECOEX_SVC_ALERT_UUID), BLE_UUID16_DECLARE(BLECOEX_SVC_ALERT_UUID),
@@ -263,7 +271,7 @@ blecent_on_read(uint16_t conn_handle,
return 0; return 0;
err: err:
/* Terminate the connection. */ /* Terminate the connection. */
return ble_gap_terminate(peer->conn_handle, BLE_ERR_REM_USER_CONN_TERM); return ble_gap_terminate(conn_handle, BLE_ERR_REM_USER_CONN_TERM);
} }
@@ -369,23 +377,40 @@ blecoex_gap_event(struct ble_gap_event *event, void *arg)
MODLOG_DFLT(INFO, "%02x:%02x:%02x:%02x:%02x:%02x", MODLOG_DFLT(INFO, "%02x:%02x:%02x:%02x:%02x:%02x",
u8p[5], u8p[4], u8p[3], u8p[2], u8p[1], u8p[0]); u8p[5], u8p[4], u8p[3], u8p[2], u8p[1], u8p[0]);
} if (client_connect == 1) {
client_connect = 2;
if (client_connect == 1 ) { /* Remember peer. */
client_connect = 2; rc = peer_add(event->connect.conn_handle);
if (rc != 0) {
MODLOG_DFLT(ERROR, "Failed to add peer; rc=%d\n", rc);
rc = ble_gap_terminate(event->connect.conn_handle,
BLE_ERR_REM_USER_CONN_TERM);
if (rc != 0) {
MODLOG_DFLT(ERROR, "Failed to terminate connection; rc=%d\n", rc);
restart_coex();
}
return 0;
}
/* Remember peer. */ /* Perform service discovery */
rc = peer_add(event->connect.conn_handle); rc = peer_disc_all(event->connect.conn_handle,
if (rc != 0) { blecent_on_disc_complete, NULL);
MODLOG_DFLT(ERROR, "Failed to add peer; rc=%d\n", rc); if(rc != 0) {
restart_coex(); MODLOG_DFLT(ERROR, "Failed to discover services; rc=%d\n", rc);
peer_delete(event->connect.conn_handle);
rc = ble_gap_terminate(event->connect.conn_handle,
BLE_ERR_REM_USER_CONN_TERM);
if (rc != 0) {
MODLOG_DFLT(ERROR, "Failed to terminate connection; rc=%d\n", rc);
restart_coex();
}
return 0;
}
} }
} else {
/* Perform service discovery */ if (client_connect == 1) {
rc = peer_disc_all(event->connect.conn_handle, MODLOG_DFLT(ERROR, "Client connection failed; status=%d\n", event->connect.status);
blecent_on_disc_complete, NULL);
if(rc != 0) {
MODLOG_DFLT(ERROR, "Failed to discover services; rc=%d\n", rc);
restart_coex(); restart_coex();
} }
} }
@@ -393,6 +418,7 @@ blecoex_gap_event(struct ble_gap_event *event, void *arg)
case BLE_GAP_EVENT_DISCONNECT: case BLE_GAP_EVENT_DISCONNECT:
MODLOG_DFLT(INFO, "Disconnect \n"); MODLOG_DFLT(INFO, "Disconnect \n");
peer_delete(event->disconnect.conn.conn_handle);
restart_coex(); restart_coex();
return 0; return 0;
@@ -497,9 +523,10 @@ ble_coex_advertise(void)
fields.name_is_complete = 1; fields.name_is_complete = 1;
} }
fields.uuids16 = (ble_uuid16_t[]) { static const ble_uuid16_t adv_uuids16[] = {
BLE_UUID16_INIT(BLECOEX_SVC_ALERT_UUID) BLE_UUID16_INIT(BLECOEX_SVC_ALERT_UUID)
}; };
fields.uuids16 = adv_uuids16;
fields.num_uuids16 = 1; fields.num_uuids16 = 1;
fields.uuids16_is_complete = 1; fields.uuids16_is_complete = 1;
@@ -569,11 +596,17 @@ void app_main(void)
} }
ble_hs_cfg.sync_cb = on_sync; ble_hs_cfg.sync_cb = on_sync;
int rc;
#if MYNEWT_VAL(BLE_INCL_SVC_DISCOVERY) || MYNEWT_VAL(BLE_GATT_CACHING_INCLUDE_SERVICES) #if MYNEWT_VAL(BLE_INCL_SVC_DISCOVERY) || MYNEWT_VAL(BLE_GATT_CACHING_INCLUDE_SERVICES)
peer_init(MYNEWT_VAL(BLE_MAX_CONNECTIONS), 64, 64, 64, 64); rc = peer_init(MYNEWT_VAL(BLE_MAX_CONNECTIONS), 64, 64, 64, 64);
#else #else
peer_init(MYNEWT_VAL(BLE_MAX_CONNECTIONS), 64, 64, 64); rc = peer_init(MYNEWT_VAL(BLE_MAX_CONNECTIONS), 64, 64, 64);
#endif #endif
if (rc != 0) {
MODLOG_DFLT(ERROR, "Failed to init peer tracking; rc=%d\n", rc);
nimble_port_deinit();
return;
}
#if CONFIG_BT_NIMBLE_GAP_SERVICE #if CONFIG_BT_NIMBLE_GAP_SERVICE
ble_svc_gap_init(); ble_svc_gap_init();
@@ -585,8 +618,18 @@ void app_main(void)
ble_svc_ans_init(); ble_svc_ans_init();
#endif #endif
ble_gatts_count_cfg(gatt_svr_svcs); rc = ble_gatts_count_cfg(gatt_svr_svcs);
ble_gatts_add_svcs(gatt_svr_svcs); if (rc != 0) {
MODLOG_DFLT(ERROR, "ble_gatts_count_cfg failed; rc=%d\n", rc);
nimble_port_deinit();
return;
}
rc = ble_gatts_add_svcs(gatt_svr_svcs);
if (rc != 0) {
MODLOG_DFLT(ERROR, "ble_gatts_add_svcs failed; rc=%d\n", rc);
nimble_port_deinit();
return;
}
nimble_port_freertos_init(ble_hs_task); nimble_port_freertos_init(ble_hs_task);
} }
@@ -5,8 +5,5 @@
# BT config # BT config
# #
CONFIG_BT_ENABLED=y CONFIG_BT_ENABLED=y
CONFIG_BTDM_CTRL_MODE_BLE_ONLY=y
CONFIG_BTDM_CTRL_MODE_BR_EDR_ONLY=n
CONFIG_BTDM_CTRL_MODE_BTDM=n
CONFIG_BT_BLUEDROID_ENABLED=n CONFIG_BT_BLUEDROID_ENABLED=n
CONFIG_BT_NIMBLE_ENABLED=y CONFIG_BT_NIMBLE_ENABLED=y
@@ -0,0 +1,4 @@
# ESP32-only BTDM controller mode (classic BT + BLE SoC)
CONFIG_BTDM_CTRL_MODE_BLE_ONLY=y
CONFIG_BTDM_CTRL_MODE_BR_EDR_ONLY=n
CONFIG_BTDM_CTRL_MODE_BTDM=n
@@ -63,6 +63,15 @@ ble_htp_cent_on_subscribe(uint16_t conn_handle,
uint8_t value[2]; uint8_t value[2];
int rc; int rc;
const struct peer *peer = peer_find(conn_handle); const struct peer *peer = peer_find(conn_handle);
if (peer == NULL) {
MODLOG_DFLT(ERROR, "Peer not found for conn_handle=%d\n", conn_handle);
return ble_gap_terminate(conn_handle, BLE_ERR_REM_USER_CONN_TERM);
}
if (error->status != 0) {
MODLOG_DFLT(ERROR, "Subscribe to temp measurement failed; status=%d\n", error->status);
return ble_gap_terminate(conn_handle, BLE_ERR_REM_USER_CONN_TERM);
}
dsc = peer_dsc_find_uuid(peer, dsc = peer_dsc_find_uuid(peer,
BLE_UUID16_DECLARE(BLE_SVC_HTP_UUID16), BLE_UUID16_DECLARE(BLE_SVC_HTP_UUID16),
@@ -86,9 +95,7 @@ ble_htp_cent_on_subscribe(uint16_t conn_handle,
return 0; return 0;
err: err:
/* Terminate the connection. */ /* Terminate the connection. */
return ble_gap_terminate(peer->conn_handle, BLE_ERR_REM_USER_CONN_TERM); return ble_gap_terminate(conn_handle, BLE_ERR_REM_USER_CONN_TERM);
return 0;
} }
/** /**
@@ -113,6 +120,15 @@ ble_htp_cent_on_write(uint16_t conn_handle,
uint8_t value[2]; uint8_t value[2];
int rc; int rc;
const struct peer *peer = peer_find(conn_handle); const struct peer *peer = peer_find(conn_handle);
if (peer == NULL) {
MODLOG_DFLT(ERROR, "Peer not found for conn_handle=%d\n", conn_handle);
return ble_gap_terminate(conn_handle, BLE_ERR_REM_USER_CONN_TERM);
}
if (error->status != 0) {
MODLOG_DFLT(ERROR, "Write to measurement interval failed; status=%d\n", error->status);
return ble_gap_terminate(conn_handle, BLE_ERR_REM_USER_CONN_TERM);
}
dsc = peer_dsc_find_uuid(peer, dsc = peer_dsc_find_uuid(peer,
BLE_UUID16_DECLARE(BLE_SVC_HTP_UUID16), BLE_UUID16_DECLARE(BLE_SVC_HTP_UUID16),
@@ -137,7 +153,7 @@ ble_htp_cent_on_write(uint16_t conn_handle,
return 0; return 0;
err: err:
/* Terminate the connection. */ /* Terminate the connection. */
return ble_gap_terminate(peer->conn_handle, BLE_ERR_REM_USER_CONN_TERM); return ble_gap_terminate(conn_handle, BLE_ERR_REM_USER_CONN_TERM);
} }
/** /**
@@ -155,6 +171,9 @@ ble_htp_cent_on_read(uint16_t conn_handle,
if (error->status == 0) { if (error->status == 0) {
MODLOG_DFLT(INFO, " attr_handle=%d value=", attr->handle); MODLOG_DFLT(INFO, " attr_handle=%d value=", attr->handle);
print_mbuf(attr->om); print_mbuf(attr->om);
} else {
MODLOG_DFLT(ERROR, "Read temperature type failed; status=%d\n", error->status);
return ble_gap_terminate(conn_handle, BLE_ERR_REM_USER_CONN_TERM);
} }
MODLOG_DFLT(INFO, "\n"); MODLOG_DFLT(INFO, "\n");
@@ -319,25 +338,15 @@ ext_ble_htp_cent_should_connect(const struct ble_gap_ext_disc_desc *disc)
{ {
int offset = 0; int offset = 0;
int ad_struct_len = 0; int ad_struct_len = 0;
uint8_t test_addr[6]; uint8_t test_addr[6] = {0};
uint32_t peer_addr[6]; if (!(disc->props & BLE_HCI_ADV_CONN_MASK)) {
memset(peer_addr, 0x0, sizeof peer_addr);
if (disc->legacy_event_type != BLE_HCI_ADV_RPT_EVTYPE_ADV_IND &&
disc->legacy_event_type != BLE_HCI_ADV_RPT_EVTYPE_DIR_IND) {
return 0; return 0;
} }
if (strlen(CONFIG_EXAMPLE_PEER_ADDR) && (strncmp(CONFIG_EXAMPLE_PEER_ADDR, "ADDR_ANY", strlen ("ADDR_ANY")) != 0)) { if (strlen(CONFIG_EXAMPLE_PEER_ADDR) && (strncmp(CONFIG_EXAMPLE_PEER_ADDR, "ADDR_ANY", strlen ("ADDR_ANY")) != 0)) {
ESP_LOGI(tag, "Peer address from menuconfig: %s", CONFIG_EXAMPLE_PEER_ADDR); ESP_LOGI(tag, "Peer address from menuconfig: %s", CONFIG_EXAMPLE_PEER_ADDR);
/* Convert string to address */ /* Convert string to address */
sscanf(CONFIG_EXAMPLE_PEER_ADDR, "%lx:%lx:%lx:%lx:%lx:%lx", if (peer_addr_parse(CONFIG_EXAMPLE_PEER_ADDR, test_addr) != 6) {
&peer_addr[5], &peer_addr[4], &peer_addr[3], return 0;
&peer_addr[2], &peer_addr[1], &peer_addr[0]);
/* Conversion */
for (int i=0; i<6; i++) {
test_addr[i] = (uint8_t )peer_addr[5 - i];
} }
if (memcmp(test_addr, disc->addr.val, sizeof(disc->addr.val)) != 0) { if (memcmp(test_addr, disc->addr.val, sizeof(disc->addr.val)) != 0) {
@@ -356,9 +365,9 @@ ext_ble_htp_cent_should_connect(const struct ble_gap_ext_disc_desc *disc)
break; break;
} }
/* Search if HTP UUID is advertised */ /* Search if HTP UUID is advertised (little-endian: 0x09 0x18 = 0x1809) */
if (disc->data[offset] == 0x03 && disc->data[offset + 1] == 0x03) { if (disc->data[offset] == 0x03 && disc->data[offset + 1] == 0x03) {
if ( disc->data[offset + 2] == 0x18 && disc->data[offset + 3] == 0x09 ) { if ( disc->data[offset + 2] == 0x09 && disc->data[offset + 3] == 0x18 ) {
return 1; return 1;
} }
} }
@@ -376,11 +385,7 @@ ble_htp_cent_should_connect(const struct ble_gap_disc_desc *disc)
struct ble_hs_adv_fields fields; struct ble_hs_adv_fields fields;
int rc; int rc;
int i; int i;
uint8_t test_addr[6]; uint8_t test_addr[6] = {0};
uint32_t peer_addr[6];
memset(peer_addr, 0x0, sizeof peer_addr);
/* The device has to be advertising connectability. */ /* The device has to be advertising connectability. */
if (disc->event_type != BLE_HCI_ADV_RPT_EVTYPE_ADV_IND && if (disc->event_type != BLE_HCI_ADV_RPT_EVTYPE_ADV_IND &&
disc->event_type != BLE_HCI_ADV_RPT_EVTYPE_DIR_IND) { disc->event_type != BLE_HCI_ADV_RPT_EVTYPE_DIR_IND) {
@@ -396,15 +401,9 @@ ble_htp_cent_should_connect(const struct ble_gap_disc_desc *disc)
if (strlen(CONFIG_EXAMPLE_PEER_ADDR) && (strncmp(CONFIG_EXAMPLE_PEER_ADDR, "ADDR_ANY", strlen("ADDR_ANY")) != 0)) { if (strlen(CONFIG_EXAMPLE_PEER_ADDR) && (strncmp(CONFIG_EXAMPLE_PEER_ADDR, "ADDR_ANY", strlen("ADDR_ANY")) != 0)) {
ESP_LOGI(tag, "Peer address from menuconfig: %s", CONFIG_EXAMPLE_PEER_ADDR); ESP_LOGI(tag, "Peer address from menuconfig: %s", CONFIG_EXAMPLE_PEER_ADDR);
/* Convert string to address */ /* Convert string to address */
sscanf(CONFIG_EXAMPLE_PEER_ADDR, "%lx:%lx:%lx:%lx:%lx:%lx", if (peer_addr_parse(CONFIG_EXAMPLE_PEER_ADDR, test_addr) != 6) {
&peer_addr[5], &peer_addr[4], &peer_addr[3], return 0;
&peer_addr[2], &peer_addr[1], &peer_addr[0]);
/* Conversion */
for (int i=0; i<6; i++) {
test_addr[i] = (uint8_t )peer_addr[i];
} }
if (memcmp(test_addr, disc->addr.val, sizeof(disc->addr.val)) != 0) { if (memcmp(test_addr, disc->addr.val, sizeof(disc->addr.val)) != 0) {
return 0; return 0;
} }
@@ -459,6 +458,9 @@ ble_htp_cent_connect_if_interesting(void *disc)
rc = ble_hs_id_infer_auto(0, &own_addr_type); rc = ble_hs_id_infer_auto(0, &own_addr_type);
if (rc != 0) { if (rc != 0) {
MODLOG_DFLT(ERROR, "error determining address type; rc=%d\n", rc); MODLOG_DFLT(ERROR, "error determining address type; rc=%d\n", rc);
#if !(MYNEWT_VAL(BLE_HOST_ALLOW_CONNECT_WITH_SCAN))
ble_htp_cent_scan();
#endif
return; return;
} }
@@ -476,6 +478,9 @@ ble_htp_cent_connect_if_interesting(void *disc)
MODLOG_DFLT(ERROR, "Error: Failed to connect to device; addr_type=%d " MODLOG_DFLT(ERROR, "Error: Failed to connect to device; addr_type=%d "
"addr=%s; rc=%d\n", "addr=%s; rc=%d\n",
addr->type, addr_str(addr->val), rc); addr->type, addr_str(addr->val), rc);
#if !(MYNEWT_VAL(BLE_HOST_ALLOW_CONNECT_WITH_SCAN))
ble_htp_cent_scan();
#endif
return; return;
} }
} }
@@ -498,11 +503,13 @@ static int
ble_htp_cent_gap_event(struct ble_gap_event *event, void *arg) ble_htp_cent_gap_event(struct ble_gap_event *event, void *arg)
{ {
struct ble_gap_conn_desc desc; struct ble_gap_conn_desc desc;
struct ble_hs_adv_fields fields;
int rc; int rc;
switch (event->type) { switch (event->type) {
case BLE_GAP_EVENT_DISC: case BLE_GAP_EVENT_DISC:
#if !CONFIG_EXAMPLE_EXTENDED_ADV
{
struct ble_hs_adv_fields fields;
rc = ble_hs_adv_parse_fields(&fields, event->disc.data, rc = ble_hs_adv_parse_fields(&fields, event->disc.data,
event->disc.length_data); event->disc.length_data);
if (rc != 0) { if (rc != 0) {
@@ -514,6 +521,8 @@ ble_htp_cent_gap_event(struct ble_gap_event *event, void *arg)
/* Try to connect to the advertiser if it looks interesting. */ /* Try to connect to the advertiser if it looks interesting. */
ble_htp_cent_connect_if_interesting(&event->disc); ble_htp_cent_connect_if_interesting(&event->disc);
}
#endif
return 0; return 0;
case BLE_GAP_EVENT_CONNECT: case BLE_GAP_EVENT_CONNECT:
@@ -746,11 +755,14 @@ app_main(void)
/* Initialize data structures to track connected peers. */ /* Initialize data structures to track connected peers. */
#if MYNEWT_VAL(BLE_INCL_SVC_DISCOVERY) || MYNEWT_VAL(BLE_GATT_CACHING_INCLUDE_SERVICES) #if MYNEWT_VAL(BLE_INCL_SVC_DISCOVERY) || MYNEWT_VAL(BLE_GATT_CACHING_INCLUDE_SERVICES)
rc = peer_init(MYNEWT_VAL(BLE_MAX_CONNECTIONS), 64, 64, 64, 64); rc = peer_init(MYNEWT_VAL(BLE_MAX_CONNECTIONS), 64, 64, 64, 64);
assert(rc == 0);
#else #else
rc = peer_init(MYNEWT_VAL(BLE_MAX_CONNECTIONS), 64, 64, 64); rc = peer_init(MYNEWT_VAL(BLE_MAX_CONNECTIONS), 64, 64, 64);
assert(rc == 0);
#endif #endif
if (rc != 0) {
ESP_LOGE(tag, "Failed to init peer tracking; rc=%d", rc);
nimble_port_deinit();
return;
}
#if CONFIG_BT_NIMBLE_GAP_SERVICE #if CONFIG_BT_NIMBLE_GAP_SERVICE
/* Set the default device name. */ /* Set the default device name. */
rc = ble_svc_gap_device_name_set("nimble-htp-cent"); rc = ble_svc_gap_device_name_set("nimble-htp-cent");
@@ -5,8 +5,5 @@
# BT config # BT config
# #
CONFIG_BT_ENABLED=y CONFIG_BT_ENABLED=y
CONFIG_BTDM_CTRL_MODE_BLE_ONLY=y
CONFIG_BTDM_CTRL_MODE_BR_EDR_ONLY=n
CONFIG_BTDM_CTRL_MODE_BTDM=n
CONFIG_BT_BLUEDROID_ENABLED=n CONFIG_BT_BLUEDROID_ENABLED=n
CONFIG_BT_NIMBLE_ENABLED=y CONFIG_BT_NIMBLE_ENABLED=y
@@ -5,9 +5,6 @@
# BT config # BT config
# #
CONFIG_BT_ENABLED=y CONFIG_BT_ENABLED=y
CONFIG_BTDM_CTRL_MODE_BLE_ONLY=y
CONFIG_BTDM_CTRL_MODE_BR_EDR_ONLY=n
CONFIG_BTDM_CTRL_MODE_BTDM=n
CONFIG_BT_BLUEDROID_ENABLED=n CONFIG_BT_BLUEDROID_ENABLED=n
CONFIG_BT_NIMBLE_ENABLED=y CONFIG_BT_NIMBLE_ENABLED=y
@@ -0,0 +1,4 @@
# ESP32-only BTDM controller mode (classic BT + BLE SoC)
CONFIG_BTDM_CTRL_MODE_BLE_ONLY=y
CONFIG_BTDM_CTRL_MODE_BR_EDR_ONLY=n
CONFIG_BTDM_CTRL_MODE_BTDM=n
@@ -0,0 +1,4 @@
# ESP32-only BTDM controller mode (classic BT + BLE SoC)
CONFIG_BTDM_CTRL_MODE_BLE_ONLY=y
CONFIG_BTDM_CTRL_MODE_BR_EDR_ONLY=n
CONFIG_BTDM_CTRL_MODE_BTDM=n
@@ -5,9 +5,6 @@
# BT config # BT config
# #
CONFIG_BT_ENABLED=y CONFIG_BT_ENABLED=y
CONFIG_BTDM_CTRL_MODE_BLE_ONLY=y
CONFIG_BTDM_CTRL_MODE_BR_EDR_ONLY=n
CONFIG_BTDM_CTRL_MODE_BTDM=n
CONFIG_BT_BLUEDROID_ENABLED=n CONFIG_BT_BLUEDROID_ENABLED=n
CONFIG_BT_NIMBLE_ENABLED=y CONFIG_BT_NIMBLE_ENABLED=y
CONFIG_BT_NIMBLE_MAX_CONNECTIONS=1 CONFIG_BT_NIMBLE_MAX_CONNECTIONS=1
@@ -68,7 +65,6 @@ CONFIG_ESP_WIFI_ENABLED=n
# Application # Application
CONFIG_APP_COMPILE_TIME_DATE=n CONFIG_APP_COMPILE_TIME_DATE=n
CONFIG_ESP_COEX_SW_COEXIST_ENABLE=n CONFIG_ESP_COEX_SW_COEXIST_ENABLE=n
CONFIG_ESP_ERR_TO_NAME_LOOKUP=n CONFIG_ESP_ERR_TO_NAME_LOOKUP=n
CONFIG_SPI_MASTER_ISR_IN_IRAM=n CONFIG_SPI_MASTER_ISR_IN_IRAM=n
@@ -82,7 +78,6 @@ CONFIG_SPI_FLASH_ENABLE_ENCRYPTED_READ_WRITE=n
#Uncomment below, if security needs to be disabled #Uncomment below, if security needs to be disabled
#CONFIG_BT_NIMBLE_SECURITY_ENABLE=n #CONFIG_BT_NIMBLE_SECURITY_ENABLE=n
#Uncomment below, if logging needs to be disabled #Uncomment below, if logging needs to be disabled
#CONFIG_LOG_DEFAULT_LEVEL_NONE=y #CONFIG_LOG_DEFAULT_LEVEL_NONE=y
#CONFIG_LOG_DEFAULT_LEVEL=0 #CONFIG_LOG_DEFAULT_LEVEL=0
@@ -0,0 +1,4 @@
# ESP32-only BTDM controller mode (classic BT + BLE SoC)
CONFIG_BTDM_CTRL_MODE_BLE_ONLY=y
CONFIG_BTDM_CTRL_MODE_BR_EDR_ONLY=n
CONFIG_BTDM_CTRL_MODE_BTDM=n
@@ -15,7 +15,7 @@
static const char *manuf_name = "ESP32 devkitC"; static const char *manuf_name = "ESP32 devkitC";
static const char *model_num = "HTP Sensor demo"; static const char *model_num = "HTP Sensor demo";
static const char *system_id = "HTP1"; static const uint8_t system_id[8] = { 'H', 'T', 'P', '1' };
static int static int
gatt_svr_chr_access_device_info(uint16_t conn_handle, uint16_t attr_handle, gatt_svr_chr_access_device_info(uint16_t conn_handle, uint16_t attr_handle,
struct ble_gatt_access_ctxt *ctxt, void *arg); struct ble_gatt_access_ctxt *ctxt, void *arg);
@@ -72,7 +72,7 @@ gatt_svr_chr_access_device_info(uint16_t conn_handle, uint16_t attr_handle,
} }
if (uuid == GATT_DIS_CHR_UUID16_SYS_ID) { if (uuid == GATT_DIS_CHR_UUID16_SYS_ID) {
rc = os_mbuf_append(ctxt->om, system_id, strlen(system_id)); rc = os_mbuf_append(ctxt->om, system_id, sizeof(system_id));
return rc == 0 ? 0 : BLE_ATT_ERR_INSUFFICIENT_RES; return rc == 0 ? 0 : BLE_ATT_ERR_INSUFFICIENT_RES;
} }
@@ -123,7 +123,7 @@ gatt_svr_init(void)
#if MYNEWT_VAL(BLE_GATTS) #if MYNEWT_VAL(BLE_GATTS)
ble_svc_gatt_init(); ble_svc_gatt_init();
#endif #endif
#if CONFIG_BT_NIMBLE_ANS_SERVICE #if CONFIG_BT_NIMBLE_HTP_SERVICE
ble_svc_htp_init(); ble_svc_htp_init();
#endif #endif
@@ -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 * SPDX-License-Identifier: Apache-2.0
*/ */
@@ -20,7 +20,7 @@
static uint8_t ext_adv_pattern_1[] = { static uint8_t ext_adv_pattern_1[] = {
0x02, BLE_HS_ADV_TYPE_FLAGS, 0x06, 0x02, BLE_HS_ADV_TYPE_FLAGS, 0x06,
0x03, BLE_HS_ADV_TYPE_COMP_UUIDS16, 0xab, 0xcd, 0x03, BLE_HS_ADV_TYPE_COMP_UUIDS16, 0xab, 0xcd,
0x03, BLE_HS_ADV_TYPE_COMP_UUIDS16, 0x18, 0x09, 0x03, BLE_HS_ADV_TYPE_COMP_UUIDS16, 0x09, 0x18,
0x12, BLE_HS_ADV_TYPE_COMP_NAME, 'n', 'i', 'm', 'b', 'l', 'e', '-', 'h', 't', 'p', '-', 'p', 'r', 'p', 'h', '-', 'e', 0x12, BLE_HS_ADV_TYPE_COMP_NAME, 'n', 'i', 'm', 'b', 'l', 'e', '-', 'h', 't', 'p', '-', 'p', 'r', 'p', 'h', '-', 'e',
}; };
#endif #endif
@@ -81,8 +81,8 @@ ext_ble_htp_prph_advertise(void)
/* enable connectable advertising */ /* enable connectable advertising */
params.connectable = 1; params.connectable = 1;
/* advertise using random addr */ /* advertise using configured addr */
params.own_addr_type = BLE_OWN_ADDR_PUBLIC; params.own_addr_type = ble_htp_prph_addr_type;
params.primary_phy = BLE_HCI_LE_PHY_1M; params.primary_phy = BLE_HCI_LE_PHY_1M;
params.secondary_phy = BLE_HCI_LE_PHY_2M; params.secondary_phy = BLE_HCI_LE_PHY_2M;
@@ -150,9 +150,10 @@ ble_htp_prph_advertise(void)
fields.name_len = strlen(device_name); fields.name_len = strlen(device_name);
fields.name_is_complete = 1; fields.name_is_complete = 1;
fields.uuids16 = (ble_uuid16_t[]) { static const ble_uuid16_t adv_uuids16[] = {
BLE_UUID16_INIT(BLE_SVC_HTP_UUID16) BLE_UUID16_INIT(BLE_SVC_HTP_UUID16)
}; };
fields.uuids16 = adv_uuids16;
fields.num_uuids16 = 1; fields.num_uuids16 = 1;
fields.uuids16_is_complete = 1; fields.uuids16_is_complete = 1;
@@ -178,23 +179,16 @@ ble_htp_prph_advertise(void)
static void static void
ble_htp_prph_tx_htp_stop(void) ble_htp_prph_tx_htp_stop(void)
{ {
xTimerStop( ble_htp_prph_tx_timer, 1000 / portTICK_PERIOD_MS ); xTimerStop( ble_htp_prph_tx_timer, 0 );
} }
/* Reset temperature measurement */ /* Reset temperature measurement */
static void static void
ble_htp_prph_tx_htp_reset(void) ble_htp_prph_tx_htp_reset(void)
{ {
int rc; if (xTimerReset(ble_htp_prph_tx_timer, 0) != pdPASS) {
MODLOG_DFLT(ERROR, "Failed to reset HTP timer\n");
if (xTimerReset(ble_htp_prph_tx_timer, 1000 / portTICK_PERIOD_MS ) == pdPASS) {
rc = 0;
} else {
rc = 1;
} }
assert(rc == 0);
} }
/* This function notifies intermediate temperature to the client */ /* This function notifies intermediate temperature to the client */
@@ -372,6 +366,11 @@ void app_main(void)
/* name, period/time, auto reload, timer ID, callback */ /* name, period/time, auto reload, timer ID, callback */
ble_htp_prph_tx_timer = xTimerCreate("ble_htp_prph_tx_timer", pdMS_TO_TICKS(1000), pdTRUE, ble_htp_prph_tx_timer = xTimerCreate("ble_htp_prph_tx_timer", pdMS_TO_TICKS(1000), pdTRUE,
(void *)0, ble_htp_prph_tx); (void *)0, ble_htp_prph_tx);
if (ble_htp_prph_tx_timer == NULL) {
MODLOG_DFLT(ERROR, "Failed to create HTP TX timer\n");
nimble_port_deinit();
return;
}
#if MYNEWT_VAL(BLE_GATTS) #if MYNEWT_VAL(BLE_GATTS)
int rc; int rc;
@@ -5,9 +5,6 @@
# BT config # BT config
# #
CONFIG_BT_ENABLED=y CONFIG_BT_ENABLED=y
CONFIG_BTDM_CTRL_MODE_BLE_ONLY=y
CONFIG_BTDM_CTRL_MODE_BR_EDR_ONLY=n
CONFIG_BTDM_CTRL_MODE_BTDM=n
CONFIG_BT_BLUEDROID_ENABLED=n CONFIG_BT_BLUEDROID_ENABLED=n
CONFIG_BT_NIMBLE_ENABLED=y CONFIG_BT_NIMBLE_ENABLED=y
CONFIG_FREERTOS_TIMER_TASK_STACK_DEPTH=4000 CONFIG_FREERTOS_TIMER_TASK_STACK_DEPTH=4000
@@ -5,9 +5,6 @@
# BT config # BT config
# #
CONFIG_BT_ENABLED=y CONFIG_BT_ENABLED=y
CONFIG_BTDM_CTRL_MODE_BLE_ONLY=y
CONFIG_BTDM_CTRL_MODE_BR_EDR_ONLY=n
CONFIG_BTDM_CTRL_MODE_BTDM=n
CONFIG_BT_BLUEDROID_ENABLED=n CONFIG_BT_BLUEDROID_ENABLED=n
CONFIG_BT_NIMBLE_ENABLED=y CONFIG_BT_NIMBLE_ENABLED=y
CONFIG_FREERTOS_TIMER_TASK_STACK_DEPTH=4000 CONFIG_FREERTOS_TIMER_TASK_STACK_DEPTH=4000
@@ -0,0 +1,4 @@
# ESP32-only BTDM controller mode (classic BT + BLE SoC)
CONFIG_BTDM_CTRL_MODE_BLE_ONLY=y
CONFIG_BTDM_CTRL_MODE_BR_EDR_ONLY=n
CONFIG_BTDM_CTRL_MODE_BTDM=n
@@ -0,0 +1,4 @@
# ESP32-only BTDM controller mode (classic BT + BLE SoC)
CONFIG_BTDM_CTRL_MODE_BLE_ONLY=y
CONFIG_BTDM_CTRL_MODE_BR_EDR_ONLY=n
CONFIG_BTDM_CTRL_MODE_BTDM=n
@@ -5,9 +5,6 @@
# BT config # BT config
# #
CONFIG_BT_ENABLED=y CONFIG_BT_ENABLED=y
CONFIG_BTDM_CTRL_MODE_BLE_ONLY=y
CONFIG_BTDM_CTRL_MODE_BR_EDR_ONLY=n
CONFIG_BTDM_CTRL_MODE_BTDM=n
CONFIG_BT_BLUEDROID_ENABLED=n CONFIG_BT_BLUEDROID_ENABLED=n
CONFIG_BT_NIMBLE_ENABLED=y CONFIG_BT_NIMBLE_ENABLED=y
CONFIG_BT_NIMBLE_MAX_CONNECTIONS=1 CONFIG_BT_NIMBLE_MAX_CONNECTIONS=1
@@ -36,7 +33,6 @@ CONFIG_BT_NIMBLE_SPS_SERVICE=n
CONFIG_BT_NIMBLE_HR_SERVICE=n CONFIG_BT_NIMBLE_HR_SERVICE=n
CONFIG_BT_NIMBLE_DIS_SERVICE=n CONFIG_BT_NIMBLE_DIS_SERVICE=n
CONFIG_BT_ALARM_MAX_NUM=15 CONFIG_BT_ALARM_MAX_NUM=15
CONFIG_BT_NIMBLE_ATT_PREFERRED_MTU=23 CONFIG_BT_NIMBLE_ATT_PREFERRED_MTU=23
@@ -80,7 +76,6 @@ CONFIG_ESP_WIFI_ENABLED=n
# Application # Application
CONFIG_APP_COMPILE_TIME_DATE=n CONFIG_APP_COMPILE_TIME_DATE=n
CONFIG_ESP_COEX_SW_COEXIST_ENABLE=n CONFIG_ESP_COEX_SW_COEXIST_ENABLE=n
CONFIG_ESP_ERR_TO_NAME_LOOKUP=n CONFIG_ESP_ERR_TO_NAME_LOOKUP=n
CONFIG_SPI_MASTER_ISR_IN_IRAM=n CONFIG_SPI_MASTER_ISR_IN_IRAM=n
@@ -94,7 +89,6 @@ CONFIG_SPI_FLASH_ENABLE_ENCRYPTED_READ_WRITE=n
#Uncomment below, if security needs to be disabled #Uncomment below, if security needs to be disabled
#CONFIG_BT_NIMBLE_SECURITY_ENABLE=n #CONFIG_BT_NIMBLE_SECURITY_ENABLE=n
#Uncomment below, if logging needs to be disabled #Uncomment below, if logging needs to be disabled
#CONFIG_LOG_DEFAULT_LEVEL_NONE=y #CONFIG_LOG_DEFAULT_LEVEL_NONE=y
#CONFIG_LOG_DEFAULT_LEVEL=0 #CONFIG_LOG_DEFAULT_LEVEL=0
@@ -0,0 +1,4 @@
# ESP32-only BTDM controller mode (classic BT + BLE SoC)
CONFIG_BTDM_CTRL_MODE_BLE_ONLY=y
CONFIG_BTDM_CTRL_MODE_BR_EDR_ONLY=n
CONFIG_BTDM_CTRL_MODE_BTDM=n
@@ -1,5 +1,5 @@
/* /*
* SPDX-FileCopyrightText: 2021-2025 Espressif Systems (Shanghai) CO LTD * SPDX-FileCopyrightText: 2021-2026 Espressif Systems (Shanghai) CO LTD
* *
* SPDX-License-Identifier: Unlicense OR CC0-1.0 * SPDX-License-Identifier: Unlicense OR CC0-1.0
*/ */
@@ -68,16 +68,9 @@ blecent_l2cap_coc_send_data(struct ble_l2cap_chan *chan)
rc = ble_l2cap_send(chan, sdu_rx_data); rc = ble_l2cap_send(chan, sdu_rx_data);
retry = 0;
while (rc == BLE_HS_ESTALLED && retry < max_retry) {
MODLOG_DFLT(INFO, "Send stalled, waiting for credits (retry=%d)", retry);
vTaskDelay(100 / portTICK_PERIOD_MS);
rc = ble_l2cap_send(chan, sdu_rx_data);
retry++;
}
if (rc == BLE_HS_ESTALLED) { if (rc == BLE_HS_ESTALLED) {
MODLOG_DFLT(INFO, "Send still stalled after %d retries, returning", retry); /* Stack took ownership of sdu_rx_data; wait for BLE_L2CAP_EVENT_COC_TX_UNSTALLED */
MODLOG_DFLT(INFO, "Send stalled, waiting for credits");
return; return;
} }
@@ -115,7 +108,7 @@ blecent_l2cap_coc_on_disc_complete(const struct peer *peer, int status, void *ar
rc = ble_l2cap_connect(conn_handle_coc, psm, MTU, sdu_rx, blecent_l2cap_coc_event_cb, NULL); rc = ble_l2cap_connect(conn_handle_coc, psm, MTU, sdu_rx, blecent_l2cap_coc_event_cb, NULL);
if (rc != 0) { if (rc != 0) {
MODLOG_DFLT(ERROR, "L2CAP COC connect failed, rc=%d", rc); MODLOG_DFLT(ERROR, "L2CAP COC connect failed, rc=%d", rc);
os_mbuf_free_chain(sdu_rx); /* sdu_rx is freed by the stack on all failure paths; do not free here */
} }
} }
@@ -163,6 +156,7 @@ blecent_l2cap_coc_event_cb(struct ble_l2cap_event *event, void *arg)
case BLE_L2CAP_EVENT_COC_DISCONNECTED: case BLE_L2CAP_EVENT_COC_DISCONNECTED:
console_printf("LE CoC disconnected, chan: %p\n", console_printf("LE CoC disconnected, chan: %p\n",
event->disconnect.chan); event->disconnect.chan);
coc_chan = NULL;
return 0; return 0;
default: default:
@@ -266,27 +260,14 @@ ext_blecent_should_connect(const struct ble_gap_ext_disc_desc *disc)
int offset = 0; int offset = 0;
int ad_struct_len = 0; int ad_struct_len = 0;
uint8_t test_addr[6]; uint8_t test_addr[6];
uint32_t peer_addr[6]; if (!(disc->props & BLE_HCI_ADV_CONN_MASK)) {
memset(peer_addr, 0x0, sizeof peer_addr);
if (disc->legacy_event_type != BLE_HCI_ADV_RPT_EVTYPE_ADV_IND &&
disc->legacy_event_type != BLE_HCI_ADV_RPT_EVTYPE_DIR_IND) {
return 0; return 0;
} }
if (strlen(CONFIG_EXAMPLE_PEER_ADDR) && if (strlen(CONFIG_EXAMPLE_PEER_ADDR) &&
(strncmp(CONFIG_EXAMPLE_PEER_ADDR, "ADDR_ANY", strlen("ADDR_ANY")) != 0)) { (strncmp(CONFIG_EXAMPLE_PEER_ADDR, "ADDR_ANY", strlen("ADDR_ANY")) != 0)) {
ESP_LOGI(tag, "Peer address from menuconfig: %s", CONFIG_EXAMPLE_PEER_ADDR); ESP_LOGI(tag, "Peer address from menuconfig: %s", CONFIG_EXAMPLE_PEER_ADDR);
/* Convert string to address */ /* Convert string to address */
sscanf(CONFIG_EXAMPLE_PEER_ADDR, "%lx:%lx:%lx:%lx:%lx:%lx", peer_addr_parse(CONFIG_EXAMPLE_PEER_ADDR, test_addr);
&peer_addr[5], &peer_addr[4], &peer_addr[3],
&peer_addr[2], &peer_addr[1], &peer_addr[0]);
/* Conversion */
for (int i=0; i<6; i++) {
test_addr[i] = (uint8_t )peer_addr[i];
}
if (memcmp(test_addr, disc->addr.val, sizeof(disc->addr.val)) != 0) { if (memcmp(test_addr, disc->addr.val, sizeof(disc->addr.val)) != 0) {
return 0; return 0;
} }
@@ -308,11 +289,11 @@ ext_blecent_should_connect(const struct ble_gap_ext_disc_desc *disc)
break; break;
} }
/* AD Type (1) + UUID16 (2) requires at least 4 bytes total */ /* AD Type (1) + UUID16 (2) requires at least 4 bytes total; UUID 0x1812 is LE [0x12, 0x18] */
if (ad_struct_len >= 3 && if (ad_struct_len >= 3 &&
disc->data[offset + 1] == 0x03 && disc->data[offset + 1] == 0x03 &&
disc->data[offset + 2] == 0x18 && disc->data[offset + 2] == 0x12 &&
disc->data[offset + 3] == 0x12) { disc->data[offset + 3] == 0x18) {
return 1; return 1;
} }
@@ -329,10 +310,6 @@ blecent_should_connect(const struct ble_gap_disc_desc *disc)
int rc; int rc;
int i; int i;
uint8_t test_addr[6]; uint8_t test_addr[6];
uint32_t peer_addr[6];
memset(peer_addr, 0x0, sizeof peer_addr);
/* The device has to be advertising connectability. */ /* The device has to be advertising connectability. */
if (disc->event_type != BLE_HCI_ADV_RPT_EVTYPE_ADV_IND && if (disc->event_type != BLE_HCI_ADV_RPT_EVTYPE_ADV_IND &&
disc->event_type != BLE_HCI_ADV_RPT_EVTYPE_DIR_IND) { disc->event_type != BLE_HCI_ADV_RPT_EVTYPE_DIR_IND) {
@@ -349,15 +326,7 @@ blecent_should_connect(const struct ble_gap_disc_desc *disc)
(strncmp(CONFIG_EXAMPLE_PEER_ADDR, "ADDR_ANY", strlen("ADDR_ANY")) != 0)) { (strncmp(CONFIG_EXAMPLE_PEER_ADDR, "ADDR_ANY", strlen("ADDR_ANY")) != 0)) {
MODLOG_DFLT(INFO, "Peer address from menuconfig:%s", CONFIG_EXAMPLE_PEER_ADDR); MODLOG_DFLT(INFO, "Peer address from menuconfig:%s", CONFIG_EXAMPLE_PEER_ADDR);
/* Convert string to address */ /* Convert string to address */
sscanf(CONFIG_EXAMPLE_PEER_ADDR, "%lx:%lx:%lx:%lx:%lx:%lx", peer_addr_parse(CONFIG_EXAMPLE_PEER_ADDR, test_addr);
&peer_addr[5], &peer_addr[4], &peer_addr[3],
&peer_addr[2], &peer_addr[1], &peer_addr[0]);
/* Conversion */
for (int i=0; i<6; i++) {
test_addr[i] = (uint8_t )peer_addr[i];
}
if (memcmp(test_addr, disc->addr.val, sizeof(disc->addr.val)) != 0) { if (memcmp(test_addr, disc->addr.val, sizeof(disc->addr.val)) != 0) {
return 0; return 0;
} }
@@ -410,6 +379,9 @@ blecent_connect_if_interesting(void *disc)
rc = ble_hs_id_infer_auto(0, &own_addr_type); rc = ble_hs_id_infer_auto(0, &own_addr_type);
if (rc != 0) { if (rc != 0) {
MODLOG_DFLT(ERROR, "error determining address type; rc=%d\n", rc); MODLOG_DFLT(ERROR, "error determining address type; rc=%d\n", rc);
#if !(MYNEWT_VAL(BLE_HOST_ALLOW_CONNECT_WITH_SCAN))
blecent_scan();
#endif
return; return;
} }
@@ -428,6 +400,9 @@ blecent_connect_if_interesting(void *disc)
MODLOG_DFLT(ERROR, "Error: Failed to connect to device; addr_type=%d " MODLOG_DFLT(ERROR, "Error: Failed to connect to device; addr_type=%d "
"addr=%s; rc=%d\n", "addr=%s; rc=%d\n",
addr->type, addr_str(addr->val), rc); addr->type, addr_str(addr->val), rc);
#if !(MYNEWT_VAL(BLE_HOST_ALLOW_CONNECT_WITH_SCAN))
blecent_scan();
#endif
return; return;
} }
} }
@@ -515,6 +490,10 @@ blecent_gap_event(struct ble_gap_event *event, void *arg)
print_conn_desc(&event->disconnect.conn); print_conn_desc(&event->disconnect.conn);
MODLOG_DFLT(INFO, "\n"); MODLOG_DFLT(INFO, "\n");
#if MYNEWT_VAL(BLE_L2CAP_COC_MAX_NUM) >= 1
coc_chan = NULL;
#endif
/* Forget about peer. */ /* Forget about peer. */
peer_delete(event->disconnect.conn.conn_handle); peer_delete(event->disconnect.conn.conn_handle);
@@ -560,6 +539,9 @@ static void
blecent_on_reset(int reason) blecent_on_reset(int reason)
{ {
MODLOG_DFLT(ERROR, "Resetting state; reason=%d\n", reason); MODLOG_DFLT(ERROR, "Resetting state; reason=%d\n", reason);
#if MYNEWT_VAL(BLE_L2CAP_COC_MAX_NUM) >= 1
coc_chan = NULL;
#endif
} }
static void static void
@@ -5,9 +5,6 @@
# BT config # BT config
# #
CONFIG_BT_ENABLED=y CONFIG_BT_ENABLED=y
CONFIG_BTDM_CTRL_MODE_BLE_ONLY=y
CONFIG_BTDM_CTRL_MODE_BR_EDR_ONLY=n
CONFIG_BTDM_CTRL_MODE_BTDM=n
CONFIG_BT_BLUEDROID_ENABLED=n CONFIG_BT_BLUEDROID_ENABLED=n
CONFIG_BT_NIMBLE_ENABLED=y CONFIG_BT_NIMBLE_ENABLED=y
CONFIG_BT_NIMBLE_L2CAP_COC_MAX_NUM=1 CONFIG_BT_NIMBLE_L2CAP_COC_MAX_NUM=1
@@ -5,9 +5,6 @@
# BT config # BT config
# #
CONFIG_BT_ENABLED=y CONFIG_BT_ENABLED=y
CONFIG_BTDM_CTRL_MODE_BLE_ONLY=y
CONFIG_BTDM_CTRL_MODE_BR_EDR_ONLY=n
CONFIG_BTDM_CTRL_MODE_BTDM=n
CONFIG_BT_BLUEDROID_ENABLED=n CONFIG_BT_BLUEDROID_ENABLED=n
CONFIG_BT_NIMBLE_ENABLED=y CONFIG_BT_NIMBLE_ENABLED=y
CONFIG_BT_NIMBLE_L2CAP_COC_MAX_NUM=1 CONFIG_BT_NIMBLE_L2CAP_COC_MAX_NUM=1
@@ -0,0 +1,4 @@
# ESP32-only BTDM controller mode (classic BT + BLE SoC)
CONFIG_BTDM_CTRL_MODE_BLE_ONLY=y
CONFIG_BTDM_CTRL_MODE_BR_EDR_ONLY=n
CONFIG_BTDM_CTRL_MODE_BTDM=n
@@ -0,0 +1,4 @@
# ESP32-only BTDM controller mode (classic BT + BLE SoC)
CONFIG_BTDM_CTRL_MODE_BLE_ONLY=y
CONFIG_BTDM_CTRL_MODE_BR_EDR_ONLY=n
CONFIG_BTDM_CTRL_MODE_BTDM=n
@@ -5,9 +5,6 @@
# BT config # BT config
# #
CONFIG_BT_ENABLED=y CONFIG_BT_ENABLED=y
CONFIG_BTDM_CTRL_MODE_BLE_ONLY=y
CONFIG_BTDM_CTRL_MODE_BR_EDR_ONLY=n
CONFIG_BTDM_CTRL_MODE_BTDM=n
CONFIG_BT_BLUEDROID_ENABLED=n CONFIG_BT_BLUEDROID_ENABLED=n
CONFIG_BT_NIMBLE_ENABLED=y CONFIG_BT_NIMBLE_ENABLED=y
CONFIG_BT_NIMBLE_L2CAP_COC_MAX_NUM=1 CONFIG_BT_NIMBLE_L2CAP_COC_MAX_NUM=1
@@ -70,7 +67,6 @@ CONFIG_ESP_WIFI_ENABLED=n
# Application # Application
CONFIG_APP_COMPILE_TIME_DATE=n CONFIG_APP_COMPILE_TIME_DATE=n
CONFIG_ESP_COEX_SW_COEXIST_ENABLE=n CONFIG_ESP_COEX_SW_COEXIST_ENABLE=n
CONFIG_ESP_ERR_TO_NAME_LOOKUP=n CONFIG_ESP_ERR_TO_NAME_LOOKUP=n
CONFIG_SPI_MASTER_ISR_IN_IRAM=n CONFIG_SPI_MASTER_ISR_IN_IRAM=n
@@ -84,7 +80,6 @@ CONFIG_SPI_FLASH_ENABLE_ENCRYPTED_READ_WRITE=n
#Uncomment below, if security needs to be disabled #Uncomment below, if security needs to be disabled
#CONFIG_BT_NIMBLE_SECURITY_ENABLE=n #CONFIG_BT_NIMBLE_SECURITY_ENABLE=n
#Uncomment below, if logging needs to be disabled #Uncomment below, if logging needs to be disabled
#CONFIG_LOG_DEFAULT_LEVEL_NONE=y #CONFIG_LOG_DEFAULT_LEVEL_NONE=y
#CONFIG_LOG_DEFAULT_LEVEL=0 #CONFIG_LOG_DEFAULT_LEVEL=0
@@ -0,0 +1,4 @@
# ESP32-only BTDM controller mode (classic BT + BLE SoC)
CONFIG_BTDM_CTRL_MODE_BLE_ONLY=y
CONFIG_BTDM_CTRL_MODE_BR_EDR_ONLY=n
CONFIG_BTDM_CTRL_MODE_BTDM=n
@@ -18,7 +18,7 @@
static uint8_t ext_adv_pattern_1[] = { static uint8_t ext_adv_pattern_1[] = {
0x02, BLE_HS_ADV_TYPE_FLAGS, 0x06, 0x02, BLE_HS_ADV_TYPE_FLAGS, 0x06,
0x03, BLE_HS_ADV_TYPE_COMP_UUIDS16, 0xab, 0xcd, 0x03, BLE_HS_ADV_TYPE_COMP_UUIDS16, 0xab, 0xcd,
0x03, BLE_HS_ADV_TYPE_COMP_UUIDS16, 0x18, 0x12, 0x03, BLE_HS_ADV_TYPE_COMP_UUIDS16, 0x12, 0x18, /* UUID 0x1812 in little-endian */
0x12, BLE_HS_ADV_TYPE_COMP_NAME, 'e', 'x', 't', '-', 'b', 'l', 'e', 'p', 'r', 'p', 'h', '-', 'l', '2', 'c', 'o', 'c', 0x12, BLE_HS_ADV_TYPE_COMP_NAME, 'e', 'x', 't', '-', 'b', 'l', 'e', 'p', 'r', 'p', 'h', '-', 'l', '2', 'c', 'o', 'c',
}; };
#endif #endif
@@ -164,9 +164,10 @@ bleprph_advertise(void)
fields.name_len = strlen(name); fields.name_len = strlen(name);
fields.name_is_complete = 1; fields.name_is_complete = 1;
fields.uuids16 = (ble_uuid16_t[]) { static const ble_uuid16_t adv_uuids16[] = {
BLE_UUID16_INIT(L2CAP_COC_UUID) BLE_UUID16_INIT(L2CAP_COC_UUID)
}; };
fields.uuids16 = adv_uuids16;
fields.num_uuids16 = 1; fields.num_uuids16 = 1;
fields.uuids16_is_complete = 1; fields.uuids16_is_complete = 1;
@@ -196,8 +197,8 @@ bleprph_l2cap_coc_accept(uint16_t conn_handle, uint16_t peer_mtu,
{ {
struct os_mbuf *sdu_rx; struct os_mbuf *sdu_rx;
console_printf("LE CoC accepting, chan: 0x%08lx, peer_mtu %d\n", console_printf("LE CoC accepting, chan: 0x%08x, peer_mtu %d\n",
(uint32_t) chan, peer_mtu); (unsigned) (uint32_t) chan, peer_mtu);
sdu_rx = os_mbuf_get_pkthdr(&sdu_os_mbuf_pool, 0); sdu_rx = os_mbuf_get_pkthdr(&sdu_os_mbuf_pool, 0);
if (!sdu_rx) { if (!sdu_rx) {
@@ -259,7 +260,7 @@ bleprph_l2cap_coc_event_cb(struct ble_l2cap_event *event, void *arg)
for (int i = 0; i < event->receive.sdu_rx->om_len; i++) { for (int i = 0; i < event->receive.sdu_rx->om_len; i++) {
console_printf("%d ", event->receive.sdu_rx->om_data[i]); console_printf("%d ", event->receive.sdu_rx->om_data[i]);
} }
os_mbuf_free(event->receive.sdu_rx); os_mbuf_free_chain(event->receive.sdu_rx);
} }
fflush(stdout); fflush(stdout);
bleprph_l2cap_coc_accept(event->receive.conn_handle, bleprph_l2cap_coc_accept(event->receive.conn_handle,
@@ -5,9 +5,6 @@
# BT config # BT config
# #
CONFIG_BT_ENABLED=y CONFIG_BT_ENABLED=y
CONFIG_BTDM_CTRL_MODE_BLE_ONLY=y
CONFIG_BTDM_CTRL_MODE_BR_EDR_ONLY=n
CONFIG_BTDM_CTRL_MODE_BTDM=n
CONFIG_BT_BLUEDROID_ENABLED=n CONFIG_BT_BLUEDROID_ENABLED=n
CONFIG_BT_NIMBLE_ENABLED=y CONFIG_BT_NIMBLE_ENABLED=y
CONFIG_BT_NIMBLE_L2CAP_COC_MAX_NUM=1 CONFIG_BT_NIMBLE_L2CAP_COC_MAX_NUM=1

Some files were not shown because too many files have changed in this diff Show More