fix(nimble): Fix issues found in review for nimble examples

This commit is contained in:
Rahul Tank
2026-07-17 12:21:28 +05:30
committed by BOT
parent 64d3d6a9c3
commit 2961c16685
73 changed files with 1290 additions and 611 deletions

View File

@@ -83,6 +83,7 @@ void app_main(void) {
rc = gap_init();
if (rc != 0) {
ESP_LOGE(TAG, "failed to initialize GAP service, error code: %d", rc);
nimble_port_deinit();
return;
}
#endif

View File

@@ -35,6 +35,9 @@ static void start_advertising(void) {
/* Set device name */
name = ble_svc_gap_device_name();
if (name == NULL) {
name = DEVICE_NAME;
}
adv_fields.name = (uint8_t *)name;
adv_fields.name_len = strlen(name);
adv_fields.name_is_complete = 1;

View File

@@ -87,6 +87,7 @@ void app_main(void) {
rc = gap_init();
if (rc != 0) {
ESP_LOGE(TAG, "failed to initialize GAP service, error code: %d", rc);
nimble_port_deinit();
return;
}
#endif

View File

@@ -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
*/
@@ -64,6 +64,9 @@ static void start_advertising(void) {
/* Set device name */
name = ble_svc_gap_device_name();
if (name == NULL) {
name = DEVICE_NAME;
}
adv_fields.name = (uint8_t *)name;
adv_fields.name_len = strlen(name);
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);
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,
.itvl_max = desc.conn_itvl,
.latency = 3,
.supervision_timeout =
desc.supervision_timeout};
.supervision_timeout = supervision_timeout};
rc = ble_gap_update_params(event->connect.conn_handle, &params);
if (rc != 0) {
ESP_LOGE(
TAG,
"failed to update connection parameters, error code: %d",
rc);
return rc;
}
}
/* Connection failed, restart advertising */
else {
start_advertising();
}
return rc;
return 0;
/* Disconnect event */
case BLE_GAP_EVENT_DISCONNECT:

View File

@@ -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
*/
@@ -54,7 +54,7 @@ static void nimble_host_task(void *param) {
nimble_port_run();
/* Clean up at exit */
vTaskDelete(NULL);
nimble_port_freertos_deinit();
}
static void heart_rate_task(void *param) {
@@ -114,6 +114,7 @@ void app_main(void) {
rc = gap_init();
if (rc != 0) {
ESP_LOGE(TAG, "failed to initialize GAP service, error code: %d", rc);
nimble_port_deinit();
return;
}
#endif
@@ -122,6 +123,7 @@ void app_main(void) {
rc = gatt_svc_init();
if (rc != 0) {
ESP_LOGE(TAG, "failed to initialize GATT server, error code: %d", rc);
nimble_port_deinit();
return;
}
@@ -129,12 +131,7 @@ void app_main(void) {
nimble_host_config_init();
/* Start NimBLE host task thread and return */
rc = xTaskCreate(nimble_host_task, "NimBLE Host", 4 * 1024, NULL,
5, NULL);
if (rc != pdPASS) {
ESP_LOGE(TAG, "failed to create NimBLE host task");
return;
}
nimble_port_freertos_init(nimble_host_task);
rc = xTaskCreate(heart_rate_task, "Heart Rate", 4 * 1024, NULL, 5, NULL);
if (rc != pdPASS) {

View File

@@ -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
*/
@@ -64,6 +64,9 @@ static void start_advertising(void) {
/* Set device name */
name = ble_svc_gap_device_name();
if (name == NULL) {
name = DEVICE_NAME;
}
adv_fields.name = (uint8_t *)name;
adv_fields.name_len = strlen(name);
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_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,
.itvl_max = desc.conn_itvl,
.latency = 3,
.supervision_timeout =
desc.supervision_timeout};
.supervision_timeout = supervision_timeout};
rc = ble_gap_update_params(event->connect.conn_handle, &params);
if (rc != 0) {
ESP_LOGE(
TAG,
"failed to update connection parameters, error code: %d",
rc);
return rc;
}
}
/* Connection failed, restart advertising */
else {
start_advertising();
}
return rc;
return 0;
/* Disconnect event */
case BLE_GAP_EVENT_DISCONNECT:

View File

@@ -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
*/
@@ -164,9 +164,11 @@ error:
/* Public functions */
void send_heart_rate_indication(void) {
if (heart_rate_ind_status && heart_rate_chr_conn_handle_inited) {
ble_gatts_indicate(heart_rate_chr_conn_handle,
heart_rate_chr_val_handle);
ESP_LOGI(TAG, "heart rate indication sent!");
int rc = ble_gatts_indicate(heart_rate_chr_conn_handle,
heart_rate_chr_val_handle);
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 */
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 */
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;
}
}

View File

@@ -15,6 +15,7 @@
#include "host/ble_gap.h"
/* Public function declarations */
void gatt_svr_reset_heart_rate_subscription(void);
void send_heart_rate_indication(void);
void gatt_svr_register_cb(struct ble_gatt_register_ctxt *ctxt, void *arg);
int gatt_svr_subscribe_cb(struct ble_gap_event *event);

View File

@@ -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
*/
@@ -59,7 +59,7 @@ static void nimble_host_task(void *param) {
nimble_port_run();
/* Clean up at exit */
vTaskDelete(NULL);
nimble_port_freertos_deinit();
}
static void heart_rate_task(void *param) {
@@ -123,6 +123,7 @@ void app_main(void) {
rc = gap_init();
if (rc != 0) {
ESP_LOGE(TAG, "failed to initialize GAP service, error code: %d", rc);
nimble_port_deinit();
return;
}
#endif
@@ -131,6 +132,7 @@ void app_main(void) {
rc = gatt_svc_init();
if (rc != 0) {
ESP_LOGE(TAG, "failed to initialize GATT server, error code: %d", rc);
nimble_port_deinit();
return;
}
@@ -138,7 +140,12 @@ void app_main(void) {
nimble_host_config_init();
/* Start NimBLE host task thread and return */
xTaskCreate(nimble_host_task, "NimBLE Host", 4*1024, NULL, 5, NULL);
xTaskCreate(heart_rate_task, "Heart Rate", 4*1024, NULL, 5, NULL);
nimble_port_freertos_init(nimble_host_task);
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;
}

View File

@@ -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
*/
@@ -12,7 +12,6 @@
inline static void format_addr(char *addr_str, uint8_t addr[]);
static void print_conn_desc(struct ble_gap_conn_desc *desc);
static void start_advertising(void);
static void set_random_addr(void);
static int gap_event_handler(struct ble_gap_event *event, void *arg);
/* Private variables */
@@ -52,20 +51,6 @@ static void print_conn_desc(struct ble_gap_conn_desc *desc) {
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) {
/* Local variables */
int rc = 0;
@@ -79,6 +64,9 @@ static void start_advertising(void) {
/* Set device name */
name = ble_svc_gap_device_name();
if (name == NULL) {
name = DEVICE_NAME;
}
adv_fields.name = (uint8_t *)name;
adv_fields.name_len = strlen(name);
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",
event->disconnect.reason);
/* Reset heart rate subscription state */
gatt_svr_reset_heart_rate_subscription();
/* Restart advertising */
start_advertising();
return rc;
@@ -324,8 +315,9 @@ void adv_init(void) {
int rc = 0;
char addr_str[18] = {0};
/* Make sure we have proper BT identity address set */
set_random_addr();
/* Make sure we have proper BT identity address set.
* 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);
if (rc != 0) {
ESP_LOGE(TAG, "device does not have any available bt address!");

View File

@@ -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
*/
@@ -24,7 +24,7 @@ static uint8_t heart_rate_chr_val[2] = {0};
static uint16_t heart_rate_chr_val_handle;
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_ind_status = false;
@@ -165,6 +165,12 @@ error:
}
/* 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) {
/* Check if connection handle is initialized */
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) {
/* Check attribute 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 */
heart_rate_chr_conn_handle = event->subscribe.conn_handle;
heart_rate_chr_conn_handle_inited = true;
heart_rate_ind_status = event->subscribe.cur_indicate;
heart_rate_ind_status = true;
/* Check security status */
if (!is_connection_encrypted(event->subscribe.conn_handle)) {

View File

@@ -113,7 +113,7 @@ void ble_receive_apple_notification_source(uint8_t *message, uint16_t message_le
uint8_t CategoryID = message[2];
char *Cidstr = CategoryID_to_String(CategoryID);
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);
}
@@ -131,14 +131,18 @@ void ble_receive_apple_data_source(uint8_t *message, uint16_t message_len)
message_len);
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;
uint8_t *attrs = &message[5];
ESP_LOGI(NimBLE_ANCS_TAG, "recevice Notification Attributes response Command_id %d NotificationUID %" PRIu32, Command_id, NotificationUID);
while(remain_attr_len > 0) {
if (remain_attr_len < 3) {
ESP_LOGE(NimBLE_ANCS_TAG, "incomplete attribute header");
break;
}
uint8_t AttributeID = attrs[0];
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");
break;
}

View File

@@ -344,7 +344,7 @@ ext_ble_ancs_advertise(void)
params.connectable = 1;
/* 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.secondary_phy = BLE_HCI_LE_PHY_2M;
params.tx_power = 127;
@@ -413,11 +413,15 @@ ble_ancs_advertise(void)
fields.tx_pwr_lvl_is_present = 1;
fields.tx_pwr_lvl = BLE_HS_ADV_TX_PWR_LVL_AUTO;
#if CONFIG_BT_NIMBLE_GAP_SERVICE
name = ble_svc_gap_device_name();
fields.name = (uint8_t *)name;
fields.name_len = strlen(name);
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.uuids16_is_complete = 1;
@@ -485,6 +489,7 @@ ble_ancs_gap_event(struct ble_gap_event *event, void *arg)
#else
ble_ancs_advertise();
#endif
return 0;
}
/** Initiate security - It will perform
@@ -544,7 +549,11 @@ ble_ancs_gap_event(struct ble_gap_event *event, void *arg)
assert(rc == 0);
ble_ancs_print_conn_desc(&desc);
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);
if (rc != 0) {
return rc;
@@ -563,6 +572,10 @@ ble_ancs_gap_event(struct ble_gap_event *event, void *arg)
case BLE_GAP_EVENT_NOTIFY_RX:
/* Peer sent us a notification or indication. */
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);
uint8_t *notificationUID = &event->notify_rx.om->om_data[4];
if (event->notify_rx.om->om_data[0] == EventIDNotificationAdded &&
@@ -773,6 +786,13 @@ app_main(void)
/* XXX Need to have template for store */
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);
}

View File

@@ -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
*/
@@ -79,6 +79,10 @@ int blecent_on_subscribe(uint16_t conn_handle,
param.cb_arg=NULL;
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;
@@ -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);
if (rc != 0) {
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;
} else {
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);
if (rc != 0) {
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;
} else {
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);
} else if (error->status == BLE_ATT_ERR_INSUFFICIENT_AUTHEN) {
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;
} 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;
}
@@ -279,6 +289,7 @@ blecent_on_disc_complete(const struct peer *peer, int status, void *arg)
blecent_on_custom_read, (void *)peer);
if (rc != 0) {
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)
{
uint8_t own_addr_type;
struct ble_gap_disc_params disc_params;
struct ble_gap_disc_params disc_params = {0};
int rc;
/* 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;
#endif
for (int i = 1; i < adv_data_len - 1; i++) {
if (adv_data[i-1] == 0x03 && adv_data[i] == 0x5b && adv_data[i+1] == 0x18) {
found = 1;
MODLOG_DFLT(DEBUG, "Found 0x5b18 at index %d\n", i);
break;
struct ble_hs_adv_fields adv_fields;
if (ble_hs_adv_parse_fields(&adv_fields, adv_data, adv_data_len) == 0) {
for (int i = 0; i < adv_fields.num_uuids16; i++) {
if (adv_fields.uuids16[i].value == BLE_UUID_RANGING_SERVICE_VAL) {
found = 1;
break;
}
}
}
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;
}
#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);
if (rc != 0) {
MODLOG_DFLT(ERROR, "error determining address type; rc=%d\n", rc);
#if !(MYNEWT_VAL(BLE_HOST_ALLOW_CONNECT_WITH_SCAN))
blecent_scan();
#endif
return;
}
rc = ble_gap_connect(own_addr_type, addr, 30000, NULL,
blecent_gap_event, NULL);
if (rc != 0) {
MODLOG_DFLT(ERROR, "Connection failed.\n");
#if !(MYNEWT_VAL(BLE_HOST_ALLOW_CONNECT_WITH_SCAN))
blecent_scan();
#endif
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);
} else if( value[0] == RASCP_RSP_OPCODE_RSP_CODE) {
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){
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;
os_mbuf_copydata(event->notify_rx.om, 0, sizeof(uint16_t), &ranging_counter);
most_recent_peer_ranging_counter=ranging_counter;
most_recent_local_ranging_counter= ranging_counter;
most_recent_peer_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,
most_recent_peer_ranging_counter,most_recent_local_ranging_counter);
return 0;

View File

@@ -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_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];
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]);
{
const uint8_t *p = (const uint8_t *)event->subev_result.steps;
for (int i = 0; i < event->subev_result.num_steps_reported; i++) {
const struct cs_steps_data *step = (const struct cs_steps_data *)p;
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;
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_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];
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]);
{
const uint8_t *p = (const uint8_t *)event->subev_result_continue.steps;
for (int i = 0; i < event->subev_result_continue.num_steps_reported; i++) {
const struct cs_steps_data *step = (const struct cs_steps_data *)p;
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;
@@ -124,6 +132,7 @@ static int blecs_gap_event(struct ble_cs_event *event, void *arg)
if (idx==1) {
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);
} else {
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");
} 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");
ranging_subevent.type = BLE_CS_EVENT_SUBEVET_RESULT_CONTINUE;
ranging_subevent.subev_result_continue = event->subev_result_continue;
/* To
* 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
*/
ind ++;
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);
idx = 0;
ind = 0;
}
}
@@ -226,6 +238,9 @@ ext_bleprph_advertise(void)
/* start advertising */
rc = ble_gap_ext_adv_start(instance, 0, 0);
if (rc != 0) {
MODLOG_DFLT(ERROR, "error starting extended advertisement; rc=%d\n", rc);
}
}
#else
/**
@@ -266,9 +281,10 @@ bleprph_advertise(void)
fields.name_len = strlen(name);
fields.name_is_complete = 1;
#endif
fields.uuids16 = (ble_uuid16_t[]) {
static const ble_uuid16_t uuids16[] = {
BLE_UUID16_INIT(BLE_UUID_RANGING_SERVICE_VAL)
};
fields.uuids16 = uuids16;
fields.num_uuids16 = 1;
fields.uuids16_is_complete = 1;
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);
bleprph_print_conn_desc(&event->disconnect.conn);
MODLOG_DFLT(INFO, "\n");
idx = 0;
ind = 0;
most_recent_local_ranging_counter = -1;
/* Connection terminated; resume advertising. */
#if CONFIG_EXAMPLE_EXTENDED_ADV
ext_bleprph_advertise();
@@ -381,7 +400,6 @@ bleprph_gap_event(struct ble_gap_event *event, void *arg)
event->notify_tx.indication);
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);
}
return 0;
@@ -409,6 +427,9 @@ static void
bleprph_on_reset(int reason)
{
MODLOG_DFLT(ERROR, "Resetting state; reason=%d\n", reason);
idx = 0;
ind = 0;
most_recent_local_ranging_counter = -1;
}
static void

View File

@@ -54,10 +54,9 @@ static void start_periodic_adv_cte(uint8_t own_addr_type)
assert(rc == 0);
/* Configure advertising data */
struct ble_hs_adv_fields adv_fields = {
.name = (const uint8_t *)"CTE_Periodic_Adv",
.name_len = strlen((char *)adv_fields.name)
};
struct ble_hs_adv_fields adv_fields = {0};
adv_fields.name = (const uint8_t *)"CTE_Periodic_Adv";
adv_fields.name_len = strlen("CTE_Periodic_Adv");
struct os_mbuf *data = os_msys_get_pkthdr(BLE_HS_ADV_MAX_FIELD_SZ, 0);
assert(data);
@@ -198,7 +197,12 @@ void app_main(void)
ESP_LOGI(TAG, "%s", direction_finding_logo);
#if defined(CONFIG_EXAMPLE_ADV_DIRECTION_FINDING_AOD)
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)
ESP_LOGI(TAG, "DIRECTION_FINDING Example Periodic Adv AOA Mode");
#endif

View File

@@ -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);
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;
break;
}
@@ -184,7 +184,7 @@ static int periodic_sync_gap_event(struct ble_gap_event *event, void *arg)
#else
#error "Please select EXAMPLE_SYNC_BY_SID or EXAMPLE_SYNC_BY_NAME in menuconfig"
#endif
if (should_sync) {
if (should_sync && disc->periodic_adv_itvl != 0) {
ble_addr_t addr;
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)
{
ESP_LOGE(TAG, "Resetting state; reason=%d", reason);
is_synced = 0;
}
static void periodic_sync_on_sync(void)

View File

@@ -206,16 +206,17 @@ ext_ble_cts_cent_should_connect(const struct ble_gap_ext_disc_desc *disc)
{
int offset = 0;
int ad_struct_len = 0;
uint8_t test_addr[6];
if (disc->legacy_event_type != BLE_HCI_ADV_RPT_EVTYPE_ADV_IND &&
disc->legacy_event_type != BLE_HCI_ADV_RPT_EVTYPE_DIR_IND) {
uint8_t test_addr[6] = {0};
if (!(disc->props & BLE_HCI_ADV_CONN_MASK)) {
return 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);
/* Convert string to address */
peer_addr_parse(CONFIG_EXAMPLE_PEER_ADDR, test_addr);
/* Convert string to address */
if (peer_addr_parse(CONFIG_EXAMPLE_PEER_ADDR, test_addr) != 6) {
return 0;
}
if (memcmp(test_addr, disc->addr.val, sizeof(disc->addr.val)) != 0) {
return 0;
}
@@ -224,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
* service (0x1805).
*/
do {
while (offset < disc->length_data) {
if (offset + 1 >= disc->length_data) {
break;
}
ad_struct_len = disc->data[offset];
if (!ad_struct_len) {
break;
}
if (offset + ad_struct_len >= disc->length_data) {
break;
}
/* Search if cts UUID is advertised */
if (disc->data[offset + 1] == 0x03) {
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 &&
disc->data[offset + temp + 1] == 0x18) {
return 1;
@@ -243,7 +251,7 @@ ext_ble_cts_cent_should_connect(const struct ble_gap_ext_disc_desc *disc)
}
}
offset += ad_struct_len + 1;
} while ( offset < disc->length_data );
}
return 0;
}
@@ -255,7 +263,7 @@ ble_cts_cent_should_connect(const struct ble_gap_disc_desc *disc)
struct ble_hs_adv_fields fields;
int rc;
int i;
uint8_t test_addr[6];
uint8_t test_addr[6] = {0};
/* The device has to be advertising connectability. */
if (disc->event_type != BLE_HCI_ADV_RPT_EVTYPE_ADV_IND &&
disc->event_type != BLE_HCI_ADV_RPT_EVTYPE_DIR_IND) {
@@ -271,7 +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)) {
ESP_LOGI(tag, "Peer address from menuconfig: %s", CONFIG_EXAMPLE_PEER_ADDR);
/* Convert string to address */
peer_addr_parse(CONFIG_EXAMPLE_PEER_ADDR, test_addr);
if (peer_addr_parse(CONFIG_EXAMPLE_PEER_ADDR, test_addr) != 6) {
return 0;
}
if (memcmp(test_addr, disc->addr.val, sizeof(disc->addr.val)) != 0) {
return 0;
}
@@ -326,6 +336,9 @@ ble_cts_cent_connect_if_interesting(void *disc)
rc = ble_hs_id_infer_auto(0, &own_addr_type);
if (rc != 0) {
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;
}
@@ -343,6 +356,9 @@ ble_cts_cent_connect_if_interesting(void *disc)
MODLOG_DFLT(ERROR, "Error: Failed to connect to device; addr_type=%d "
"addr=%s; rc=%d\n",
addr->type, addr_str(addr->val), rc);
#if !(MYNEWT_VAL(BLE_HOST_ALLOW_CONNECT_WITH_SCAN))
ble_cts_cent_scan();
#endif
return;
}
}
@@ -365,11 +381,13 @@ static int
ble_cts_cent_gap_event(struct ble_gap_event *event, void *arg)
{
struct ble_gap_conn_desc desc;
struct ble_hs_adv_fields fields;
int rc;
switch (event->type) {
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,
event->disc.length_data);
if (rc != 0) {
@@ -381,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. */
ble_cts_cent_connect_if_interesting(&event->disc);
}
#endif
return 0;
case BLE_GAP_EVENT_CONNECT:
@@ -597,11 +617,14 @@ app_main(void)
/* Initialize data structures to track connected peers. */
#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);
assert(rc == 0);
#else
rc = peer_init(MYNEWT_VAL(BLE_MAX_CONNECTIONS), 64, 64, 64);
assert(rc == 0);
#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
/* Set the default device name. */

View File

@@ -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
*/
@@ -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;
/* day of week */
/* time gives day range of [0, 6], current_time_sevice
has day range of [1,7] */
ctime->et_256.d_d_t.day_of_week = timeinfo.tm_wday + 1;
/* tm_wday: 0=Sunday..6=Saturday; CTS: 1=Monday..7=Sunday */
ctime->et_256.d_d_t.day_of_week = (timeinfo.tm_wday == 0) ? 7 : timeinfo.tm_wday;
/* fractions_256 */
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_min = ctime.et_256.d_d_t.d_t.minutes;
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);
if (now == (time_t)-1) {
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.dst_offset = info.dst_offset;
gettimeofday(&last_updated, NULL);
adjust_reason = (CHANGE_OF_DST_MASK | CHANGE_OF_TIME_ZONE_MASK);
return 0;
}
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;
info->hours_since_update = hours_since_update;
}
adjust_reason = (CHANGE_OF_DST_MASK | CHANGE_OF_TIME_ZONE_MASK);
return 0;
}
int

