mirror of
https://github.com/espressif/esp-idf.git
synced 2026-10-02 11:10:54 +03:00
fix(nimble): Fix vulnerabilities in NimBLE examples
This commit is contained in:
+17
-2
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user