fix(nimble): Fix vulnerabilities in NimBLE examples

This commit is contained in:
Shreeyash
2026-02-06 18:47:08 +05:30
parent b9f2b4b547
commit 5319914af2
43 changed files with 902 additions and 316 deletions
@@ -54,6 +54,7 @@ static int get_version(int argc, char **argv)
{
esp_chip_info_t info;
uint32_t flash_size;
const char *model_str;
esp_chip_info(&info);
if(esp_flash_get_size(NULL, &flash_size) != ESP_OK) {
printf("Get flash size failed");
@@ -61,7 +62,21 @@ static int get_version(int argc, char **argv)
}
printf("IDF Version:%s\r\n", esp_get_idf_version());
printf("Chip info:\r\n");
printf("\tmodel:%s\r\n", info.model == CHIP_ESP32 ? "ESP32" : "Unknow");
switch (info.model) {
case CHIP_ESP32: model_str = "ESP32"; break;
case CHIP_ESP32S3: model_str = "ESP32-S3"; break;
case CHIP_ESP32C3: model_str = "ESP32-C3"; break;
case CHIP_ESP32C2: model_str = "ESP32-C2"; break;
case CHIP_ESP32C6: model_str = "ESP32-C6"; break;
case CHIP_ESP32H2: model_str = "ESP32-H2"; break;
case CHIP_ESP32C61: model_str = "ESP32-C61"; break;
#ifdef CHIP_ESP32C5
case CHIP_ESP32C5: model_str = "ESP32-C5"; break;
#endif
default: model_str = "Unknown"; break;
}
printf("\tmodel:%s\r\n", model_str);
printf("\tcores:%d\r\n", info.cores);
printf("\tfeature:%s%s%s%s%" PRIu32 "%s\r\n",
info.features & CHIP_FEATURE_WIFI_BGN ? "/802.11bgn" : "",
@@ -122,7 +137,7 @@ static void register_free(void)
ESP_ERROR_CHECK( esp_console_cmd_register(&cmd) );
}
/* 'heap' command prints minumum heap size */
/* 'heap' command prints minimum heap size */
static int heap_size(int argc, char **argv)
{
uint32_t heap_size = heap_caps_get_minimum_free_size(MALLOC_CAP_DEFAULT);
@@ -111,8 +111,8 @@ peer_find(uint16_t conn_handle);
/* Console */
int scli_init(void);
void ble_register_cli(void);
int scli_receive_key(int *key);
int cli_receive_key(int *key);
int scli_receive_key(int key[6]);
int cli_receive_key(int key[6]);
int scli_receive_yesno(bool *key);
void scli_reset_queue(void);
@@ -58,9 +58,10 @@ static int blecent_gap_event(struct ble_gap_event *event, void *arg);
static SemaphoreHandle_t xSemaphore;
static int mbuf_len_total;
static int failure_count;
static TaskHandle_t throughput_task_handle = NULL;
static int conn_params_def[] = {40, 40, 0, 500, 80, 80};
/* test_data accepts test_name and test_time from CLI */
static int test_data[] = {1, 600, 0};
static int test_data[6] = {1, 600, 0, 0, 0, 0};
static int mtu_def = 512;
static ble_addr_t conn_addr;
static uint16_t handle;
@@ -225,6 +226,7 @@ static int blecent_read(uint16_t conn_handle, uint16_t val_handle,
return 0;
err:
xSemaphoreGive(xSemaphore);
/* Terminate the connection. */
vTaskDelay(100 / portTICK_PERIOD_MS);
return ble_gap_terminate(peer->conn_handle, BLE_ERR_REM_USER_CONN_TERM);
@@ -240,7 +242,8 @@ int update_phy(uint16_t conn_handle, uint8_t phy_mode)
current_phy_updated = 0;
rc = ble_gap_set_prefered_le_phy(conn_handle, BLE_HCI_LE_PHY_1M_PREF_MASK, BLE_HCI_LE_PHY_1M_PREF_MASK, 0);
if(rc != 0) {
ESP_LOGI(tag, "Requested PHY: 1M failed.");
current_phy_updated = 1;
ESP_LOGE(tag, "Requested PHY: 1M failed, rc=%d", rc);
}
else {
ESP_LOGI(tag, "Requested PHY: 1M");
@@ -251,7 +254,8 @@ int update_phy(uint16_t conn_handle, uint8_t phy_mode)
current_phy_updated = 0;
rc = ble_gap_set_prefered_le_phy(conn_handle, BLE_HCI_LE_PHY_2M_PREF_MASK, BLE_HCI_LE_PHY_2M_PREF_MASK, 0);
if(rc != 0) {
ESP_LOGI(tag, "Requested PHY: 2M failed.");
current_phy_updated = 1;
ESP_LOGE(tag, "Requested PHY: 2M failed, rc=%d", rc);
}
else {
ESP_LOGI(tag, "Requested PHY: 2M");
@@ -262,7 +266,8 @@ int update_phy(uint16_t conn_handle, uint8_t phy_mode)
current_phy_updated = 0;
rc = ble_gap_set_prefered_le_phy(conn_handle, BLE_HCI_LE_PHY_CODED_PREF_MASK, BLE_HCI_LE_PHY_CODED_PREF_MASK, 0x01);
if(rc != 0) {
ESP_LOGI(tag, "Requested PHY: Coded S2 failed.");
current_phy_updated = 1;
ESP_LOGE(tag, "Requested PHY: Coded S2 failed, rc=%d", rc);
}
else {
ESP_LOGI(tag, "Requested PHY: Coded S2");
@@ -273,7 +278,8 @@ int update_phy(uint16_t conn_handle, uint8_t phy_mode)
current_phy_updated = 0;
rc = ble_gap_set_prefered_le_phy(conn_handle, BLE_HCI_LE_PHY_CODED_PREF_MASK, BLE_HCI_LE_PHY_CODED_PREF_MASK, 0x02);
if(rc != 0) {
ESP_LOGI(tag, "Requested PHY: Coded S8 failed.");
current_phy_updated = 1;
ESP_LOGE(tag, "Requested PHY: Coded S8 failed, rc=%d", rc);
}
else {
ESP_LOGI(tag, "Requested PHY: Coded S8");
@@ -294,9 +300,29 @@ static void throughput_task(void *arg)
struct peer *peer = (struct peer *)arg;
const struct peer_chr *chr;
const struct peer_dsc *dsc;
struct ble_gap_conn_desc desc;
uint16_t conn_handle;
int rc = 0;
/* Store conn_handle immediately to avoid UAF if peer is freed */
if (peer == NULL) {
ESP_LOGE(tag, "Invalid peer, deleting task");
throughput_task_handle = NULL;
vTaskDelete(NULL);
return;
}
conn_handle = peer->conn_handle;
while (1) {
/* Check if connection is still valid using stored conn_handle */
rc = ble_gap_conn_find(conn_handle, &desc);
if (rc != 0) {
ESP_LOGI(tag, "Connection lost, deleting throughput task");
throughput_task_handle = NULL;
vTaskDelete(NULL);
return;
}
vTaskDelay(4000 / portTICK_PERIOD_MS);
ESP_LOGI(tag, "Format for throughput demo:: throughput read 100");
printf(" ====================================================================================\n");
@@ -329,12 +355,15 @@ static void throughput_task(void *arg)
scli_reset_queue();
#if CONFIG_EXAMPLE_EXTENDED_ADV
if(test_data[2] >= 0) {
rc = update_phy(handle, test_data[2]);
rc = update_phy(conn_handle, test_data[2]);
if(rc != 0) {
ESP_LOGI(tag, "Failed to update phy.\n");
}
while (!current_phy_updated) {
vTaskDelay(100 / portTICK_PERIOD_MS);
ESP_LOGE(tag, "Failed to update phy, rc=%d. Skipping PHY update wait.", rc);
/* Flag is already set to 1 on failure, but skip wait loop for clarity */
} else {
/* Wait for PHY update event to complete */
while (!current_phy_updated) {
vTaskDelay(100 / portTICK_PERIOD_MS);
}
}
}
#endif
@@ -354,10 +383,17 @@ static void throughput_task(void *arg)
}
if (test_data[1] > 0) {
rc = blecent_read(peer->conn_handle, chr->chr.val_handle,
rc = blecent_read(conn_handle, chr->chr.val_handle,
blecent_repeat_read, (void *) peer, test_data[1]);
if (rc != 0) {
ESP_LOGE(tag, "Error while reading from GATTS; rc = %d", rc);
/* Delete task on critical error (connection lost or fatal error) */
if (rc == BLE_HS_ENOTCONN || rc == BLE_HS_EDONE) {
ESP_LOGI(tag, "Connection error, deleting throughput task");
throughput_task_handle = NULL;
vTaskDelete(NULL);
return;
}
}
} else {
ESP_LOGE(tag, "Please enter non-zero value for test time in seconds!!");
@@ -375,9 +411,16 @@ static void throughput_task(void *arg)
}
if (test_data[1] > 0) {
rc = blecent_write(peer->conn_handle, chr->chr.val_handle, (void *) peer, test_data[1]);
rc = blecent_write(conn_handle, chr->chr.val_handle, (void *) peer, test_data[1]);
if (rc != 0) {
ESP_LOGE(tag, "Error while writing data; rc = %d", rc);
/* Delete task on critical error (connection lost or fatal error) */
if (rc == BLE_HS_ENOTCONN || rc == BLE_HS_EDONE) {
ESP_LOGI(tag, "Connection error, deleting throughput task");
throughput_task_handle = NULL;
vTaskDelete(NULL);
return;
}
}
} else {
ESP_LOGE(tag, "Please enter non-zero value for test time in seconds!!");
@@ -403,10 +446,17 @@ static void throughput_task(void *arg)
break;
}
rc = blecent_notify(peer->conn_handle, dsc->dsc.handle,
rc = blecent_notify(conn_handle, dsc->dsc.handle,
NULL, (void *) peer, test_data[1]);
if (rc != 0) {
ESP_LOGE(tag, "Subscribing to notification failed; rc = %d ", rc);
/* Delete task on critical error (connection lost or fatal error) */
if (rc == BLE_HS_ENOTCONN || rc == BLE_HS_EDONE) {
ESP_LOGI(tag, "Connection error, deleting throughput task");
throughput_task_handle = NULL;
vTaskDelete(NULL);
return;
}
} else {
ESP_LOGI(tag, "Subscribed to notifications. Throughput number"
" can be seen on peripheral terminal after %d seconds",
@@ -421,13 +471,20 @@ static void throughput_task(void *arg)
vTaskDelay(5000 / portTICK_PERIOD_MS);
}
vTaskDelete(NULL);
}
static void
blecent_read_write_subscribe(const struct peer *peer)
{
xTaskCreate(throughput_task, "throughput_task", 4096, (void *) peer, 10, NULL);
/* Delete previous task if it exists */
/* Capture handle and set global to NULL atomically to prevent race condition
* where task deletes itself between NULL check and vTaskDelete call */
TaskHandle_t task_to_delete = throughput_task_handle;
throughput_task_handle = NULL;
if (task_to_delete != NULL) {
vTaskDelete(task_to_delete);
}
xTaskCreate(throughput_task, "throughput_task", 4096, (void *) peer, 10, &throughput_task_handle);
return;
}
@@ -515,6 +572,7 @@ ext_blecent_should_connect(const struct ble_gap_ext_disc_desc *disc)
uint8_t test_addr[6];
uint32_t peer_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) {
return 0;
@@ -526,9 +584,9 @@ ext_blecent_should_connect(const struct ble_gap_ext_disc_desc *disc)
&peer_addr[5], &peer_addr[4], &peer_addr[3],
&peer_addr[2], &peer_addr[1], &peer_addr[0]);
/* Conversion */
/* Conversion */
for (int i=0; i<6; i++) {
test_addr[i] = (uint8_t )peer_addr[i];
test_addr[5 - i] = (uint8_t )peer_addr[i];
}
if (memcmp(test_addr, disc->addr.val, sizeof(disc->addr.val)) != 0) {
return 0;
@@ -538,17 +596,21 @@ ext_blecent_should_connect(const struct ble_gap_ext_disc_desc *disc)
/* The device has to advertise support LE PHY UUID (0xABF2).
*/
do {
ad_struct_len = disc->data[offset];
if (!ad_struct_len) {
if (offset + 1 >= (int)disc->length_data) { /* At least read length and type */
break;
}
ad_struct_len = disc->data[offset];
if (!ad_struct_len || offset + ad_struct_len + 1 > (int)disc->length_data) {
break;
}
/* Search for Complete Local Name (AD type 0x09) */
if (disc->data[offset + 1] == 0x09 && phy_uuid_found) {
int name_len = disc->data[offset] - 1; /* Length minus type byte */
char serv_name[] = "nimble_prph";
if (name_len > 0) {
ESP_LOGI(tag, "Device Name = %.*s",name_len, (char *)&disc->data[offset + 2]);
ESP_LOGI(tag, "Device Name = %.*s", name_len, (char *)&disc->data[offset + 2]);
if (name_len == strlen(serv_name) &&
memcmp(&disc->data[offset + 2], serv_name, name_len) == 0) {
ESP_LOGI(tag, "central connect to `nimble_prph` success");
@@ -556,18 +618,18 @@ ext_blecent_should_connect(const struct ble_gap_ext_disc_desc *disc)
}
return 0;
}
}
}
/* 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 ) {
phy_uuid_found = 1;
}
}
/* Search if LE PHY UUID is advertised */
if (disc->data[offset] == 0x03 && disc->data[offset + 1] == 0x03 &&
offset + 3 < (int)disc->length_data &&
disc->data[offset + 2] == 0xAB && disc->data[offset + 3] == 0xF2) {
phy_uuid_found = 1;
}
offset += ad_struct_len + 1;
} while ( offset < disc->length_data );
} while (offset < (int)disc->length_data);
return phy_uuid_found;
}
@@ -788,6 +850,15 @@ blecent_gap_event(struct ble_gap_event *event, void *arg)
print_conn_desc(&event->disconnect.conn);
ESP_LOGI(tag, " ");
/* Delete throughput task if it exists */
/* Capture handle and set global to NULL atomically to prevent race condition
* where task deletes itself between NULL check and vTaskDelete call */
TaskHandle_t task_to_delete = throughput_task_handle;
throughput_task_handle = NULL;
if (task_to_delete != NULL) {
vTaskDelete(task_to_delete);
}
/* Forget about peer. */
peer_delete(event->disconnect.conn.conn_handle);
vTaskDelay(200);
@@ -882,7 +953,9 @@ blecent_on_sync(void)
if (scli_receive_yesno(&yes)) {
if (yes) {
ESP_LOGI(tag, " Enter preferred MTU, format:: `MTU 512` ");
if (scli_receive_key(&mtu_def)) {
int mtu_buf[6];
if (scli_receive_key(mtu_buf)) {
mtu_def = mtu_buf[0];
ESP_LOGI(tag, "MTU provided by user= %d", mtu_def);
} else {
ESP_LOGD(tag, "No input for setting MTU; use default mtu = %d", mtu_def);
@@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2015-2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@@ -131,9 +131,12 @@ print_adv_fields(const struct ble_hs_adv_fields *fields)
}
if (fields->name != NULL) {
assert(fields->name_len < sizeof s - 1);
memcpy(s, fields->name, fields->name_len);
s[fields->name_len] = '\0';
size_t copy_len = fields->name_len;
if (copy_len >= sizeof(s)) {
copy_len = sizeof(s) - 1;
}
memcpy(s, fields->name, copy_len);
s[copy_len] = '\0';
MODLOG_DFLT(DEBUG, " name(%scomplete)=%s\n",
fields->name_is_complete ? "" : "in", s);
}
@@ -358,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;
@@ -492,31 +492,7 @@ peer_inc_add(struct peer *peer, uint16_t svc_start_handle,
svc = peer_svc_find(peer, gatt_incl_svc->start_handle, &prev);
if (!svc) {
/* secondary service */
svc = os_memblock_get(&peer_svc_pool);
if (svc == NULL) {
/* out of memory */
return BLE_HS_ENOMEM;
}
memset(svc, 0, sizeof *svc);
svc->svc.start_handle = gatt_incl_svc->start_handle;
svc->svc.end_handle = gatt_incl_svc->end_handle;
memcpy(&svc->svc.uuid, &gatt_incl_svc->uuid, sizeof(ble_uuid_any_t));
SLIST_INIT(&svc->chrs);
SLIST_INIT(&svc->incl_svc);
if (prev == NULL) {
SLIST_INSERT_HEAD(&peer->svcs, svc, next);
} else {
SLIST_INSERT_AFTER(prev, svc, next);
}
}
/* Including the services into inlucding list */
cur_svc = peer_svc_find_range(peer, gatt_incl_svc->handle);
if (cur_svc == NULL) {
@@ -533,11 +509,38 @@ peer_inc_add(struct peer *peer, uint16_t svc_start_handle,
return 0;
}
/* Allocate incl_svc first, before allocating secondary service.
* This ensures we don't leak a secondary service if incl_svc allocation fails. */
incl_svc = os_memblock_get(&peer_incl_svc_pool);
if (incl_svc == NULL) {
return BLE_HS_ENOMEM;
}
/* Now allocate secondary service if needed, after incl_svc allocation succeeds */
if (!svc) {
/* secondary service */
svc = os_memblock_get(&peer_svc_pool);
if (svc == NULL) {
/* Free incl_svc before returning */
os_memblock_put(&peer_incl_svc_pool, incl_svc);
return BLE_HS_ENOMEM;
}
memset(svc, 0, sizeof *svc);
svc->svc.start_handle = gatt_incl_svc->start_handle;
svc->svc.end_handle = gatt_incl_svc->end_handle;
memcpy(&svc->svc.uuid, &gatt_incl_svc->uuid, sizeof(ble_uuid_any_t));
SLIST_INIT(&svc->chrs);
SLIST_INIT(&svc->incl_svc);
if (prev == NULL) {
SLIST_INSERT_HEAD(&peer->svcs, svc, next);
} else {
SLIST_INSERT_AFTER(prev, svc, next);
}
}
incl_svc->svc = *gatt_incl_svc;
if (incl_svc_prev == NULL) {
@@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2015-2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@@ -8,6 +8,7 @@
#include <ctype.h>
#include "esp_log.h"
#include <string.h>
#include <strings.h>
#include <esp_log.h>
#include <esp_console.h>
#include "esp_vfs_dev.h"
@@ -22,9 +23,23 @@
#define YES_NO_PARAM (5000 / portTICK_PERIOD_MS)
static QueueHandle_t cli_handle;
static int key[3];
static int conn_param[10];
static int mtu;
#define CLI_CONN_PARAM_COUNT 6
#define CLI_MSG_TYPE_CONN_PARAM 1
#define CLI_MSG_TYPE_MTU 2
#define CLI_MSG_TYPE_THROUGHPUT 3
#define CLI_MSG_TYPE_YESNO 4
struct cli_msg {
int type;
union {
int conn_param[CLI_CONN_PARAM_COUNT];
int mtu;
int key[3];
bool yes;
} data;
};
#define CONSOLE_PROMPT_LEN_MAX (32)
@@ -41,56 +56,77 @@ static int conn_param_handler(int argc, char *argv[])
return -1;
}
sscanf(argv[1], "%d", &conn_param[0]);
sscanf(argv[2], "%d", &conn_param[1]);
sscanf(argv[3], "%d", &conn_param[2]);
sscanf(argv[4], "%d", &conn_param[3]);
sscanf(argv[5], "%d", &conn_param[4]);
sscanf(argv[6], "%d", &conn_param[5]);
struct cli_msg msg = {
.type = CLI_MSG_TYPE_CONN_PARAM,
};
ESP_LOGI("You entered", "%s %d %d %d %d %d %d", argv[0], conn_param[0], conn_param[1],
conn_param[2], conn_param[3], conn_param[4], conn_param[5]);
xQueueSend(cli_handle, &conn_param[0], 500 / portTICK_PERIOD_MS);
sscanf(argv[1], "%d", &msg.data.conn_param[0]);
sscanf(argv[2], "%d", &msg.data.conn_param[1]);
sscanf(argv[3], "%d", &msg.data.conn_param[2]);
sscanf(argv[4], "%d", &msg.data.conn_param[3]);
sscanf(argv[5], "%d", &msg.data.conn_param[4]);
sscanf(argv[6], "%d", &msg.data.conn_param[5]);
ESP_LOGI("You entered", "%s %d %d %d %d %d %d", argv[0], msg.data.conn_param[0], msg.data.conn_param[1],
msg.data.conn_param[2], msg.data.conn_param[3], msg.data.conn_param[4], msg.data.conn_param[5]);
if (cli_handle == NULL) {
ESP_LOGE("CLI", "Queue not initialized");
return -1;
}
xQueueSend(cli_handle, &msg, 500 / portTICK_PERIOD_MS);
return 0;
}
static int conn_mtu_handler(int argc, char *argv[])
{
int ret;
int mtu;
ESP_LOGI("MTU Arguments entered", "%d", argc);
if (argc != 2) {
return -1;
}
sscanf(argv[1], "%d", &mtu);
ESP_LOGI("You entered", "%s %d", argv[0], mtu);
xQueueSend(cli_handle, &mtu, 500 / portTICK_PERIOD_MS);
ret = sscanf(argv[1], "%d", &mtu);
if (ret != 1) {
return -1;
}
struct cli_msg msg = {
.type = CLI_MSG_TYPE_MTU,
.data.mtu = mtu,
};
if (cli_handle) {
xQueueSend(cli_handle, &msg, 500 / portTICK_PERIOD_MS);
}
return 0;
}
static int throughput_demo_handler(int argc, char *argv[])
{
char pkey[8];
struct cli_msg msg = {
.type = CLI_MSG_TYPE_THROUGHPUT,
};
if (argc != 4) {
return -1;
}
sscanf(argv[1], "%s", pkey);
sscanf(argv[1], "%7s", pkey);
if (strcmp(pkey, "read") == 0) {
key[0] = 1;
msg.data.key[0] = 1;
} else if (strcmp(pkey, "write") == 0) {
key[0] = 2;
msg.data.key[0] = 2;
} else if (strcmp(pkey, "notify") == 0) {
key[0] = 3;
msg.data.key[0] = 3;
} else {
key[0] = 0;
msg.data.key[0] = 0;
}
sscanf(argv[2], "%d", &key[1]);
sscanf(argv[3], "%d", &key[2]);
ESP_LOGI("Throughput demo handler", "%s %s %d %d", argv[0], argv[1], key[1], key[2]);
xQueueSend(cli_handle, &key[0], 500 / portTICK_PERIOD_MS);
sscanf(argv[2], "%d", &msg.data.key[1]);
sscanf(argv[3], "%d", &msg.data.key[2]);
ESP_LOGI("Throughput demo handler", "%s %s %d %d", argv[0], argv[1], msg.data.key[1], msg.data.key[2]);
xQueueSend(cli_handle, &msg, 500 / portTICK_PERIOD_MS);
return 0;
}
@@ -104,32 +140,80 @@ static int yesno_handler(int argc, char *argv[])
return -1;
}
sscanf(argv[1], "%s", yesno);
sscanf(argv[1], "%3s", yesno);
if (strcmp(yesno, "Yes") || strcmp (yesno, "YES") || strcmp(yesno, "yes")) {
if (strcmp(yesno, "Yes") == 0 || strcmp(yesno, "YES") == 0 || strcmp(yesno, "yes") == 0) {
yes = 1;
} else {
} else if (strcmp(yesno, "No") == 0 || strcmp(yesno, "NO") == 0 || strcmp(yesno, "no") == 0) {
yes = 0;
} else {
yes = 0; /* invalid input */
}
ESP_LOGI("User entered", "%s %s", argv[0], yesno);
xQueueSend(cli_handle, &yes, 500 / portTICK_PERIOD_MS);
/* Send as 24-byte buffer to match queue item size */
uint8_t yesno_buf[24] = {0};
yesno_buf[0] = (uint8_t)yes;
if (cli_handle) {
xQueueSend(cli_handle, yesno_buf, 500 / portTICK_PERIOD_MS);
}
return 0;
}
int scli_receive_yesno(bool *console_key)
{
return xQueueReceive(cli_handle, console_key, YES_NO_PARAM);
/* 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);
if (ret == pdPASS) {
*console_key = (bool)temp_buf[0]; /* Extract first byte as bool */
}
return ret;
}
int scli_receive_key(int *console_key)
int scli_receive_key(int console_key[6])
{
return xQueueReceive(cli_handle, console_key, BLE_RX_PARAM);
struct cli_msg msg;
if (xQueueReceive(cli_handle, &msg, BLE_RX_PARAM) != pdTRUE) {
return 0;
}
switch (msg.type) {
case CLI_MSG_TYPE_MTU:
console_key[0] = msg.data.mtu;
return 1;
case CLI_MSG_TYPE_CONN_PARAM:
memcpy(console_key, msg.data.conn_param,
sizeof(msg.data.conn_param));
return 1;
case CLI_MSG_TYPE_THROUGHPUT:
memcpy(console_key, msg.data.key, sizeof(msg.data.key));
return 1;
default:
return 0;
}
}
int cli_receive_key(int *console_key)
int cli_receive_key(int console_key[6])
{
return xQueueReceive(cli_handle, console_key, BLE_RX_TIMEOUT);
struct cli_msg msg;
if (xQueueReceive(cli_handle, &msg, BLE_RX_TIMEOUT) != pdTRUE) {
return 0;
}
switch (msg.type) {
case CLI_MSG_TYPE_CONN_PARAM:
memcpy(console_key, msg.data.conn_param, sizeof(msg.data.conn_param));
return 1;
case CLI_MSG_TYPE_THROUGHPUT:
memcpy(console_key, msg.data.key, sizeof(msg.data.key));
return 1;
case CLI_MSG_TYPE_MTU:
console_key[0] = msg.data.mtu;
return 1;
default:
return 0;
}
}
void scli_reset_queue(void)
@@ -169,7 +253,7 @@ void ble_register_cli(void)
esp_console_cmd_register(&cmds[i]);
}
cli_handle = xQueueCreate( 1, sizeof(int) * 6);
cli_handle = xQueueCreate(1, sizeof(struct cli_msg));
if (cli_handle == NULL) {
return;
}
@@ -507,8 +507,11 @@ void app_main(void)
ble_hs_cfg.store_status_cb = ble_store_util_status_rr;
/* Initialize Notify Task */
xTaskCreate(notify_task, "notify_task", 4096, NULL, 10, NULL);
BaseType_t task_rc = xTaskCreate(notify_task, "notify_task", 4096, NULL, 10, NULL);
if (task_rc != pdPASS) {
ESP_LOGE(tag, "Failed to create notify_task (rc=%d)", task_rc);
return ;
}
#if MYNEWT_VAL(BLE_GATTS)
rc = gatt_svr_init();
assert(rc == 0);