View File

@@ -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
*/
@@ -79,8 +79,8 @@ ext_ble_cts_prph_advertise(void)
/* enable connectable advertising */
params.connectable = 1;
/* advertise using random addr */
params.own_addr_type = BLE_OWN_ADDR_PUBLIC;
/* advertise using configured addr */
params.own_addr_type = ble_cts_prph_addr_type;
params.primary_phy = BLE_HCI_LE_PHY_1M;
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_is_complete = 1;
fields.uuids16 = (ble_uuid16_t[]) {
static const ble_uuid16_t adv_uuids16[] = {
BLE_UUID16_INIT(BLE_SVC_CTS_UUID16)
};
fields.uuids16 = adv_uuids16;
fields.num_uuids16 = 1;
fields.uuids16_is_complete = 1;

View File

@@ -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),
&gatt_svr_chr_val, NULL);
ble_gatts_chr_updated(attr_handle);
MODLOG_DFLT(INFO, "Notification/Indication scheduled for "
"all subscribed peers.\n");
if (rc == 0) {
ble_gatts_chr_updated(attr_handle);
MODLOG_DFLT(INFO, "Notification/Indication scheduled for "
"all subscribed peers.\n");
}
return rc;
}
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) {
rc = os_mbuf_append(ctxt->om,
&gatt_svr_dsc_val,
sizeof(gatt_svr_chr_val));
sizeof(gatt_svr_dsc_val));
return rc == 0 ? 0 : BLE_ATT_ERR_INSUFFICIENT_RES;
}
goto unknown;

View File

@@ -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
*/
@@ -90,9 +90,11 @@ dynamic_service_advertise(void)
fields.name_len = strlen(name);
fields.name_is_complete = 1;
fields.uuids16 = (ble_uuid16_t[]) {
BLE_UUID16_INIT(GATT_SVR_SVC_ALERT_UUID)
};
/* Must be static: ble_gap_adv_set_fields stores the pointer, not the data.
* 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.uuids16_is_complete = 1;
@@ -143,8 +145,11 @@ dynamic_service_gap_event(struct ble_gap_event *event, void *arg)
event->connect.status);
if (event->connect.status == 0) {
rc = ble_gap_conn_find(event->connect.conn_handle, &desc);
assert(rc == 0);
dynamic_service_print_conn_desc(&desc);
if (rc != 0) {
MODLOG_DFLT(ERROR, "Failed to find connection; rc=%d\n", rc);
} else {
dynamic_service_print_conn_desc(&desc);
}
}
MODLOG_DFLT(INFO, "\n");
@@ -282,11 +287,19 @@ app_main(void)
#if MYNEWT_VAL(BLE_GATTS)
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. */
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
nimble_port_freertos_init(dynamic_service_host_task);

View File

@@ -78,6 +78,7 @@ enc_adv_data_cent_on_read(uint16_t conn_handle,
{
int rc;
struct ble_store_value_ead value_ead = {0};
struct ble_gap_conn_desc desc;
struct peer *p;
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);
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);
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)) {
/* Now perform GATT read procedures against the peer */
enc_adv_data_cent_read(peer);
} else {
ble_gap_terminate(peer->conn_handle, BLE_ERR_REM_USER_CONN_TERM);
}
}
#endif
@@ -289,7 +296,17 @@ enc_adv_data_cent_decrypt(uint8_t length_data, const uint8_t *data, const uint8_
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];
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:");
for (int i = 0; i < dec_data_len + 1; i++) {
@@ -318,9 +335,8 @@ enc_adv_data_cent_ext_should_connect(const struct ble_gap_ext_disc_desc *disc)
{
int offset = 0;
int ad_struct_len = 0;
uint8_t test_addr[6];
if (disc->legacy_event_type != BLE_HCI_ADV_RPT_EVTYPE_ADV_IND &&
disc->legacy_event_type != BLE_HCI_ADV_RPT_EVTYPE_DIR_IND) {
uint8_t test_addr[6] = {0};
if (!(disc->props & BLE_HCI_ADV_CONN_MASK)) {
return 0;
}
if (strlen(CONFIG_EXAMPLE_PEER_ADDR) && (strncmp(CONFIG_EXAMPLE_PEER_ADDR, "ADDR_ANY", strlen ("ADDR_ANY")) != 0)) {
@@ -355,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));
memcpy(&kmp[counter].peer_addr, &disc->addr.val, PEER_ADDR_VAL_SIZE);
kmp[counter].key_material_exist = false;
counter++;
if (counter > CONFIG_BT_NIMBLE_MAX_CONNECTIONS) {
@@ -382,7 +399,7 @@ enc_adv_data_cent_should_connect(const struct ble_gap_disc_desc *disc)
struct ble_hs_adv_fields fields;
int rc;
int i;
uint8_t test_addr[6];
uint8_t test_addr[6] = {0};
if (disc->event_type != BLE_HCI_ADV_RPT_EVTYPE_ADV_IND &&
disc->event_type != BLE_HCI_ADV_RPT_EVTYPE_DIR_IND) {
return 0;
@@ -416,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));
memcpy(&kmp[counter].peer_addr, &disc->addr.val, PEER_ADDR_VAL_SIZE);
kmp[counter].key_material_exist = false;
counter++;
if (counter > CONFIG_BT_NIMBLE_MAX_CONNECTIONS) {
@@ -470,6 +488,9 @@ enc_adv_data_cent_connect_if_interesting(void *disc)
rc = ble_hs_id_infer_auto(0, &own_addr_type);
if (rc != 0) {
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;
}
@@ -488,6 +509,9 @@ enc_adv_data_cent_connect_if_interesting(void *disc)
MODLOG_DFLT(ERROR, "Error: Failed to connect to device; addr_type=%d "
"addr=%s; rc=%d\n",
addr->type, addr_str(addr->val), rc);
#if !(MYNEWT_VAL(BLE_HOST_ALLOW_CONNECT_WITH_SCAN))
enc_adv_data_cent_scan();
#endif
return;
}
}
@@ -555,12 +579,15 @@ enc_adv_data_cent_gap_event(struct ble_gap_event *event, void *arg)
rc = peer_add(event->connect.conn_handle);
if (rc != 0) {
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;
}
rc = peer_set_addr(event->connect.conn_handle, desc.peer_id_addr.val);
if (rc != 0) {
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;
}
@@ -727,11 +754,14 @@ app_main(void)
/* Initialize data structures to track connected peers. */
#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);
assert(rc == 0);
#else
rc = peer_init(MYNEWT_VAL(BLE_MAX_CONNECTIONS), 64, 64, 64);
assert(rc == 0);
#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
/* Set the default device name. */

View File

@@ -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
*/
@@ -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),
&gatt_svr_chr_val, NULL);
ble_gatts_chr_updated(attr_handle);
MODLOG_DFLT(INFO, "Notification/Indication scheduled for "
"all subscribed peers.\n");
if (rc == 0) {
ble_gatts_chr_updated(attr_handle);
MODLOG_DFLT(INFO, "Notification/Indication scheduled for "
"all subscribed peers.\n");
}
return rc;
}
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) {
rc = os_mbuf_append(ctxt->om,
&gatt_svr_dsc_val,
sizeof(gatt_svr_chr_val));
sizeof(gatt_svr_dsc_val));
return rc == 0 ? 0 : BLE_ATT_ERR_INSUFFICIENT_RES;
}
goto unknown;

View File

@@ -140,8 +140,8 @@ enc_adv_data_prph_ext_advertise(void)
/* enable connectable advertising */
params.connectable = 1;
/* advertise using random addr */
params.own_addr_type = BLE_OWN_ADDR_PUBLIC;
/* advertise using configured addr */
params.own_addr_type = own_addr_type;
params.primary_phy = BLE_HCI_LE_PHY_1M;
params.secondary_phy = BLE_HCI_LE_PHY_2M;
@@ -163,6 +163,10 @@ enc_adv_data_prph_ext_advertise(void)
/* get mbuf with adv data */
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));
temp[sizeof(ext_adv_pattern)] = 1 + encrypted_adv_data_len;
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;
int rc;
const unsigned encrypted_adv_data_len = BLE_EAD_ENCRYPTED_PAYLOAD_SIZE(sizeof(unencrypted_adv_pattern));
uint8_t encrypted_adv_data[encrypted_adv_data_len];
static const ble_uuid16_t adv_uuids16[] = {
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);
/* First check if any instance is already active */
@@ -207,8 +214,6 @@ enc_adv_data_prph_advertise(void)
memset (&params, 0, sizeof(params));
memset (&fields, 0, sizeof(fields));
own_addr_type = BLE_OWN_ADDR_PUBLIC;
/* enable connectable advertising */
params.conn_mode = BLE_GAP_CONN_MODE_UND;
params.disc_mode = BLE_GAP_DISC_MODE_GEN;
@@ -222,9 +227,7 @@ enc_adv_data_prph_advertise(void)
fields.name_len = 3;
fields.name_is_complete = 1;
fields.uuids16 = (ble_uuid16_t[]) {
BLE_UUID16_INIT(0x2C01) /** For the central to recognise this device */
};
fields.uuids16 = adv_uuids16;
fields.num_uuids16 = 1;
fields.uuids16_is_complete = 1;
@@ -397,17 +400,22 @@ enc_adv_data_prph_on_reset(int reason)
static void
ble_app_set_addr(void)
{
ble_addr_t addr;
ble_addr_t addr = {0};
int rc;
/* generate new non-resolvable private address */
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 */
rc = ble_hs_id_set_rnd(addr.val);
assert(rc == 0);
if (rc != 0) {
MODLOG_DFLT(ERROR, "Failed to set random address; rc=%d\n", rc);
return;
}
}
#endif

View File

@@ -17,16 +17,16 @@ static uint8_t own_addr_type;
static int blecoex_gap_event(struct ble_gap_event *event, void *arg);
void ble_coex_advertise(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,
struct ble_gatt_access_ctxt *ctxt, void *arg) {
int rc = 0;
if (ctxt->op == BLE_GATT_ACCESS_OP_READ_CHR) {
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) {
return rc;
return BLE_ATT_ERR_INSUFFICIENT_RES;
}
} else if (ctxt->op == BLE_GATT_ACCESS_OP_READ_DSC) {
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];
int rc;
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,
BLE_UUID16_DECLARE(BLECOEX_SVC_ALERT_UUID),
@@ -216,7 +220,7 @@ blecent_on_write(uint16_t conn_handle,
return 0;
err:
/* 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];
int rc;
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,
BLE_UUID16_DECLARE(BLECOEX_SVC_ALERT_UUID),
@@ -263,7 +271,7 @@ blecent_on_read(uint16_t conn_handle,
return 0;
err:
/* 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",
u8p[5], u8p[4], u8p[3], u8p[2], u8p[1], u8p[0]);
}
if (client_connect == 1) {
client_connect = 2;
if (client_connect == 1 ) {
client_connect = 2;
/* Remember peer. */
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. */
rc = peer_add(event->connect.conn_handle);
if (rc != 0) {
MODLOG_DFLT(ERROR, "Failed to add peer; rc=%d\n", rc);
restart_coex();
/* Perform service discovery */
rc = peer_disc_all(event->connect.conn_handle,
blecent_on_disc_complete, NULL);
if(rc != 0) {
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;
}
}
/* Perform service discovery */
rc = peer_disc_all(event->connect.conn_handle,
blecent_on_disc_complete, NULL);
if(rc != 0) {
MODLOG_DFLT(ERROR, "Failed to discover services; rc=%d\n", rc);
} else {
if (client_connect == 1) {
MODLOG_DFLT(ERROR, "Client connection failed; status=%d\n", event->connect.status);
restart_coex();
}
}
@@ -393,6 +418,7 @@ blecoex_gap_event(struct ble_gap_event *event, void *arg)
case BLE_GAP_EVENT_DISCONNECT:
MODLOG_DFLT(INFO, "Disconnect \n");
peer_delete(event->disconnect.conn.conn_handle);
restart_coex();
return 0;
@@ -497,9 +523,10 @@ ble_coex_advertise(void)
fields.name_is_complete = 1;
}
fields.uuids16 = (ble_uuid16_t[]) {
static const ble_uuid16_t adv_uuids16[] = {
BLE_UUID16_INIT(BLECOEX_SVC_ALERT_UUID)
};
fields.uuids16 = adv_uuids16;
fields.num_uuids16 = 1;
fields.uuids16_is_complete = 1;
@@ -569,11 +596,17 @@ void app_main(void)
}
ble_hs_cfg.sync_cb = on_sync;
int rc;
#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
peer_init(MYNEWT_VAL(BLE_MAX_CONNECTIONS), 64, 64, 64);
rc = peer_init(MYNEWT_VAL(BLE_MAX_CONNECTIONS), 64, 64, 64);
#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
ble_svc_gap_init();
@@ -585,8 +618,18 @@ void app_main(void)
ble_svc_ans_init();
#endif
ble_gatts_count_cfg(gatt_svr_svcs);
ble_gatts_add_svcs(gatt_svr_svcs);
rc = ble_gatts_count_cfg(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);
}

View File

