diff --git a/examples/bluetooth/ble_get_started/nimble/NimBLE_GATT_Server/main/include/gatt_svc.h b/examples/bluetooth/ble_get_started/nimble/NimBLE_GATT_Server/main/include/gatt_svc.h index 70276a26cb..975136bd9d 100644 --- a/examples/bluetooth/ble_get_started/nimble/NimBLE_GATT_Server/main/include/gatt_svc.h +++ b/examples/bluetooth/ble_get_started/nimble/NimBLE_GATT_Server/main/include/gatt_svc.h @@ -18,6 +18,7 @@ void send_heart_rate_indication(void); void gatt_svr_register_cb(struct ble_gatt_register_ctxt *ctxt, void *arg); void gatt_svr_subscribe_cb(struct ble_gap_event *event); +void gatt_svr_reset_heart_rate_subscription(void); int gatt_svc_init(void); #endif // GATT_SVR_H diff --git a/examples/bluetooth/ble_get_started/nimble/NimBLE_GATT_Server/main/main.c b/examples/bluetooth/ble_get_started/nimble/NimBLE_GATT_Server/main/main.c index 5283e2e785..ee95a2dd84 100644 --- a/examples/bluetooth/ble_get_started/nimble/NimBLE_GATT_Server/main/main.c +++ b/examples/bluetooth/ble_get_started/nimble/NimBLE_GATT_Server/main/main.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2024-2025 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Unlicense OR CC0-1.0 */ @@ -80,7 +80,7 @@ static void heart_rate_task(void *param) { void app_main(void) { /* Local variables */ - int rc = 0; + BaseType_t rc = 0; esp_err_t ret; /* LED initialization */ @@ -129,7 +129,17 @@ 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); + 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; + } + + 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; } diff --git a/examples/bluetooth/ble_get_started/nimble/NimBLE_GATT_Server/main/src/gap.c b/examples/bluetooth/ble_get_started/nimble/NimBLE_GATT_Server/main/src/gap.c index 7c7b3dde2a..20f3171a8e 100644 --- a/examples/bluetooth/ble_get_started/nimble/NimBLE_GATT_Server/main/src/gap.c +++ b/examples/bluetooth/ble_get_started/nimble/NimBLE_GATT_Server/main/src/gap.c @@ -186,6 +186,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; diff --git a/examples/bluetooth/ble_get_started/nimble/NimBLE_GATT_Server/main/src/gatt_svc.c b/examples/bluetooth/ble_get_started/nimble/NimBLE_GATT_Server/main/src/gatt_svc.c index 0337fd01be..4e521e348b 100644 --- a/examples/bluetooth/ble_get_started/nimble/NimBLE_GATT_Server/main/src/gatt_svc.c +++ b/examples/bluetooth/ble_get_started/nimble/NimBLE_GATT_Server/main/src/gatt_svc.c @@ -23,7 +23,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; @@ -240,6 +240,12 @@ void gatt_svr_subscribe_cb(struct ble_gap_event *event) { } } +void gatt_svr_reset_heart_rate_subscription(void) { + heart_rate_chr_conn_handle = BLE_HS_CONN_HANDLE_NONE; + heart_rate_chr_conn_handle_inited = false; + heart_rate_ind_status = false; +} + /* * GATT server initialization * 1. Initialize GATT service diff --git a/examples/bluetooth/nimble/ble_ancs/main/ble_ancs.c b/examples/bluetooth/nimble/ble_ancs/main/ble_ancs.c index 27881703da..1ec0346aa6 100644 --- a/examples/bluetooth/nimble/ble_ancs/main/ble_ancs.c +++ b/examples/bluetooth/nimble/ble_ancs/main/ble_ancs.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2021-2024 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2021-2025 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Unlicense OR CC0-1.0 */ @@ -103,7 +103,7 @@ char *CategoryID_to_String(uint8_t CategoryID) void ble_receive_apple_notification_source(uint8_t *message, uint16_t message_len) { - if (!message || message_len < 5) { + if (!message || message_len < 8) { return; } @@ -126,14 +126,19 @@ void ble_receive_apple_data_source(uint8_t *message, uint16_t message_len) switch (Command_id) { case CommandIDGetNotificationAttributes: { + if (message_len < 5) { + ESP_LOGE(NimBLE_ANCS_TAG, "Invalid message length for attributes: %d", + message_len); + return; + } uint32_t NotificationUID = (message[1]) | (message[2]<< 8) | (message[3]<< 16) | (message[4] << 24); uint32_t remian_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(remian_attr_len > 0) { + while(remian_attr_len >= 3) { uint8_t AttributeID = attrs[0]; uint16_t len = attrs[1] | (attrs[2] << 8); - if(len > (remian_attr_len -3)) { + if(len > remian_attr_len - 3) { ESP_LOGE(NimBLE_ANCS_TAG, "data error"); break; } diff --git a/examples/bluetooth/nimble/ble_ancs/main/main.c b/examples/bluetooth/nimble/ble_ancs/main/main.c index f07af8b239..9301d0f42e 100644 --- a/examples/bluetooth/nimble/ble_ancs/main/main.c +++ b/examples/bluetooth/nimble/ble_ancs/main/main.c @@ -72,7 +72,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, 0x11, - 0x0e, BLE_HS_ADV_TYPE_COMP_NAME, 'n', 'i', 'm', 'b', 'l', 'e', '-', 'a', 'n', 'c', 's', '-', 'e', + 0x0d, BLE_HS_ADV_TYPE_COMP_NAME, 'n', 'i', 'm', 'b', 'l', 'e', '-', 'a', 'n', 'c', 's', '-', 'e', }; #endif @@ -338,14 +338,14 @@ ext_ble_ancs_advertise(void) } /* use defaults for non-set params */ - memset (¶ms, 0, sizeof(params)); + memset(¶ms, 0, sizeof(params)); - /* enable connectable advertising */ + /* enable connectable, scannable advertising */ params.connectable = 1; + params.scannable = 1; - /* advertise using random addr */ + /* advertise using configured addr */ params.own_addr_type = BLE_OWN_ADDR_PUBLIC; - params.primary_phy = BLE_HCI_LE_PHY_1M; params.secondary_phy = BLE_HCI_LE_PHY_2M; params.tx_power = 127; @@ -359,8 +359,6 @@ ext_ble_ancs_advertise(void) ble_ancs_gap_event, NULL); assert (rc == 0); - /* in this case only scan response is allowed */ - /* get mbuf for scan rsp data */ data = os_msys_get_pkthdr(sizeof(ext_adv_pattern_1), 0); assert(data); @@ -369,7 +367,7 @@ ext_ble_ancs_advertise(void) rc = os_mbuf_append(data, ext_adv_pattern_1, sizeof(ext_adv_pattern_1)); assert(rc == 0); - rc = ble_gap_ext_adv_set_data(instance, data); + rc = ble_gap_ext_adv_rsp_set_data(instance, data); assert (rc == 0); /* start advertising */ @@ -578,10 +576,18 @@ ble_ancs_gap_event(struct ble_gap_event *event, void *arg) notificationUID, sizeof(p_attr)/sizeof(ble_noti_attr_list_t), p_attr); } } else if (event->notify_rx.attr_handle == data_source_handle) { + uint16_t new_len = data_buffer.len + event->notify_rx.om->om_len; + if (new_len > sizeof(data_buffer.buffer)) { + MODLOG_DFLT(ERROR, "data_buffer overflow: %d + %d > %d", + data_buffer.len, event->notify_rx.om->om_len, + (int)sizeof(data_buffer.buffer)); + data_buffer.len = 0; + return 0; + } memcpy(&data_buffer.buffer[data_buffer.len], - event->notify_rx.om->om_data, - event->notify_rx.om->om_len); - data_buffer.len += event->notify_rx.om->om_len; + event->notify_rx.om->om_data, + event->notify_rx.om->om_len); + data_buffer.len = new_len; if (event->notify_rx.om->om_len == (MTU_size - 3)) { esp_timer_start_periodic(periodic_timer, 500000); diff --git a/examples/bluetooth/nimble/ble_chan_sound_initiator/main/main.c b/examples/bluetooth/nimble/ble_chan_sound_initiator/main/main.c index 736791372c..899b7a4ff9 100644 --- a/examples/bluetooth/nimble/ble_chan_sound_initiator/main/main.c +++ b/examples/bluetooth/nimble/ble_chan_sound_initiator/main/main.c @@ -69,14 +69,16 @@ int blecent_on_subscribe(uint16_t conn_handle, MODLOG_DFLT(INFO, "Subscribe complete; status=%d conn_handle=%d " "attr_handle=%d\n", error->status, conn_handle, attr->handle); - subscribe_all++; - if (subscribe_all == 4){ - struct ble_cs_initiator_procedure_start_params param; - memset(¶m,0,sizeof param); - param.conn_handle=conn_handle; - param.cb=blecs_gap_event; - param.cb_arg=NULL; - ble_cs_initiator_procedure_start(¶m); + if (error->status == 0) { + subscribe_all++; + if (subscribe_all == 4){ + struct ble_cs_initiator_procedure_start_params param; + memset(¶m,0,sizeof param); + param.conn_handle=conn_handle; + param.cb=blecs_gap_event; + param.cb_arg=NULL; + ble_cs_initiator_procedure_start(¶m); + } } return 0; @@ -161,13 +163,16 @@ blecent_on_custom_read(uint16_t conn_handle, MODLOG_DFLT(INFO, "Read complete RAS FEATURES; status=%d conn_handle=%d", error->status, conn_handle); if (error->status == 0) { - uint32_t var; + uint32_t var = 0; int rc = 0; - if (attr->om && OS_MBUF_PKTLEN(attr->om) > 0) { - os_mbuf_copydata(attr->om, 0, OS_MBUF_PKTLEN(attr->om), &var); - } else { - MODLOG_DFLT(ERROR, "Error: No data in the attribute\n"); - } + uint16_t pktlen = (attr->om ? OS_MBUF_PKTLEN(attr->om) : 0); + if (attr->om && pktlen > 0 && pktlen <= sizeof(var)) { + os_mbuf_copydata(attr->om, 0, pktlen, &var); + } + else { + MODLOG_DFLT(ERROR, "Error: Invalid data length=%u in the attribute\n", pktlen); + return -1; + } MODLOG_DFLT(INFO, " attr_handle = %u value = %" PRIu32, attr->handle, var); if (var & REAL_TIME_RANGING_DATA_BIT) { @@ -400,8 +405,8 @@ static int blecs_gap_event(struct ble_cs_event *event, void *arg){ return 0; } if (event->subev_result.num_steps_reported) { - memcpy(&local_cs_steps_data, event->subev_result.steps, sizeof local_cs_steps_data); - + size_t copy_size = event->subev_result.num_steps_reported * sizeof(struct cs_steps_data); + memcpy(&local_cs_steps_data, event->subev_result.steps, MIN(copy_size, sizeof(local_cs_steps_data))); } nap=event->subev_result.num_antenna_paths; most_recent_local_ranging_counter=event->subev_result.procedure_counter; @@ -486,6 +491,7 @@ blecent_gap_event(struct ble_gap_event *event, void *arg) return 0; } connh = event->connect.conn_handle; + subscribe_all = 0; rc = ble_gap_security_initiate(event->connect.conn_handle); if (rc != 0) { MODLOG_DFLT(INFO, "Security could not be initiated, rc = %d\n", rc); @@ -580,7 +586,7 @@ blecent_gap_event(struct ble_gap_event *event, void *arg) 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=0; + most_recent_local_ranging_counter= ranging_counter; if (most_recent_peer_ranging_counter!=most_recent_local_ranging_counter) { MODLOG_DFLT(INFO, "Ranging counter mismatch : %" PRId32 " , %" PRId32, @@ -601,14 +607,26 @@ blecent_gap_event(struct ble_gap_event *event, void *arg) } else if (ble_svc_ras_od_val_handle == event->notify_rx.attr_handle) { MODLOG_DFLT(INFO, "Received On Demand Ranging Data\n"); - struct segment ras_segment; int notif_len = OS_MBUF_PKTLEN(event->notify_rx.om); - os_mbuf_copydata(event->notify_rx.om, 0,notif_len , &ras_segment); - MODLOG_DFLT(INFO, "Received On Demand Ranging Data , len = %d\n",notif_len); - uint8_t * data= (uint8_t *)ras_segment.data; - for(int i=0;i= sizeof(struct segment_header) && notif_len <= RAS_OD_RX_BUF_MAX) { + uint8_t ras_buf[RAS_OD_RX_BUF_MAX]; + int rc_copy = os_mbuf_copydata(event->notify_rx.om, 0, notif_len, ras_buf); + if (rc_copy == 0) { + uint8_t *data = ras_buf + sizeof(struct segment_header); + size_t data_len = notif_len - sizeof(struct segment_header); + + MODLOG_DFLT(INFO, + "Received On Demand Ranging Data , len = %d\n", + notif_len); + + for (size_t i = 0; i < data_len; i++) { + MODLOG_DFLT(INFO, "data[%d] = %d\n", (int)i, data[i]); + } + } } +#undef RAS_OD_RX_BUF_MAX /* handle the incoming notification diff --git a/examples/bluetooth/nimble/ble_chan_sound_reflector/main/main.c b/examples/bluetooth/nimble/ble_chan_sound_reflector/main/main.c index 5779b32746..12dee1c02f 100644 --- a/examples/bluetooth/nimble/ble_chan_sound_reflector/main/main.c +++ b/examples/bluetooth/nimble/ble_chan_sound_reflector/main/main.c @@ -116,8 +116,9 @@ static int blecs_gap_event(struct ble_cs_event *event, void *arg) most_recent_local_ranging_counter=event->subev_result.procedure_counter; } else if(event->subev_result.procedure_done_status == BLE_HCI_LE_CS_SUBEVENT_DONE_STATUS_PARTIAL) { - ranging_subevent.type=BLE_CS_EVENT_SUBEVET_RESULT; - ranging_subevent.subev_result= event->subev_result; + memset(&ranging_subevent, 0, sizeof(ranging_subevent)); + ranging_subevent.type = BLE_CS_EVENT_SUBEVET_RESULT; + ranging_subevent.subev_result = event->subev_result; idx++; if (idx==1) { most_recent_local_ranging_counter=event->subev_result.procedure_counter; @@ -133,6 +134,7 @@ 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 diff --git a/examples/bluetooth/nimble/ble_cte/common_components/cte_config/cte_config.c b/examples/bluetooth/nimble/ble_cte/common_components/cte_config/cte_config.c index 63da99a130..8aed7f5a75 100644 --- a/examples/bluetooth/nimble/ble_cte/common_components/cte_config/cte_config.c +++ b/examples/bluetooth/nimble/ble_cte/common_components/cte_config/cte_config.c @@ -81,7 +81,11 @@ uint8_t antenna_signal_index[4] = {CTE_ANT0_IDX, CTE_ANT1_IDX, CTE_ANT2_IDX, CTE int ble_direction_finding_antenna_init(uint8_t* gpio_array,uint8_t gpio_array_len){ int rc; // GPIO configuration - uint32_t gpio_pin_maks = 0; + uint64_t gpio_pin_maks = 0; + + if (!gpio_array || gpio_array_len > 4 || gpio_array_len == 0) { + return ESP_ERR_INVALID_ARG; + } for (int i = 0; i < gpio_array_len; i++){ gpio_pin_maks |= (1ULL << gpio_array[i]); } @@ -95,6 +99,7 @@ int ble_direction_finding_antenna_init(uint8_t* gpio_array,uint8_t gpio_array_le rc = gpio_config(&gpio_conf); if(rc != 0) { ESP_LOGE("DF","config fault GPIO failed"); + return rc; } // gpio bind signal for (int i = 0; i < gpio_array_len; i++){ diff --git a/examples/bluetooth/nimble/ble_cts/cts_cent/main/main.c b/examples/bluetooth/nimble/ble_cts/cts_cent/main/main.c index 128b6afd3a..2d3bb9d659 100644 --- a/examples/bluetooth/nimble/ble_cts/cts_cent/main/main.c +++ b/examples/bluetooth/nimble/ble_cts/cts_cent/main/main.c @@ -19,8 +19,8 @@ static const char *tag = "NimBLE_CTS_CENT"; static int ble_cts_cent_gap_event(struct ble_gap_event *event, void *arg); -static char *day_of_week[7] = { - "Unknown" +static char *day_of_week[8] = { + "Unknown", "Monday", "Tuesday", "Wednesday", @@ -33,10 +33,14 @@ void ble_store_config_init(void); static void ble_cts_cent_scan(void); void printtime(struct ble_svc_cts_curr_time ctime) { + uint8_t dow = ctime.et_256.d_d_t.day_of_week; + const char *dow_str = (dow >= 1 && dow <= 7) ? day_of_week[dow] : day_of_week[0]; + if (dow >= 8) { + dow = 0; + } ESP_LOGI(tag, "Date : %d/%d/%d %s", ctime.et_256.d_d_t.d_t.day, ctime.et_256.d_d_t.d_t.month, - ctime.et_256.d_d_t.d_t.year, - day_of_week[ctime.et_256.d_d_t.day_of_week]); + ctime.et_256.d_d_t.d_t.year, dow_str); ESP_LOGI(tag, "hours : %d minutes : %d ", ctime.et_256.d_d_t.d_t.hours, ctime.et_256.d_d_t.d_t.minutes); @@ -55,6 +59,7 @@ ble_cts_cent_on_read(uint16_t conn_handle, struct ble_gatt_attr *attr, void *arg) { + int rc = 0; struct ble_svc_cts_curr_time ctime; /* store the read time */ MODLOG_DFLT(INFO, "Read Current time complete; status=%d conn_handle=%d\n", error->status, conn_handle); @@ -66,8 +71,12 @@ ble_cts_cent_on_read(uint16_t conn_handle, goto err; } MODLOG_DFLT(INFO, "\n"); - ble_hs_mbuf_to_flat(attr->om, &ctime, sizeof(ctime), NULL); - printtime(ctime); + rc = ble_hs_mbuf_to_flat(attr->om, &ctime, sizeof(ctime), NULL); + if (rc == 0 && ctime.et_256.d_d_t.day_of_week <= 7) { + printtime(ctime); + } else { + MODLOG_DFLT(WARN, "Invalid CTS time data; rc=%d day_of_week=%d\n", rc, ctime.et_256.d_d_t.day_of_week); + } return 0; err: /* Terminate the connection. */ @@ -234,7 +243,7 @@ ext_ble_cts_cent_should_connect(const struct ble_gap_ext_disc_desc *disc) /* Search if cts UUID is advertised */ if (disc->data[offset + 1] == 0x03) { int temp = 2; - while(temp < disc->data[offset + 1]) { + while (temp < ad_struct_len) { if(disc->data[offset + temp] == 0x05 && disc->data[offset + temp + 1] == 0x18) { return 1; @@ -491,7 +500,7 @@ ble_cts_cent_gap_event(struct ble_gap_event *event, void *arg) #else #if MYNEWT_VAL(BLE_GATTC) /*** Go for service discovery after encryption has been successfully enabled ***/ - rc = peer_disc_all(event->connect.conn_handle, + rc = peer_disc_all(event->enc_change.conn_handle, ble_cts_cent_on_disc_complete, NULL); if (rc != 0) { MODLOG_DFLT(ERROR, "Failed to discover services; rc=%d\n", rc); @@ -510,7 +519,7 @@ ble_cts_cent_gap_event(struct ble_gap_event *event, void *arg) event->cache_assoc.status, (event->cache_assoc.cache_state == 0) ? "INVALID" : "LOADED"); /* Perform service discovery */ - rc = peer_disc_all(event->connect.conn_handle, + rc = peer_disc_all(event->cache_assoc.conn_handle, blecent_on_disc_complete, NULL); if(rc != 0) { MODLOG_DFLT(ERROR, "Failed to discover services; rc=%d\n", rc); diff --git a/examples/bluetooth/nimble/ble_cts/cts_prph/main/gatt_svr.c b/examples/bluetooth/nimble/ble_cts/cts_prph/main/gatt_svr.c index 7a5cc19367..b790d53709 100644 --- a/examples/bluetooth/nimble/ble_cts/cts_prph/main/gatt_svr.c +++ b/examples/bluetooth/nimble/ble_cts/cts_prph/main/gatt_svr.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2017-2023 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2017-2025 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -16,6 +16,7 @@ #include #include "sys/time.h" +static const char *TAG = "CTS_GATT_SVR"; void gatt_svr_register_cb(struct ble_gatt_register_ctxt *ctxt, void *arg) @@ -85,7 +86,21 @@ int fetch_current_time(struct ble_svc_cts_curr_time *ctime) { int set_current_time(struct ble_svc_cts_curr_time ctime) { time_t now; struct tm timeinfo; - struct timeval tv_now; + struct timeval tv_now = {0}; + + /* Basic sanity validation for incoming time fields */ + if (ctime.et_256.d_d_t.d_t.year < 1900 || + ctime.et_256.d_d_t.d_t.year > 9999 || + ctime.et_256.d_d_t.d_t.month < 1 || ctime.et_256.d_d_t.d_t.month > 12 || + ctime.et_256.d_d_t.d_t.day < 1 || ctime.et_256.d_d_t.d_t.day > 31 || + ctime.et_256.d_d_t.d_t.hours > 23 || + ctime.et_256.d_d_t.d_t.minutes > 59 || + ctime.et_256.d_d_t.d_t.seconds > 59 || + ctime.et_256.d_d_t.day_of_week < 1 || ctime.et_256.d_d_t.day_of_week > 7) { + ESP_LOGE(TAG, "Invalid current time parameters"); + return -1; + } + /* fill date_time */ timeinfo.tm_year= ctime.et_256.d_d_t.d_t.year - 1900 ; timeinfo.tm_mon = ctime.et_256.d_d_t.d_t.month - 1; @@ -95,7 +110,12 @@ int set_current_time(struct ble_svc_cts_curr_time ctime) { 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; now = mktime(&timeinfo); + if (now == (time_t)-1) { + ESP_LOGE(TAG, "Failed to convert current time"); + return -1; + } tv_now.tv_sec = now; + tv_now.tv_usec = 0; settimeofday(&tv_now, NULL); /* set the last updated */ gettimeofday(&last_updated, NULL); diff --git a/examples/bluetooth/nimble/ble_enc_adv_data/enc_adv_data_cent/main/main.c b/examples/bluetooth/nimble/ble_enc_adv_data/enc_adv_data_cent/main/main.c index a141d0f2e0..9a8c9e4453 100644 --- a/examples/bluetooth/nimble/ble_enc_adv_data/enc_adv_data_cent/main/main.c +++ b/examples/bluetooth/nimble/ble_enc_adv_data/enc_adv_data_cent/main/main.c @@ -102,8 +102,21 @@ enc_adv_data_cent_on_read(uint16_t conn_handle, value_ead.km = (struct key_material *) malloc (sizeof(struct key_material)); + if (value_ead.km == NULL) { + MODLOG_DFLT(ERROR, "Failed to allocate memory for key material"); + goto err; + } + memset(value_ead.km, 0, sizeof(struct key_material)); + /* Validate mbuf has enough data before copying */ + if (attr->om == NULL || OS_MBUF_PKTLEN(attr->om) < (BLE_EAD_KEY_SIZE + BLE_EAD_IV_SIZE)) { + MODLOG_DFLT(ERROR, "Invalid mbuf or insufficient data size"); + free(value_ead.km); + value_ead.km = NULL; + goto err; + } + os_mbuf_copydata(attr->om, 0, BLE_EAD_KEY_SIZE, &value_ead.km->session_key); os_mbuf_copydata(attr->om, BLE_EAD_KEY_SIZE, BLE_EAD_IV_SIZE, &value_ead.km->iv); @@ -120,8 +133,17 @@ enc_adv_data_cent_on_read(uint16_t conn_handle, MODLOG_DFLT(INFO, "Writing of session key, iv, and peer addr to NVS success"); } + if (value_ead.km != NULL) { + free(value_ead.km); + value_ead.km = NULL; + } + err: /* Terminate the connection. */ + if (value_ead.km != NULL) { + free(value_ead.km); + value_ead.km = NULL; + } return ble_gap_terminate(conn_handle, BLE_ERR_REM_USER_CONN_TERM); } @@ -244,6 +266,10 @@ enc_adv_data_cent_decrypt(uint8_t length_data, const uint8_t *data, const uint8_ switch (op) { case BLE_GAP_ENC_ADV_DATA: enc_data = (uint8_t *) malloc (sizeof(uint8_t) * len); + if (enc_data == NULL) { + MODLOG_DFLT(ERROR, "Failed to allocate enc_data"); + return 0; + } memcpy(enc_data, data + offset + 2, len); memcpy(&key_ead.peer_addr.val, peer_addr, PEER_ADDR_VAL_SIZE); @@ -262,6 +288,7 @@ enc_adv_data_cent_decrypt(uint8_t length_data, const uint8_t *data, const uint8_ MODLOG_DFLT(INFO, "Decryption of adv data done successfully"); } else { MODLOG_DFLT(INFO, "Decryption of adv data failed"); + free(enc_data); return 0; } @@ -272,6 +299,7 @@ enc_adv_data_cent_decrypt(uint8_t length_data, const uint8_t *data, const uint8_ MODLOG_DFLT(INFO, "0x%02X ", temp[i]); } MODLOG_DFLT(INFO, "\n"); + free(enc_data); return 1; default: diff --git a/examples/bluetooth/nimble/ble_enc_adv_data/enc_adv_data_prph/main/main.c b/examples/bluetooth/nimble/ble_enc_adv_data/enc_adv_data_prph/main/main.c index 78a3159eb4..53e0302299 100644 --- a/examples/bluetooth/nimble/ble_enc_adv_data/enc_adv_data_prph/main/main.c +++ b/examples/bluetooth/nimble/ble_enc_adv_data/enc_adv_data_prph/main/main.c @@ -68,8 +68,8 @@ enc_adv_data_prph_print_conn_desc(struct ble_gap_conn_desc *desc) desc->sec_state.bonded); } -static void -enc_adv_data_prph_encrypt_set(uint8_t * out_encrypted_adv_data, +static int +enc_adv_data_prph_encrypt_set(uint8_t *out_encrypted_adv_data, const unsigned encrypted_adv_data_len) { int rc; @@ -85,13 +85,13 @@ enc_adv_data_prph_encrypt_set(uint8_t * out_encrypted_adv_data, print_bytes(unencrypted_adv_data, unencrypted_adv_data_len); MODLOG_DFLT(INFO, "\n"); - rc = ble_ead_encrypt(km.session_key, km.iv, unencrypted_adv_data, unencrypted_adv_data_len, encrypted_adv_data); - if (rc == 0) { - MODLOG_DFLT(INFO, "Encryption of adv data done successfully"); - } else { - MODLOG_DFLT(INFO, "Encryption of adv data failed"); - return; + rc = ble_ead_encrypt(km.session_key, km.iv, unencrypted_adv_data, + unencrypted_adv_data_len, encrypted_adv_data); + if (rc != 0) { + MODLOG_DFLT(ERROR, "Encryption of adv data failed; rc=%d", rc); + return rc; } + MODLOG_DFLT(INFO, "Encryption of adv data done successfully"); MODLOG_DFLT(INFO, "Data after encryption:"); print_bytes(encrypted_adv_data, encrypted_adv_data_len); @@ -99,6 +99,7 @@ enc_adv_data_prph_encrypt_set(uint8_t * out_encrypted_adv_data, /** Contains Randomiser ## Encrypted Advertising Data ## MIC */ memcpy(out_encrypted_adv_data, encrypted_adv_data, encrypted_adv_data_len); + return 0; } /** @@ -111,7 +112,6 @@ enc_adv_data_prph_advertise(void) { struct ble_gap_adv_params params; struct ble_hs_adv_fields fields; - uint8_t own_addr_type; int rc; const unsigned encrypted_adv_data_len = BLE_EAD_ENCRYPTED_PAYLOAD_SIZE(sizeof(unencrypted_adv_pattern)); @@ -149,7 +149,10 @@ enc_adv_data_prph_advertise(void) fields.uuids16_is_complete = 1; /** Getting the encrypted advertising data */ - enc_adv_data_prph_encrypt_set(encrypted_adv_data, encrypted_adv_data_len); + rc = enc_adv_data_prph_encrypt_set(encrypted_adv_data, encrypted_adv_data_len); + if (rc != 0) { + return; + } fields.enc_adv_data = encrypted_adv_data; fields.enc_adv_data_len = encrypted_adv_data_len; diff --git a/examples/bluetooth/nimble/ble_gattc_gatts_coex/main/main.c b/examples/bluetooth/nimble/ble_gattc_gatts_coex/main/main.c index a3b60e3363..d9d16a91e0 100644 --- a/examples/bluetooth/nimble/ble_gattc_gatts_coex/main/main.c +++ b/examples/bluetooth/nimble/ble_gattc_gatts_coex/main/main.c @@ -21,9 +21,20 @@ static bool 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)); + if (rc != 0) { + return rc; + } + } else if (ctxt->op == BLE_GATT_ACCESS_OP_READ_DSC) { + static uint8_t dsc_data[1] = {0x01}; // Example descriptor value + return os_mbuf_append(ctxt->om, dsc_data, sizeof(dsc_data)); + } + else if (ctxt->op == BLE_GATT_ACCESS_OP_WRITE_CHR) { + MODLOG_DFLT(INFO, "Characteristic written"); + return 0; } return 0; } diff --git a/examples/bluetooth/nimble/ble_htp/htp_cent/main/main.c b/examples/bluetooth/nimble/ble_htp/htp_cent/main/main.c index 281dadc610..447631ae3e 100644 --- a/examples/bluetooth/nimble/ble_htp/htp_cent/main/main.c +++ b/examples/bluetooth/nimble/ble_htp/htp_cent/main/main.c @@ -162,6 +162,10 @@ ble_htp_cent_on_read(uint16_t conn_handle, uint16_t value; int rc; const struct peer *peer = peer_find(conn_handle); + if (peer == NULL) { + MODLOG_DFLT(ERROR, "Lost peer 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(BLE_SVC_HTP_UUID16), @@ -330,7 +334,7 @@ ext_ble_htp_cent_should_connect(const struct ble_gap_ext_disc_desc *disc) /* Conversion */ for (int i=0; i<6; i++) { - test_addr[i] = (uint8_t )peer_addr[i]; + test_addr[i] = (uint8_t )peer_addr[5 - i]; } if (memcmp(test_addr, disc->addr.val, sizeof(disc->addr.val)) != 0) { @@ -341,23 +345,23 @@ ext_ble_htp_cent_should_connect(const struct ble_gap_ext_disc_desc *disc) /* The device has to advertise support for the Health thermometer * service (0x1809). */ - do { + while (offset < disc->length_data) { + ad_struct_len = disc->data[offset]; - if (!ad_struct_len) { + if (ad_struct_len == 0 || offset + ad_struct_len + 1 > disc->length_data) { break; } /* Search if HTP UUID is advertised */ - 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 + 1] == 0x03) { + if (disc->data[offset + 2] == 0x09 && disc->data[offset + 3] == 0x18) { return 1; } } offset += ad_struct_len + 1; - - } while ( offset < disc->length_data ); + } return 0; } @@ -605,7 +609,7 @@ ble_htp_cent_gap_event(struct ble_gap_event *event, void *arg) #else #if MYNEWT_VAL(BLE_GATTC) /*** Go for service discovery after encryption has been successfully enabled ***/ - rc = peer_disc_all(event->connect.conn_handle, + rc = peer_disc_all(event->enc_change.conn_handle, ble_htp_cent_on_disc_complete, NULL); if (rc != 0) { MODLOG_DFLT(ERROR, "Failed to discover services; rc=%d\n", rc); @@ -624,7 +628,7 @@ ble_htp_cent_gap_event(struct ble_gap_event *event, void *arg) event->cache_assoc.status, (event->cache_assoc.cache_state == 0) ? "INVALID" : "LOADED"); /* Perform service discovery */ - rc = peer_disc_all(event->connect.conn_handle, + rc = peer_disc_all(event->cache_assoc.conn_handle, blecent_on_disc_complete, NULL); if(rc != 0) { MODLOG_DFLT(ERROR, "Failed to discover services; rc=%d\n", rc); diff --git a/examples/bluetooth/nimble/ble_l2cap_coc/coc_blecent/main/main.c b/examples/bluetooth/nimble/ble_l2cap_coc/coc_blecent/main/main.c index 209d5e2e84..e6cff455f2 100644 --- a/examples/bluetooth/nimble/ble_l2cap_coc/coc_blecent/main/main.c +++ b/examples/bluetooth/nimble/ble_l2cap_coc/coc_blecent/main/main.c @@ -44,6 +44,8 @@ blecent_l2cap_coc_send_data(struct ble_l2cap_chan *chan) int rc = 0; int len = 512; uint8_t value[len]; + int retry = 0; + const int max_retry = 10; for (int i = 0; i < len; i++) { value[i] = i; @@ -53,20 +55,32 @@ blecent_l2cap_coc_send_data(struct ble_l2cap_chan *chan) sdu_rx_data = os_mbuf_get_pkthdr(&sdu_os_mbuf_pool, 0); if (sdu_rx_data == NULL) { vTaskDelay(10 / portTICK_PERIOD_MS); - sdu_rx_data = os_mbuf_get_pkthdr(&sdu_os_mbuf_pool, 0); + retry++; } - } while (sdu_rx_data == NULL); - + } while (sdu_rx_data == NULL && retry < max_retry); + if (sdu_rx_data == NULL) { + MODLOG_DFLT(ERROR, "Failed to alloc mbuf after %d retries", max_retry); + return; + } os_mbuf_append(sdu_rx_data, value, len); print_mbuf_data(sdu_rx_data); rc = ble_l2cap_send(chan, sdu_rx_data); - while (rc == BLE_HS_ESTALLED) { + 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); + return; + } + if (rc == 0) { MODLOG_DFLT(INFO, "Data sent successfully"); } else { @@ -75,6 +89,7 @@ blecent_l2cap_coc_send_data(struct ble_l2cap_chan *chan) } } + /** * After connection is established on GAP layer, service discovery is performed. On * it's completion, this API is called for making a connection is on L2CAP layer. @@ -83,11 +98,25 @@ static void blecent_l2cap_coc_on_disc_complete(const struct peer *peer, int status, void *arg) { uint16_t psm = 0x1002; - struct os_mbuf *sdu_rx; + struct os_mbuf *sdu_rx = NULL; + int rc; + + if (status != 0) { + MODLOG_DFLT(WARN, "Service discovery failed (status=%d), skip L2CAP COC", status); + return; + } sdu_rx = os_mbuf_get_pkthdr(&sdu_os_mbuf_pool, 0); - ble_l2cap_connect(conn_handle_coc, psm, MTU, sdu_rx, blecent_l2cap_coc_event_cb, - NULL); + if (sdu_rx == NULL) { + MODLOG_DFLT(ERROR, "Failed to allocate sdu_rx"); + return; + } + + 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); + } } /** @@ -265,22 +294,31 @@ ext_blecent_should_connect(const struct ble_gap_ext_disc_desc *disc) /* The device has to advertise support for L2CAP COC UUID (0x1812). */ do { + if (offset + 1 > disc->length_data) { + break; + } + ad_struct_len = disc->data[offset]; if (!ad_struct_len) { break; } - /* Search if ANS UUID is advertised */ - if (disc->data[offset] == 0x03 && disc->data[offset + 1] == 0x03) { - if ( disc->data[offset + 2] == 0x18 && disc->data[offset + 3] == 0x12 ) { - return 1; - } + if (offset + ad_struct_len + 1 > disc->length_data) { + break; + } + + /* AD Type (1) + UUID16 (2) requires at least 4 bytes total */ + if (ad_struct_len >= 3 && + disc->data[offset + 1] == 0x03 && + disc->data[offset + 2] == 0x18 && + disc->data[offset + 3] == 0x12) { + return 1; } offset += ad_struct_len + 1; - } while ( offset < disc->length_data ); + } while (offset < disc->length_data); return 0; } #else diff --git a/examples/bluetooth/nimble/ble_l2cap_coc/coc_bleprph/main/main.c b/examples/bluetooth/nimble/ble_l2cap_coc/coc_bleprph/main/main.c index a4e9cb5cef..1eda92dab1 100644 --- a/examples/bluetooth/nimble/ble_l2cap_coc/coc_bleprph/main/main.c +++ b/examples/bluetooth/nimble/ble_l2cap_coc/coc_bleprph/main/main.c @@ -340,6 +340,9 @@ bleprph_gap_event(struct ble_gap_event *event, void *arg) bleprph_print_conn_desc(&desc); #if MYNEWT_VAL(BLE_L2CAP_COC_MAX_NUM) >= 1 rc = ble_l2cap_create_server(psm, MTU, bleprph_l2cap_coc_event_cb, NULL); + if (rc != 0) { + MODLOG_DFLT(ERROR, "Failed to create L2CAP CoC server; rc=%d", rc); + } #endif } return 0; diff --git a/examples/bluetooth/nimble/ble_multi_adv/main/gatt_svr.c b/examples/bluetooth/nimble/ble_multi_adv/main/gatt_svr.c index a142dc9091..a3a0564255 100644 --- a/examples/bluetooth/nimble/ble_multi_adv/main/gatt_svr.c +++ b/examples/bluetooth/nimble/ble_multi_adv/main/gatt_svr.c @@ -13,6 +13,8 @@ #include "services/gatt/ble_svc_gatt.h" #include "multi_adv.h" +static uint8_t gatt_svr_chr_val = 0x01; /* Example characteristic value */ + static const ble_uuid128_t gatt_svr_svc_uuid = BLE_UUID128_INIT(0x2d, 0x71, 0xa2, 0x59, 0xb4, 0x58, 0xc8, 0x12, 0x99, 0x99, 0x43, 0x95, 0x12, 0x2f, 0x46, 0x59); @@ -81,24 +83,39 @@ static int gatt_svc_access(uint16_t conn_handle, uint16_t attr_handle, struct ble_gatt_access_ctxt *ctxt, void *arg) { + int rc = 0; switch (ctxt->op) { case BLE_GATT_ACCESS_OP_READ_CHR: MODLOG_DFLT(INFO, "Characteristic read; conn_handle=%d attr_handle=%d\n", conn_handle, attr_handle); - return 0; + rc = os_mbuf_append(ctxt->om, + &gatt_svr_chr_val, + sizeof(gatt_svr_chr_val)); + return rc == 0 ? 0 : BLE_ATT_ERR_INSUFFICIENT_RES; + break; case BLE_GATT_ACCESS_OP_WRITE_CHR: MODLOG_DFLT(INFO, "Characteristic write; conn_handle=%d attr_handle=%d", conn_handle, attr_handle); - return 0; + rc = os_mbuf_copydata(ctxt->om, + 0, + sizeof(gatt_svr_chr_val), + &gatt_svr_chr_val); + return rc == 0 ? 0 : BLE_ATT_ERR_INVALID_ATTR_VALUE_LEN; + break; case BLE_GATT_ACCESS_OP_READ_DSC: MODLOG_DFLT(INFO, "Descriptor read; conn_handle=%d attr_handle=%d\n", conn_handle, attr_handle); - return 0; + rc = os_mbuf_append(ctxt->om, + &gatt_svr_dsc_val, + sizeof(gatt_svr_dsc_val)); + return rc == 0 ? 0 : BLE_ATT_ERR_INSUFFICIENT_RES; + break; case BLE_GATT_ACCESS_OP_WRITE_DSC: goto unknown; + break; default: goto unknown; diff --git a/examples/bluetooth/nimble/ble_pawr_adv_conn/ble_pawr_adv_conn/main/main.c b/examples/bluetooth/nimble/ble_pawr_adv_conn/ble_pawr_adv_conn/main/main.c index b88e82538d..4286cf7be6 100644 --- a/examples/bluetooth/nimble/ble_pawr_adv_conn/ble_pawr_adv_conn/main/main.c +++ b/examples/bluetooth/nimble/ble_pawr_adv_conn/ble_pawr_adv_conn/main/main.c @@ -70,6 +70,7 @@ gap_event_cb(struct ble_gap_event *event, void *arg) uint8_t adv_handle; uint8_t subevent; uint8_t phy_mask; + uint8_t actual_sent = 0; switch (event->type) { @@ -101,26 +102,38 @@ 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; + 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); + ESP_LOGE(TAG, "No memory at subevt %d", i); + // Free previously allocated data to prevent memory leak + for (uint8_t j = 0; j < actual_sent; j++) { + os_mbuf_free_chain(sub_data_params[j].data); + sub_data_params[j].data = NULL; + } + actual_sent = 0; // Do not call set_periodic_adv_subev_data break; } 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); - os_mbuf_append(data, sub_data_pattern, BLE_PAWR_SUB_DATA_LEN); + if (os_mbuf_append(data, sub_data_pattern, BLE_PAWR_SUB_DATA_LEN) != 0) { + os_mbuf_free_chain(data); + break; + } sub_data_params[i].subevent = sub; sub_data_params[i].response_slot_start = 0; 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); - if (rc) { - ESP_LOGE(TAG, "Failed to set Subevent Data, rc = 0x%x", rc); + if (actual_sent > 0) { + rc = ble_gap_set_periodic_adv_subev_data(event->periodic_adv_subev_data_req.adv_handle, + actual_sent, sub_data_params); + if (rc) { + ESP_LOGE(TAG, "Failed to set Subevent Data, rc = 0x%x", rc); + } } return 0; diff --git a/examples/bluetooth/nimble/ble_periodic_sync/main/main.c b/examples/bluetooth/nimble/ble_periodic_sync/main/main.c index 567338d5d2..daf2ee4e3e 100644 --- a/examples/bluetooth/nimble/ble_periodic_sync/main/main.c +++ b/examples/bluetooth/nimble/ble_periodic_sync/main/main.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2021-2023 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2021-2025 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Unlicense OR CC0-1.0 */ @@ -114,11 +114,11 @@ periodic_sync_gap_event(struct ble_gap_event *event, void *arg) struct ble_gap_ext_disc_desc *disc = ((struct ble_gap_ext_disc_desc *)(&event->ext_disc)); if (disc->sid == 2 && synced == 0) { synced++; - const ble_addr_t addr; + ble_addr_t addr; uint8_t adv_sid; struct ble_gap_periodic_sync_params params; int rc; - memcpy((void *)&addr, (void *)&disc->addr, sizeof(disc->addr)); + memcpy(&addr, &disc->addr, sizeof(disc->addr)); memcpy(&adv_sid, &disc->sid, sizeof(disc->sid)); params.skip = 10; params.sync_timeout = 1000; diff --git a/examples/bluetooth/nimble/ble_phy/phy_cent/main/main.c b/examples/bluetooth/nimble/ble_phy/phy_cent/main/main.c index cec4bcaa3a..894022e78d 100644 --- a/examples/bluetooth/nimble/ble_phy/phy_cent/main/main.c +++ b/examples/bluetooth/nimble/ble_phy/phy_cent/main/main.c @@ -236,6 +236,7 @@ ext_blecent_should_connect(const struct ble_gap_ext_disc_desc *disc) int ad_struct_len = 0; uint8_t test_addr[6]; uint32_t peer_addr[6]; + uint8_t type = 0; memset(peer_addr, 0x0, sizeof peer_addr); @@ -252,7 +253,7 @@ ext_blecent_should_connect(const struct ble_gap_ext_disc_desc *disc) /* 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) { @@ -264,21 +265,20 @@ ext_blecent_should_connect(const struct ble_gap_ext_disc_desc *disc) */ do { ad_struct_len = disc->data[offset]; - - if (!ad_struct_len) { + 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; + type = disc->data[offset + 1]; + if ((type == 0x02 || type == 0x03) && ad_struct_len >= 3) { + /* Scan UUID bytes for LE_PHY_UUID16 (little-endian: 0xF2 0xAB) */ + 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 ); + } while (offset < disc->length_data); return 0; } @@ -484,42 +484,37 @@ blecent_on_sync(void) rc = ble_hs_util_ensure_addr(0); assert(rc == 0); - s_current_phy = BLE_HCI_LE_PHY_1M_PREF_MASK; - 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); - if (s_current_phy != BLE_HCI_LE_PHY_1M_PREF_MASK) { - /* Check if peer address is set in EXAMPLE_PEER_ADDR */ - if (strlen(CONFIG_EXAMPLE_PEER_ADDR) && - (strncmp(CONFIG_EXAMPLE_PEER_ADDR, "ADDR_ANY", strlen("ADDR_ANY")) != 0)) { - /* User wants to connect on 2M or coded phy directly */ - sscanf(CONFIG_EXAMPLE_PEER_ADDR, "%lx:%lx:%lx:%lx:%lx:%lx", - &peer_addr[5], &peer_addr[4], &peer_addr[3], - &peer_addr[2], &peer_addr[1], &peer_addr[0]); + if (strlen(CONFIG_EXAMPLE_PEER_ADDR) && + (strncmp(CONFIG_EXAMPLE_PEER_ADDR, "ADDR_ANY", strlen("ADDR_ANY")) != 0)) { + /* User wants to connect on 2M or coded phy directly */ + sscanf(CONFIG_EXAMPLE_PEER_ADDR, "%lx:%lx:%lx:%lx:%lx:%lx", + &peer_addr[5], &peer_addr[4], &peer_addr[3], + &peer_addr[2], &peer_addr[1], &peer_addr[0]); - /* Conversion */ - for (int i=0; i<6; i++) { - test_addr[i] = (uint8_t )peer_addr[i]; - } - - for(ii = 0 ;ii < 6; ii++) - conn_addr.val[ii] = test_addr[ii]; - - conn_addr.type = 0; - - vTaskDelay(300); - - if (s_current_phy == BLE_HCI_LE_PHY_2M_PREF_MASK) - s_current_phy = BLE_HCI_LE_PHY_1M_PREF_MASK | 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); + /* Conversion */ + for (int i=0; i<6; i++) { + test_addr[i] = (uint8_t )peer_addr[i]; } + + for(ii = 0 ;ii < 6; ii++) + conn_addr.val[ii] = test_addr[ii]; + + conn_addr.type = 0; + + vTaskDelay(300); + + s_current_phy = BLE_HCI_LE_PHY_1M_PREF_MASK | 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); } else { -/* Begin scanning for a peripheral to connect to. */ + s_current_phy = BLE_HCI_LE_PHY_1M_PREF_MASK; + /* Begin scanning for a peripheral to connect to. */ blecent_scan(); } } diff --git a/examples/bluetooth/nimble/ble_phy/phy_prph/main/gatt_svr.c b/examples/bluetooth/nimble/ble_phy/phy_prph/main/gatt_svr.c index c5c5f45d17..52ee798707 100644 --- a/examples/bluetooth/nimble/ble_phy/phy_prph/main/gatt_svr.c +++ b/examples/bluetooth/nimble/ble_phy/phy_prph/main/gatt_svr.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2021-2025 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Unlicense OR CC0-1.0 */ @@ -69,22 +69,26 @@ gatt_svr_chr_access_le_phy(uint16_t conn_handle, uint16_t attr_handle, case BLE_GATT_ACCESS_OP_WRITE_CHR: len = OS_MBUF_PKTLEN(ctxt->om); - if (len > 0) { - le_phy_val = (uint8_t *)malloc(len * sizeof(uint8_t)); - if (le_phy_val) { - rc = ble_hs_mbuf_to_flat(ctxt->om, le_phy_val, len, &copied_len); - if (rc == 0) { - MODLOG_DFLT(INFO, "Write received of len = %d", copied_len); - return 0; - } else { - MODLOG_DFLT(ERROR, "Failed to receive write characteristic"); - } - } + if (len == 0) { + return BLE_ATT_ERR_INVALID_ATTR_VALUE_LEN; } - break; + le_phy_val = (uint8_t *)malloc(len); + if (le_phy_val == NULL) { + return BLE_ATT_ERR_INSUFFICIENT_RES; + } + + rc = ble_hs_mbuf_to_flat(ctxt->om, le_phy_val, len, &copied_len); + free(le_phy_val); + if (rc == 0) { + MODLOG_DFLT(INFO, "Write received of len = %d", (int)copied_len); + return 0; + } + + MODLOG_DFLT(ERROR, "Failed to receive write characteristic"); + return BLE_ATT_ERR_INSUFFICIENT_RES; default: - break; + return BLE_ATT_ERR_UNLIKELY; } } diff --git a/examples/bluetooth/nimble/ble_proximity_sensor/proximity_sensor_cent/main/main.c b/examples/bluetooth/nimble/ble_proximity_sensor/proximity_sensor_cent/main/main.c index 1089883280..db7c007b33 100644 --- a/examples/bluetooth/nimble/ble_proximity_sensor/proximity_sensor_cent/main/main.c +++ b/examples/bluetooth/nimble/ble_proximity_sensor/proximity_sensor_cent/main/main.c @@ -70,7 +70,10 @@ ble_prox_cent_on_write(uint16_t conn_handle, const struct peer_chr *chr; int rc; const struct peer *peer = peer_find(conn_handle); - + if (peer == NULL) { + MODLOG_DFLT(ERROR, "Error: peer not found for conn_handle=%d", conn_handle); + return 0; + } chr = peer_chr_find_uuid(peer, BLE_UUID16_DECLARE(BLE_SVC_TX_POWER_UUID16), BLE_UUID16_DECLARE(BLE_SVC_PROX_CHR_UUID16_TX_PWR_LVL)); @@ -247,7 +250,7 @@ ext_ble_prox_cent_should_connect(const struct ble_gap_ext_disc_desc *disc) /* 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) { @@ -266,9 +269,15 @@ ext_ble_prox_cent_should_connect(const struct ble_gap_ext_disc_desc *disc) } /* Search if Proximity Sensor (Link loss) UUID is advertised */ - if (disc->data[offset] == 0x03 && disc->data[offset + 1] == 0x03) { - if ( disc->data[offset + 2] == 0x18 && disc->data[offset + 3] == 0x03 ) { - return 1; + if (disc->data[offset + 1] == 0x03) { + int uuid_offset = offset + 2; + int uuid_end = offset + 1 + disc->data[offset]; // len includes type+data + while (uuid_offset + 1 < uuid_end) { + // BLE uses little-endian: 0x1803 is stored as 0x03 0x18 + if (disc->data[uuid_offset] == 0x03 && disc->data[uuid_offset + 1] == 0x18) { + return 1; + } + uuid_offset += 2; } } @@ -553,7 +562,7 @@ ble_prox_cent_gap_event(struct ble_gap_event *event, void *arg) #else #if MYNEWT_VAL(BLE_GATTC) /*** Go for service discovery after encryption has been successfully enabled ***/ - rc = peer_disc_all(event->connect.conn_handle, + rc = peer_disc_all(event->enc_change.conn_handle, ble_prox_cent_on_disc_complete, NULL); if (rc != 0) { MODLOG_DFLT(ERROR, "Failed to discover services; rc=%d\n", rc); @@ -572,7 +581,7 @@ ble_prox_cent_gap_event(struct ble_gap_event *event, void *arg) event->cache_assoc.status, (event->cache_assoc.cache_state == 0) ? "INVALID" : "LOADED"); /* Perform service discovery */ - rc = peer_disc_all(event->connect.conn_handle, + rc = peer_disc_all(event->cache_assoc.conn_handle, blecent_on_disc_complete, NULL); if(rc != 0) { MODLOG_DFLT(ERROR, "Failed to discover services; rc=%d\n", rc); @@ -636,7 +645,7 @@ ble_prox_cent_gap_event(struct ble_gap_event *event, void *arg) void ble_prox_cent_path_loss_task(void *pvParameters) { - int8_t rssi; + int8_t rssi = 0; int rc; int path_loss; @@ -685,7 +694,10 @@ ble_prox_cent_link_loss_task(void *pvParameters) while (1) { for (int i = 0; i <= MYNEWT_VAL(BLE_MAX_CONNECTIONS); i++) { if (disconn_peer[i].link_lost && disconn_peer[i].addr != NULL) { - MODLOG_DFLT(INFO, "Link lost for device with conn_handle %d", i); + MODLOG_DFLT(INFO, "Link lost for peer %02x:%02x:%02x:%02x:%02x:%02x, slot %d", + disconn_peer[i].addr[5], disconn_peer[i].addr[4], + disconn_peer[i].addr[3], disconn_peer[i].addr[2], + disconn_peer[i].addr[1], disconn_peer[i].addr[0], i); } } vTaskDelay(5000 / portTICK_PERIOD_MS); diff --git a/examples/bluetooth/nimble/ble_spp/spp_client/main/main.c b/examples/bluetooth/nimble/ble_spp/spp_client/main/main.c index 5b5fb206e5..83478518fe 100644 --- a/examples/bluetooth/nimble/ble_spp/spp_client/main/main.c +++ b/examples/bluetooth/nimble/ble_spp/spp_client/main/main.c @@ -23,6 +23,7 @@ static int ble_spp_client_gap_event(struct ble_gap_event *event, void *arg); QueueHandle_t spp_common_uart_queue = NULL; void ble_store_config_init(void); uint16_t attribute_handle[CONFIG_BT_NIMBLE_MAX_CONNECTIONS + 1]; +static SemaphoreHandle_t g_attr_handle_mutex = NULL; static void ble_spp_client_scan(void); static ble_addr_t connected_addr[CONFIG_BT_NIMBLE_MAX_CONNECTIONS + 1]; @@ -73,8 +74,19 @@ ble_spp_client_set_handle(const struct peer *peer) chr = peer_chr_find_uuid(peer, BLE_UUID16_DECLARE(GATT_SPP_SVC_UUID), BLE_UUID16_DECLARE(GATT_SPP_CHR_UUID)); + + if (chr == NULL) { + MODLOG_DFLT(ERROR, "Error: Peer lacks SPP characteristic\n"); + return; + } + if (g_attr_handle_mutex != NULL) { + xSemaphoreTake(g_attr_handle_mutex, portMAX_DELAY); + } attribute_handle[peer->conn_handle] = chr->chr.val_handle; MODLOG_DFLT(INFO, "attribute_handle %x\n", attribute_handle[peer->conn_handle]); + if (g_attr_handle_mutex != NULL) { + xSemaphoreGive(g_attr_handle_mutex); + } dsc = peer_dsc_find_uuid(peer, BLE_UUID16_DECLARE(GATT_SPP_SVC_UUID), @@ -295,8 +307,10 @@ ble_spp_client_gap_event(struct ble_gap_event *event, void *arg) MODLOG_DFLT(INFO, "Connection established "); rc = ble_gap_conn_find(event->connect.conn_handle, &desc); assert(rc == 0); - memcpy(&connected_addr[event->connect.conn_handle].val, desc.peer_id_addr.val, - PEER_ADDR_VAL_SIZE); + if (event->connect.conn_handle <= CONFIG_BT_NIMBLE_MAX_CONNECTIONS) { + memcpy(&connected_addr[event->connect.conn_handle].val, desc.peer_id_addr.val, + PEER_ADDR_VAL_SIZE); + } print_conn_desc(&desc); MODLOG_DFLT(INFO, "\n"); @@ -333,7 +347,13 @@ ble_spp_client_gap_event(struct ble_gap_event *event, void *arg) /* 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); + } peer_delete(event->disconnect.conn.conn_handle); /* Resume scanning. */ @@ -422,19 +442,39 @@ void ble_client_uart_task(void *pvParameters) } memset(temp, 0x0, event.size); uart_read_bytes(UART_NUM_0, temp, event.size, portMAX_DELAY); - for ( i = 0; i <= CONFIG_BT_NIMBLE_MAX_CONNECTIONS; i++) { + /* Collect valid connections while holding mutex to prevent race conditions */ + struct { + uint16_t conn_handle; + uint16_t attr_handle; + } valid_conns[CONFIG_BT_NIMBLE_MAX_CONNECTIONS + 1]; + int valid_count = 0; + + if (g_attr_handle_mutex != NULL) { + xSemaphoreTake(g_attr_handle_mutex, portMAX_DELAY); + } + for (i = 0; i <= CONFIG_BT_NIMBLE_MAX_CONNECTIONS; i++) { if (attribute_handle[i] != 0) { -#if MYNEWT_VAL(BLE_GATTC) - rc = ble_gattc_write_flat(i, attribute_handle[i], temp, event.size, NULL, NULL); - if (rc == 0) { - ESP_LOGI(tag, "Write in uart task success!"); - } else { - ESP_LOGI(tag, "Error in writing characteristic rc=%d", rc); - } -#endif - vTaskDelay(10); + valid_conns[valid_count].conn_handle = i; + valid_conns[valid_count].attr_handle = attribute_handle[i]; + valid_count++; } } + if (g_attr_handle_mutex != NULL) { + xSemaphoreGive(g_attr_handle_mutex); + } + + /* Write to all valid connections (outside mutex to avoid blocking) */ + for (i = 0; i < valid_count; i++) { +#if MYNEWT_VAL(BLE_GATTC) + rc = ble_gattc_write_flat(valid_conns[i].conn_handle, valid_conns[i].attr_handle, temp, event.size, NULL, NULL); + if (rc == 0) { + ESP_LOGI(tag, "Write in uart task success!"); + } else { + ESP_LOGI(tag, "Error in writing characteristic rc=%d", rc); + } +#endif + vTaskDelay(10); + } free(temp); } break; @@ -484,6 +524,13 @@ app_main(void) return; } + /* Initialize mutex for attribute_handle protection */ + g_attr_handle_mutex = xSemaphoreCreateMutex(); + if (g_attr_handle_mutex == NULL) { + ESP_LOGE(tag, "Failed to create attribute handle mutex"); + return; + } + /* Initialize UART driver and start uart task */ ble_spp_uart_init(); diff --git a/examples/bluetooth/nimble/ble_spp/spp_server/main/main.c b/examples/bluetooth/nimble/ble_spp/spp_server/main/main.c index b79521be69..42f01344a2 100644 --- a/examples/bluetooth/nimble/ble_spp/spp_server/main/main.c +++ b/examples/bluetooth/nimble/ble_spp/spp_server/main/main.c @@ -163,7 +163,9 @@ ble_spp_server_gap_event(struct ble_gap_event *event, void *arg) ble_spp_server_print_conn_desc(&event->disconnect.conn); MODLOG_DFLT(INFO, "\n"); - conn_handle_subs[event->disconnect.conn.conn_handle] = false; + if (event->disconnect.conn.conn_handle <= CONFIG_BT_NIMBLE_MAX_CONNECTIONS) { + conn_handle_subs[event->disconnect.conn.conn_handle] = false; + } /* Connection terminated; resume advertising. */ ble_spp_server_advertise(); @@ -202,7 +204,9 @@ ble_spp_server_gap_event(struct ble_gap_event *event, void *arg) event->subscribe.cur_notify, event->subscribe.prev_indicate, event->subscribe.cur_indicate); - conn_handle_subs[event->subscribe.conn_handle] = true; + if (event->subscribe.conn_handle <= CONFIG_BT_NIMBLE_MAX_CONNECTIONS) { + conn_handle_subs[event->subscribe.conn_handle] = true; + } return 0; default: @@ -360,6 +364,10 @@ void ble_server_uart_task(void *pvParameters) if (event.size) { uint8_t *ntf; ntf = (uint8_t *)malloc(sizeof(uint8_t) * event.size); + if (ntf == NULL) { + MODLOG_DFLT(ERROR, "malloc failed for UART data, size=%u", event.size); + continue; + } memset(ntf, 0x00, event.size); uart_read_bytes(UART_NUM_0, ntf, event.size, portMAX_DELAY); diff --git a/examples/bluetooth/nimble/blecent/main/main.c b/examples/bluetooth/nimble/blecent/main/main.c index 652cbe05fe..6b5fbcc18b 100644 --- a/examples/bluetooth/nimble/blecent/main/main.c +++ b/examples/bluetooth/nimble/blecent/main/main.c @@ -121,6 +121,10 @@ blecent_on_custom_write(uint16_t conn_handle, error->status, conn_handle, attr->handle); 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); @@ -257,6 +261,7 @@ blecent_on_subscribe(uint16_t conn_handle, if (peer == NULL) { MODLOG_DFLT(ERROR, "Error in finding peer, aborting..."); ble_gap_terminate(conn_handle, BLE_ERR_REM_USER_CONN_TERM); + return 0; } /* Subscribe to, write to, and read the custom characteristic*/ blecent_custom_gatt_operations(peer); @@ -286,7 +291,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, "Error: peer not found for conn_handle=%d", conn_handle); + return ble_gap_terminate(conn_handle, BLE_ERR_REM_USER_CONN_TERM); // Use conn_handle to avoid dereference + } dsc = peer_dsc_find_uuid(peer, BLE_UUID16_DECLARE(BLECENT_SVC_ALERT_UUID), BLE_UUID16_DECLARE(BLECENT_CHR_UNR_ALERT_STAT_UUID), @@ -338,7 +346,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, "Error: peer not found for conn_handle=%d", conn_handle); + return ble_gap_terminate(conn_handle, BLE_ERR_REM_USER_CONN_TERM); + } chr = peer_chr_find_uuid(peer, BLE_UUID16_DECLARE(BLECENT_SVC_ALERT_UUID), BLE_UUID16_DECLARE(BLECENT_CHR_ALERT_NOT_CTRL_PT)); @@ -877,7 +888,7 @@ blecent_gap_event(struct ble_gap_event *event, void *arg) event->cache_assoc.status, (event->cache_assoc.cache_state == 0) ? "INVALID" : "LOADED"); /* Perform service discovery */ - rc = peer_disc_all(event->connect.conn_handle, + rc = peer_disc_all(event->cache_assoc.conn_handle, blecent_on_disc_complete, NULL); if(rc != 0) { MODLOG_DFLT(ERROR, "Failed to discover services; rc=%d\n", rc); diff --git a/examples/bluetooth/nimble/blecsc/main/gatt_svr.c b/examples/bluetooth/nimble/blecsc/main/gatt_svr.c index 6ca3038441..54425cfd03 100644 --- a/examples/bluetooth/nimble/blecsc/main/gatt_svr.c +++ b/examples/bluetooth/nimble/blecsc/main/gatt_svr.c @@ -191,6 +191,9 @@ gatt_svr_chr_access_sc_control_point(uint16_t conn_handle, /* Allocate response buffer */ om_indication = ble_hs_mbuf_att_pkt(); + if (om_indication == NULL) { + return BLE_HS_ENOMEM; + } switch(op_code){ #if (CSC_FEATURES & CSC_FEATURE_WHEEL_REV_DATA) @@ -200,6 +203,7 @@ gatt_svr_chr_access_sc_control_point(uint16_t conn_handle, sizeof(new_cumulative_wheel_rev_arr), new_cumulative_wheel_rev_arr); if (rc != 0){ + os_mbuf_free_chain(om_indication); return BLE_ATT_ERR_INVALID_ATTR_VALUE_LEN; } @@ -216,7 +220,8 @@ gatt_svr_chr_access_sc_control_point(uint16_t conn_handle, /* Read new sensor location value*/ rc = os_mbuf_copydata(ctxt->om, 1, 1, &new_sensor_location); if (rc != 0){ - return BLE_ATT_ERR_INVALID_ATTR_VALUE_LEN; + os_mbuf_free_chain(om_indication); + return BLE_ATT_ERR_INVALID_ATTR_VALUE_LEN; } @@ -244,7 +249,8 @@ gatt_svr_chr_access_sc_control_point(uint16_t conn_handle, rc = os_mbuf_append(om_indication, &response, sizeof(response)); if (rc != 0){ - return BLE_ATT_ERR_INSUFFICIENT_RES; + os_mbuf_free_chain(om_indication); + return BLE_ATT_ERR_INSUFFICIENT_RES; } #if (CSC_FEATURES & CSC_FEATURE_MULTIPLE_SENSOR_LOC) @@ -252,17 +258,24 @@ gatt_svr_chr_access_sc_control_point(uint16_t conn_handle, if (op_code == SC_CP_OP_REQ_SUPPORTED_SENSOR_LOCATIONS){ rc = os_mbuf_append(om_indication, &csc_supported_sensor_locations, sizeof(csc_supported_sensor_locations)); - } - - if (rc != 0){ - return BLE_ATT_ERR_INSUFFICIENT_RES; + if (rc != 0){ + os_mbuf_free_chain(om_indication); + return BLE_ATT_ERR_INSUFFICIENT_RES; + } } #endif 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); + return rc; } static int diff --git a/examples/bluetooth/nimble/blehr/main/main.c b/examples/bluetooth/nimble/blehr/main/main.c index 94b7b495fd..747a41bbbc 100644 --- a/examples/bluetooth/nimble/blehr/main/main.c +++ b/examples/bluetooth/nimble/blehr/main/main.c @@ -200,6 +200,9 @@ blehr_gap_event(struct ble_gap_event *event, void *arg) case BLE_GAP_EVENT_DISCONNECT: MODLOG_DFLT(INFO, "disconnect; reason=%d\n", event->disconnect.reason); + notify_state = false; + blehr_tx_hrate_stop(); + conn_handle = BLE_HS_CONN_HANDLE_NONE; /* Connection terminated; resume advertising */ blehr_advertise(); break; diff --git a/examples/bluetooth/nimble/bleprph_host_only/main/main.c b/examples/bluetooth/nimble/bleprph_host_only/main/main.c index 9523937350..4429b14dfd 100644 --- a/examples/bluetooth/nimble/bleprph_host_only/main/main.c +++ b/examples/bluetooth/nimble/bleprph_host_only/main/main.c @@ -245,7 +245,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; @@ -497,6 +499,7 @@ app_main(void) ret = nimble_port_init(); if (ret != ESP_OK) { ESP_LOGE(tag, "Failed to init nimble %d ", ret); + hci_uart_close(); return; } /* Initialize the NimBLE host configuration. */ diff --git a/examples/bluetooth/nimble/bleprph_host_only/main/uart_driver.c b/examples/bluetooth/nimble/bleprph_host_only/main/uart_driver.c index 876373c710..55d98ebb36 100644 --- a/examples/bluetooth/nimble/bleprph_host_only/main/uart_driver.c +++ b/examples/bluetooth/nimble/bleprph_host_only/main/uart_driver.c @@ -1,11 +1,12 @@ /* - * SPDX-FileCopyrightText: 2021-2024 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2021-2025 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Unlicense OR CC0-1.0 */ #include #include +#include #include "freertos/FreeRTOS.h" #include "freertos/task.h" #include "freertos/queue.h" @@ -44,6 +45,7 @@ enum { }; TaskHandle_t s_rx_task_hdl; +static volatile bool s_shutdown_flag = false; static void IRAM_ATTR hci_uart_rx_task(void *arg) { @@ -53,9 +55,15 @@ static void IRAM_ATTR hci_uart_rx_task(void *arg) uint32_t len_total_read = 0; uint8_t rx_st = UART_RX_TYPE; - while (1) { - len_now_read = uart_read_bytes(UART_NO, &buf[len_total_read], len_to_read, portMAX_DELAY); - assert(len_now_read == len_to_read); + 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 timeout occurred, continue loop to check shutdown flag again + if (len_now_read == 0) { + continue; + } + len_total_read += len_now_read; switch (rx_st) { @@ -130,6 +138,10 @@ static void IRAM_ATTR hci_uart_rx_task(void *arg) m = ble_transport_alloc_acl_from_ll(); if (!m) { ESP_LOGE(TAG, "No buffers"); + rx_st = UART_RX_TYPE; + len_to_read = 1; + len_total_read = 0; + break; } if ((rc = os_mbuf_append(m, &data[1], len_total_read - 1)) != 0) { @@ -180,7 +192,7 @@ ble_transport_ll_init(void) void ble_transport_ll_deinit(void) { - + hci_uart_close(); } int @@ -228,6 +240,7 @@ void hci_uart_open(void) intr_alloc_flags = ESP_INTR_FLAG_IRAM; #endif + s_shutdown_flag = false; // Reset shutdown flag on open ESP_ERROR_CHECK(uart_driver_install(UART_NO, UART_BUF_SZ * 2, UART_BUF_SZ * 2, 0, NULL, intr_alloc_flags)); ESP_ERROR_CHECK(uart_param_config(UART_NO, &uart_config)); ESP_ERROR_CHECK(uart_set_pin(UART_NO, UART_TX_PIN, UART_RX_PIN, -1, -1)); @@ -238,7 +251,26 @@ void hci_uart_open(void) void hci_uart_close(void) { if (s_rx_task_hdl) { - vTaskDelete(s_rx_task_hdl); + + s_shutdown_flag = true; + + int wait_count = 0; + const int max_wait_count = 5; + TaskHandle_t task_handle = s_rx_task_hdl; + + while (wait_count < max_wait_count) { + vTaskDelay(pdMS_TO_TICKS(100)); + wait_count++; + + } + + + if (s_rx_task_hdl == task_handle) { + vTaskDelete(s_rx_task_hdl); + vTaskDelay(pdMS_TO_TICKS(100)); + } + s_rx_task_hdl = NULL; } + uart_driver_delete(UART_NO); } diff --git a/examples/bluetooth/nimble/bleprph_wifi_coex/main/main.c b/examples/bluetooth/nimble/bleprph_wifi_coex/main/main.c index 4d31b9d308..6d7a450551 100644 --- a/examples/bluetooth/nimble/bleprph_wifi_coex/main/main.c +++ b/examples/bluetooth/nimble/bleprph_wifi_coex/main/main.c @@ -167,8 +167,10 @@ static void cmd_ping_on_ping_success(esp_ping_handle_t hdl, void *args) esp_ping_get_profile(hdl, ESP_PING_PROF_IPADDR, &target_addr, sizeof(target_addr)); esp_ping_get_profile(hdl, ESP_PING_PROF_SIZE, &recv_len, sizeof(recv_len)); esp_ping_get_profile(hdl, ESP_PING_PROF_TIMEGAP, &elapsed_time, sizeof(elapsed_time)); + const char *ip_str = IP_IS_V4(&target_addr) ? inet_ntoa(*ip_2_ip4(&target_addr)) : + inet6_ntoa(*ip_2_ip6(&target_addr)); printf("%" PRIu32 "bytes from %s icmp_seq=%d ttl=%d time=%" PRIu32 "ms\n", - recv_len, inet_ntoa(target_addr.u_addr.ip4), seqno, ttl, elapsed_time); + recv_len, ip_str, seqno, ttl, elapsed_time); } static void cmd_ping_on_ping_timeout(esp_ping_handle_t hdl, void *args) @@ -177,7 +179,9 @@ static void cmd_ping_on_ping_timeout(esp_ping_handle_t hdl, void *args) ip_addr_t target_addr; esp_ping_get_profile(hdl, ESP_PING_PROF_SEQNO, &seqno, sizeof(seqno)); esp_ping_get_profile(hdl, ESP_PING_PROF_IPADDR, &target_addr, sizeof(target_addr)); - printf("From %s icmp_seq=%d timeout\n", inet_ntoa(target_addr.u_addr.ip4), seqno); + const char *ip_str = IP_IS_V4(&target_addr) ? inet_ntoa(*ip_2_ip4(&target_addr)) : + inet6_ntoa(*ip_2_ip6(&target_addr)); + printf("From %s icmp_seq=%d timeout\n", ip_str, seqno); } diff --git a/examples/bluetooth/nimble/common/nimble_central_utils/misc.c b/examples/bluetooth/nimble/common/nimble_central_utils/misc.c index 44dfade97b..08537545be 100644 --- a/examples/bluetooth/nimble/common/nimble_central_utils/misc.c +++ b/examples/bluetooth/nimble/common/nimble_central_utils/misc.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2021-2025 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Unlicense OR CC0-1.0 */ @@ -152,9 +152,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); } diff --git a/examples/bluetooth/nimble/common/nimble_central_utils/peer.c b/examples/bluetooth/nimble/common/nimble_central_utils/peer.c index e4a2070cfb..1ccb7283e2 100644 --- a/examples/bluetooth/nimble/common/nimble_central_utils/peer.c +++ b/examples/bluetooth/nimble/common/nimble_central_utils/peer.c @@ -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); @@ -341,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; diff --git a/examples/bluetooth/nimble/common/nimble_peripheral_utils/scli.c b/examples/bluetooth/nimble/common/nimble_peripheral_utils/scli.c index 0a5b4565ce..f7d1cedbe1 100644 --- a/examples/bluetooth/nimble/common/nimble_peripheral_utils/scli.c +++ b/examples/bluetooth/nimble/common/nimble_peripheral_utils/scli.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2021-2025 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Unlicense OR CC0-1.0 */ @@ -32,7 +32,7 @@ static int enter_passkey_handler(int argc, char *argv[]) return -1; } - sscanf(argv[1], "%s", pkey); + sscanf(argv[1], "%7s", pkey); ESP_LOGI("You entered", "%s %s", argv[0], argv[1]); num = pkey[0]; @@ -45,7 +45,9 @@ static int enter_passkey_handler(int argc, char *argv[]) xQueueSend(cli_handle, &key, 0); } } else { - sscanf(pkey, "%d", &key); + if (sscanf(pkey, "%d", &key) != 1) { + key = 0; + } xQueueSend(cli_handle, &key, 0); } @@ -84,14 +86,14 @@ static void scli_task(void *arg) QueueHandle_t uart_queue; uart_event_t event; - uart_driver_install(uart_num, 256, 0, 8, &uart_queue, 0); + ESP_ERROR_CHECK(uart_driver_install(uart_num, 256, 0, 8, &uart_queue, 0)); /* Initialize the console */ esp_console_config_t console_config = { .max_cmdline_args = 8, .max_cmdline_length = 256, }; - esp_console_init(&console_config); + ESP_ERROR_CHECK(esp_console_init(&console_config)); while (!stop) { i = 0; @@ -107,6 +109,9 @@ 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; + } if (linebuf[i] == '\r') { uart_write_bytes(uart_num, "\r\n", 2); } else { @@ -115,12 +120,16 @@ static void scli_task(void *arg) i++; } } - } while ((i < 255) && linebuf[i - 1] != '\r'); + + } while ((i < 255) && (i == 0 || linebuf[i - 1] != '\r')); if (stop) { break; } /* Remove the truncating \r\n */ - linebuf[strlen((char *)linebuf) - 1] = '\0'; + size_t len = strlen((char *)linebuf); + if (len > 0) { + linebuf[len - 1] = '\0'; + } ret = esp_console_run((char *) linebuf, &cmd_ret); if (ret < 0) { break; @@ -144,3 +153,40 @@ int scli_init(void) } return ESP_OK; } + +int scli_deinit(void) +{ + if (cli_task == NULL) { + return ESP_OK; // Already deinitialized + } + + // Signal task to exit + stop = 1; + + // Wait for task to exit (it will clean up UART and console) + int timeout_ms = 200; + while (timeout_ms > 0 && cli_task != NULL && eTaskGetState(cli_task) != eDeleted) { + vTaskDelay(pdMS_TO_TICKS(10)); + timeout_ms -= 10; + } + + // Force delete if still running (shouldn't happen if task exits properly) + if (cli_task != NULL && eTaskGetState(cli_task) != eDeleted) { + vTaskDelete(cli_task); + // If force-deleted, clean up resources manually + uart_driver_delete(0); + esp_console_deinit(); + } + cli_task = NULL; + + // Clean up queue + if (cli_handle != NULL) { + vQueueDelete(cli_handle); + cli_handle = NULL; + } + + // Reset stop flag + stop = 0; + + return ESP_OK; +} diff --git a/examples/bluetooth/nimble/hci/main/dtm_configuration_command.c b/examples/bluetooth/nimble/hci/main/dtm_configuration_command.c index e7ac664405..37f221c1ec 100644 --- a/examples/bluetooth/nimble/hci/main/dtm_configuration_command.c +++ b/examples/bluetooth/nimble/hci/main/dtm_configuration_command.c @@ -46,9 +46,16 @@ static int dtm_set_ble_tx_power_command(int argc, char **argv) static int dtm_get_ble_tx_power_command(int argc, char **argv) { - esp_power_level_t power_level = 0xFF; + esp_power_level_t power_level; + power_level = esp_ble_tx_power_get_enhanced(ESP_BLE_ENHANCED_PWR_TYPE_DEFAULT, 0); - printf("\nCurrent BLE TX power is %d level\n", power_level); + + if (power_level == ESP_PWR_LVL_INVALID) { + ESP_LOGI(__func__,"TX power is not available!\n"); + return 1; + } + + ESP_LOGI(__func__,"\nCurrent BLE TX power is %d level\n", power_level); return 0; } diff --git a/examples/bluetooth/nimble/power_save/main/main.c b/examples/bluetooth/nimble/power_save/main/main.c index 790f0f7489..20cc5195ec 100644 --- a/examples/bluetooth/nimble/power_save/main/main.c +++ b/examples/bluetooth/nimble/power_save/main/main.c @@ -227,15 +227,21 @@ bleprph_advertise(void) #endif #if MYNEWT_VAL(BLE_POWER_CONTROL) -static void bleprph_power_control(uint16_t conn_handle) +static int 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); + if (rc != 0) { + return rc; + } rc = ble_gap_set_transmit_power_reporting_enable(conn_handle, 0x1, 0x1); - assert (rc == 0); + if (rc != 0) { + return rc; + } + + return 0; } #endif @@ -317,10 +323,13 @@ bleprph_gap_event(struct ble_gap_event *event, void *arg) } #if MYNEWT_VAL(BLE_POWER_CONTROL) - bleprph_power_control(event->connect.conn_handle); - - ble_gap_event_listener_register(&power_control_event_listener, - bleprph_gap_power_event, NULL); + if (event->connect.status == 0) { + rc = bleprph_power_control(event->connect.conn_handle); + if (rc == 0) { + ble_gap_event_listener_register(&power_control_event_listener, + bleprph_gap_power_event, NULL); + } + } #endif return 0; diff --git a/examples/bluetooth/nimble/throughput_app/blecent_throughput/components/cmd_system/cmd_system.c b/examples/bluetooth/nimble/throughput_app/blecent_throughput/components/cmd_system/cmd_system.c index 0e5b9f354a..60a4735a44 100644 --- a/examples/bluetooth/nimble/throughput_app/blecent_throughput/components/cmd_system/cmd_system.c +++ b/examples/bluetooth/nimble/throughput_app/blecent_throughput/components/cmd_system/cmd_system.c @@ -63,6 +63,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"); @@ -70,7 +71,18 @@ 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" : "Unknown"); + 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; + case CHIP_ESP32C5: model_str = "ESP32-C5"; break; + 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" : "", diff --git a/examples/bluetooth/nimble/throughput_app/blecent_throughput/main/gattc.h b/examples/bluetooth/nimble/throughput_app/blecent_throughput/main/gattc.h index aea4a3762f..6762d3d42c 100644 --- a/examples/bluetooth/nimble/throughput_app/blecent_throughput/main/gattc.h +++ b/examples/bluetooth/nimble/throughput_app/blecent_throughput/main/gattc.h @@ -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); diff --git a/examples/bluetooth/nimble/throughput_app/blecent_throughput/main/main.c b/examples/bluetooth/nimble/throughput_app/blecent_throughput/main/main.c index 96a700fd14..f0c123d39e 100644 --- a/examples/bluetooth/nimble/throughput_app/blecent_throughput/main/main.c +++ b/examples/bluetooth/nimble/throughput_app/blecent_throughput/main/main.c @@ -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); diff --git a/examples/bluetooth/nimble/throughput_app/blecent_throughput/main/misc.c b/examples/bluetooth/nimble/throughput_app/blecent_throughput/main/misc.c index b7d6997c73..4492ba84df 100644 --- a/examples/bluetooth/nimble/throughput_app/blecent_throughput/main/misc.c +++ b/examples/bluetooth/nimble/throughput_app/blecent_throughput/main/misc.c @@ -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); } diff --git a/examples/bluetooth/nimble/throughput_app/blecent_throughput/main/peer.c b/examples/bluetooth/nimble/throughput_app/blecent_throughput/main/peer.c index 4ef4ab09d9..af34f8e582 100644 --- a/examples/bluetooth/nimble/throughput_app/blecent_throughput/main/peer.c +++ b/examples/bluetooth/nimble/throughput_app/blecent_throughput/main/peer.c @@ -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) { diff --git a/examples/bluetooth/nimble/throughput_app/blecent_throughput/main/scli.c b/examples/bluetooth/nimble/throughput_app/blecent_throughput/main/scli.c index 9b9455a9ec..1366f96481 100644 --- a/examples/bluetooth/nimble/throughput_app/blecent_throughput/main/scli.c +++ b/examples/bluetooth/nimble/throughput_app/blecent_throughput/main/scli.c @@ -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 #include "esp_log.h" #include +#include #include #include #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; } diff --git a/examples/bluetooth/nimble/throughput_app/bleprph_throughput/main/main.c b/examples/bluetooth/nimble/throughput_app/bleprph_throughput/main/main.c index 0ce9e3811e..da2d922f0d 100644 --- a/examples/bluetooth/nimble/throughput_app/bleprph_throughput/main/main.c +++ b/examples/bluetooth/nimble/throughput_app/bleprph_throughput/main/main.c @@ -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);