@@ -63,6 +63,15 @@ ble_htp_cent_on_subscribe(uint16_t conn_handle,
uint8_t value[2];
int rc;
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,
BLE_UUID16_DECLARE(BLE_SVC_HTP_UUID16),
@@ -86,9 +95,7 @@ ble_htp_cent_on_subscribe(uint16_t conn_handle,
return 0;
err:
/* Terminate the connection. */
return ble_gap_terminate(peer->conn_handle, BLE_ERR_REM_USER_CONN_TERM);
return 0;
return ble_gap_terminate(conn_handle, BLE_ERR_REM_USER_CONN_TERM);
}
/**
@@ -113,6 +120,15 @@ ble_htp_cent_on_write(uint16_t conn_handle,
uint8_t value[2];
int rc;
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,
BLE_UUID16_DECLARE(BLE_SVC_HTP_UUID16),
@@ -137,7 +153,7 @@ ble_htp_cent_on_write(uint16_t conn_handle,
return 0;
err:
/* 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) {
MODLOG_DFLT(INFO, " attr_handle=%d value=", attr->handle);
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");
@@ -319,18 +338,15 @@ ext_ble_htp_cent_should_connect(const struct ble_gap_ext_disc_desc *disc)
{
int offset = 0;
int ad_struct_len = 0;
uint8_t test_addr[6];
uint8_t parsed_addr[6];
if (disc->legacy_event_type != BLE_HCI_ADV_RPT_EVTYPE_ADV_IND &&
disc->legacy_event_type != BLE_HCI_ADV_RPT_EVTYPE_DIR_IND) {
uint8_t test_addr[6] = {0};
if (!(disc->props & BLE_HCI_ADV_CONN_MASK)) {
return 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);
/* Convert string to address */
peer_addr_parse(CONFIG_EXAMPLE_PEER_ADDR, parsed_addr);
for (int i = 0; i < 6; i++) {
test_addr[i] = parsed_addr[5 - i];
if (peer_addr_parse(CONFIG_EXAMPLE_PEER_ADDR, test_addr) != 6) {
return 0;
}
if (memcmp(test_addr, disc->addr.val, sizeof(disc->addr.val)) != 0) {
@@ -349,9 +365,9 @@ ext_ble_htp_cent_should_connect(const struct ble_gap_ext_disc_desc *disc)
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 + 2] == 0x18 && disc->data[offset + 3] == 0x09 ) {
if ( disc->data[offset + 2] == 0x09 && disc->data[offset + 3] == 0x18 ) {
return 1;
}
}
@@ -369,7 +385,7 @@ ble_htp_cent_should_connect(const struct ble_gap_disc_desc *disc)
struct ble_hs_adv_fields fields;
int rc;
int i;
uint8_t test_addr[6];
uint8_t test_addr[6] = {0};
/* The device has to be advertising connectability. */
if (disc->event_type != BLE_HCI_ADV_RPT_EVTYPE_ADV_IND &&
disc->event_type != BLE_HCI_ADV_RPT_EVTYPE_DIR_IND) {
@@ -385,7 +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)) {
ESP_LOGI(tag, "Peer address from menuconfig: %s", CONFIG_EXAMPLE_PEER_ADDR);
/* Convert string to address */
peer_addr_parse(CONFIG_EXAMPLE_PEER_ADDR, test_addr);
if (peer_addr_parse(CONFIG_EXAMPLE_PEER_ADDR, test_addr) != 6) {
return 0;
}
if (memcmp(test_addr, disc->addr.val, sizeof(disc->addr.val)) != 0) {
return 0;
}
@@ -440,6 +458,9 @@ ble_htp_cent_connect_if_interesting(void *disc)
rc = ble_hs_id_infer_auto(0, &own_addr_type);
if (rc != 0) {
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;
}
@@ -457,6 +478,9 @@ ble_htp_cent_connect_if_interesting(void *disc)
MODLOG_DFLT(ERROR, "Error: Failed to connect to device; addr_type=%d "
"addr=%s; rc=%d\n",
addr->type, addr_str(addr->val), rc);
#if !(MYNEWT_VAL(BLE_HOST_ALLOW_CONNECT_WITH_SCAN))
ble_htp_cent_scan();
#endif
return;
}
}
@@ -479,11 +503,13 @@ static int
ble_htp_cent_gap_event(struct ble_gap_event *event, void *arg)
{
struct ble_gap_conn_desc desc;
struct ble_hs_adv_fields fields;
int rc;
switch (event->type) {
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,
event->disc.length_data);
if (rc != 0) {
@@ -495,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. */
ble_htp_cent_connect_if_interesting(&event->disc);
}
#endif
return 0;
case BLE_GAP_EVENT_CONNECT:
@@ -727,11 +755,14 @@ app_main(void)
/* Initialize data structures to track connected peers. */
#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);
assert(rc == 0);
#else
rc = peer_init(MYNEWT_VAL(BLE_MAX_CONNECTIONS), 64, 64, 64);
assert(rc == 0);
#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
/* Set the default device name. */
rc = ble_svc_gap_device_name_set("nimble-htp-cent");

View File

@@ -15,7 +15,7 @@
static const char *manuf_name = "ESP32 devkitC";
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
gatt_svr_chr_access_device_info(uint16_t conn_handle, uint16_t attr_handle,
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) {
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;
}

View File

@@ -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
*/
@@ -20,7 +20,7 @@
static uint8_t ext_adv_pattern_1[] = {
0x02, BLE_HS_ADV_TYPE_FLAGS, 0x06,
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',
};
#endif
@@ -81,8 +81,8 @@ ext_ble_htp_prph_advertise(void)
/* enable connectable advertising */
params.connectable = 1;
/* advertise using random addr */
params.own_addr_type = BLE_OWN_ADDR_PUBLIC;
/* advertise using configured addr */
params.own_addr_type = ble_htp_prph_addr_type;
params.primary_phy = BLE_HCI_LE_PHY_1M;
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_is_complete = 1;
fields.uuids16 = (ble_uuid16_t[]) {
static const ble_uuid16_t adv_uuids16[] = {
BLE_UUID16_INIT(BLE_SVC_HTP_UUID16)
};
fields.uuids16 = adv_uuids16;
fields.num_uuids16 = 1;
fields.uuids16_is_complete = 1;
@@ -178,23 +179,16 @@ ble_htp_prph_advertise(void)
static 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 */
static void
ble_htp_prph_tx_htp_reset(void)
{
int rc;
if (xTimerReset(ble_htp_prph_tx_timer, 1000 / portTICK_PERIOD_MS ) == pdPASS) {
rc = 0;
} else {
rc = 1;
if (xTimerReset(ble_htp_prph_tx_timer, 0) != pdPASS) {
MODLOG_DFLT(ERROR, "Failed to reset HTP timer\n");
}
assert(rc == 0);
}
/* This function notifies intermediate temperature to the client */
@@ -372,6 +366,11 @@ void app_main(void)
/* name, period/time, auto reload, timer ID, callback */
ble_htp_prph_tx_timer = xTimerCreate("ble_htp_prph_tx_timer", pdMS_TO_TICKS(1000), pdTRUE,
(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)
int rc;

View File

@@ -68,16 +68,9 @@ blecent_l2cap_coc_send_data(struct ble_l2cap_chan *chan)
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) {
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;
}
@@ -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);
if (rc != 0) {
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:
console_printf("LE CoC disconnected, chan: %p\n",
event->disconnect.chan);
coc_chan = NULL;
return 0;
default:
@@ -266,8 +260,7 @@ ext_blecent_should_connect(const struct ble_gap_ext_disc_desc *disc)
int offset = 0;
int ad_struct_len = 0;
uint8_t test_addr[6];
if (disc->legacy_event_type != BLE_HCI_ADV_RPT_EVTYPE_ADV_IND &&
disc->legacy_event_type != BLE_HCI_ADV_RPT_EVTYPE_DIR_IND) {
if (!(disc->props & BLE_HCI_ADV_CONN_MASK)) {
return 0;
}
if (strlen(CONFIG_EXAMPLE_PEER_ADDR) &&
@@ -296,11 +289,11 @@ ext_blecent_should_connect(const struct ble_gap_ext_disc_desc *disc)
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 &&
disc->data[offset + 1] == 0x03 &&
disc->data[offset + 2] == 0x18 &&
disc->data[offset + 3] == 0x12) {
disc->data[offset + 2] == 0x12 &&
disc->data[offset + 3] == 0x18) {
return 1;
}
@@ -386,6 +379,9 @@ blecent_connect_if_interesting(void *disc)
rc = ble_hs_id_infer_auto(0, &own_addr_type);
if (rc != 0) {
MODLOG_DFLT(ERROR, "error determining address type; rc=%d\n", rc);
#if !(MYNEWT_VAL(BLE_HOST_ALLOW_CONNECT_WITH_SCAN))
blecent_scan();
#endif
return;
}
@@ -404,6 +400,9 @@ blecent_connect_if_interesting(void *disc)
MODLOG_DFLT(ERROR, "Error: Failed to connect to device; addr_type=%d "
"addr=%s; rc=%d\n",
addr->type, addr_str(addr->val), rc);
#if !(MYNEWT_VAL(BLE_HOST_ALLOW_CONNECT_WITH_SCAN))
blecent_scan();
#endif
return;
}
}
@@ -491,6 +490,10 @@ blecent_gap_event(struct ble_gap_event *event, void *arg)
print_conn_desc(&event->disconnect.conn);
MODLOG_DFLT(INFO, "\n");
#if MYNEWT_VAL(BLE_L2CAP_COC_MAX_NUM) >= 1
coc_chan = NULL;
#endif
/* Forget about peer. */
peer_delete(event->disconnect.conn.conn_handle);
@@ -536,6 +539,9 @@ static void
blecent_on_reset(int 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

View File

@@ -18,7 +18,7 @@
static uint8_t ext_adv_pattern_1[] = {
0x02, BLE_HS_ADV_TYPE_FLAGS, 0x06,
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',
};
#endif
@@ -164,9 +164,10 @@ bleprph_advertise(void)
fields.name_len = strlen(name);
fields.name_is_complete = 1;
fields.uuids16 = (ble_uuid16_t[]) {
static const ble_uuid16_t adv_uuids16[] = {
BLE_UUID16_INIT(L2CAP_COC_UUID)
};
fields.uuids16 = adv_uuids16;
fields.num_uuids16 = 1;
fields.uuids16_is_complete = 1;
@@ -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++) {
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);
bleprph_l2cap_coc_accept(event->receive.conn_handle,

View File

@@ -109,6 +109,9 @@ gatt_svc_access(uint16_t conn_handle, uint16_t attr_handle,
case BLE_GATT_ACCESS_OP_WRITE_CHR:
MODLOG_DFLT(INFO, "Characteristic write; conn_handle=%d attr_handle=%d",
conn_handle, attr_handle);
if (OS_MBUF_PKTLEN(ctxt->om) != sizeof(gatt_svr_chr_val)) {
return BLE_ATT_ERR_INVALID_ATTR_VALUE_LEN;
}
rc = os_mbuf_copydata(ctxt->om,
0,
sizeof(gatt_svr_chr_val),

View File

@@ -374,7 +374,7 @@ ble_multi_adv_gap_event(struct ble_gap_event *event, void *arg)
assert(rc == 0);
ble_multi_adv_print_conn_desc(&desc);
ble_multi_perform_gatt_proc(desc.our_id_addr);
ble_multi_perform_gatt_proc(desc.our_ota_addr);
}
MODLOG_DFLT(INFO, "\n");
return 0;

View File

@@ -102,18 +102,21 @@ ble_cent_client_gap_event(struct ble_gap_event *event, void *arg)
case BLE_GAP_EVENT_CONNECT:
if (event->connect.status == 0) {
s_ble_multi_conn_num++;
ESP_LOGI(TAG, "Connection established. Handle:%d, Total:%d", event->connect.conn_handle,
++s_ble_multi_conn_num);
s_ble_multi_conn_num);
/* Remember peer. */
rc = peer_add(event->connect.conn_handle);
if (rc != 0) {
ESP_LOGE(TAG, "Failed to add peer; rc=%d\n", rc);
ble_gap_terminate(event->connect.conn_handle, BLE_ERR_REM_USER_CONN_TERM);
} else {
/* Perform service discovery */
rc = peer_disc_svc_by_uuid(event->connect.conn_handle, remote_svc_uuid,
ble_cent_on_disc_complete, NULL);
if(rc != 0) {
ESP_LOGE(TAG, "Failed to discover services; rc=%d\n", rc);
ble_gap_terminate(event->connect.conn_handle, BLE_ERR_REM_USER_CONN_TERM);
}
}
} else {
@@ -130,9 +133,10 @@ ble_cent_client_gap_event(struct ble_gap_event *event, void *arg)
/* Forget about peer. */
peer_delete(event->disconnect.conn.conn_handle);
s_ble_multi_conn_num--;
ESP_LOGI(TAG, "Central disconnected; Handle:%d, Reason=%d, Total:%d",
event->disconnect.conn.conn_handle, event->disconnect.reason,
--s_ble_multi_conn_num);
s_ble_multi_conn_num);
/* Resume scanning. */
ble_cent_scan();
@@ -282,8 +286,8 @@ ble_cent_scan(void)
return;
}
struct ble_gap_ext_disc_params uncoded_disc_params;
struct ble_gap_ext_disc_params coded_disc_params;
struct ble_gap_ext_disc_params uncoded_disc_params = {0};
struct ble_gap_ext_disc_params coded_disc_params = {0};
/* Perform a passive scan. I.e., don't send follow-up scan requests to
* each advertiser.
@@ -409,8 +413,10 @@ blecent_on_sync(void)
* the `MINIMUM_CONN_INTERVAL` should be greater than ((261 * 8us) * 2 + 150us) * 10 = 43260us.
*
*/
rc = ble_gap_common_factor_set(true, (BLE_PREF_CONN_ITVL_MS * 1000) / 625);
assert(rc == 0);
if (BLE_PEER_MAX_NUM > 0) {
rc = ble_gap_common_factor_set(true, (BLE_PREF_CONN_ITVL_MS * 1000) / 625);
assert(rc == 0);
}
/* Make sure we have proper identity address set (public preferred) */
rc = ble_hs_util_ensure_addr(0);

View File

@@ -24,7 +24,7 @@ static uint8_t ext_adv_pattern_1[] = {
#endif
static const char *TAG = "ESP_MULTI_CONN_PRPH";
static uint8_t s_ble_prph_conn_num = 0;
static volatile uint8_t s_ble_prph_conn_num = 0;
static SemaphoreHandle_t s_sem_restart_adv = NULL;
static int ble_prph_gap_event(struct ble_gap_event *event, void *arg);
@@ -194,8 +194,9 @@ ble_prph_gap_event(struct ble_gap_event *event, void *arg)
case BLE_GAP_EVENT_CONNECT:
if (event->connect.status == 0) {
/* A new connection was established. */
s_ble_prph_conn_num++;
ESP_LOGI(TAG, "Connection established. Handle:%d. Total:%d", event->connect.conn_handle,
++s_ble_prph_conn_num);
s_ble_prph_conn_num);
#if CONFIG_EXAMPLE_RESTART_ADV_AFTER_CONNECTED
ble_prph_restart_adv();
#endif //CONFIG_EXAMPLE_RESTART_ADV_AFTER_CONNECTED
@@ -206,8 +207,9 @@ ble_prph_gap_event(struct ble_gap_event *event, void *arg)
return 0;
case BLE_GAP_EVENT_DISCONNECT:
s_ble_prph_conn_num--;
ESP_LOGI(TAG, "Disconnect. Handle:%d. Reason=%d. Total:%d",
event->disconnect.conn.conn_handle, event->disconnect.reason, --s_ble_prph_conn_num);
event->disconnect.conn.conn_handle, event->disconnect.reason, s_ble_prph_conn_num);
/* Connection terminated; resume advertising. */
ble_prph_restart_adv();

View File

@@ -42,11 +42,20 @@ gap_event_cb(struct ble_gap_event *event, void *arg)
event->periodic_adv_subev_data_req.subevent_data_count);
sent_num = event->periodic_adv_subev_data_req.subevent_data_count;
if (sent_num > BLE_PAWR_NUM_SUBEVTS) {
ESP_LOGE(TAG, "subevent_data_count %d exceeds max %d", sent_num, BLE_PAWR_NUM_SUBEVTS);
sent_num = BLE_PAWR_NUM_SUBEVTS;
}
uint8_t actual_sent = 0;
for (uint8_t i = 0; i < sent_num; i++) {
data = os_msys_get_pkthdr(BLE_PAWR_SUB_DATA_LEN, 0);
if (!data) {
ESP_LOGE(TAG, "No memory, %d", i);
break;
for (uint8_t j = 0; j < i; j++) {
os_mbuf_free_chain(sub_data_params[j].data);
sub_data_params[j].data = NULL;
}
return 0;
}
sub = (i + event->periodic_adv_subev_data_req.subevent_start) % BLE_PAWR_NUM_SUBEVTS;
memset(&sub_data_pattern[1], sub, BLE_PAWR_SUB_DATA_LEN - 1);
@@ -56,10 +65,11 @@ gap_event_cb(struct ble_gap_event *event, void *arg)
sub_data_params[i].response_slot_count = BLE_PAWR_NUM_RSP_SLOTS;
sub_data_params[i].data = data;
sub_data_pattern[0]++;
actual_sent++;
}
rc = ble_gap_set_periodic_adv_subev_data(event->periodic_adv_subev_data_req.adv_handle,
sent_num, sub_data_params);
actual_sent, sub_data_params);
if (rc) {
ESP_LOGE(TAG, "Failed to set Subevent Data, rc = 0x%x", rc);
}
@@ -72,7 +82,9 @@ gap_event_cb(struct ble_gap_event *event, void *arg)
event->periodic_adv_response.response_slot,
event->periodic_adv_response.data_length);
const uint8_t *data = event->periodic_adv_response.data;
ESP_LOGI(TAG, "data: 0x%0x, 0x%0x", data[0], data[1]);
if (data != NULL && event->periodic_adv_response.data_length >= 2) {
ESP_LOGI(TAG, "data: 0x%0x, 0x%0x", data[0], data[1]);
}
} else {
ESP_LOGE(TAG, "[Response] subevent:%d, response_slot:%d, rsp_data status:%d",
event->periodic_adv_response.subevent,
@@ -102,8 +114,7 @@ start_periodic_adv(uint8_t own_addr_type)
#endif
/* Get the local address. */
uint8_t addr_type = own_addr_type == BLE_OWN_ADDR_RANDOM ? BLE_ADDR_RANDOM : BLE_ADDR_PUBLIC;
rc = ble_hs_id_copy_addr(addr_type, addr, NULL);
rc = ble_hs_id_copy_addr(own_addr_type, addr, NULL);
assert (rc == 0);
ESP_LOGI(TAG, "Device Address %02x:%02x:%02x:%02x:%02x:%02x", addr[5], addr[4], addr[3],

View File

@@ -47,7 +47,7 @@ gap_event_cb(struct ble_gap_event *event, void *arg)
return 0;
}
if (disc->periodic_adv_itvl && fields.name_len && !memcmp(fields.name, TARGET_NAME, strlen(TARGET_NAME))) {
if (disc->periodic_adv_itvl && fields.name_len == strlen(TARGET_NAME) && !memcmp(fields.name, TARGET_NAME, fields.name_len)) {
create_periodic_sync(disc);
}
return 0;
@@ -71,6 +71,10 @@ gap_event_cb(struct ble_gap_event *event, void *arg)
return 0;
}
// create a special data for checking manually in ADV side
if (event->periodic_report.data == NULL || event->periodic_report.data_length == 0) {
os_mbuf_free_chain(data);
return 0;
}
sub_data_pattern[0] = event->periodic_report.data[0];
memset(sub_data_pattern + 1, event->periodic_report.subevent, BLE_PAWR_RSP_DATA_LEN - 1);
os_mbuf_append(data, sub_data_pattern, BLE_PAWR_RSP_DATA_LEN);
@@ -190,6 +194,7 @@ static void
on_reset(int reason)
{
ESP_LOGE(TAG, "Resetting state; reason=%d\n", reason);
synced = false;
}
static void

View File

@@ -151,6 +151,10 @@ gap_event_cb(struct ble_gap_event *event, void *arg)
event->periodic_adv_response.response_slot,
event->periodic_adv_response.data_length);
const uint8_t *data = event->periodic_adv_response.data;
if (data == NULL || event->periodic_adv_response.data_length < 10) {
ESP_LOGE(TAG, "Invalid response data: NULL or too short (%d)", event->periodic_adv_response.data_length);
return 0;
}
ESP_LOGI(TAG, "data: 0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x",
data[0], data[1], data[2], data[3], data[4], data[5], data[6], data[7], data[8], data[9]);
@@ -165,10 +169,10 @@ gap_event_cb(struct ble_gap_event *event, void *arg)
rc = ble_gap_connect_with_synced(own_addr_type,adv_handle,subevent,&peer_addr,BLE_PAWR_CONN_TIMEOUT_MS,phy_mask,NULL,NULL,NULL,gap_event_cb,NULL);
if (rc != 0 ) {
ESP_LOGI(TAG,"Error: Failed to connect to device , rc = %d\n",rc);
}else {
} else {
ESP_LOGI(TAG,"Connection create sent, adv handle = %d, subevent = %d", adv_handle, subevent);
conn = 1;
}
conn = 1;
}
} else {
ESP_LOGE(TAG, "[Response] subevent:%d, response_slot:%d, rsp_data status:%d",
@@ -269,6 +273,7 @@ static void
on_reset(int reason)
{
ESP_LOGE(TAG, "Resetting state; reason=%d\n", reason);
conn = 0;
}
static void

View File

@@ -100,7 +100,7 @@ gap_event_cb(struct ble_gap_event *event, void *arg)
return 0;
}
if (fields.name_len && !memcmp(fields.name, TARGET_NAME, strlen(TARGET_NAME))) {
if (fields.name_len == strlen(TARGET_NAME) && !memcmp(fields.name, TARGET_NAME, fields.name_len)) {
create_periodic_sync(disc);
}
return 0;
@@ -229,6 +229,11 @@ start_scan(void)
int rc;
struct ble_gap_ext_disc_params disc_params;
/* Cancel any active scan first to reset the duplicate filter. */
if (ble_gap_disc_active()) {
ble_gap_disc_cancel();
}
/* Perform a passive scan. I.e., don't send follow-up scan requests to
* each advertiser.
*/
@@ -258,6 +263,7 @@ static void
on_reset(int reason)
{
ESP_LOGE(TAG, "Resetting state; reason=%d\n", reason);
synced = false;
}
static void

View File

@@ -106,7 +106,6 @@ periodic_sync_gap_event(struct ble_gap_event *event, void *arg)
if (disc->sid == 2 && synced == 0) {
struct ble_gap_periodic_sync_params params = {0};
int rc;
synced++;
params.skip = 10;
params.sync_timeout = 1000;
@@ -117,7 +116,11 @@ periodic_sync_gap_event(struct ble_gap_event *event, void *arg)
params.filter_duplicates = 1;
#endif
rc = ble_gap_periodic_adv_sync_create(&disc->addr, disc->sid, &params, periodic_sync_gap_event, NULL);
assert(rc == 0);
if (rc != 0) {
MODLOG_DFLT(ERROR, "Failed to create periodic sync; rc=%d\n", rc);
} else {
synced++;
}
}
return 0;
}
@@ -151,6 +154,7 @@ static void
periodic_sync_on_reset(int reason)
{
MODLOG_DFLT(ERROR, "Resetting state; reason=%d\n", reason);
synced = 0;
}
static void

View File

@@ -66,17 +66,28 @@ blecent_on_read(uint16_t conn_handle,
MODLOG_DFLT(INFO, " attr_handle=%d value=", attr->handle);
print_mbuf(attr->om);
}
MODLOG_DFLT(INFO, "\n");
if (error->status != 0) {
MODLOG_DFLT(ERROR, "Read failed; terminating connection\n");
ble_gap_terminate(conn_handle, BLE_ERR_REM_USER_CONN_TERM);
return 0;
}
/* Write 1000 bytes to the LE PHY characteristic.*/
const struct peer_chr *chr;
int len = 1000;
uint8_t value[len];
const int len = 1000;
uint8_t *value;
int rc;
struct os_mbuf *txom;
const struct peer *peer = peer_find(conn_handle);
if (peer == NULL) {
MODLOG_DFLT(ERROR, "Error: peer not found for conn_handle=%d\n", conn_handle);
ble_gap_terminate(conn_handle, BLE_ERR_REM_USER_CONN_TERM);
return 0;
}
chr = peer_chr_find_uuid(peer,
BLE_UUID16_DECLARE(LE_PHY_UUID16),
BLE_UUID16_DECLARE(LE_PHY_CHR_UUID16));
@@ -86,12 +97,19 @@ blecent_on_read(uint16_t conn_handle,
goto err;
}
value = malloc(len);
if (value == NULL) {
MODLOG_DFLT(ERROR, "Insufficient memory\n");
goto err;
}
/* Fill the value array with data */
for (int i = 0; i < len; i++) {
value[i] = i;
}
txom = ble_hs_mbuf_from_flat(&value, len);
txom = ble_hs_mbuf_from_flat(value, len);
free(value);
if (!txom) {
MODLOG_DFLT(ERROR, "Insufficient memory");
goto err;
@@ -108,7 +126,7 @@ blecent_on_read(uint16_t conn_handle,
err:
/* 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);
}
static void
@@ -234,18 +252,15 @@ ext_blecent_should_connect(const struct ble_gap_ext_disc_desc *disc)
{
int offset = 0;
int ad_struct_len = 0;
uint8_t test_addr[6];
if (disc->legacy_event_type != BLE_HCI_ADV_RPT_EVTYPE_ADV_IND &&
disc->legacy_event_type != BLE_HCI_ADV_RPT_EVTYPE_DIR_IND) {
uint8_t test_addr[6] = {0};
if (!(disc->props & BLE_HCI_ADV_CONN_MASK)) {
return 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);
/* Convert string to address */
uint8_t parsed_addr[6];
peer_addr_parse(CONFIG_EXAMPLE_PEER_ADDR, parsed_addr);
for (int i = 0; i < 6; i++) {
test_addr[5 - i] = parsed_addr[i];
if (peer_addr_parse(CONFIG_EXAMPLE_PEER_ADDR, test_addr) != 6) {
return 0;
}
if (memcmp(test_addr, disc->addr.val, sizeof(disc->addr.val)) != 0) {
@@ -255,19 +270,24 @@ ext_blecent_should_connect(const struct ble_gap_ext_disc_desc *disc)
/* The device has to advertise support LE PHY UUID (0xABF2).
*/
do {
while (offset < disc->length_data) {
if (offset + 1 >= disc->length_data) {
break;
}
ad_struct_len = disc->data[offset];
if (!ad_struct_len || (offset + ad_struct_len + 1 > disc->length_data)) {
break;
}
/* Search if LE PHY UUID is advertised */
if (disc->data[offset] == 0x03 && disc->data[offset + 1] == 0x03) {
if ( disc->data[offset + 2] == 0xAB && disc->data[offset + 3] == 0xF2 ) {
return 1;
/* Search if LE PHY UUID is advertised (UUID list, type 0x02 or 0x03) */
if (ad_struct_len >= 3 && (disc->data[offset + 1] == 0x02 || disc->data[offset + 1] == 0x03)) {
for (int i = 2; i + 1 <= ad_struct_len; i += 2) {
if (disc->data[offset + i] == 0xF2 && disc->data[offset + i + 1] == 0xAB) {
return 1;
}
}
}
offset += ad_struct_len + 1;
} while (offset < disc->length_data);
}
return 0;
}
@@ -301,6 +321,9 @@ blecent_connect_if_interesting(void *disc)
rc = ble_hs_id_infer_auto(0, &own_addr_type);
if (rc != 0) {
MODLOG_DFLT(ERROR, "error determining address type; rc=%d\n", rc);
#if !(MYNEWT_VAL(BLE_HOST_ALLOW_CONNECT_WITH_SCAN))
blecent_scan();
#endif
return;
}
@@ -322,6 +345,9 @@ blecent_connect_if_interesting(void *disc)
MODLOG_DFLT(ERROR, "Error: Failed to connect to device; addr_type=%d "
"addr=%s; rc=%d\n",
conn_addr.type, addr_str(conn_addr.val), rc);
#if !(MYNEWT_VAL(BLE_HOST_ALLOW_CONNECT_WITH_SCAN))
blecent_scan();
#endif
return;
}
}
@@ -344,6 +370,7 @@ static int
blecent_gap_event(struct ble_gap_event *event, void *arg)
{
struct ble_gap_conn_desc desc;
uint8_t own_addr_type;
int rc;
switch (event->type) {
@@ -419,20 +446,36 @@ blecent_gap_event(struct ble_gap_event *event, void *arg)
case BLE_HCI_LE_PHY_CODED_PREF_MASK:
return 0;
default:
return 0;
}
vTaskDelay(200);
rc = ble_hs_id_infer_auto(0, &own_addr_type);
if (rc != 0) {
MODLOG_DFLT(ERROR, "error determining address type; rc=%d\n", rc);
return 0;
}
/* Attempt direct connection on 2M or Coded phy now */
if (s_current_phy == BLE_HCI_LE_PHY_CODED_PREF_MASK) {
MODLOG_DFLT(INFO, " Attempting to initiate connection on Coded PHY \n");
ble_gap_ext_connect(0, &conn_addr, 30000, BLE_HCI_LE_PHY_CODED_PREF_MASK,
NULL, NULL, NULL, blecent_gap_event, NULL);
rc = ble_gap_ext_connect(own_addr_type, &conn_addr, 30000, BLE_HCI_LE_PHY_CODED_PREF_MASK,
NULL, NULL, NULL, blecent_gap_event, NULL);
if (rc != 0) {
MODLOG_DFLT(ERROR, "Error: Failed to initiate ext connect; rc=%d\n", rc);
}
}
else if (s_current_phy == BLE_HCI_LE_PHY_2M_PREF_MASK) {
MODLOG_DFLT(INFO, " Attempting to initiate connection on 2M PHY \n");
ble_gap_ext_connect(0, &conn_addr, 30000, (BLE_HCI_LE_PHY_1M_PREF_MASK | BLE_HCI_LE_PHY_2M_PREF_MASK),
NULL, NULL, NULL, blecent_gap_event, NULL);
rc = ble_gap_ext_connect(own_addr_type, &conn_addr, 30000,
(BLE_HCI_LE_PHY_1M_PREF_MASK | BLE_HCI_LE_PHY_2M_PREF_MASK),
NULL, NULL, NULL, blecent_gap_event, NULL);
if (rc != 0) {
MODLOG_DFLT(ERROR, "Error: Failed to initiate ext connect; rc=%d\n", rc);
}
}
return 0;
@@ -464,11 +507,18 @@ blecent_on_sync(void)
{
int ii, rc;
uint8_t all_phy;
uint8_t own_addr_type;
uint8_t test_addr[6];
/* Make sure we have proper identity address set (public preferred) */
rc = ble_hs_util_ensure_addr(0);
assert(rc == 0);
rc = ble_hs_id_infer_auto(0, &own_addr_type);
if (rc != 0) {
MODLOG_DFLT(ERROR, "error determining address type; rc=%d\n", rc);
return;
}
all_phy = BLE_HCI_LE_PHY_1M_PREF_MASK | BLE_HCI_LE_PHY_2M_PREF_MASK | BLE_HCI_LE_PHY_CODED_PREF_MASK;
set_default_le_phy(all_phy, all_phy);
@@ -484,10 +534,14 @@ blecent_on_sync(void)
vTaskDelay(300);
s_current_phy = BLE_HCI_LE_PHY_1M_PREF_MASK | BLE_HCI_LE_PHY_2M_PREF_MASK ;
s_current_phy = BLE_HCI_LE_PHY_2M_PREF_MASK;
ble_gap_ext_connect(0, &conn_addr, 30000, s_current_phy,
NULL, NULL, NULL, blecent_gap_event, NULL);
rc = ble_gap_ext_connect(own_addr_type, &conn_addr, 30000,
BLE_HCI_LE_PHY_1M_PREF_MASK | s_current_phy,
NULL, NULL, NULL, blecent_gap_event, NULL);
if (rc != 0) {
MODLOG_DFLT(ERROR, "Error: Failed to initiate ext connect; rc=%d\n", rc);
}
}
else {
s_current_phy = BLE_HCI_LE_PHY_1M_PREF_MASK;
@@ -531,11 +585,14 @@ app_main(void)
/* Initialize data structures to track connected peers. */
#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);
assert(rc == 0);
#else
rc = peer_init(MYNEWT_VAL(BLE_MAX_CONNECTIONS), 64, 64, 64);
assert(rc == 0);
#endif
if (rc != 0) {
MODLOG_DFLT(ERROR, "Failed to init peer; rc=%d\n", rc);
nimble_port_deinit();
return;
}
#if CONFIG_BT_NIMBLE_GAP_SERVICE
/* Set the default device name. */
rc = ble_svc_gap_device_name_set("blecent-phy");

View File

@@ -31,8 +31,7 @@ static const struct ble_gatt_svc_def gatt_svr_svcs_le_phy[] = {
.uuid = BLE_UUID16_DECLARE(LE_PHY_CHR_UUID16),
.access_cb = gatt_svr_chr_access_le_phy,
.val_handle = &gatt_svr_chr_val_handle,
.flags = BLE_GATT_CHR_F_READ | BLE_GATT_CHR_F_READ_ENC | BLE_GATT_CHR_F_WRITE
| BLE_GATT_CHR_F_WRITE_ENC,
.flags = BLE_GATT_CHR_F_READ | BLE_GATT_CHR_F_WRITE,
}, {
0, /* No more characteristics in this service. */
}

View File

@@ -17,22 +17,19 @@
static uint8_t ext_adv_pattern_1M[] = {
0x02, BLE_HS_ADV_TYPE_FLAGS, 0x06,
0x03, BLE_HS_ADV_TYPE_COMP_UUIDS16, 0xab, 0xcd,
0x03, BLE_HS_ADV_TYPE_COMP_UUIDS16, 0xAB, 0xF2,
0x03, BLE_HS_ADV_TYPE_COMP_UUIDS16, 0xF2, 0xAB,
0x0e, BLE_HS_ADV_TYPE_COMP_NAME, 'b', 'l', 'e', 'p', 'r', 'p', 'h', '-', 'p', 'h', 'y', '-', '1', 'M',
};
static uint8_t ext_adv_pattern_2M[] = {
0x02, BLE_HS_ADV_TYPE_FLAGS, 0x06,
0x03, BLE_HS_ADV_TYPE_COMP_UUIDS16, 0xab, 0xcd,
0x03, BLE_HS_ADV_TYPE_COMP_UUIDS16, 0xAB, 0xF2,
0x03, BLE_HS_ADV_TYPE_COMP_UUIDS16, 0xF2, 0xAB,
0x0e, BLE_HS_ADV_TYPE_COMP_NAME, 'b', 'l', 'e', 'p', 'r', 'p', 'h', '-', 'p', 'h', 'y', '-', '2', 'M',
};
static uint8_t ext_adv_pattern_coded[] = {
0x02, BLE_HS_ADV_TYPE_FLAGS, 0x06,
0x03, BLE_HS_ADV_TYPE_COMP_UUIDS16, 0xab, 0xcd,
0x03, BLE_HS_ADV_TYPE_COMP_UUIDS16, 0xAB, 0xF2,
0x03, BLE_HS_ADV_TYPE_COMP_UUIDS16, 0xF2, 0xAB,
0x11, BLE_HS_ADV_TYPE_COMP_NAME, 'b', 'l', 'e', 'p', 'r', 'p', 'h', '-', 'p', 'h', 'y', '-', 'c', 'o', 'd', 'e',
'd',
};
@@ -239,7 +236,10 @@ bleprph_gap_event(struct ble_gap_event *event, void *arg)
MODLOG_DFLT(INFO, "connection updated; status=%d ",
event->conn_update.status);
rc = ble_gap_conn_find(event->conn_update.conn_handle, &desc);
assert(rc == 0);
if (rc != 0) {
MODLOG_DFLT(ERROR, "ble_gap_conn_find failed; rc=%d\n", rc);
return 0;
}
bleprph_print_conn_desc(&desc);
MODLOG_DFLT(INFO, "\n");
return 0;
@@ -352,9 +352,11 @@ app_main(void)
assert(rc == 0);
#endif
#if CONFIG_BT_NIMBLE_GAP_SERVICE
/* Set the default device name. */
rc = ble_svc_gap_device_name_set("bleprph-phy");
assert(rc == 0);
#endif
/* XXX Need to have template for store */
ble_store_config_init();

View File

@@ -12,3 +12,4 @@ CONFIG_BT_BLUEDROID_ENABLED=n
CONFIG_BT_NIMBLE_ENABLED=y
CONFIG_BT_NIMBLE_EXT_ADV=y
CONFIG_BT_NIMBLE_BLE_GATT_BLOB_TRANSFER=y
CONFIG_BT_NIMBLE_MSYS_1_BLOCK_COUNT=64

View File

@@ -19,7 +19,6 @@
#endif
static const char *tag = "NimBLE_PROX_CENT";
static uint8_t link_supervision_timeout;
static int8_t tx_pwr_lvl;
static struct ble_prox_cent_conn_peer conn_peer[MYNEWT_VAL(BLE_MAX_CONNECTIONS) + 1];
static struct ble_prox_cent_link_lost_peer disconn_peer[MYNEWT_VAL(BLE_MAX_CONNECTIONS) + 1];
@@ -41,7 +40,11 @@ ble_prox_cent_on_read(uint16_t conn_handle,
if (error->status == 0) {
MODLOG_DFLT(INFO, " attr_handle=%d value=", attr->handle);
print_mbuf(attr->om);
os_mbuf_copydata(attr->om, 0, attr->om->om_len, &tx_pwr_lvl);
if (attr->om->om_len != sizeof(tx_pwr_lvl)) {
MODLOG_DFLT(ERROR, "Unexpected TX power level length: %d\n", attr->om->om_len);
return 0;
}
os_mbuf_copydata(attr->om, 0, sizeof(tx_pwr_lvl), &tx_pwr_lvl);
conn_peer[conn_handle].calc_path_loss = true;
}
@@ -129,8 +132,10 @@ ble_prox_cent_read_write_subscribe(const struct peer *peer)
goto err;
}
/* Alert Level: 0=No Alert, 1=Mild Alert, 2=High Alert (BLE SIG LLS spec) */
static const uint8_t alert_level = 1;
rc = ble_gattc_write_flat(peer->conn_handle, chr->chr.val_handle,
&link_supervision_timeout, sizeof(link_supervision_timeout),
&alert_level, sizeof(alert_level),
ble_prox_cent_on_write, NULL);
if (rc != 0) {
MODLOG_DFLT(ERROR, "Error: Failed to write characteristic; rc=%d\n",
@@ -228,19 +233,13 @@ ext_ble_prox_cent_should_connect(const struct ble_gap_ext_disc_desc *disc)
int offset = 0;
int ad_struct_len = 0;
uint8_t test_addr[6];
if (disc->legacy_event_type != BLE_HCI_ADV_RPT_EVTYPE_ADV_IND &&
disc->legacy_event_type != BLE_HCI_ADV_RPT_EVTYPE_DIR_IND) {
if (!(disc->props & BLE_HCI_ADV_CONN_MASK)) {
return 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);
/* Convert string to address */
uint8_t parsed_addr[6];
peer_addr_parse(CONFIG_EXAMPLE_PEER_ADDR, parsed_addr);
for (int i = 0; i < 6; i++) {
test_addr[5 - i] = parsed_addr[i];
}
/* Convert string to address; peer_addr_parse outputs little-endian matching disc->addr.val */
peer_addr_parse(CONFIG_EXAMPLE_PEER_ADDR, test_addr);
if (memcmp(test_addr, disc->addr.val, sizeof(disc->addr.val)) != 0) {
return 0;
}
@@ -256,9 +255,9 @@ ext_ble_prox_cent_should_connect(const struct ble_gap_ext_disc_desc *disc)
break;
}
/* Search if Proximity Sensor (Link loss) UUID is advertised */
/* Search if Proximity Sensor (Link loss) UUID 0x1803 is advertised (little-endian: [0x03, 0x18]) */
if (disc->data[offset] == 0x03 && disc->data[offset + 1] == 0x03) {
if ( disc->data[offset + 2] == 0x18 && disc->data[offset + 3] == 0x03 ) {
if ( disc->data[offset + 2] == 0x03 && disc->data[offset + 3] == 0x18 ) {
return 1;
}
}
@@ -347,6 +346,9 @@ ble_prox_cent_connect_if_interesting(void *disc)
rc = ble_hs_id_infer_auto(0, &own_addr_type);
if (rc != 0) {
MODLOG_DFLT(ERROR, "error determining address type; rc=%d\n", rc);
#if !(MYNEWT_VAL(BLE_HOST_ALLOW_CONNECT_WITH_SCAN))
ble_prox_cent_scan();
#endif
return;
}
@@ -364,6 +366,9 @@ ble_prox_cent_connect_if_interesting(void *disc)
MODLOG_DFLT(ERROR, "Error: Failed to connect to device; addr_type=%d "
"addr=%s; rc=%d\n",
addr->type, addr_str(addr->val), rc);
#if !(MYNEWT_VAL(BLE_HOST_ALLOW_CONNECT_WITH_SCAN))
ble_prox_cent_scan();
#endif
return;
}
}
@@ -415,8 +420,6 @@ ble_prox_cent_gap_event(struct ble_gap_event *event, void *arg)
print_conn_desc(&desc);
MODLOG_DFLT(INFO, "\n");
link_supervision_timeout = 8 * desc.conn_itvl;
/* Remember peer. */
rc = peer_add(event->connect.conn_handle);
if (rc != 0) {
@@ -427,7 +430,7 @@ ble_prox_cent_gap_event(struct ble_gap_event *event, void *arg)
/* Check if this device is reconnected */
for (int i = 0; i <= MYNEWT_VAL(BLE_MAX_CONNECTIONS); i++) {
if (disconn_peer[i].addr != NULL) {
if (memcmp(disconn_peer[i].addr, &desc.peer_id_addr.val, BLE_ADDR_LEN)) {
if (memcmp(disconn_peer[i].addr, &desc.peer_id_addr.val, BLE_ADDR_LEN) == 0) {
/* Peer reconnected. Stop alert for this peer */
free(disconn_peer[i].addr);
disconn_peer[i].addr = NULL;
@@ -500,8 +503,10 @@ ble_prox_cent_gap_event(struct ble_gap_event *event, void *arg)
}
}
/* Stop calculating path loss, restart once connection is established again */
conn_peer[event->disconnect.conn.conn_handle].calc_path_loss = false;
conn_peer[event->disconnect.conn.conn_handle].val_handle = 0;
if (event->disconnect.conn.conn_handle <= MYNEWT_VAL(BLE_MAX_CONNECTIONS)) {
conn_peer[event->disconnect.conn.conn_handle].calc_path_loss = false;
conn_peer[event->disconnect.conn.conn_handle].val_handle = 0;
}
/* Forget about peer. */
peer_delete(event->disconnect.conn.conn_handle);
@@ -726,12 +731,12 @@ app_main(void)
return;
}
/* Initialize a task to keep checking path loss of the link */
ble_prox_cent_init();
for (int i = 0; i <= MYNEWT_VAL(BLE_MAX_CONNECTIONS); i++) {
disconn_peer[i].addr = NULL;
disconn_peer[i].link_lost = true;
disconn_peer[i].link_lost = false;
}
/* Initialize tasks after disconn_peer array is ready */
ble_prox_cent_init();
/* Configure the host. */
ble_hs_cfg.reset_cb = ble_prox_cent_on_reset;

View File

@@ -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
*/
@@ -21,7 +21,7 @@
static uint8_t ext_adv_pattern_1[] = {
0x02, BLE_HS_ADV_TYPE_FLAGS, 0x06,
0x03, BLE_HS_ADV_TYPE_COMP_UUIDS16, 0xab, 0xcd,
0x03, BLE_HS_ADV_TYPE_COMP_UUIDS16, 0x18, 0x03,
0x03, BLE_HS_ADV_TYPE_COMP_UUIDS16, 0x03, 0x18, /* UUID 0x1803 in little-endian */
0x13, BLE_HS_ADV_TYPE_COMP_NAME, 'n', 'i', 'm', 'b', 'l', 'e', '-', 'p', 'r', 'o', 'x', '-', 'p', 'r', 'p', 'h', '-', 'e',
};
#endif
@@ -80,8 +80,8 @@ ext_ble_prox_prph_advertise(void)
/* enable connectable advertising */
params.connectable = 1;
/* advertise using random addr */
params.own_addr_type = BLE_OWN_ADDR_PUBLIC;
/* advertise using the inferred address type */
params.own_addr_type = ble_prox_prph_addr_type;
params.primary_phy = BLE_HCI_LE_PHY_1M;
params.secondary_phy = BLE_HCI_LE_PHY_2M;
@@ -145,9 +145,11 @@ ble_prox_prph_advertise(void)
fields.tx_pwr_lvl_is_present = 1;
fields.tx_pwr_lvl = BLE_HS_ADV_TX_PWR_LVL_AUTO;
#if CONFIG_BT_NIMBLE_GAP_SERVICE
fields.name = (uint8_t *)device_name;
fields.name_len = strlen(device_name);
fields.name_is_complete = 1;
#endif
fields.uuids16 = (ble_uuid16_t[]) {
BLE_UUID16_INIT(BLE_SVC_LINK_LOSS_UUID16)
@@ -301,13 +303,19 @@ void app_main(void)
ble_hs_cfg.sm_sc = 1;
ble_hs_cfg.sm_mitm = 1;
#if CONFIG_BT_NIMBLE_GAP_SERVICE
ble_svc_gap_init();
#endif
#if MYNEWT_VAL(BLE_GATTS)
ble_svc_gatt_init();
#endif
#if CONFIG_BT_NIMBLE_GAP_SERVICE
int rc;
/* Set the default device name */
rc = ble_svc_gap_device_name_set(device_name);
assert(rc == 0);
#endif
/* Start the task */
nimble_port_freertos_init(ble_prox_prph_host_task);

View File

@@ -11,6 +11,7 @@
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "esp_err.h"
#include "esp_log.h"
#include "driver/spi_slave.h"
#include "driver/gpio.h"
@@ -101,12 +102,17 @@ void app_main(void)
t.length = 1024 * 8;
t.tx_buffer = NULL;
t.rx_buffer = recvbuf;
t.flags = SPI_SLAVE_TRANS_DMA_BUFFER_ALIGN_AUTO;
/* This call enables the SPI slave interface to receive to the recvbuf. The transaction is
* initialized by the SPI master, however, so it will not actually happen until the master starts a hardware transaction
* by pulling CS low and pulsing the clock etc.
*/
ret = spi_slave_transmit(RCV_HOST, &t, portMAX_DELAY);
if (ret != ESP_OK) {
ESP_LOGE("SPI_SLAVE", "spi_slave_transmit failed: %s", esp_err_to_name(ret));
continue;
}
/* Get the actual number of bytes received */
int rcv_bytes = t.trans_len / 8;

View File

@@ -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
*/
@@ -69,8 +69,6 @@ static void
ble_spp_client_set_handle(const struct peer *peer)
{
const struct peer_chr *chr;
const struct peer_dsc *dsc;
uint8_t value[2];
chr = peer_chr_find_uuid(peer,
BLE_UUID16_DECLARE(GATT_SPP_SVC_UUID),
BLE_UUID16_DECLARE(GATT_SPP_CHR_UUID));
@@ -79,6 +77,10 @@ ble_spp_client_set_handle(const struct peer *peer)
MODLOG_DFLT(ERROR, "Error: Peer lacks SPP characteristic\n");
return;
}
if (peer->conn_handle > CONFIG_BT_NIMBLE_MAX_CONNECTIONS) {
MODLOG_DFLT(ERROR, "Error: conn_handle %d out of range\n", peer->conn_handle);
return;
}
if (g_attr_handle_mutex != NULL) {
xSemaphoreTake(g_attr_handle_mutex, portMAX_DELAY);
}
@@ -88,19 +90,6 @@ ble_spp_client_set_handle(const struct peer *peer)
xSemaphoreGive(g_attr_handle_mutex);
}
dsc = peer_dsc_find_uuid(peer,
BLE_UUID16_DECLARE(GATT_SPP_SVC_UUID),
BLE_UUID16_DECLARE(GATT_SPP_CHR_UUID),
BLE_UUID16_DECLARE(BLE_GATT_DSC_CLT_CFG_UUID16));
if (dsc == NULL) {
MODLOG_DFLT(ERROR, "Error: Peer lacks a CCCD for the subscribable characteristic\n");
return;
}
value[0] = 1;
value[1] = 0;
ble_gattc_write_flat(peer->conn_handle, dsc->dsc.handle,
value, sizeof(value), NULL, NULL);
}
/**
@@ -247,6 +236,9 @@ ble_spp_client_connect_if_interesting(const struct ble_gap_disc_desc *disc)
rc = ble_hs_id_infer_auto(0, &own_addr_type);
if (rc != 0) {
MODLOG_DFLT(ERROR, "error determining address type; rc=%d\n", rc);
#if !(MYNEWT_VAL(BLE_HOST_ALLOW_CONNECT_WITH_SCAN))
ble_spp_client_scan();
#endif
return;
}
@@ -260,6 +252,9 @@ ble_spp_client_connect_if_interesting(const struct ble_gap_disc_desc *disc)
MODLOG_DFLT(ERROR, "Error: Failed to connect to device; addr_type=%d "
"addr=%s; rc=%d\n",
disc->addr.type, addr_str(disc->addr.val), rc);
#if !(MYNEWT_VAL(BLE_HOST_ALLOW_CONNECT_WITH_SCAN))
ble_spp_client_scan();
#endif
return;
}
}
@@ -346,13 +341,15 @@ ble_spp_client_gap_event(struct ble_gap_event *event, void *arg)
MODLOG_DFLT(INFO, "\n");
/* Forget about peer. */
memset(&connected_addr[event->disconnect.conn.conn_handle].val, 0, PEER_ADDR_VAL_SIZE);
if (g_attr_handle_mutex != NULL) {
xSemaphoreTake(g_attr_handle_mutex, portMAX_DELAY);
}
attribute_handle[event->disconnect.conn.conn_handle] = 0;
if (g_attr_handle_mutex != NULL) {
xSemaphoreGive(g_attr_handle_mutex);
if (event->disconnect.conn.conn_handle <= CONFIG_BT_NIMBLE_MAX_CONNECTIONS) {
memset(&connected_addr[event->disconnect.conn.conn_handle].val, 0, PEER_ADDR_VAL_SIZE);
if (g_attr_handle_mutex != NULL) {
xSemaphoreTake(g_attr_handle_mutex, portMAX_DELAY);
}
attribute_handle[event->disconnect.conn.conn_handle] = 0;
if (g_attr_handle_mutex != NULL) {
xSemaphoreGive(g_attr_handle_mutex);
}
}
peer_delete(event->disconnect.conn.conn_handle);
@@ -499,7 +496,11 @@ static void ble_spp_uart_init(void)
};
//Install UART driver, and get the queue.
uart_driver_install(UART_NUM_0, 4096, 8192, 10, &spp_common_uart_queue, 0);
esp_err_t err = uart_driver_install(UART_NUM_0, 4096, 8192, 10, &spp_common_uart_queue, 0);
if (err != ESP_OK) {
ESP_LOGE(tag, "uart_driver_install failed: %d", err);
return;
}
//Set UART parameters
uart_param_config(UART_NUM_0, &uart_config);
//Set UART pins
@@ -528,6 +529,7 @@ app_main(void)
g_attr_handle_mutex = xSemaphoreCreateMutex();
if (g_attr_handle_mutex == NULL) {
ESP_LOGE(tag, "Failed to create attribute handle mutex");
nimble_port_deinit();
return;
}

View File

@@ -411,7 +411,11 @@ static void ble_spp_uart_init(void)
.source_clk = UART_SCLK_DEFAULT,
};
//Install UART driver, and get the queue.
uart_driver_install(UART_NUM_0, 4096, 8192, 10, &spp_common_uart_queue, 0);
esp_err_t err = uart_driver_install(UART_NUM_0, 4096, 8192, 10, &spp_common_uart_queue, 0);
if (err != ESP_OK) {
ESP_LOGE("SPP_SERVER", "uart_driver_install failed: %d", err);
return;
}
//Set UART parameters
uart_param_config(UART_NUM_0, &uart_config);
//Set UART pins

View File

@@ -154,6 +154,10 @@ blecent_on_custom_subscribe(uint16_t conn_handle,
MODLOG_DFLT(INFO, "\n");
peer = peer_find(conn_handle);
if (peer == NULL) {
MODLOG_DFLT(WARN, "Peer not found (conn_handle=%d), likely disconnected\n", conn_handle);
return 0;
}
chr = peer_chr_find_uuid(peer,
remote_svc_uuid,
remote_chr_uuid);
@@ -477,9 +481,6 @@ ext_blecent_should_connect(const struct ble_gap_ext_disc_desc *disc)
{
int offset = 0;
int ad_struct_len = 0;
#if CONFIG_EXAMPLE_USE_CI_ADDRESS
uint32_t *addr_offset;
#endif // CONFIG_EXAMPLE_USE_CI_ADDRESS
uint8_t test_addr[6];
if (disc->legacy_event_type != BLE_HCI_ADV_RPT_EVTYPE_ADV_IND &&
disc->legacy_event_type != BLE_HCI_ADV_RPT_EVTYPE_DIR_IND) {
@@ -493,8 +494,8 @@ ext_blecent_should_connect(const struct ble_gap_ext_disc_desc *disc)
#endif
#if CONFIG_EXAMPLE_USE_CI_ADDRESS
addr_offset = (uint32_t *)&test_addr[1];
*addr_offset = atoi(CONFIG_EXAMPLE_PEER_ADDR);
uint32_t addr_val = (uint32_t)atoi(CONFIG_EXAMPLE_PEER_ADDR);
memcpy(&test_addr[1], &addr_val, sizeof(addr_val));
test_addr[5] = 0xC3;
test_addr[0] = CONFIG_IDF_FIRMWARE_CHIP_ID;
#endif
@@ -534,9 +535,6 @@ blecent_should_connect(const struct ble_gap_disc_desc *disc)
struct ble_hs_adv_fields fields;
int rc;
int i;
#if CONFIG_EXAMPLE_USE_CI_ADDRESS
uint32_t *addr_offset;
#endif // CONFIG_EXAMPLE_USE_CI_ADDRESS
uint8_t test_addr[6];
/* The device has to be advertising connectability. */
if (disc->event_type != BLE_HCI_ADV_RPT_EVTYPE_ADV_IND &&
@@ -558,8 +556,8 @@ blecent_should_connect(const struct ble_gap_disc_desc *disc)
printf("peer--> %s\n", addr_str(test_addr));
#endif
#if CONFIG_EXAMPLE_USE_CI_ADDRESS
addr_offset = (uint32_t *)&test_addr[1];
*addr_offset = atoi(CONFIG_EXAMPLE_PEER_ADDR);
uint32_t addr_val = (uint32_t)atoi(CONFIG_EXAMPLE_PEER_ADDR);
memcpy(&test_addr[1], &addr_val, sizeof(addr_val));
test_addr[5] = 0xC3;
test_addr[0] = CONFIG_IDF_FIRMWARE_CHIP_ID;
#endif
@@ -618,6 +616,9 @@ blecent_connect_if_interesting(void *disc)
rc = ble_hs_id_infer_auto(0, &own_addr_type);
if (rc != 0) {
MODLOG_DFLT(ERROR, "error determining address type; rc=%d\n", rc);
#if !(MYNEWT_VAL(BLE_HOST_ALLOW_CONNECT_WITH_SCAN))
blecent_scan();
#endif
return;
}
@@ -636,6 +637,9 @@ blecent_connect_if_interesting(void *disc)
MODLOG_DFLT(ERROR, "Error: Failed to connect to device; addr_type=%d "
"addr=%s; rc=%d\n",
addr->type, addr_str(addr->val), rc);
#if !(MYNEWT_VAL(BLE_HOST_ALLOW_CONNECT_WITH_SCAN))
blecent_scan();
#endif
return;
}
}
@@ -645,17 +649,28 @@ static void blecent_power_control(uint16_t conn_handle)
{
int rc;
rc = ble_gap_read_remote_transmit_power_level(conn_handle, 0x01 ); // Attempting on LE 1M phy
assert (rc == 0);
rc = ble_gap_read_remote_transmit_power_level(conn_handle, 0x01);
if (rc != 0) {
MODLOG_DFLT(WARN, "ble_gap_read_remote_transmit_power_level failed; rc=%d\n", rc);
return;
}
rc = ble_gap_set_transmit_power_reporting_enable(conn_handle, 0x01, 0x01);
assert (rc == 0);
if (rc != 0) {
MODLOG_DFLT(WARN, "ble_gap_set_transmit_power_reporting_enable failed; rc=%d\n", rc);
return;
}
rc = ble_gap_set_path_loss_reporting_param(conn_handle, 60, 10, 30, 10, 2 ); //demo values
assert (rc == 0);
rc = ble_gap_set_path_loss_reporting_param(conn_handle, 60, 10, 30, 10, 2);
if (rc != 0) {
MODLOG_DFLT(WARN, "ble_gap_set_path_loss_reporting_param failed; rc=%d\n", rc);
return;
}
rc = ble_gap_set_path_loss_reporting_enable(conn_handle, 0x01);
assert (rc == 0);
if (rc != 0) {
MODLOG_DFLT(WARN, "ble_gap_set_path_loss_reporting_enable failed; rc=%d\n", rc);
}
}
#endif
@@ -936,11 +951,16 @@ blecent_gap_event(struct ble_gap_event *event, void *arg)
break;
}
}
if (i >= bearers) {
/* CID not found; nothing to remove */
return 0;
}
while (i < (bearers - 1)) {
cids[i] = cids[i + 1];
i += 1;
}
cids[i] = 0;
bearers--;
/* Now Abort */
return 0;
@@ -1092,12 +1112,6 @@ app_main(void)
/* XXX Need to have template for store */
ble_store_config_init();
nimble_port_freertos_init(blecent_host_task);
#if CONFIG_EXAMPLE_INIT_DEINIT_LOOP
stack_init_deinit();
#endif
#if MYNEWT_VAL(BLE_EATT_CHAN_NUM) > 0
bearers = 0;
for (int i = 0; i < MYNEWT_VAL(BLE_EATT_CHAN_NUM); i++) {
@@ -1105,4 +1119,10 @@ app_main(void)
}
#endif
nimble_port_freertos_init(blecent_host_task);
#if CONFIG_EXAMPLE_INIT_DEINIT_LOOP
stack_init_deinit();
#endif
}

View File

@@ -245,7 +245,20 @@ gatt_svr_chr_access_sc_control_point(uint16_t conn_handle,
break;
}
/* Append response value */
/* Append Response Op Code, Request Op Code, and Response Value */
uint8_t rsp_op = SC_CP_OP_RESPONSE;
rc = os_mbuf_append(om_indication, &rsp_op, sizeof(rsp_op));
if (rc != 0) {
os_mbuf_free_chain(om_indication);
return BLE_ATT_ERR_INSUFFICIENT_RES;
}
rc = os_mbuf_append(om_indication, &op_code, sizeof(op_code));
if (rc != 0) {
os_mbuf_free_chain(om_indication);
return BLE_ATT_ERR_INSUFFICIENT_RES;
}
rc = os_mbuf_append(om_indication, &response, sizeof(response));
if (rc != 0){
@@ -267,14 +280,7 @@ gatt_svr_chr_access_sc_control_point(uint16_t conn_handle,
rc = ble_gatts_indicate_custom(conn_handle, csc_control_point_handle,
om_indication);
if (rc != 0) {
goto done;
}
return rc;
done:
os_mbuf_free_chain(om_indication);
/* om_indication is consumed (freed) by ble_gatts_indicate_custom regardless of result */
return rc;
}
@@ -328,6 +334,9 @@ gatt_svr_chr_notify_csc_measurement(uint16_t conn_handle)
#endif
om = ble_hs_mbuf_from_flat(data_buf, data_offset);
if (om == NULL) {
return BLE_HS_ENOMEM;
}
rc = ble_gatts_notify_custom(conn_handle, csc_measurement_handle, om);
return rc;

View File

@@ -24,6 +24,7 @@
#include "console/console.h"
#include "nimble/ble.h"
#include "host/ble_hs.h"
#include "host/util/util.h"
#include "services/gap/ble_svc_gap.h"
#include "blecsc_sens.h"
#include "nimble/nimble_port.h"
@@ -198,14 +199,16 @@ blecsc_measurement(struct ble_npl_event *ev)
{
int rc;
rc = ble_npl_callout_reset(&blecsc_measure_timer, portTICK_PERIOD_MS * 10);
rc = ble_npl_callout_reset(&blecsc_measure_timer, ble_npl_time_ms_to_ticks32(1000));
assert(rc == 0);
blecsc_simulate_speed_and_cadence();
if (notify_state) {
rc = gatt_svr_chr_notify_csc_measurement(conn_handle);
assert(rc == 0);
if (rc != 0) {
MODLOG_DFLT(WARN, "gatt_svr_chr_notify_csc_measurement failed; rc=%d\n", rc);
}
}
}
@@ -232,6 +235,8 @@ blecsc_gap_event(struct ble_gap_event *event, void *arg)
case BLE_GAP_EVENT_DISCONNECT:
MODLOG_DFLT(INFO, "disconnect; reason=%d\n", event->disconnect.reason);
conn_handle = 0;
notify_state = false;
gatt_svr_set_cp_indicate(0);
/* Connection terminated; resume advertising */
blecsc_advertise();
break;
@@ -272,6 +277,9 @@ blecsc_on_sync(void)
{
int rc;
rc = ble_hs_util_ensure_addr(0);
assert(rc == 0);
/* Figure out address to use while advertising (no privacy) */
rc = ble_hs_id_infer_auto(0, &blecsc_addr_type);
assert(rc == 0);
@@ -321,7 +329,7 @@ app_main(void)
/* Initialize measurement and notification timer */
ble_npl_callout_init(&blecsc_measure_timer, nimble_port_get_dflt_eventq(),
blecsc_measurement, NULL);
rc = ble_npl_callout_reset(&blecsc_measure_timer, portTICK_PERIOD_MS * 100);
rc = ble_npl_callout_reset(&blecsc_measure_timer, ble_npl_time_ms_to_ticks32(1000));
assert(rc == 0);
#if MYNEWT_VAL(BLE_GATTS)

View File

@@ -130,23 +130,7 @@ blehr_advertise(void)
static void
blehr_tx_hrate_stop(void)
{
xTimerStop( blehr_tx_timer, 1000 / portTICK_PERIOD_MS );
}
/* Reset heart rate measurement */
static void
blehr_tx_hrate_reset(void)
{
int rc;
if (xTimerReset(blehr_tx_timer, 1000 / portTICK_PERIOD_MS ) == pdPASS) {
rc = 0;
} else {
rc = 1;
}
assert(rc == 0);
xTimerStop(blehr_tx_timer, 0);
}
/* This function simulates heart beat and notifies it to the client */
@@ -173,11 +157,15 @@ blehr_tx_hrate(TimerHandle_t ev)
}
om = ble_hs_mbuf_from_flat(hrm, sizeof(hrm));
if (om == NULL) {
MODLOG_DFLT(WARN, "ble_hs_mbuf_from_flat failed; out of memory\n");
return;
}
rc = ble_gatts_notify_custom(conn_handle, hrs_hrm_handle, om);
assert(rc == 0);
blehr_tx_hrate_reset();
if (rc != 0) {
MODLOG_DFLT(WARN, "ble_gatts_notify_custom failed; rc=%d\n", rc);
}
}
static int
@@ -218,10 +206,11 @@ blehr_gap_event(struct ble_gap_event *event, void *arg)
event->subscribe.cur_notify, hrs_hrm_handle);
if (event->subscribe.attr_handle == hrs_hrm_handle) {
notify_state = event->subscribe.cur_notify;
blehr_tx_hrate_reset();
} else if (event->subscribe.attr_handle != hrs_hrm_handle) {
notify_state = event->subscribe.cur_notify;
blehr_tx_hrate_stop();
if (notify_state) {
xTimerStart(blehr_tx_timer, 0);
} else {
blehr_tx_hrate_stop();
}
}
ESP_LOGI("BLE_GAP_SUBSCRIBE_EVENT", "conn_handle from subscribe=%d", conn_handle);
break;

View File

@@ -164,9 +164,11 @@ gatt_svc_access(uint16_t conn_handle, uint16_t attr_handle,
sizeof(gatt_svr_chr_val),
sizeof(gatt_svr_chr_val),
&gatt_svr_chr_val, NULL);
ble_gatts_chr_updated(attr_handle);
MODLOG_DFLT(INFO, "Notification/Indication scheduled for "
"all subscribed peers.\n");
if (rc == 0) {
ble_gatts_chr_updated(attr_handle);
MODLOG_DFLT(INFO, "Notification/Indication scheduled for "
"all subscribed peers.\n");
}
return rc;
}
goto unknown;
@@ -183,7 +185,7 @@ gatt_svc_access(uint16_t conn_handle, uint16_t attr_handle,
if (ble_uuid_cmp(uuid, &gatt_svr_dsc_uuid.u) == 0) {
rc = os_mbuf_append(ctxt->om,
&gatt_svr_dsc_val,
sizeof(gatt_svr_chr_val));
sizeof(gatt_svr_dsc_val));
return rc == 0 ? 0 : BLE_ATT_ERR_INSUFFICIENT_RES;
}
goto unknown;

View File

@@ -106,8 +106,8 @@ ext_bleprph_advertise(void)
/* enable connectable advertising */
params.connectable = 1;
/* advertise using random addr */
params.own_addr_type = BLE_OWN_ADDR_PUBLIC;
/* advertise using configured/inferred addr type */
params.own_addr_type = own_addr_type;
params.primary_phy = BLE_HCI_LE_PHY_1M;
params.secondary_phy = BLE_HCI_LE_PHY_2M;
@@ -186,9 +186,10 @@ bleprph_advertise(void)
fields.name_is_complete = 1;
#endif
fields.uuids16 = (ble_uuid16_t[]) {
static const ble_uuid16_t adv_uuids16[] = {
BLE_UUID16_INIT(GATT_SVR_SVC_ALERT_UUID)
};
fields.uuids16 = adv_uuids16;
fields.num_uuids16 = 1;
fields.uuids16_is_complete = 1;
@@ -216,11 +217,16 @@ static void bleprph_power_control(uint16_t conn_handle)
{
int rc;
rc = ble_gap_read_remote_transmit_power_level(conn_handle, 0x01 ); // Attempting on LE 1M phy
assert (rc == 0);
rc = ble_gap_read_remote_transmit_power_level(conn_handle, 0x01);
if (rc != 0) {
MODLOG_DFLT(WARN, "ble_gap_read_remote_transmit_power_level failed; rc=%d\n", rc);
return;
}
rc = ble_gap_set_transmit_power_reporting_enable(conn_handle, 0x1, 0x1);
assert (rc == 0);
if (rc != 0) {
MODLOG_DFLT(WARN, "ble_gap_set_transmit_power_reporting_enable failed; rc=%d\n", rc);
}
}
#endif
@@ -272,7 +278,9 @@ bleprph_gap_event(struct ble_gap_event *event, void *arg)
}
#if MYNEWT_VAL(BLE_POWER_CONTROL)
bleprph_power_control(event->connect.conn_handle);
if (event->connect.status == 0) {
bleprph_power_control(event->connect.conn_handle);
}
#endif
return 0;
@@ -281,6 +289,13 @@ bleprph_gap_event(struct ble_gap_event *event, void *arg)
bleprph_print_conn_desc(&event->disconnect.conn);
MODLOG_DFLT(INFO, "\n");
#if MYNEWT_VAL(BLE_EATT_CHAN_NUM) > 0
bearers = 0;
for (int i = 0; i < MYNEWT_VAL(BLE_EATT_CHAN_NUM); i++) {
cids[i] = 0;
}
#endif
/* Connection terminated; resume advertising. */
#if CONFIG_EXAMPLE_EXTENDED_ADV
ext_bleprph_advertise();
@@ -491,17 +506,21 @@ bleprph_on_reset(int reason)
static void
ble_app_set_addr(void)
{
ble_addr_t addr;
ble_addr_t addr = {0};
int rc;
/* generate new non-resolvable private address */
rc = ble_hs_id_gen_rnd(0, &addr);
assert(rc == 0);
if (rc != 0) {
MODLOG_DFLT(ERROR, "ble_hs_id_gen_rnd failed; rc=%d\n", rc);
return;
}
/* set generated address */
rc = ble_hs_id_set_rnd(addr.val);
assert(rc == 0);
if (rc != 0) {
MODLOG_DFLT(ERROR, "ble_hs_id_set_rnd failed; rc=%d\n", rc);
}
}
#endif
@@ -621,6 +640,13 @@ app_main(void)
/* XXX Need to have template for store */
ble_store_config_init();
#if MYNEWT_VAL(BLE_EATT_CHAN_NUM) > 0
bearers = 0;
for (int i = 0; i < MYNEWT_VAL(BLE_EATT_CHAN_NUM); i++) {
cids[i] = 0;
}
#endif
nimble_port_freertos_init(bleprph_host_task);
/* Initialize command line interface to accept input from user */
@@ -628,11 +654,4 @@ app_main(void)
if (rc != ESP_OK) {
ESP_LOGE(tag, "scli_init() failed");
}
#if MYNEWT_VAL(BLE_EATT_CHAN_NUM) > 0
bearers = 0;
for (int i = 0; i < MYNEWT_VAL(BLE_EATT_CHAN_NUM); i++) {
cids[i] = 0;
}
#endif
}

View File

@@ -145,9 +145,11 @@ gatt_svc_access(uint16_t conn_handle, uint16_t attr_handle,
sizeof(gatt_svr_chr_val),
sizeof(gatt_svr_chr_val),
&gatt_svr_chr_val, NULL);
ble_gatts_chr_updated(attr_handle);
MODLOG_DFLT(INFO, "Notification/Indication scheduled for "
"all subscribed peers.\n");
if (rc == 0) {
ble_gatts_chr_updated(attr_handle);
MODLOG_DFLT(INFO, "Notification/Indication scheduled for "
"all subscribed peers.\n");
}
return rc;
}
goto unknown;
@@ -164,7 +166,7 @@ gatt_svc_access(uint16_t conn_handle, uint16_t attr_handle,
if (ble_uuid_cmp(uuid, &gatt_svr_dsc_uuid.u) == 0) {
rc = os_mbuf_append(ctxt->om,
&gatt_svr_dsc_val,
sizeof(gatt_svr_chr_val));
sizeof(gatt_svr_dsc_val));
return rc == 0 ? 0 : BLE_ATT_ERR_INSUFFICIENT_RES;
}
goto unknown;

View File

@@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2015-2025 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2015-2026 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@@ -85,8 +85,8 @@ ext_bleprph_advertise(void)
/* enable connectable advertising */
params.connectable = 1;
/* advertise using random addr */
params.own_addr_type = BLE_OWN_ADDR_PUBLIC;
/* advertise using configured/inferred addr type */
params.own_addr_type = own_addr_type;
params.primary_phy = BLE_HCI_LE_PHY_1M;
params.secondary_phy = BLE_HCI_LE_PHY_2M;
@@ -155,15 +155,18 @@ bleprph_advertise(void)
fields.tx_pwr_lvl_is_present = 1;
fields.tx_pwr_lvl = BLE_HS_ADV_TX_PWR_LVL_AUTO;
#if CONFIG_BT_NIMBLE_GAP_SERVICE
const char *name;
name = ble_svc_gap_device_name();
fields.name = (uint8_t *)name;
fields.name_len = strlen(name);
fields.name_is_complete = 1;
#endif
fields.uuids16 = (ble_uuid16_t[]) {
static const ble_uuid16_t adv_uuids16[] = {
BLE_UUID16_INIT(GATT_SVR_SVC_ALERT_UUID)
};
fields.uuids16 = adv_uuids16;
fields.num_uuids16 = 1;
fields.uuids16_is_complete = 1;
@@ -191,11 +194,16 @@ static void bleprph_power_control(uint16_t conn_handle)
{
int rc;
rc = ble_gap_read_remote_transmit_power_level(conn_handle, 0x01 ); // Attempting on LE 1M phy
assert (rc == 0);
rc = ble_gap_read_remote_transmit_power_level(conn_handle, 0x01);
if (rc != 0) {
MODLOG_DFLT(WARN, "ble_gap_read_remote_transmit_power_level failed; rc=%d\n", rc);
return;
}
rc = ble_gap_set_transmit_power_reporting_enable(conn_handle, 0x1, 0x1);
assert (rc == 0);
if (rc != 0) {
MODLOG_DFLT(WARN, "ble_gap_set_transmit_power_reporting_enable failed; rc=%d\n", rc);
}
}
#endif
@@ -419,17 +427,21 @@ bleprph_on_reset(int reason)
static void
ble_app_set_addr(void)
{
ble_addr_t addr;
ble_addr_t addr = {0};
int rc;
/* generate new non-resolvable private address */
rc = ble_hs_id_gen_rnd(0, &addr);
assert(rc == 0);
if (rc != 0) {
MODLOG_DFLT(ERROR, "ble_hs_id_gen_rnd failed; rc=%d\n", rc);
return;
}
/* set generated address */
rc = ble_hs_id_set_rnd(addr.val);
assert(rc == 0);
if (rc != 0) {
MODLOG_DFLT(ERROR, "ble_hs_id_set_rnd failed; rc=%d\n", rc);
}
}
#endif

View File

@@ -53,18 +53,36 @@ static void IRAM_ATTR hci_uart_rx_task(void *arg)
int len_now_read = -1;
uint32_t len_to_read = 1;
uint32_t len_total_read = 0;
uint32_t len_state_read = 0;
uint8_t rx_st = UART_RX_TYPE;
while (!s_shutdown_flag) {
// Use timeout instead of portMAX_DELAY to allow periodic shutdown flag check
len_now_read = uart_read_bytes(UART_NO, &buf[len_total_read], len_to_read, pdMS_TO_TICKS(100));
if (len_state_read < len_to_read) {
// Use timeout instead of portMAX_DELAY to allow periodic shutdown flag check
len_now_read = uart_read_bytes(UART_NO, &buf[len_total_read],
len_to_read - len_state_read,
pdMS_TO_TICKS(100));
// If timeout occurred, continue loop to check shutdown flag again
if (len_now_read == 0) {
continue;
// If timeout occurred, continue loop to check shutdown flag again
if (len_now_read == 0) {
continue;
}
if (len_now_read < 0) {
ESP_LOGE(TAG, "uart_read_bytes failed: %d", len_now_read);
rx_st = UART_RX_TYPE;
len_to_read = 1;
len_total_read = 0;
len_state_read = 0;
continue;
}
len_total_read += len_now_read;
len_state_read += len_now_read;
if (len_state_read < len_to_read) {
continue;
}
}
len_total_read += len_now_read;
len_state_read = 0;
switch (rx_st) {
case UART_RX_TYPE: {
@@ -83,6 +101,18 @@ static void IRAM_ATTR hci_uart_rx_task(void *arg)
case UART_RX_LEN: {
if (buf[0] == DATA_TYPE_ACL) {
len_to_read = buf[3] | (buf[4] << 8);
if (len_total_read + len_to_read > sizeof(buf)) {
ESP_LOGE(TAG, "ACL packet length %lu exceeds buffer size, discarding", (unsigned long)len_to_read);
/* Drain the unread payload bytes so the UART stream stays
* synchronised; without this the next UART_RX_TYPE read
* would pick up a payload byte, not a valid H4 type byte. */
uart_flush_input(UART_NO);
rx_st = UART_RX_TYPE;
len_to_read = 1;
len_total_read = 0;
len_state_read = 0;
break;
}
} else if (buf[0] == DATA_TYPE_EVENT) {
len_to_read = buf[2];
} else {
@@ -107,6 +137,10 @@ static void IRAM_ATTR hci_uart_rx_task(void *arg)
ESP_LOGE(TAG, "Received HCI data length at host (%d)"
"exceeds maximum configured HCI event buffer size (%d).",
totlen, MYNEWT_VAL(BLE_TRANSPORT_EVT_SIZE));
rx_st = UART_RX_TYPE;
len_to_read = 1;
len_total_read = 0;
len_state_read = 0;
break;
}
@@ -121,6 +155,10 @@ static void IRAM_ATTR hci_uart_rx_task(void *arg)
/* Skip advertising report if we're out of memory */
if (!evbuf) {
ESP_LOGE(TAG, "No buffers");
rx_st = UART_RX_TYPE;
len_to_read = 1;
len_total_read = 0;
len_state_read = 0;
break;
}
} else {
@@ -141,13 +179,18 @@ static void IRAM_ATTR hci_uart_rx_task(void *arg)
rx_st = UART_RX_TYPE;
len_to_read = 1;
len_total_read = 0;
len_state_read = 0;
break;
}
if ((rc = os_mbuf_append(m, &data[1], len_total_read - 1)) != 0) {
ESP_LOGE(TAG, "%s failed to os_mbuf_append; rc = %d", __func__, rc);
os_mbuf_free_chain(m);
return;
rx_st = UART_RX_TYPE;
len_to_read = 1;
len_total_read = 0;
len_state_read = 0;
break;
}
ble_transport_to_hs_acl(m);
@@ -156,6 +199,7 @@ static void IRAM_ATTR hci_uart_rx_task(void *arg)
rx_st = UART_RX_TYPE;
len_to_read = 1;
len_total_read = 0;
len_state_read = 0;
}
break;
@@ -166,7 +210,8 @@ static void IRAM_ATTR hci_uart_rx_task(void *arg)
}
}
vTaskDelete(NULL);
s_rx_task_hdl = NULL;
vTaskDelete(NULL);
}
void hci_uart_send(uint8_t *buf, uint16_t len)
@@ -176,7 +221,10 @@ void hci_uart_send(uint8_t *buf, uint16_t len)
while (len) {
len_write = uart_write_bytes(UART_NO, p, len);
assert(len_write > 0);
if (len_write <= 0) {
ESP_LOGE(TAG, "uart_write_bytes failed: %d", len_write);
return;
}
len -= len_write;
p += len_write;
}
@@ -216,7 +264,7 @@ int
ble_transport_to_ll_cmd_impl(void *buf)
{
int len = 3 + ((uint8_t *)buf)[2] + 1;
uint8_t data[258];
uint8_t data[259];
data[0] = HCI_H4_CMD;
memcpy(data + 1, buf, len - 1);
hci_uart_send(data, len);
@@ -262,7 +310,7 @@ void hci_uart_close(void)
const int max_wait_count = 5;
TaskHandle_t task_handle = s_rx_task_hdl;
while (wait_count < max_wait_count) {
while (wait_count < max_wait_count && s_rx_task_hdl == task_handle) {
vTaskDelay(pdMS_TO_TICKS(100));
wait_count++;
@@ -272,8 +320,8 @@ void hci_uart_close(void)
if (s_rx_task_hdl == task_handle) {
vTaskDelete(s_rx_task_hdl);
vTaskDelay(pdMS_TO_TICKS(100));
s_rx_task_hdl = NULL;
}
s_rx_task_hdl = NULL;
}
uart_driver_delete(UART_NO);

View File

@@ -92,6 +92,10 @@ static void event_handler(void* arg, esp_event_base_t event_base,
void wifi_init_sta(void)
{
s_wifi_event_group = xEventGroupCreate();
if (s_wifi_event_group == NULL) {
ESP_LOGE(TAG, "Failed to create wifi event group");
return;
}
ESP_ERROR_CHECK(esp_netif_init());
@@ -195,7 +199,7 @@ static void cmd_ping_on_ping_end(esp_ping_handle_t hdl, void *args)
esp_ping_get_profile(hdl, ESP_PING_PROF_REPLY, &received, sizeof(received));
esp_ping_get_profile(hdl, ESP_PING_PROF_IPADDR, &target_addr, sizeof(target_addr));
esp_ping_get_profile(hdl, ESP_PING_PROF_DURATION, &total_time_ms, sizeof(total_time_ms));
uint32_t loss = (uint32_t)((1 - ((float)received) / transmitted) * 100);
uint32_t loss = (transmitted > 0) ? (uint32_t)((1 - ((float)received) / transmitted) * 100) : 0;
if (IP_IS_V4(&target_addr)) {
printf("\n--- %s ping statistics ---\n", inet_ntoa(*ip_2_ip4(&target_addr)));
} else {
@@ -347,9 +351,10 @@ bleprph_advertise(void)
fields.name_len = strlen(name);
fields.name_is_complete = 1;
fields.uuids16 = (ble_uuid16_t[]) {
static const ble_uuid16_t adv_uuids16[] = {
BLE_UUID16_INIT(GATT_SVR_SVC_ALERT_UUID)
};
fields.uuids16 = adv_uuids16;
fields.num_uuids16 = 1;
fields.uuids16_is_complete = 1;

View File

@@ -12,12 +12,20 @@
int
peer_addr_parse(const char *addr_str, uint8_t addr[PEER_ADDR_VAL_SIZE])
{
unsigned int tmp[6] = {0};
int rc;
int i;
if (addr_str == NULL) {
return 0;
}
return sscanf(addr_str, "%hhx:%hhx:%hhx:%hhx:%hhx:%hhx",
&addr[5], &addr[4], &addr[3],
&addr[2], &addr[1], &addr[0]);
rc = sscanf(addr_str, "%x:%x:%x:%x:%x:%x",
&tmp[5], &tmp[4], &tmp[3],
&tmp[2], &tmp[1], &tmp[0]);
for (i = 0; i < PEER_ADDR_VAL_SIZE; i++) {
addr[i] = (uint8_t)tmp[i];
}
return rc;
}
/**
@@ -98,7 +106,7 @@ print_conn_desc(const struct ble_gap_conn_desc *desc)
}
#if MYNEWT_VAL(BLE_EXT_ADV)
void
static void
print_addr(const void *addr, const char *name)
{
const uint8_t *u8p;
@@ -254,11 +262,9 @@ print_adv_fields(const struct ble_hs_adv_fields *fields)
if (fields->device_addr_is_present) {
MODLOG_DFLT(DEBUG, " device_addr=");
u8p = fields->device_addr;
MODLOG_DFLT(DEBUG, "%s ", addr_str(u8p));
u8p += BLE_HS_ADV_PUBLIC_TGT_ADDR_ENTRY_LEN;
MODLOG_DFLT(DEBUG, "addr_type %d ", *u8p);
u8p = fields->device_addr;
MODLOG_DFLT(DEBUG, "%s addr_type %d ", addr_str(u8p),
fields->device_addr_type);
}
if (fields->le_role_is_present) {

View File

@@ -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
*/
@@ -167,7 +167,7 @@ peer_dsc_add(struct peer *peer, uint16_t chr_val_handle,
if (prev == NULL) {
SLIST_INSERT_HEAD(&chr->dscs, dsc, next);
} else {
SLIST_NEXT(prev, next) = dsc;
SLIST_INSERT_AFTER(prev, dsc, next);
}
return 0;
@@ -196,6 +196,7 @@ peer_disc_dscs(struct peer *peer)
peer_dsc_disced, peer);
if (rc != 0) {
peer_disc_complete(peer, rc);
return;
}
peer->disc_prev_chr_val = chr->chr.val_handle;
@@ -357,7 +358,7 @@ peer_chr_add(struct peer *peer, uint16_t svc_start_handle,
if (prev == NULL) {
SLIST_INSERT_HEAD(&svc->chrs, chr, next);
} else {
SLIST_NEXT(prev, next) = chr;
SLIST_INSERT_AFTER(prev, chr, next);
}
return 0;
@@ -407,12 +408,15 @@ peer_disc_chrs(struct peer *peer)
struct peer_svc *svc;
int rc;
/* Search through the list of discovered service for the first service that
* contains undiscovered characteristics. Then, discover all
* characteristics belonging to that service.
*/
SLIST_FOREACH(svc, &peer->svcs, next) {
if (!peer_svc_is_empty(svc) && SLIST_EMPTY(&svc->chrs)) {
/* Advance past the last processed service, or start from the beginning. */
if (peer->cur_svc == NULL) {
svc = SLIST_FIRST(&peer->svcs);
} else {
svc = SLIST_NEXT(peer->cur_svc, next);
}
for (; svc != NULL; svc = SLIST_NEXT(svc, next)) {
if (!peer_svc_is_empty(svc)) {
peer->cur_svc = svc;
rc = ble_gattc_disc_all_chrs(peer->conn_handle,
svc->svc.start_handle,
@@ -596,17 +600,24 @@ peer_disc_incs(struct peer *peer)
if (peer->cur_svc == NULL) {
if (peer->disc_prev_chr_val > 0) {
peer_disc_chrs(peer);
return;
}
return;
}
}
/* Skip empty services rather than aborting include discovery early. */
while (peer->cur_svc != NULL && peer_svc_is_empty(peer->cur_svc)) {
peer->cur_svc = SLIST_NEXT(peer->cur_svc, next);
}
svc = peer->cur_svc;
if (svc != NULL && !peer_svc_is_empty(svc)) {
if (svc != NULL) {
rc = ble_gattc_find_inc_svcs(peer->conn_handle,
svc->svc.start_handle,
svc->svc.end_handle,
peer_inc_disced, peer);
if (rc != 0) {
peer->cur_svc = NULL;
peer_disc_chrs(peer);
}
} else {
@@ -684,6 +695,10 @@ peer_svc_find_uuid(const struct peer *peer, const ble_uuid_t *uuid)
{
const struct peer_svc *svc;
if (peer == NULL || uuid == NULL) {
return NULL;
}
SLIST_FOREACH(svc, &peer->svcs, next) {
if (ble_uuid_cmp(&svc->svc.uuid.u, uuid) == 0) {
return svc;
@@ -700,6 +715,10 @@ peer_chr_find_uuid(const struct peer *peer, const ble_uuid_t *svc_uuid,
const struct peer_svc *svc;
const struct peer_chr *chr;
if (chr_uuid == NULL) {
return NULL;
}
svc = peer_svc_find_uuid(peer, svc_uuid);
if (svc == NULL) {
return NULL;
@@ -721,6 +740,10 @@ peer_dsc_find_uuid(const struct peer *peer, const ble_uuid_t *svc_uuid,
const struct peer_chr *chr;
const struct peer_dsc *dsc;
if (dsc_uuid == NULL) {
return NULL;
}
chr = peer_chr_find_uuid(peer, svc_uuid, chr_uuid);
if (chr == NULL) {
return NULL;
@@ -810,6 +833,7 @@ peer_svc_disced(uint16_t conn_handle, const struct ble_gatt_error *error,
#else
/* All services discovered; start discovering characteristics. */
if (peer->disc_prev_chr_val > 0) {
peer->cur_svc = NULL;
peer_disc_chrs(peer);
}
#endif
@@ -979,6 +1003,7 @@ peer_free_mem(void)
{
free(peer_mem);
peer_mem = NULL;
SLIST_INIT(&peers);
free(peer_svc_mem);
peer_svc_mem = NULL;

View File

@@ -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
*/
@@ -20,23 +20,27 @@
static TaskHandle_t cli_task;
static QueueHandle_t cli_handle;
static int stop;
static volatile int stop;
static int enter_passkey_handler(int argc, char *argv[])
{
int key;
char pkey[8];
char pkey[8] = {0};
int num;
if (argc != 2) {
return -1;
}
if (cli_handle == NULL) {
return -1;
}
sscanf(argv[1], "%7s", pkey);
ESP_LOGI("You entered", "%s %s", argv[0], argv[1]);
num = pkey[0];
if (isalpha(num)) {
if (isalpha((unsigned char)num)) {
if ((strcasecmp(pkey, "Y") == 0) || (strcasecmp(pkey, "Yes") == 0)) {
key = 1;
xQueueSend(cli_handle, &key, 0);
@@ -56,6 +60,9 @@ static int enter_passkey_handler(int argc, char *argv[])
int scli_receive_key(int *console_key)
{
if (cli_handle == NULL) {
return pdFALSE;
}
return xQueueReceive(cli_handle, console_key, BLE_RX_TIMEOUT);
}
@@ -108,10 +115,8 @@ static void scli_task(void *arg)
}
}
if (event.type == UART_DATA) {
while (uart_read_bytes(uart_num, (uint8_t *) &linebuf[i], 1, 0)) {
if (i >= sizeof(linebuf) - 1) {
break;
}
while (i < sizeof(linebuf) - 1 &&
uart_read_bytes(uart_num, (uint8_t *) &linebuf[i], 1, 0)) {
if (linebuf[i] == '\r') {
uart_write_bytes(uart_num, "\r\n", 2);
} else {
@@ -143,12 +148,14 @@ int scli_init(void)
/* Register CLI "key <value>" to accept input from user during pairing */
ble_register_cli();
xTaskCreate(scli_task, "scli_cli", 4096, (void *) 0, 3, &cli_task);
if (cli_task == NULL) {
cli_handle = xQueueCreate(1, sizeof(int));
if (cli_handle == NULL) {
return ESP_FAIL;
}
cli_handle = xQueueCreate( 1, sizeof(int) );
if (cli_handle == NULL) {
xTaskCreate(scli_task, "scli_cli", 4096, (void *) 0, 3, &cli_task);
if (cli_task == NULL) {
vQueueDelete(cli_handle);
cli_handle = NULL;
return ESP_FAIL;
}
return ESP_OK;

View File

@@ -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
*/
@@ -32,7 +32,7 @@ static int dtm_set_ble_tx_power_command(int argc, char **argv)
}
ESP_LOGI(__func__, "Set tx power level '%d'", dtm_set_tx_power_cmd_args.cmd_params->ival[0]);
if (dtm_set_tx_power_cmd_args.cmd_params->ival[0] > 15) {
if (dtm_set_tx_power_cmd_args.cmd_params->ival[0] < 0 || dtm_set_tx_power_cmd_args.cmd_params->ival[0] > 15) {
return 2;
}
@@ -48,6 +48,11 @@ static int dtm_get_ble_tx_power_command(int argc, char **argv)
{
esp_power_level_t power_level;
if (esp_bt_controller_get_status() != ESP_BT_CONTROLLER_STATUS_ENABLED) {
esp_rom_printf("\nPlease enable BLE DTM mode first by using the command enable_ble_dtm -e 1 before sending this command.\n");
return 2;
}
power_level = esp_ble_tx_power_get_enhanced(ESP_BLE_ENHANCED_PWR_TYPE_DEFAULT, 0);
if (power_level == ESP_PWR_LVL_INVALID) {
@@ -67,10 +72,18 @@ static int dtm_reconfig_uart_pins_command(int argc, char **argv)
return 1;
}
ESP_LOGI(__func__, "reconfig tx:'%d', rx: '%d'",
dtm_reconfig_uart_cmd_args.tx_pin->ival[0], dtm_reconfig_uart_cmd_args.rx_pin->ival[0]);
hci_uart_reconfig_pin(dtm_reconfig_uart_cmd_args.tx_pin->ival[0],
dtm_reconfig_uart_cmd_args.rx_pin->ival[0], -1, -1);
int tx_pin = dtm_reconfig_uart_cmd_args.tx_pin->ival[0];
int rx_pin = dtm_reconfig_uart_cmd_args.rx_pin->ival[0];
if (tx_pin < 0 || rx_pin < 0) {
ESP_LOGE(__func__, "Invalid GPIO pin: tx=%d, rx=%d", tx_pin, rx_pin);
return 1;
}
ESP_LOGI(__func__, "reconfig tx:'%d', rx: '%d'", tx_pin, rx_pin);
int rc = hci_uart_reconfig_pin(tx_pin, rx_pin, -1, -1);
if (rc != 0) {
ESP_LOGE(__func__, "Failed to reconfig UART pins; rc=%d", rc);
return 1;
}
return 0;
}

View File

@@ -151,9 +151,11 @@ gatt_svc_access(uint16_t conn_handle, uint16_t attr_handle,
sizeof(gatt_svr_chr_val),
sizeof(gatt_svr_chr_val),
&gatt_svr_chr_val, NULL);
ble_gatts_chr_updated(attr_handle);
MODLOG_DFLT(INFO, "Notification/Indication scheduled for "
"all subscribed peers.\n");
if (rc == 0) {
ble_gatts_chr_updated(attr_handle);
MODLOG_DFLT(INFO, "Notification/Indication scheduled for "
"all subscribed peers.\n");
}
return rc;
}
goto unknown;
@@ -170,7 +172,7 @@ gatt_svc_access(uint16_t conn_handle, uint16_t attr_handle,
if (ble_uuid_cmp(uuid, &gatt_svr_dsc_uuid.u) == 0) {
rc = os_mbuf_append(ctxt->om,
&gatt_svr_dsc_val,
sizeof(gatt_svr_chr_val));
sizeof(gatt_svr_dsc_val));
return rc == 0 ? 0 : BLE_ATT_ERR_INSUFFICIENT_RES;
}
goto unknown;

View File

@@ -184,9 +184,10 @@ bleprph_advertise(void)
fields.name_is_complete = 1;
#endif
fields.uuids16 = (ble_uuid16_t[]) {
static const ble_uuid16_t adv_uuids16[] = {
BLE_UUID16_INIT(GATT_SVR_SVC_ALERT_UUID)
};
fields.uuids16 = adv_uuids16;
fields.num_uuids16 = 1;
fields.uuids16_is_complete = 1;
@@ -480,17 +481,21 @@ bleprph_on_reset(int reason)
static void
ble_app_set_addr(void)
{
ble_addr_t addr;
ble_addr_t addr = {0};
int rc;
/* generate new non-resolvable private address */
rc = ble_hs_id_gen_rnd(0, &addr);
assert(rc == 0);
if (rc != 0) {
MODLOG_DFLT(ERROR, "ble_hs_id_gen_rnd failed; rc=%d\n", rc);
return;
}
/* set generated address */
rc = ble_hs_id_set_rnd(addr.val);
assert(rc == 0);
if (rc != 0) {
MODLOG_DFLT(ERROR, "ble_hs_id_set_rnd failed; rc=%d\n", rc);
}
}
#endif
@@ -507,8 +512,8 @@ bleprph_on_sync(void)
#if CONFIG_EXAMPLE_USE_CI_ADDRESS
if (strlen(CONFIG_EXAMPLE_CI_ADDRESS_OFFSET)) {
uint8_t addr[6] = {0};
uint32_t *offset = (uint32_t *)&addr[1];
*offset = atoi(CONFIG_EXAMPLE_CI_ADDRESS_OFFSET);
uint32_t offset_val = (uint32_t)atoi(CONFIG_EXAMPLE_CI_ADDRESS_OFFSET);
memcpy(&addr[1], &offset_val, sizeof(offset_val));
addr[5] = 0xC3;
addr[0] = CONFIG_IDF_FIRMWARE_CHIP_ID;
rc = ble_hs_id_set_rnd(addr);

View File

@@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2015-2025 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2015-2026 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@@ -170,8 +170,10 @@ static void register_heap(void)
static int tasks_info(int argc, char **argv)
{
const size_t bytes_per_task = 40; /* see vTaskList description */
char *task_list_buffer = malloc(uxTaskGetNumberOfTasks() * bytes_per_task);
/* Use a larger per-task estimate (80 bytes) plus a safety margin of 10 extra
* slots to absorb TOCTOU races and SMP mode affinity fields. */
const size_t bytes_per_task = 80;
char *task_list_buffer = malloc((uxTaskGetNumberOfTasks() + 10) * bytes_per_task);
if (task_list_buffer == NULL) {
ESP_LOGE(TAG, "failed to allocate buffer for vTaskList output");
return 1;
@@ -219,14 +221,19 @@ static int deep_sleep(int argc, char **argv)
return 1;
}
if (deep_sleep_args.wakeup_time->count) {
uint64_t timeout = 1000ULL * deep_sleep_args.wakeup_time->ival[0];
int wakeup_ms = deep_sleep_args.wakeup_time->ival[0];
if (wakeup_ms <= 0) {
ESP_LOGE(TAG, "Invalid wakeup time: %d ms (must be > 0)", wakeup_ms);
return 1;
}
uint64_t timeout = 1000ULL * wakeup_ms;
ESP_LOGI(TAG, "Enabling timer wakeup, timeout=%lluus", timeout);
ESP_ERROR_CHECK( esp_sleep_enable_timer_wakeup(timeout) );
}
if (deep_sleep_args.wakeup_gpio_num->count) {
int io_num = deep_sleep_args.wakeup_gpio_num->ival[0];
if (!rtc_gpio_is_valid_gpio(io_num)) {
ESP_LOGE(TAG, "GPIO %d is not an RTC IO", io_num);
if (io_num < 0 || !rtc_gpio_is_valid_gpio(io_num)) {
ESP_LOGE(TAG, "GPIO %d is not a valid RTC IO", io_num);
return 1;
}
int level = 0;
@@ -237,11 +244,13 @@ static int deep_sleep(int argc, char **argv)
return 1;
}
}
#if SOC_PM_SUPPORT_EXT1_WAKEUP
ESP_LOGI(TAG, "Enabling wakeup on GPIO%d, wakeup on %s level",
io_num, level ? "HIGH" : "LOW");
#if SOC_PM_SUPPORT_EXT1_WAKEUP
ESP_ERROR_CHECK( esp_sleep_enable_ext1_wakeup_io(1ULL << io_num, level) );
#else
ESP_LOGE(TAG, "GPIO wakeup from deep sleep not supported on this target");
return 1;
#endif
}
@@ -311,22 +320,44 @@ static int light_sleep(int argc, char **argv)
ESP_LOGE(TAG, "Invalid wakeup level: %d", level);
return 1;
}
if (!GPIO_IS_VALID_GPIO(io_num)) {
ESP_LOGE(TAG, "Invalid GPIO number: %d", io_num);
return 1;
}
/* Configure the pin as input with a pull to avoid floating and false wakeups */
gpio_config_t io_conf = {
.pin_bit_mask = 1ULL << io_num,
.mode = GPIO_MODE_INPUT,
.pull_up_en = (level == 0) ? GPIO_PULLUP_ENABLE : GPIO_PULLUP_DISABLE,
.pull_down_en = (level == 1) ? GPIO_PULLDOWN_ENABLE : GPIO_PULLDOWN_DISABLE,
.intr_type = GPIO_INTR_DISABLE,
};
esp_err_t gpio_cfg_err = gpio_config(&io_conf);
if (gpio_cfg_err != ESP_OK) {
ESP_LOGE(TAG, "gpio_config failed for GPIO%d: %s", io_num, esp_err_to_name(gpio_cfg_err));
return 1;
}
ESP_LOGI(TAG, "Enabling wakeup on GPIO%d, wakeup on %s level",
io_num, level ? "HIGH" : "LOW");
ESP_ERROR_CHECK( gpio_wakeup_enable(io_num, level ? GPIO_INTR_HIGH_LEVEL : GPIO_INTR_LOW_LEVEL) );
esp_err_t wakeup_err = gpio_wakeup_enable(io_num, level ? GPIO_INTR_HIGH_LEVEL : GPIO_INTR_LOW_LEVEL);
if (wakeup_err != ESP_OK) {
ESP_LOGE(TAG, "gpio_wakeup_enable failed for GPIO%d: %s", io_num, esp_err_to_name(wakeup_err));
return 1;
}
}
if (io_count > 0) {
ESP_ERROR_CHECK( esp_sleep_enable_gpio_wakeup() );
}
if (CONFIG_ESP_CONSOLE_UART_NUM <= UART_NUM_1) {
if (CONFIG_ESP_CONSOLE_UART_NUM >= 0 && CONFIG_ESP_CONSOLE_UART_NUM <= UART_NUM_1) {
ESP_LOGI(TAG, "Enabling UART wakeup (press ENTER to exit light sleep)");
uart_wakeup_cfg_t uart_wakeup_cfg = {.wakeup_mode = UART_WK_MODE_ACTIVE_THRESH, .rx_edge_threshold = 3};
ESP_ERROR_CHECK( uart_wakeup_setup(CONFIG_ESP_CONSOLE_UART_NUM, &uart_wakeup_cfg) );
ESP_ERROR_CHECK( esp_sleep_enable_uart_wakeup(CONFIG_ESP_CONSOLE_UART_NUM) );
}
fflush(stdout);
uart_wait_tx_idle_polling(CONFIG_ESP_CONSOLE_UART_NUM);
if (CONFIG_ESP_CONSOLE_UART_NUM >= 0) {
uart_wait_tx_idle_polling(CONFIG_ESP_CONSOLE_UART_NUM);
}
esp_light_sleep_start();
uint32_t causes = esp_sleep_get_wakeup_causes();

View File

@@ -71,7 +71,7 @@ static uint16_t handle;
#define PHY_CODED_S8 3
#if CONFIG_EXAMPLE_EXTENDED_ADV
static int current_phy_updated;
static volatile int current_phy_updated;
#endif
/* State for callback-chained read throughput test */
@@ -194,8 +194,9 @@ blecent_notify(uint16_t conn_handle, uint16_t val_handle,
return 0;
err:
/* Terminate the connection. */
return ble_gap_terminate(peer->conn_handle, BLE_ERR_REM_USER_CONN_TERM);
/* Terminate the connection; return original error code so caller detects failure. */
ble_gap_terminate(peer->conn_handle, BLE_ERR_REM_USER_CONN_TERM);
return rc;
}
static int blecent_write(uint16_t conn_handle, uint16_t val_handle,
@@ -599,6 +600,11 @@ read_cleanup:
break;
case NOTIFY_THROUGHPUT:
if (test_data[1] <= 0) {
ESP_LOGE(tag, "Please enter non-zero value for test time in seconds!!");
break;
}
if (test_data[2] == PHY_CODED_S2) {
switch_conn_params(conn_handle, &conn_params_coded_s2);
} else if (test_data[2] == PHY_CODED_S8) {
@@ -641,7 +647,7 @@ read_cleanup:
" can be seen on peripheral terminal after %d seconds",
test_data[1]);
}
vTaskDelay(test_data[1]*1000 / portTICK_PERIOD_MS);
vTaskDelay((TickType_t)test_data[1] * 1000 / portTICK_PERIOD_MS);
/* Unsubscribe so the next notify test triggers a fresh
* BLE_GAP_EVENT_SUBSCRIBE on the peripheral (cur_notify 0→1) */
@@ -762,22 +768,17 @@ ext_blecent_should_connect(const struct ble_gap_ext_disc_desc *disc)
{
int offset = 0;
int ad_struct_len = 0;
uint8_t test_addr[6];
uint8_t parsed_addr[6];
uint8_t phy_uuid_found = 0;
if (disc->legacy_event_type != BLE_HCI_ADV_RPT_EVTYPE_ADV_IND &&
disc->legacy_event_type != BLE_HCI_ADV_RPT_EVTYPE_DIR_IND) {
if (!(disc->props & BLE_HCI_ADV_CONN_MASK)) {
return 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);
/* Convert string to address */
/* peer_addr_parse stores address in little-endian order matching disc->addr.val;
* no byte reversal needed. */
peer_addr_parse(CONFIG_EXAMPLE_PEER_ADDR, parsed_addr);
for (int i = 0; i < 6; i++) {
test_addr[5 - i] = parsed_addr[i];
}
if (memcmp(test_addr, disc->addr.val, sizeof(disc->addr.val)) != 0) {
if (memcmp(parsed_addr, disc->addr.val, sizeof(disc->addr.val)) != 0) {
return 0;
}
}
@@ -860,9 +861,13 @@ blecent_should_connect(const struct ble_gap_disc_desc *disc)
char serv_name[] = "nimble_prph";
if (fields.name != NULL) {
ESP_LOGI(tag, "Device Name = %s", (char *)fields.name);
/* fields.name is not null-terminated; use %.*s for safe printing */
ESP_LOGI(tag, "Device Name = %.*s", fields.name_len, (char *)fields.name);
if (memcmp(fields.name, serv_name, fields.name_len) == 0) {
/* Require exact length match to prevent prefix false-positives and
* avoid reading past the end of serv_name (stack over-read). */
if (fields.name_len == (uint8_t)strlen(serv_name) &&
memcmp(fields.name, serv_name, fields.name_len) == 0) {
ESP_LOGI(tag, "central connect to `nimble_prph` success");
return 1;
}
@@ -912,6 +917,9 @@ blecent_connect_if_interesting(void *disc)
rc = ble_hs_id_infer_auto(0, &own_addr_type);
if (rc != 0) {
ESP_LOGE(tag, "error determining address type; rc=%d", rc);
#if !(MYNEWT_VAL(BLE_HOST_ALLOW_CONNECT_WITH_SCAN))
blecent_scan();
#endif
return;
}
@@ -924,6 +932,9 @@ blecent_connect_if_interesting(void *disc)
ESP_LOGE(tag, "Error: Failed to connect to device; addr_type=%d "
"addr=%s; rc=%d\n",
conn_addr.type, addr_str(conn_addr.val), rc);
#if !(MYNEWT_VAL(BLE_HOST_ALLOW_CONNECT_WITH_SCAN))
blecent_scan();
#endif
return;
}
}
@@ -1038,7 +1049,6 @@ blecent_gap_event(struct ble_gap_event *event, void *arg)
/* Forget about peer. */
peer_delete(event->disconnect.conn.conn_handle);
vTaskDelay(200);
/* Resume scanning. */
blecent_scan();
@@ -1212,9 +1222,11 @@ app_main(void)
assert(rc == 0);
#endif
#if CONFIG_BT_NIMBLE_GAP_SERVICE
/* Set the default device name. */
rc = ble_svc_gap_device_name_set("gattc-throughput");
assert(rc == 0);
#endif
/* XXX Need to have template for store */
ble_store_config_init();
@@ -1241,32 +1253,9 @@ app_main(void)
printf(" | |\n");
printf("\n ===============================================================================================\n");
const char *prompt = LOG_COLOR_I "Throughput demo >> " LOG_RESET_COLOR;
while (true) {
/* Get a line using linenoise.
* The line is returned when ENTER is pressed.
*/
char *line = linenoise(prompt);
if (line == NULL) { /* Ignore empty lines */
continue;
}
/* Add the command to the history */
linenoiseHistoryAdd(line);
/* Try to run the command */
int ret;
esp_err_t err = esp_console_run(line, &ret);
if (err == ESP_ERR_NOT_FOUND) {
printf("Unrecognized command\n");
} else if (err == ESP_ERR_INVALID_ARG) {
// command was empty
} else if (err == ESP_OK && ret != ESP_OK) {
printf("Command returned non-zero error code: 0x%x (%s)\n", ret, esp_err_to_name(ret));
} else if (err != ESP_OK) {
printf("Internal error: %s\n", esp_err_to_name(err));
}
/* linenoise allocates line buffer on the heap, so need to free it */
linenoiseFree(line);
}
/* Start the REPL task that was created (but left blocked) by
* esp_console_new_repl_uart. Without this call the task would wait
* forever, leaking its 4 KB stack and TCB. */
ESP_ERROR_CHECK(esp_console_start_repl(repl));
/* app_main can now return; the REPL task handles console I/O from here. */
}

View File

@@ -28,30 +28,44 @@ peer_addr_parse(const char *addr_str, uint8_t addr[PEER_ADDR_VAL_SIZE])
void
print_bytes(const uint8_t *bytes, int len)
{
/* Build the entire hex string into a buffer first and log it in one call.
* Calling MODLOG_DFLT per byte adds a full log header and newline to each
* byte, breaking the intended colon-separated format and blocking the CPU. */
char buf[256];
int pos = 0;
int i;
for (i = 0; i < len; i++) {
MODLOG_DFLT(DEBUG, "%s0x%02x", i != 0 ? ":" : "", bytes[i]);
for (i = 0; i < len && pos < (int)(sizeof(buf) - 5); i++) {
if (i != 0) {
buf[pos++] = ':';
}
pos += snprintf(buf + pos, sizeof(buf) - pos, "0x%02x", bytes[i]);
}
buf[pos] = '\0';
MODLOG_DFLT(DEBUG, "%s", buf);
}
void
print_mbuf(const struct os_mbuf *om)
{
int colon, i;
char buf[512];
int pos = 0;
int colon = 0;
int i;
colon = 0;
while (om != NULL) {
if (colon) {
MODLOG_DFLT(INFO, ":");
} else {
colon = 1;
}
for (i = 0; i < om->om_len; i++) {
MODLOG_DFLT(INFO, "%s0x%02x", i != 0 ? ":" : "", om->om_data[i]);
while (om != NULL && pos < (int)(sizeof(buf) - 6)) {
for (i = 0; i < om->om_len && pos < (int)(sizeof(buf) - 6); i++) {
if (colon) {
buf[pos++] = ':';
} else {
colon = 1;
}
pos += snprintf(buf + pos, sizeof(buf) - pos, "0x%02x", om->om_data[i]);
}
om = SLIST_NEXT(om, om_next);
}
buf[pos] = '\0';
MODLOG_DFLT(INFO, "%s", buf);
}
char *

View File

@@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2015-2026 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@@ -40,7 +40,7 @@ chr_end_handle(const struct peer_svc *svc, const struct peer_chr *chr);
int
chr_is_empty(const struct peer_svc *svc, const struct peer_chr *chr);
static struct peer_chr *
peer_chr_find(const struct peer_svc *svc, uint16_t chr_def_handle,
peer_chr_find(const struct peer_svc *svc, uint16_t chr_val_handle,
struct peer_chr **out_prev);
static void
peer_disc_chrs(struct peer *peer);
@@ -168,7 +168,7 @@ peer_dsc_add(struct peer *peer, uint16_t chr_val_handle,
if (prev == NULL) {
SLIST_INSERT_HEAD(&chr->dscs, dsc, next);
} else {
SLIST_NEXT(prev, next) = dsc;
SLIST_INSERT_AFTER(prev, dsc, next);
}
return 0;
@@ -197,6 +197,7 @@ peer_disc_dscs(struct peer *peer)
peer_dsc_disced, peer);
if (rc != 0) {
peer_disc_complete(peer, rc);
return;
}
peer->disc_prev_chr_val = chr->chr.val_handle;
@@ -340,7 +341,7 @@ peer_chr_add(struct peer *peer, uint16_t svc_start_handle,
return BLE_HS_EUNKNOWN;
}
chr = peer_chr_find(svc, gatt_chr->def_handle, &prev);
chr = peer_chr_find(svc, gatt_chr->val_handle, &prev);
if (chr != NULL) {
/* Characteristic already discovered. */
return 0;
@@ -408,13 +409,20 @@ peer_disc_chrs(struct peer *peer)
struct peer_svc *svc;
int rc;
/* Search through the list of discovered service for the first service that
* contains undiscovered characteristics. Then, discover all
* characteristics belonging to that service.
*/
/* Advance cur_svc to the next service to discover characteristics for.
* Starting from NULL means start from the first service in the list.
* This sequential approach prevents re-processing services that had no
* characteristics (where SLIST_EMPTY would remain true and cause an
* infinite loop with the old SLIST_FOREACH-from-start approach). */
if (peer->cur_svc == NULL) {
peer->cur_svc = SLIST_FIRST(&peer->svcs);
} else {
peer->cur_svc = SLIST_NEXT(peer->cur_svc, next);
}
SLIST_FOREACH(svc, &peer->svcs, next) {
if (!peer_svc_is_empty(svc) && SLIST_EMPTY(&svc->chrs)) {
/* Scan forward past empty services to find the next one to process */
for (svc = peer->cur_svc; svc != NULL; svc = SLIST_NEXT(svc, next)) {
if (!peer_svc_is_empty(svc)) {
peer->cur_svc = svc;
rc = ble_gattc_disc_all_chrs(peer->conn_handle,
svc->svc.start_handle,
@@ -600,9 +608,10 @@ peer_disc_incs(struct peer *peer)
peer->cur_svc = SLIST_NEXT(peer->cur_svc, next);
if (peer->cur_svc == NULL) {
if (peer->disc_prev_chr_val > 0) {
/* cur_svc is already NULL: peer_disc_chrs starts from first svc */
peer_disc_chrs(peer);
return;
}
return; /* Always return; don't fall through into svc processing */
}
}
@@ -613,10 +622,18 @@ peer_disc_incs(struct peer *peer)
svc->svc.end_handle,
peer_inc_disced, peer);
if (rc != 0) {
/* Hard error: skip to characteristic discovery from beginning */
peer->cur_svc = NULL;
peer_disc_chrs(peer);
}
} else if (svc != NULL) {
/* svc is empty: advance to next service for include discovery */
peer_disc_incs(peer);
} else {
peer_disc_chrs(peer);
/* cur_svc is NULL on entry: no services at all */
if (peer->disc_prev_chr_val > 0) {
peer_disc_chrs(peer);
}
}
}
#endif
@@ -690,8 +707,12 @@ peer_svc_find_uuid(const struct peer *peer, const ble_uuid_t *uuid)
{
const struct peer_svc *svc;
if (peer == NULL || uuid == NULL) {
return NULL;
}
SLIST_FOREACH(svc, &peer->svcs, next) {
if ((uuid != NULL) && (ble_uuid_cmp(&(svc->svc.uuid.u), uuid) == 0)) {
if (ble_uuid_cmp(&(svc->svc.uuid.u), uuid) == 0) {
return svc;
}
}
@@ -727,6 +748,10 @@ peer_dsc_find_uuid(const struct peer *peer, const ble_uuid_t *svc_uuid,
const struct peer_chr *chr;
const struct peer_dsc *dsc;
if (peer == NULL) {
return NULL;
}
chr = peer_chr_find_uuid(peer, svc_uuid, chr_uuid);
if (chr == NULL) {
return NULL;
@@ -816,6 +841,7 @@ peer_svc_disced(uint16_t conn_handle, const struct ble_gatt_error *error,
#else
/* All services discovered; start discovering characteristics. */
if (peer->disc_prev_chr_val > 0) {
peer->cur_svc = NULL;
peer_disc_chrs(peer);
}
#endif
@@ -920,6 +946,8 @@ peer_add(uint16_t conn_handle)
static void
peer_free_mem(void)
{
SLIST_INIT(&peers);
free(peer_mem);
peer_mem = NULL;

View File

@@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2015-2025 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2015-2026 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@@ -102,7 +102,7 @@ static int conn_mtu_handler(int argc, char *argv[])
static int throughput_demo_handler(int argc, char *argv[])
{
char pkey[8];
char pkey[8] = {0};
struct cli_msg msg = {
.type = CLI_MSG_TYPE_THROUGHPUT,
};
@@ -111,7 +111,15 @@ static int throughput_demo_handler(int argc, char *argv[])
return -1;
}
sscanf(argv[1], "%7s", pkey);
if (cli_handle == NULL) {
ESP_LOGE("CLI", "Queue not initialized");
return -1;
}
if (sscanf(argv[1], "%7s", pkey) != 1) {
ESP_LOGE("CLI", "Failed to parse throughput type");
return -1;
}
if (strcmp(pkey, "read") == 0) {
msg.data.key[0] = 1;
@@ -133,14 +141,17 @@ static int throughput_demo_handler(int argc, char *argv[])
static int yesno_handler(int argc, char *argv[])
{
char yesno[4];
char yesno[4] = {0};
bool yes;
if (argc != 2) {
return -1;
}
sscanf(argv[1], "%3s", yesno);
if (sscanf(argv[1], "%3s", yesno) != 1) {
ESP_LOGE("CLI", "Failed to parse yes/no argument");
return -1;
}
if (strcmp(yesno, "Yes") == 0 || strcmp(yesno, "YES") == 0 || strcmp(yesno, "yes") == 0) {
yes = 1;
@@ -151,23 +162,29 @@ static int yesno_handler(int argc, char *argv[])
}
ESP_LOGI("User entered", "%s %s", argv[0], yesno);
/* Send as 24-byte buffer to match queue item size */
uint8_t yesno_buf[24] = {0};
yesno_buf[0] = (uint8_t)yes;
/* Use struct cli_msg to exactly match the queue item size (sizeof(struct cli_msg))
* and avoid stack buffer over-read from sending undersized raw buffers. */
struct cli_msg msg = {
.type = CLI_MSG_TYPE_YESNO,
.data.yes = yes,
};
if (cli_handle) {
xQueueSend(cli_handle, yesno_buf, 500 / portTICK_PERIOD_MS);
xQueueSend(cli_handle, &msg, 500 / portTICK_PERIOD_MS);
}
return 0;
}
int scli_receive_yesno(bool *console_key)
{
/* Receive into temporary 24-byte buffer to match queue item size,
* then extract bool value to prevent buffer overflow */
uint8_t temp_buf[24];
int ret = xQueueReceive(cli_handle, temp_buf, YES_NO_PARAM);
struct cli_msg msg;
int ret;
if (cli_handle == NULL) {
return pdFALSE;
}
ret = xQueueReceive(cli_handle, &msg, YES_NO_PARAM);
if (ret == pdPASS) {
*console_key = (bool)temp_buf[0]; /* Extract first byte as bool */
*console_key = msg.data.yes;
}
return ret;
}
@@ -175,6 +192,9 @@ int scli_receive_yesno(bool *console_key)
int scli_receive_key(int console_key[6])
{
struct cli_msg msg;
if (cli_handle == NULL) {
return 0;
}
if (xQueueReceive(cli_handle, &msg, BLE_RX_PARAM) != pdTRUE) {
return 0;
}
@@ -198,6 +218,9 @@ int scli_receive_key(int console_key[6])
int cli_receive_key(int console_key[6])
{
struct cli_msg msg;
if (cli_handle == NULL) {
return 0;
}
if (xQueueReceive(cli_handle, &msg, BLE_RX_TIMEOUT) != pdTRUE) {
return 0;
}

View File

@@ -68,10 +68,17 @@ ext_get_data(uint8_t ext_adv_pattern[], int size)
int rc;
data = os_msys_get_pkthdr(size, 0);
assert(data);
if (!data) {
ESP_LOGE(tag, "ext_get_data: mbuf alloc failed");
return NULL;
}
rc = os_mbuf_append(data, ext_adv_pattern, size);
assert(rc == 0);
if (rc != 0) {
ESP_LOGE(tag, "ext_get_data: mbuf_append failed; rc=%d", rc);
os_mbuf_free_chain(data);
return NULL;
}
return data;
}
@@ -147,13 +154,16 @@ ext_bleprph_advertise(void)
/*enable connectable advertising for all Phy*/
params.connectable = 1;
/* advertise using random addr */
params.own_addr_type = BLE_OWN_ADDR_PUBLIC;
/* Use dynamically inferred address type (set in gatts_on_sync via ble_hs_id_infer_auto) */
params.own_addr_type = gatts_addr_type;
/* Set current phy; get mbuf for scan rsp data; fill mbuf with scan rsp data */
params.primary_phy = BLE_HCI_LE_PHY_1M_PREF_MASK ;
params.secondary_phy = BLE_HCI_LE_PHY_2M_PREF_MASK ;
data = ext_get_data(ext_adv_pattern, sizeof(ext_adv_pattern));
if (!data) {
return;
}
params.sid = 0;
params.itvl_min = BLE_GAP_ADV_FAST_INTERVAL1_MIN;
@@ -282,7 +292,11 @@ notify_task(void *arg)
/* Memory not available for mbuf, yield briefly */
vTaskDelay(1);
}
} while (om == NULL);
} while (om == NULL && notify_state);
if (om == NULL) {
/* notify_state went false while waiting; stop test */
break;
}
rc = ble_gatts_notify_custom(conn_handle, notify_handle, om);
if (rc != 0) {
@@ -348,12 +362,14 @@ gatts_gap_event(struct ble_gap_event *event, void *arg)
}
if (event->connect.status != 0) {
/* Connection failed; resume advertising */
/* Connection failed; resume advertising. Skip HCI/conn_handle
* updates since the connection handle is invalid on failure. */
#if CONFIG_EXAMPLE_EXTENDED_ADV
ext_bleprph_advertise();
#else
gatts_advertise();
#endif
break;
}
rc = ble_hs_hci_util_set_data_len(event->connect.conn_handle,
@@ -419,10 +435,15 @@ gatts_gap_event(struct ble_gap_event *event, void *arg)
}
} else {
ESP_LOGI(tag, "Notifications disabled");
/* Wake up notify_task so it can exit the test loop cleanly;
* without this the task would block forever on ulTaskNotifyTake. */
if (notify_task_handle) {
xTaskNotifyGive(notify_task_handle);
}
}
} else if (event->subscribe.attr_handle != notify_handle) {
notify_state = event->subscribe.cur_notify;
}
/* Do NOT modify notify_state for other characteristics: that would
* corrupt the throughput test state while it is running. */
break;
case BLE_GAP_EVENT_NOTIFY_TX:
@@ -533,7 +554,8 @@ void app_main(void)
BaseType_t task_rc = xTaskCreate(notify_task, "notify_task", 4096, NULL, 10, &notify_task_handle);
if (task_rc != pdPASS) {
ESP_LOGE(tag, "Failed to create notify_task (rc=%d)", task_rc);
return ;
nimble_port_deinit();
return;
}
#if MYNEWT_VAL(BLE_GATTS)
rc = gatt_svr_init();

View File

@@ -22,7 +22,7 @@
static const char *TAG = "l2cap_coc_cent";
#define L2CAP_COC_PSM 0x0080
#define L2CAP_COC_PSM 0x0080 /* valid dynamic LE L2CAP CoC PSM (0x0080-0x00FF) */
#define L2CAP_COC_MTU CONFIG_EXAMPLE_L2CAP_COC_MTU
#define COC_BUF_COUNT (6 * MYNEWT_VAL(BLE_L2CAP_COC_MAX_NUM))
/* Block size must include mbuf headers so each SDU fits in one pool entry. */
@@ -144,12 +144,9 @@ static void cent_l2cap_coc_connect(uint16_t conn_handle)
if (rc != 0) {
ESP_LOGE(TAG, "L2CAP COC connect failed; rc=%d", rc);
l2cap_connecting = false;
/* EINVAL: NimBLE returns before chan alloc, sdu_rx not consumed — free it.
* ENOTCONN: NimBLE frees sdu_rx on all ENOTCONN paths (early !conn check
* and late TX failure via ble_l2cap_coc_cleanup_chan). Do not free here. */
if (rc == BLE_HS_EINVAL) {
os_mbuf_free_chain(sdu_rx);
}
/* NimBLE takes ownership of sdu_rx on ALL error paths from ble_l2cap_connect
* (freed via ble_l2cap_chan_free → ble_l2cap_coc_cleanup_chan or directly in
* ble_l2cap_sig_coc_connect validation). Never free here to avoid double-free. */
}
}
@@ -721,6 +718,8 @@ void app_main(void)
ret = nimble_port_init();
if (ret != ESP_OK) {
ESP_LOGE(TAG, "nimble_port_init failed; rc=%d", ret);
vEventGroupDelete(coc_event_group);
coc_event_group = NULL;
return;
}
@@ -739,6 +738,9 @@ void app_main(void)
if (xTaskCreate(cent_send_task, "cent_send_task", 4096, NULL, 5, NULL) != pdPASS) {
ESP_LOGE(TAG, "Failed to create cent_send_task");
nimble_port_deinit();
vEventGroupDelete(coc_event_group);
coc_event_group = NULL;
return;
}

View File

@@ -20,7 +20,7 @@
static const char *TAG = "l2cap_coc_prph";
#define L2CAP_COC_PSM 0x0080
#define L2CAP_COC_PSM 0x0080 /* valid dynamic LE L2CAP CoC PSM (0x0080-0x00FF) */
#define L2CAP_COC_MTU CONFIG_EXAMPLE_L2CAP_COC_MTU
#define COC_BUF_COUNT (6 * MYNEWT_VAL(BLE_L2CAP_COC_MAX_NUM))
/* Block size must include mbuf headers so each SDU fits in one pool entry. */
@@ -199,7 +199,11 @@ static void prph_advertise(void)
fields.name_len = strlen(name);
fields.name_is_complete = 1;
#endif
fields.uuids16 = (ble_uuid16_t[]){ BLE_UUID16_INIT(L2CAP_COC_UUID) };
/* Must be static: ble_gap_adv_set_fields copies the pointer, not the data.
* A stack compound literal becomes dangling after prph_advertise returns,
* causing corruption when BLE_NIMBLE_ENABLE_CONN_REATTEMPT re-uses the pointer. */
static const ble_uuid16_t adv_uuids16[] = { BLE_UUID16_INIT(L2CAP_COC_UUID) };
fields.uuids16 = adv_uuids16;
fields.num_uuids16 = 1;
fields.uuids16_is_complete = 1;
@@ -238,7 +242,11 @@ static int prph_l2cap_coc_accept(struct ble_l2cap_chan *chan)
return BLE_HS_ENOMEM;
}
int rc = ble_l2cap_recv_ready(chan, sdu_rx);
if (rc != 0) {
/* ble_l2cap_coc_recv_ready stores sdu_rx AFTER the BLE_HS_EBUSY check but
* BEFORE the BLE_HS_ENOENT check. On BLE_HS_EBUSY the buffer was never
* stored and must be freed here; on success or BLE_HS_ENOENT the buffer is
* owned by chan->coc_rx.sdus[] and freed by ble_l2cap_coc_cleanup_chan. */
if (rc != 0 && rc != BLE_HS_ENOENT) {
os_mbuf_free_chain(sdu_rx);
}
return rc;