mirror of
https://github.com/espressif/esp-idf.git
synced 2026-10-02 03:00:34 +03:00
fix(nimble): Fix vulnerabilities in NimBLE examples
This commit is contained in:
@@ -18,6 +18,7 @@
|
|||||||
void send_heart_rate_indication(void);
|
void send_heart_rate_indication(void);
|
||||||
void gatt_svr_register_cb(struct ble_gatt_register_ctxt *ctxt, void *arg);
|
void gatt_svr_register_cb(struct ble_gatt_register_ctxt *ctxt, void *arg);
|
||||||
void gatt_svr_subscribe_cb(struct ble_gap_event *event);
|
void gatt_svr_subscribe_cb(struct ble_gap_event *event);
|
||||||
|
void gatt_svr_reset_heart_rate_subscription(void);
|
||||||
int gatt_svc_init(void);
|
int gatt_svc_init(void);
|
||||||
|
|
||||||
#endif // GATT_SVR_H
|
#endif // GATT_SVR_H
|
||||||
|
|||||||
@@ -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
|
* SPDX-License-Identifier: Unlicense OR CC0-1.0
|
||||||
*/
|
*/
|
||||||
@@ -80,7 +80,7 @@ static void heart_rate_task(void *param) {
|
|||||||
|
|
||||||
void app_main(void) {
|
void app_main(void) {
|
||||||
/* Local variables */
|
/* Local variables */
|
||||||
int rc = 0;
|
BaseType_t rc = 0;
|
||||||
esp_err_t ret;
|
esp_err_t ret;
|
||||||
|
|
||||||
/* LED initialization */
|
/* LED initialization */
|
||||||
@@ -129,7 +129,17 @@ void app_main(void) {
|
|||||||
nimble_host_config_init();
|
nimble_host_config_init();
|
||||||
|
|
||||||
/* Start NimBLE host task thread and return */
|
/* Start NimBLE host task thread and return */
|
||||||
xTaskCreate(nimble_host_task, "NimBLE Host", 4*1024, NULL, 5, NULL);
|
rc = xTaskCreate(nimble_host_task, "NimBLE Host", 4 * 1024, NULL,
|
||||||
xTaskCreate(heart_rate_task, "Heart Rate", 4*1024, NULL, 5, 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;
|
return;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -186,6 +186,9 @@ static int gap_event_handler(struct ble_gap_event *event, void *arg) {
|
|||||||
ESP_LOGI(TAG, "disconnected from peer; reason=%d",
|
ESP_LOGI(TAG, "disconnected from peer; reason=%d",
|
||||||
event->disconnect.reason);
|
event->disconnect.reason);
|
||||||
|
|
||||||
|
/* Reset heart rate subscription state */
|
||||||
|
gatt_svr_reset_heart_rate_subscription();
|
||||||
|
|
||||||
/* Restart advertising */
|
/* Restart advertising */
|
||||||
start_advertising();
|
start_advertising();
|
||||||
return rc;
|
return rc;
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ static uint8_t heart_rate_chr_val[2] = {0};
|
|||||||
static uint16_t heart_rate_chr_val_handle;
|
static uint16_t heart_rate_chr_val_handle;
|
||||||
static const ble_uuid16_t heart_rate_chr_uuid = BLE_UUID16_INIT(0x2A37);
|
static const ble_uuid16_t heart_rate_chr_uuid = BLE_UUID16_INIT(0x2A37);
|
||||||
|
|
||||||
static uint16_t heart_rate_chr_conn_handle = 0;
|
static uint16_t heart_rate_chr_conn_handle = BLE_HS_CONN_HANDLE_NONE;
|
||||||
static bool heart_rate_chr_conn_handle_inited = false;
|
static bool heart_rate_chr_conn_handle_inited = false;
|
||||||
static bool heart_rate_ind_status = false;
|
static bool heart_rate_ind_status = false;
|
||||||
|
|
||||||
@@ -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
|
* GATT server initialization
|
||||||
* 1. Initialize GATT service
|
* 1. Initialize GATT service
|
||||||
|
|||||||
@@ -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
|
* 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)
|
void ble_receive_apple_notification_source(uint8_t *message, uint16_t message_len)
|
||||||
{
|
{
|
||||||
if (!message || message_len < 5) {
|
if (!message || message_len < 8) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -126,14 +126,19 @@ void ble_receive_apple_data_source(uint8_t *message, uint16_t message_len)
|
|||||||
switch (Command_id)
|
switch (Command_id)
|
||||||
{
|
{
|
||||||
case CommandIDGetNotificationAttributes: {
|
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 NotificationUID = (message[1]) | (message[2]<< 8) | (message[3]<< 16) | (message[4] << 24);
|
||||||
uint32_t remian_attr_len = message_len - 5;
|
uint32_t remian_attr_len = message_len - 5;
|
||||||
uint8_t *attrs = &message[5];
|
uint8_t *attrs = &message[5];
|
||||||
ESP_LOGI(NimBLE_ANCS_TAG, "recevice Notification Attributes response Command_id %d NotificationUID %" PRIu32, Command_id, NotificationUID);
|
ESP_LOGI(NimBLE_ANCS_TAG, "recevice Notification Attributes response Command_id %d NotificationUID %" PRIu32, Command_id, NotificationUID);
|
||||||
while(remian_attr_len > 0) {
|
while(remian_attr_len >= 3) {
|
||||||
uint8_t AttributeID = attrs[0];
|
uint8_t AttributeID = attrs[0];
|
||||||
uint16_t len = attrs[1] | (attrs[2] << 8);
|
uint16_t len = attrs[1] | (attrs[2] << 8);
|
||||||
if(len > (remian_attr_len -3)) {
|
if(len > remian_attr_len - 3) {
|
||||||
ESP_LOGE(NimBLE_ANCS_TAG, "data error");
|
ESP_LOGE(NimBLE_ANCS_TAG, "data error");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -72,7 +72,7 @@ static uint8_t ext_adv_pattern_1[] = {
|
|||||||
0x02, BLE_HS_ADV_TYPE_FLAGS, 0x06,
|
0x02, BLE_HS_ADV_TYPE_FLAGS, 0x06,
|
||||||
0x03, BLE_HS_ADV_TYPE_COMP_UUIDS16, 0xab, 0xcd,
|
0x03, BLE_HS_ADV_TYPE_COMP_UUIDS16, 0xab, 0xcd,
|
||||||
0x03, BLE_HS_ADV_TYPE_COMP_UUIDS16, 0x18, 0x11,
|
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
|
#endif
|
||||||
|
|
||||||
@@ -338,14 +338,14 @@ ext_ble_ancs_advertise(void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* use defaults for non-set params */
|
/* 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.connectable = 1;
|
||||||
|
params.scannable = 1;
|
||||||
|
|
||||||
/* advertise using random addr */
|
/* advertise using configured addr */
|
||||||
params.own_addr_type = BLE_OWN_ADDR_PUBLIC;
|
params.own_addr_type = BLE_OWN_ADDR_PUBLIC;
|
||||||
|
|
||||||
params.primary_phy = BLE_HCI_LE_PHY_1M;
|
params.primary_phy = BLE_HCI_LE_PHY_1M;
|
||||||
params.secondary_phy = BLE_HCI_LE_PHY_2M;
|
params.secondary_phy = BLE_HCI_LE_PHY_2M;
|
||||||
params.tx_power = 127;
|
params.tx_power = 127;
|
||||||
@@ -359,8 +359,6 @@ ext_ble_ancs_advertise(void)
|
|||||||
ble_ancs_gap_event, NULL);
|
ble_ancs_gap_event, NULL);
|
||||||
assert (rc == 0);
|
assert (rc == 0);
|
||||||
|
|
||||||
/* in this case only scan response is allowed */
|
|
||||||
|
|
||||||
/* get mbuf for scan rsp data */
|
/* get mbuf for scan rsp data */
|
||||||
data = os_msys_get_pkthdr(sizeof(ext_adv_pattern_1), 0);
|
data = os_msys_get_pkthdr(sizeof(ext_adv_pattern_1), 0);
|
||||||
assert(data);
|
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));
|
rc = os_mbuf_append(data, ext_adv_pattern_1, sizeof(ext_adv_pattern_1));
|
||||||
assert(rc == 0);
|
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);
|
assert (rc == 0);
|
||||||
|
|
||||||
/* start advertising */
|
/* 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);
|
notificationUID, sizeof(p_attr)/sizeof(ble_noti_attr_list_t), p_attr);
|
||||||
}
|
}
|
||||||
} else if (event->notify_rx.attr_handle == data_source_handle) {
|
} 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],
|
memcpy(&data_buffer.buffer[data_buffer.len],
|
||||||
event->notify_rx.om->om_data,
|
event->notify_rx.om->om_data,
|
||||||
event->notify_rx.om->om_len);
|
event->notify_rx.om->om_len);
|
||||||
data_buffer.len += event->notify_rx.om->om_len;
|
data_buffer.len = new_len;
|
||||||
|
|
||||||
if (event->notify_rx.om->om_len == (MTU_size - 3)) {
|
if (event->notify_rx.om->om_len == (MTU_size - 3)) {
|
||||||
esp_timer_start_periodic(periodic_timer, 500000);
|
esp_timer_start_periodic(periodic_timer, 500000);
|
||||||
|
|||||||
@@ -69,14 +69,16 @@ int blecent_on_subscribe(uint16_t conn_handle,
|
|||||||
MODLOG_DFLT(INFO, "Subscribe complete; status=%d conn_handle=%d "
|
MODLOG_DFLT(INFO, "Subscribe complete; status=%d conn_handle=%d "
|
||||||
"attr_handle=%d\n",
|
"attr_handle=%d\n",
|
||||||
error->status, conn_handle, attr->handle);
|
error->status, conn_handle, attr->handle);
|
||||||
subscribe_all++;
|
if (error->status == 0) {
|
||||||
if (subscribe_all == 4){
|
subscribe_all++;
|
||||||
struct ble_cs_initiator_procedure_start_params param;
|
if (subscribe_all == 4){
|
||||||
memset(¶m,0,sizeof param);
|
struct ble_cs_initiator_procedure_start_params param;
|
||||||
param.conn_handle=conn_handle;
|
memset(¶m,0,sizeof param);
|
||||||
param.cb=blecs_gap_event;
|
param.conn_handle=conn_handle;
|
||||||
param.cb_arg=NULL;
|
param.cb=blecs_gap_event;
|
||||||
ble_cs_initiator_procedure_start(¶m);
|
param.cb_arg=NULL;
|
||||||
|
ble_cs_initiator_procedure_start(¶m);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
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);
|
MODLOG_DFLT(INFO, "Read complete RAS FEATURES; status=%d conn_handle=%d", error->status, conn_handle);
|
||||||
|
|
||||||
if (error->status == 0) {
|
if (error->status == 0) {
|
||||||
uint32_t var;
|
uint32_t var = 0;
|
||||||
int rc = 0;
|
int rc = 0;
|
||||||
if (attr->om && OS_MBUF_PKTLEN(attr->om) > 0) {
|
uint16_t pktlen = (attr->om ? OS_MBUF_PKTLEN(attr->om) : 0);
|
||||||
os_mbuf_copydata(attr->om, 0, OS_MBUF_PKTLEN(attr->om), &var);
|
if (attr->om && pktlen > 0 && pktlen <= sizeof(var)) {
|
||||||
} else {
|
os_mbuf_copydata(attr->om, 0, pktlen, &var);
|
||||||
MODLOG_DFLT(ERROR, "Error: No data in the attribute\n");
|
}
|
||||||
}
|
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);
|
MODLOG_DFLT(INFO, " attr_handle = %u value = %" PRIu32, attr->handle, var);
|
||||||
|
|
||||||
if (var & REAL_TIME_RANGING_DATA_BIT) {
|
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;
|
return 0;
|
||||||
}
|
}
|
||||||
if (event->subev_result.num_steps_reported) {
|
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;
|
nap=event->subev_result.num_antenna_paths;
|
||||||
most_recent_local_ranging_counter=event->subev_result.procedure_counter;
|
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;
|
return 0;
|
||||||
}
|
}
|
||||||
connh = event->connect.conn_handle;
|
connh = event->connect.conn_handle;
|
||||||
|
subscribe_all = 0;
|
||||||
rc = ble_gap_security_initiate(event->connect.conn_handle);
|
rc = ble_gap_security_initiate(event->connect.conn_handle);
|
||||||
if (rc != 0) {
|
if (rc != 0) {
|
||||||
MODLOG_DFLT(INFO, "Security could not be initiated, rc = %d\n", rc);
|
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;
|
uint16_t ranging_counter;
|
||||||
os_mbuf_copydata(event->notify_rx.om, 0, sizeof(uint16_t), &ranging_counter);
|
os_mbuf_copydata(event->notify_rx.om, 0, sizeof(uint16_t), &ranging_counter);
|
||||||
most_recent_peer_ranging_counter=ranging_counter;
|
most_recent_peer_ranging_counter=ranging_counter;
|
||||||
most_recent_local_ranging_counter=0;
|
most_recent_local_ranging_counter= ranging_counter;
|
||||||
|
|
||||||
if (most_recent_peer_ranging_counter!=most_recent_local_ranging_counter) {
|
if (most_recent_peer_ranging_counter!=most_recent_local_ranging_counter) {
|
||||||
MODLOG_DFLT(INFO, "Ranging counter mismatch : %" PRId32 " , %" PRId32,
|
MODLOG_DFLT(INFO, "Ranging counter mismatch : %" PRId32 " , %" PRId32,
|
||||||
@@ -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) {
|
} else if (ble_svc_ras_od_val_handle == event->notify_rx.attr_handle) {
|
||||||
MODLOG_DFLT(INFO, "Received On Demand Ranging Data\n");
|
MODLOG_DFLT(INFO, "Received On Demand Ranging Data\n");
|
||||||
|
|
||||||
struct segment ras_segment;
|
|
||||||
int notif_len = OS_MBUF_PKTLEN(event->notify_rx.om);
|
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);
|
#define RAS_OD_RX_BUF_MAX 512
|
||||||
uint8_t * data= (uint8_t *)ras_segment.data;
|
if (notif_len >= sizeof(struct segment_header) && notif_len <= RAS_OD_RX_BUF_MAX) {
|
||||||
for(int i=0;i<notif_len-sizeof(struct segment_header);i++){
|
uint8_t ras_buf[RAS_OD_RX_BUF_MAX];
|
||||||
MODLOG_DFLT(INFO, "data[%d] = %d\n",i,data[i]);
|
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
|
handle the incoming notification
|
||||||
|
|||||||
@@ -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;
|
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) {
|
} else if(event->subev_result.procedure_done_status == BLE_HCI_LE_CS_SUBEVENT_DONE_STATUS_PARTIAL) {
|
||||||
ranging_subevent.type=BLE_CS_EVENT_SUBEVET_RESULT;
|
memset(&ranging_subevent, 0, sizeof(ranging_subevent));
|
||||||
ranging_subevent.subev_result= event->subev_result;
|
ranging_subevent.type = BLE_CS_EVENT_SUBEVET_RESULT;
|
||||||
|
ranging_subevent.subev_result = event->subev_result;
|
||||||
idx++;
|
idx++;
|
||||||
if (idx==1) {
|
if (idx==1) {
|
||||||
most_recent_local_ranging_counter=event->subev_result.procedure_counter;
|
most_recent_local_ranging_counter=event->subev_result.procedure_counter;
|
||||||
@@ -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");
|
MODLOG_DFLT(INFO, "LE CS Subevent Result Continue , status: Aborted\n");
|
||||||
} else if ( event->subev_result_continue.procedure_done_status == BLE_HCI_LE_CS_SUBEVENT_DONE_STATUS_COMPLETE) {
|
} else if ( event->subev_result_continue.procedure_done_status == BLE_HCI_LE_CS_SUBEVENT_DONE_STATUS_COMPLETE) {
|
||||||
MODLOG_DFLT(INFO, "LE CS Subevent Result Continue , status: Complete\n");
|
MODLOG_DFLT(INFO, "LE CS Subevent Result Continue , status: Complete\n");
|
||||||
|
ranging_subevent.type = BLE_CS_EVENT_SUBEVET_RESULT_CONTINUE;
|
||||||
ranging_subevent.subev_result_continue = event->subev_result_continue;
|
ranging_subevent.subev_result_continue = event->subev_result_continue;
|
||||||
/* To
|
/* To
|
||||||
* Get total number of CS procedure from CS enable event and then accordigly indicate to most recent ranging counter
|
* Get total number of CS procedure from CS enable event and then accordigly indicate to most recent ranging counter
|
||||||
|
|||||||
@@ -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 ble_direction_finding_antenna_init(uint8_t* gpio_array,uint8_t gpio_array_len){
|
||||||
int rc;
|
int rc;
|
||||||
// GPIO configuration
|
// 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++){
|
for (int i = 0; i < gpio_array_len; i++){
|
||||||
gpio_pin_maks |= (1ULL << gpio_array[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);
|
rc = gpio_config(&gpio_conf);
|
||||||
if(rc != 0) {
|
if(rc != 0) {
|
||||||
ESP_LOGE("DF","config fault GPIO failed");
|
ESP_LOGE("DF","config fault GPIO failed");
|
||||||
|
return rc;
|
||||||
}
|
}
|
||||||
// gpio bind signal
|
// gpio bind signal
|
||||||
for (int i = 0; i < gpio_array_len; i++){
|
for (int i = 0; i < gpio_array_len; i++){
|
||||||
|
|||||||
@@ -19,8 +19,8 @@
|
|||||||
static const char *tag = "NimBLE_CTS_CENT";
|
static const char *tag = "NimBLE_CTS_CENT";
|
||||||
static int ble_cts_cent_gap_event(struct ble_gap_event *event, void *arg);
|
static int ble_cts_cent_gap_event(struct ble_gap_event *event, void *arg);
|
||||||
|
|
||||||
static char *day_of_week[7] = {
|
static char *day_of_week[8] = {
|
||||||
"Unknown"
|
"Unknown",
|
||||||
"Monday",
|
"Monday",
|
||||||
"Tuesday",
|
"Tuesday",
|
||||||
"Wednesday",
|
"Wednesday",
|
||||||
@@ -33,10 +33,14 @@ void ble_store_config_init(void);
|
|||||||
static void ble_cts_cent_scan(void);
|
static void ble_cts_cent_scan(void);
|
||||||
|
|
||||||
void printtime(struct ble_svc_cts_curr_time ctime) {
|
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,
|
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.month,
|
||||||
ctime.et_256.d_d_t.d_t.year,
|
ctime.et_256.d_d_t.d_t.year, dow_str);
|
||||||
day_of_week[ctime.et_256.d_d_t.day_of_week]);
|
|
||||||
ESP_LOGI(tag, "hours : %d minutes : %d ",
|
ESP_LOGI(tag, "hours : %d minutes : %d ",
|
||||||
ctime.et_256.d_d_t.d_t.hours,
|
ctime.et_256.d_d_t.d_t.hours,
|
||||||
ctime.et_256.d_d_t.d_t.minutes);
|
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,
|
struct ble_gatt_attr *attr,
|
||||||
void *arg)
|
void *arg)
|
||||||
{
|
{
|
||||||
|
int rc = 0;
|
||||||
struct ble_svc_cts_curr_time ctime; /* store the read time */
|
struct ble_svc_cts_curr_time ctime; /* store the read time */
|
||||||
MODLOG_DFLT(INFO, "Read Current time complete; status=%d conn_handle=%d\n",
|
MODLOG_DFLT(INFO, "Read Current time complete; status=%d conn_handle=%d\n",
|
||||||
error->status, conn_handle);
|
error->status, conn_handle);
|
||||||
@@ -66,8 +71,12 @@ ble_cts_cent_on_read(uint16_t conn_handle,
|
|||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
MODLOG_DFLT(INFO, "\n");
|
MODLOG_DFLT(INFO, "\n");
|
||||||
ble_hs_mbuf_to_flat(attr->om, &ctime, sizeof(ctime), NULL);
|
rc = ble_hs_mbuf_to_flat(attr->om, &ctime, sizeof(ctime), NULL);
|
||||||
printtime(ctime);
|
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;
|
return 0;
|
||||||
err:
|
err:
|
||||||
/* Terminate the connection. */
|
/* 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 */
|
/* Search if cts UUID is advertised */
|
||||||
if (disc->data[offset + 1] == 0x03) {
|
if (disc->data[offset + 1] == 0x03) {
|
||||||
int temp = 2;
|
int temp = 2;
|
||||||
while(temp < disc->data[offset + 1]) {
|
while (temp < ad_struct_len) {
|
||||||
if(disc->data[offset + temp] == 0x05 &&
|
if(disc->data[offset + temp] == 0x05 &&
|
||||||
disc->data[offset + temp + 1] == 0x18) {
|
disc->data[offset + temp + 1] == 0x18) {
|
||||||
return 1;
|
return 1;
|
||||||
@@ -491,7 +500,7 @@ ble_cts_cent_gap_event(struct ble_gap_event *event, void *arg)
|
|||||||
#else
|
#else
|
||||||
#if MYNEWT_VAL(BLE_GATTC)
|
#if MYNEWT_VAL(BLE_GATTC)
|
||||||
/*** Go for service discovery after encryption has been successfully enabled ***/
|
/*** 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);
|
ble_cts_cent_on_disc_complete, NULL);
|
||||||
if (rc != 0) {
|
if (rc != 0) {
|
||||||
MODLOG_DFLT(ERROR, "Failed to discover services; rc=%d\n", rc);
|
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.status,
|
||||||
(event->cache_assoc.cache_state == 0) ? "INVALID" : "LOADED");
|
(event->cache_assoc.cache_state == 0) ? "INVALID" : "LOADED");
|
||||||
/* Perform service discovery */
|
/* 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);
|
blecent_on_disc_complete, NULL);
|
||||||
if(rc != 0) {
|
if(rc != 0) {
|
||||||
MODLOG_DFLT(ERROR, "Failed to discover services; rc=%d\n", rc);
|
MODLOG_DFLT(ERROR, "Failed to discover services; rc=%d\n", rc);
|
||||||
|
|||||||
@@ -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
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
*/
|
*/
|
||||||
@@ -16,6 +16,7 @@
|
|||||||
#include <time.h>
|
#include <time.h>
|
||||||
#include "sys/time.h"
|
#include "sys/time.h"
|
||||||
|
|
||||||
|
static const char *TAG = "CTS_GATT_SVR";
|
||||||
|
|
||||||
void
|
void
|
||||||
gatt_svr_register_cb(struct ble_gatt_register_ctxt *ctxt, void *arg)
|
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) {
|
int set_current_time(struct ble_svc_cts_curr_time ctime) {
|
||||||
time_t now;
|
time_t now;
|
||||||
struct tm timeinfo;
|
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 */
|
/* fill date_time */
|
||||||
timeinfo.tm_year= ctime.et_256.d_d_t.d_t.year - 1900 ;
|
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;
|
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_sec = ctime.et_256.d_d_t.d_t.seconds;
|
||||||
timeinfo.tm_wday = ctime.et_256.d_d_t.day_of_week - 1;
|
timeinfo.tm_wday = ctime.et_256.d_d_t.day_of_week - 1;
|
||||||
now = mktime(&timeinfo);
|
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_sec = now;
|
||||||
|
tv_now.tv_usec = 0;
|
||||||
settimeofday(&tv_now, NULL);
|
settimeofday(&tv_now, NULL);
|
||||||
/* set the last updated */
|
/* set the last updated */
|
||||||
gettimeofday(&last_updated, NULL);
|
gettimeofday(&last_updated, NULL);
|
||||||
|
|||||||
@@ -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));
|
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));
|
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, 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);
|
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");
|
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:
|
err:
|
||||||
/* Terminate the connection. */
|
/* 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);
|
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) {
|
switch (op) {
|
||||||
case BLE_GAP_ENC_ADV_DATA:
|
case BLE_GAP_ENC_ADV_DATA:
|
||||||
enc_data = (uint8_t *) malloc (sizeof(uint8_t) * len);
|
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(enc_data, data + offset + 2, len);
|
||||||
|
|
||||||
memcpy(&key_ead.peer_addr.val, peer_addr, PEER_ADDR_VAL_SIZE);
|
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");
|
MODLOG_DFLT(INFO, "Decryption of adv data done successfully");
|
||||||
} else {
|
} else {
|
||||||
MODLOG_DFLT(INFO, "Decryption of adv data failed");
|
MODLOG_DFLT(INFO, "Decryption of adv data failed");
|
||||||
|
free(enc_data);
|
||||||
return 0;
|
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, "0x%02X ", temp[i]);
|
||||||
}
|
}
|
||||||
MODLOG_DFLT(INFO, "\n");
|
MODLOG_DFLT(INFO, "\n");
|
||||||
|
free(enc_data);
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
|||||||
@@ -68,8 +68,8 @@ enc_adv_data_prph_print_conn_desc(struct ble_gap_conn_desc *desc)
|
|||||||
desc->sec_state.bonded);
|
desc->sec_state.bonded);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static int
|
||||||
enc_adv_data_prph_encrypt_set(uint8_t * out_encrypted_adv_data,
|
enc_adv_data_prph_encrypt_set(uint8_t *out_encrypted_adv_data,
|
||||||
const unsigned encrypted_adv_data_len)
|
const unsigned encrypted_adv_data_len)
|
||||||
{
|
{
|
||||||
int rc;
|
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);
|
print_bytes(unencrypted_adv_data, unencrypted_adv_data_len);
|
||||||
MODLOG_DFLT(INFO, "\n");
|
MODLOG_DFLT(INFO, "\n");
|
||||||
|
|
||||||
rc = ble_ead_encrypt(km.session_key, km.iv, unencrypted_adv_data, unencrypted_adv_data_len, encrypted_adv_data);
|
rc = ble_ead_encrypt(km.session_key, km.iv, unencrypted_adv_data,
|
||||||
if (rc == 0) {
|
unencrypted_adv_data_len, encrypted_adv_data);
|
||||||
MODLOG_DFLT(INFO, "Encryption of adv data done successfully");
|
if (rc != 0) {
|
||||||
} else {
|
MODLOG_DFLT(ERROR, "Encryption of adv data failed; rc=%d", rc);
|
||||||
MODLOG_DFLT(INFO, "Encryption of adv data failed");
|
return rc;
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
MODLOG_DFLT(INFO, "Encryption of adv data done successfully");
|
||||||
|
|
||||||
MODLOG_DFLT(INFO, "Data after encryption:");
|
MODLOG_DFLT(INFO, "Data after encryption:");
|
||||||
print_bytes(encrypted_adv_data, encrypted_adv_data_len);
|
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 */
|
/** Contains Randomiser ## Encrypted Advertising Data ## MIC */
|
||||||
memcpy(out_encrypted_adv_data, encrypted_adv_data, encrypted_adv_data_len);
|
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_gap_adv_params params;
|
||||||
struct ble_hs_adv_fields fields;
|
struct ble_hs_adv_fields fields;
|
||||||
uint8_t own_addr_type;
|
|
||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
const unsigned encrypted_adv_data_len = BLE_EAD_ENCRYPTED_PAYLOAD_SIZE(sizeof(unencrypted_adv_pattern));
|
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;
|
fields.uuids16_is_complete = 1;
|
||||||
|
|
||||||
/** Getting the encrypted advertising data */
|
/** 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 = encrypted_adv_data;
|
||||||
fields.enc_adv_data_len = encrypted_adv_data_len;
|
fields.enc_adv_data_len = encrypted_adv_data_len;
|
||||||
|
|||||||
@@ -21,9 +21,20 @@ static bool client_connect = 0;
|
|||||||
|
|
||||||
static int gatt_svr_access_cb(uint16_t conn_handle, uint16_t attr_handle,
|
static int gatt_svr_access_cb(uint16_t conn_handle, uint16_t attr_handle,
|
||||||
struct ble_gatt_access_ctxt *ctxt, void *arg) {
|
struct ble_gatt_access_ctxt *ctxt, void *arg) {
|
||||||
|
int rc = 0;
|
||||||
if (ctxt->op == BLE_GATT_ACCESS_OP_READ_CHR) {
|
if (ctxt->op == BLE_GATT_ACCESS_OP_READ_CHR) {
|
||||||
static uint8_t data[1] = {42}; // Example value
|
static uint8_t data[1] = {42}; // Example value
|
||||||
os_mbuf_append(ctxt->om, data, sizeof(data));
|
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;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -162,6 +162,10 @@ ble_htp_cent_on_read(uint16_t conn_handle,
|
|||||||
uint16_t value;
|
uint16_t value;
|
||||||
int rc;
|
int rc;
|
||||||
const struct peer *peer = peer_find(conn_handle);
|
const struct peer *peer = peer_find(conn_handle);
|
||||||
|
if (peer == NULL) {
|
||||||
|
MODLOG_DFLT(ERROR, "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,
|
chr = peer_chr_find_uuid(peer,
|
||||||
BLE_UUID16_DECLARE(BLE_SVC_HTP_UUID16),
|
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 */
|
/* Conversion */
|
||||||
for (int i=0; i<6; i++) {
|
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) {
|
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
|
/* The device has to advertise support for the Health thermometer
|
||||||
* service (0x1809).
|
* service (0x1809).
|
||||||
*/
|
*/
|
||||||
do {
|
while (offset < disc->length_data) {
|
||||||
|
|
||||||
ad_struct_len = disc->data[offset];
|
ad_struct_len = disc->data[offset];
|
||||||
|
|
||||||
if (!ad_struct_len) {
|
if (ad_struct_len == 0 || offset + ad_struct_len + 1 > disc->length_data) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Search if HTP UUID is advertised */
|
/* Search if HTP UUID is advertised */
|
||||||
if (disc->data[offset] == 0x03 && disc->data[offset + 1] == 0x03) {
|
if (disc->data[offset + 1] == 0x03) {
|
||||||
if ( disc->data[offset + 2] == 0x18 && disc->data[offset + 3] == 0x09 ) {
|
if (disc->data[offset + 2] == 0x09 && disc->data[offset + 3] == 0x18) {
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
offset += ad_struct_len + 1;
|
offset += ad_struct_len + 1;
|
||||||
|
}
|
||||||
} while ( offset < disc->length_data );
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -605,7 +609,7 @@ ble_htp_cent_gap_event(struct ble_gap_event *event, void *arg)
|
|||||||
#else
|
#else
|
||||||
#if MYNEWT_VAL(BLE_GATTC)
|
#if MYNEWT_VAL(BLE_GATTC)
|
||||||
/*** Go for service discovery after encryption has been successfully enabled ***/
|
/*** 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);
|
ble_htp_cent_on_disc_complete, NULL);
|
||||||
if (rc != 0) {
|
if (rc != 0) {
|
||||||
MODLOG_DFLT(ERROR, "Failed to discover services; rc=%d\n", rc);
|
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.status,
|
||||||
(event->cache_assoc.cache_state == 0) ? "INVALID" : "LOADED");
|
(event->cache_assoc.cache_state == 0) ? "INVALID" : "LOADED");
|
||||||
/* Perform service discovery */
|
/* 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);
|
blecent_on_disc_complete, NULL);
|
||||||
if(rc != 0) {
|
if(rc != 0) {
|
||||||
MODLOG_DFLT(ERROR, "Failed to discover services; rc=%d\n", rc);
|
MODLOG_DFLT(ERROR, "Failed to discover services; rc=%d\n", rc);
|
||||||
|
|||||||
@@ -44,6 +44,8 @@ blecent_l2cap_coc_send_data(struct ble_l2cap_chan *chan)
|
|||||||
int rc = 0;
|
int rc = 0;
|
||||||
int len = 512;
|
int len = 512;
|
||||||
uint8_t value[len];
|
uint8_t value[len];
|
||||||
|
int retry = 0;
|
||||||
|
const int max_retry = 10;
|
||||||
|
|
||||||
for (int i = 0; i < len; i++) {
|
for (int i = 0; i < len; i++) {
|
||||||
value[i] = 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);
|
sdu_rx_data = os_mbuf_get_pkthdr(&sdu_os_mbuf_pool, 0);
|
||||||
if (sdu_rx_data == NULL) {
|
if (sdu_rx_data == NULL) {
|
||||||
vTaskDelay(10 / portTICK_PERIOD_MS);
|
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);
|
os_mbuf_append(sdu_rx_data, value, len);
|
||||||
|
|
||||||
print_mbuf_data(sdu_rx_data);
|
print_mbuf_data(sdu_rx_data);
|
||||||
|
|
||||||
rc = ble_l2cap_send(chan, 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);
|
vTaskDelay(100 / portTICK_PERIOD_MS);
|
||||||
rc = ble_l2cap_send(chan, sdu_rx_data);
|
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) {
|
if (rc == 0) {
|
||||||
MODLOG_DFLT(INFO, "Data sent successfully");
|
MODLOG_DFLT(INFO, "Data sent successfully");
|
||||||
} else {
|
} 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
|
* 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.
|
* 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)
|
blecent_l2cap_coc_on_disc_complete(const struct peer *peer, int status, void *arg)
|
||||||
{
|
{
|
||||||
uint16_t psm = 0x1002;
|
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);
|
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,
|
if (sdu_rx == NULL) {
|
||||||
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).
|
/* The device has to advertise support for L2CAP COC UUID (0x1812).
|
||||||
*/
|
*/
|
||||||
do {
|
do {
|
||||||
|
if (offset + 1 > disc->length_data) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
ad_struct_len = disc->data[offset];
|
ad_struct_len = disc->data[offset];
|
||||||
|
|
||||||
if (!ad_struct_len) {
|
if (!ad_struct_len) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Search if ANS UUID is advertised */
|
if (offset + ad_struct_len + 1 > disc->length_data) {
|
||||||
if (disc->data[offset] == 0x03 && disc->data[offset + 1] == 0x03) {
|
break;
|
||||||
if ( disc->data[offset + 2] == 0x18 && disc->data[offset + 3] == 0x12 ) {
|
}
|
||||||
return 1;
|
|
||||||
}
|
/* 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;
|
offset += ad_struct_len + 1;
|
||||||
|
|
||||||
} while ( offset < disc->length_data );
|
} while (offset < disc->length_data);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
|
|||||||
@@ -340,6 +340,9 @@ bleprph_gap_event(struct ble_gap_event *event, void *arg)
|
|||||||
bleprph_print_conn_desc(&desc);
|
bleprph_print_conn_desc(&desc);
|
||||||
#if MYNEWT_VAL(BLE_L2CAP_COC_MAX_NUM) >= 1
|
#if MYNEWT_VAL(BLE_L2CAP_COC_MAX_NUM) >= 1
|
||||||
rc = ble_l2cap_create_server(psm, MTU, bleprph_l2cap_coc_event_cb, NULL);
|
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
|
#endif
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
|
|||||||
@@ -13,6 +13,8 @@
|
|||||||
#include "services/gatt/ble_svc_gatt.h"
|
#include "services/gatt/ble_svc_gatt.h"
|
||||||
#include "multi_adv.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 =
|
static const ble_uuid128_t gatt_svr_svc_uuid =
|
||||||
BLE_UUID128_INIT(0x2d, 0x71, 0xa2, 0x59, 0xb4, 0x58, 0xc8, 0x12,
|
BLE_UUID128_INIT(0x2d, 0x71, 0xa2, 0x59, 0xb4, 0x58, 0xc8, 0x12,
|
||||||
0x99, 0x99, 0x43, 0x95, 0x12, 0x2f, 0x46, 0x59);
|
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,
|
gatt_svc_access(uint16_t conn_handle, uint16_t attr_handle,
|
||||||
struct ble_gatt_access_ctxt *ctxt, void *arg)
|
struct ble_gatt_access_ctxt *ctxt, void *arg)
|
||||||
{
|
{
|
||||||
|
int rc = 0;
|
||||||
switch (ctxt->op) {
|
switch (ctxt->op) {
|
||||||
case BLE_GATT_ACCESS_OP_READ_CHR:
|
case BLE_GATT_ACCESS_OP_READ_CHR:
|
||||||
MODLOG_DFLT(INFO, "Characteristic read; conn_handle=%d attr_handle=%d\n",
|
MODLOG_DFLT(INFO, "Characteristic read; conn_handle=%d attr_handle=%d\n",
|
||||||
conn_handle, attr_handle);
|
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:
|
case BLE_GATT_ACCESS_OP_WRITE_CHR:
|
||||||
MODLOG_DFLT(INFO, "Characteristic write; conn_handle=%d attr_handle=%d",
|
MODLOG_DFLT(INFO, "Characteristic write; conn_handle=%d attr_handle=%d",
|
||||||
conn_handle, attr_handle);
|
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:
|
case BLE_GATT_ACCESS_OP_READ_DSC:
|
||||||
MODLOG_DFLT(INFO, "Descriptor read; conn_handle=%d attr_handle=%d\n",
|
MODLOG_DFLT(INFO, "Descriptor read; conn_handle=%d attr_handle=%d\n",
|
||||||
conn_handle, attr_handle);
|
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:
|
case BLE_GATT_ACCESS_OP_WRITE_DSC:
|
||||||
goto unknown;
|
goto unknown;
|
||||||
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
goto unknown;
|
goto unknown;
|
||||||
|
|||||||
@@ -70,6 +70,7 @@ gap_event_cb(struct ble_gap_event *event, void *arg)
|
|||||||
uint8_t adv_handle;
|
uint8_t adv_handle;
|
||||||
uint8_t subevent;
|
uint8_t subevent;
|
||||||
uint8_t phy_mask;
|
uint8_t phy_mask;
|
||||||
|
uint8_t actual_sent = 0;
|
||||||
|
|
||||||
switch (event->type) {
|
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);
|
event->periodic_adv_subev_data_req.subevent_data_count);
|
||||||
|
|
||||||
sent_num = 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++) {
|
for (uint8_t i = 0; i < sent_num; i++) {
|
||||||
data = os_msys_get_pkthdr(BLE_PAWR_SUB_DATA_LEN, 0);
|
data = os_msys_get_pkthdr(BLE_PAWR_SUB_DATA_LEN, 0);
|
||||||
if (!data) {
|
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;
|
break;
|
||||||
}
|
}
|
||||||
sub = (i + event->periodic_adv_subev_data_req.subevent_start) % BLE_PAWR_NUM_SUBEVTS;
|
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);
|
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].subevent = sub;
|
||||||
sub_data_params[i].response_slot_start = 0;
|
sub_data_params[i].response_slot_start = 0;
|
||||||
sub_data_params[i].response_slot_count = BLE_PAWR_NUM_RSP_SLOTS;
|
sub_data_params[i].response_slot_count = BLE_PAWR_NUM_RSP_SLOTS;
|
||||||
sub_data_params[i].data = data;
|
sub_data_params[i].data = data;
|
||||||
sub_data_pattern[0]++;
|
sub_data_pattern[0]++;
|
||||||
|
actual_sent++;
|
||||||
}
|
}
|
||||||
|
if (actual_sent > 0) {
|
||||||
rc = ble_gap_set_periodic_adv_subev_data(event->periodic_adv_subev_data_req.adv_handle,
|
rc = ble_gap_set_periodic_adv_subev_data(event->periodic_adv_subev_data_req.adv_handle,
|
||||||
sent_num, sub_data_params);
|
actual_sent, sub_data_params);
|
||||||
if (rc) {
|
if (rc) {
|
||||||
ESP_LOGE(TAG, "Failed to set Subevent Data, rc = 0x%x", rc);
|
ESP_LOGE(TAG, "Failed to set Subevent Data, rc = 0x%x", rc);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
|||||||
@@ -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
|
* 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));
|
struct ble_gap_ext_disc_desc *disc = ((struct ble_gap_ext_disc_desc *)(&event->ext_disc));
|
||||||
if (disc->sid == 2 && synced == 0) {
|
if (disc->sid == 2 && synced == 0) {
|
||||||
synced++;
|
synced++;
|
||||||
const ble_addr_t addr;
|
ble_addr_t addr;
|
||||||
uint8_t adv_sid;
|
uint8_t adv_sid;
|
||||||
struct ble_gap_periodic_sync_params params;
|
struct ble_gap_periodic_sync_params params;
|
||||||
int rc;
|
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));
|
memcpy(&adv_sid, &disc->sid, sizeof(disc->sid));
|
||||||
params.skip = 10;
|
params.skip = 10;
|
||||||
params.sync_timeout = 1000;
|
params.sync_timeout = 1000;
|
||||||
|
|||||||
@@ -236,6 +236,7 @@ ext_blecent_should_connect(const struct ble_gap_ext_disc_desc *disc)
|
|||||||
int ad_struct_len = 0;
|
int ad_struct_len = 0;
|
||||||
uint8_t test_addr[6];
|
uint8_t test_addr[6];
|
||||||
uint32_t peer_addr[6];
|
uint32_t peer_addr[6];
|
||||||
|
uint8_t type = 0;
|
||||||
|
|
||||||
memset(peer_addr, 0x0, sizeof peer_addr);
|
memset(peer_addr, 0x0, sizeof peer_addr);
|
||||||
|
|
||||||
@@ -252,7 +253,7 @@ ext_blecent_should_connect(const struct ble_gap_ext_disc_desc *disc)
|
|||||||
|
|
||||||
/* Conversion */
|
/* Conversion */
|
||||||
for (int i=0; i<6; i++) {
|
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) {
|
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 {
|
do {
|
||||||
ad_struct_len = disc->data[offset];
|
ad_struct_len = disc->data[offset];
|
||||||
|
if (!ad_struct_len || (offset + ad_struct_len + 1 > disc->length_data)) {
|
||||||
if (!ad_struct_len) {
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
type = disc->data[offset + 1];
|
||||||
/* Search if LE PHY UUID is advertised */
|
if ((type == 0x02 || type == 0x03) && ad_struct_len >= 3) {
|
||||||
if (disc->data[offset] == 0x03 && disc->data[offset + 1] == 0x03) {
|
/* Scan UUID bytes for LE_PHY_UUID16 (little-endian: 0xF2 0xAB) */
|
||||||
if ( disc->data[offset + 2] == 0xAB && disc->data[offset + 3] == 0xF2 ) {
|
for (int i = 2; i + 1 < ad_struct_len; i += 2) {
|
||||||
return 1;
|
if (disc->data[offset + i] == 0xF2 && disc->data[offset + i + 1] == 0xAB) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
offset += ad_struct_len + 1;
|
offset += ad_struct_len + 1;
|
||||||
|
} while (offset < disc->length_data);
|
||||||
} while ( offset < disc->length_data );
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -484,42 +484,37 @@ blecent_on_sync(void)
|
|||||||
rc = ble_hs_util_ensure_addr(0);
|
rc = ble_hs_util_ensure_addr(0);
|
||||||
assert(rc == 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;
|
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);
|
set_default_le_phy(all_phy, all_phy);
|
||||||
|
|
||||||
if (s_current_phy != BLE_HCI_LE_PHY_1M_PREF_MASK) {
|
if (strlen(CONFIG_EXAMPLE_PEER_ADDR) &&
|
||||||
/* Check if peer address is set in EXAMPLE_PEER_ADDR */
|
(strncmp(CONFIG_EXAMPLE_PEER_ADDR, "ADDR_ANY", strlen("ADDR_ANY")) != 0)) {
|
||||||
if (strlen(CONFIG_EXAMPLE_PEER_ADDR) &&
|
/* User wants to connect on 2M or coded phy directly */
|
||||||
(strncmp(CONFIG_EXAMPLE_PEER_ADDR, "ADDR_ANY", strlen("ADDR_ANY")) != 0)) {
|
sscanf(CONFIG_EXAMPLE_PEER_ADDR, "%lx:%lx:%lx:%lx:%lx:%lx",
|
||||||
/* User wants to connect on 2M or coded phy directly */
|
&peer_addr[5], &peer_addr[4], &peer_addr[3],
|
||||||
sscanf(CONFIG_EXAMPLE_PEER_ADDR, "%lx:%lx:%lx:%lx:%lx:%lx",
|
&peer_addr[2], &peer_addr[1], &peer_addr[0]);
|
||||||
&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++) {
|
for (int i=0; i<6; i++) {
|
||||||
test_addr[i] = (uint8_t )peer_addr[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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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 {
|
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();
|
blecent_scan();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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
|
* 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:
|
case BLE_GATT_ACCESS_OP_WRITE_CHR:
|
||||||
len = OS_MBUF_PKTLEN(ctxt->om);
|
len = OS_MBUF_PKTLEN(ctxt->om);
|
||||||
if (len > 0) {
|
if (len == 0) {
|
||||||
le_phy_val = (uint8_t *)malloc(len * sizeof(uint8_t));
|
return BLE_ATT_ERR_INVALID_ATTR_VALUE_LEN;
|
||||||
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");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
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:
|
default:
|
||||||
break;
|
return BLE_ATT_ERR_UNLIKELY;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -70,7 +70,10 @@ ble_prox_cent_on_write(uint16_t conn_handle,
|
|||||||
const struct peer_chr *chr;
|
const struct peer_chr *chr;
|
||||||
int rc;
|
int rc;
|
||||||
const struct peer *peer = peer_find(conn_handle);
|
const struct peer *peer = peer_find(conn_handle);
|
||||||
|
if (peer == NULL) {
|
||||||
|
MODLOG_DFLT(ERROR, "Error: peer not found for conn_handle=%d", conn_handle);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
chr = peer_chr_find_uuid(peer,
|
chr = peer_chr_find_uuid(peer,
|
||||||
BLE_UUID16_DECLARE(BLE_SVC_TX_POWER_UUID16),
|
BLE_UUID16_DECLARE(BLE_SVC_TX_POWER_UUID16),
|
||||||
BLE_UUID16_DECLARE(BLE_SVC_PROX_CHR_UUID16_TX_PWR_LVL));
|
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 */
|
/* Conversion */
|
||||||
for (int i=0; i<6; i++) {
|
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) {
|
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 */
|
/* Search if Proximity Sensor (Link loss) UUID is advertised */
|
||||||
if (disc->data[offset] == 0x03 && disc->data[offset + 1] == 0x03) {
|
if (disc->data[offset + 1] == 0x03) {
|
||||||
if ( disc->data[offset + 2] == 0x18 && disc->data[offset + 3] == 0x03 ) {
|
int uuid_offset = offset + 2;
|
||||||
return 1;
|
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
|
#else
|
||||||
#if MYNEWT_VAL(BLE_GATTC)
|
#if MYNEWT_VAL(BLE_GATTC)
|
||||||
/*** Go for service discovery after encryption has been successfully enabled ***/
|
/*** 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);
|
ble_prox_cent_on_disc_complete, NULL);
|
||||||
if (rc != 0) {
|
if (rc != 0) {
|
||||||
MODLOG_DFLT(ERROR, "Failed to discover services; rc=%d\n", rc);
|
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.status,
|
||||||
(event->cache_assoc.cache_state == 0) ? "INVALID" : "LOADED");
|
(event->cache_assoc.cache_state == 0) ? "INVALID" : "LOADED");
|
||||||
/* Perform service discovery */
|
/* 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);
|
blecent_on_disc_complete, NULL);
|
||||||
if(rc != 0) {
|
if(rc != 0) {
|
||||||
MODLOG_DFLT(ERROR, "Failed to discover services; rc=%d\n", rc);
|
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
|
void
|
||||||
ble_prox_cent_path_loss_task(void *pvParameters)
|
ble_prox_cent_path_loss_task(void *pvParameters)
|
||||||
{
|
{
|
||||||
int8_t rssi;
|
int8_t rssi = 0;
|
||||||
int rc;
|
int rc;
|
||||||
int path_loss;
|
int path_loss;
|
||||||
|
|
||||||
@@ -685,7 +694,10 @@ ble_prox_cent_link_loss_task(void *pvParameters)
|
|||||||
while (1) {
|
while (1) {
|
||||||
for (int i = 0; i <= MYNEWT_VAL(BLE_MAX_CONNECTIONS); i++) {
|
for (int i = 0; i <= MYNEWT_VAL(BLE_MAX_CONNECTIONS); i++) {
|
||||||
if (disconn_peer[i].link_lost && disconn_peer[i].addr != NULL) {
|
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);
|
vTaskDelay(5000 / portTICK_PERIOD_MS);
|
||||||
|
|||||||
@@ -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;
|
QueueHandle_t spp_common_uart_queue = NULL;
|
||||||
void ble_store_config_init(void);
|
void ble_store_config_init(void);
|
||||||
uint16_t attribute_handle[CONFIG_BT_NIMBLE_MAX_CONNECTIONS + 1];
|
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 void ble_spp_client_scan(void);
|
||||||
static ble_addr_t connected_addr[CONFIG_BT_NIMBLE_MAX_CONNECTIONS + 1];
|
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,
|
chr = peer_chr_find_uuid(peer,
|
||||||
BLE_UUID16_DECLARE(GATT_SPP_SVC_UUID),
|
BLE_UUID16_DECLARE(GATT_SPP_SVC_UUID),
|
||||||
BLE_UUID16_DECLARE(GATT_SPP_CHR_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;
|
attribute_handle[peer->conn_handle] = chr->chr.val_handle;
|
||||||
MODLOG_DFLT(INFO, "attribute_handle %x\n", attribute_handle[peer->conn_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,
|
dsc = peer_dsc_find_uuid(peer,
|
||||||
BLE_UUID16_DECLARE(GATT_SPP_SVC_UUID),
|
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 ");
|
MODLOG_DFLT(INFO, "Connection established ");
|
||||||
rc = ble_gap_conn_find(event->connect.conn_handle, &desc);
|
rc = ble_gap_conn_find(event->connect.conn_handle, &desc);
|
||||||
assert(rc == 0);
|
assert(rc == 0);
|
||||||
memcpy(&connected_addr[event->connect.conn_handle].val, desc.peer_id_addr.val,
|
if (event->connect.conn_handle <= CONFIG_BT_NIMBLE_MAX_CONNECTIONS) {
|
||||||
PEER_ADDR_VAL_SIZE);
|
memcpy(&connected_addr[event->connect.conn_handle].val, desc.peer_id_addr.val,
|
||||||
|
PEER_ADDR_VAL_SIZE);
|
||||||
|
}
|
||||||
print_conn_desc(&desc);
|
print_conn_desc(&desc);
|
||||||
MODLOG_DFLT(INFO, "\n");
|
MODLOG_DFLT(INFO, "\n");
|
||||||
|
|
||||||
@@ -333,7 +347,13 @@ ble_spp_client_gap_event(struct ble_gap_event *event, void *arg)
|
|||||||
|
|
||||||
/* Forget about peer. */
|
/* Forget about peer. */
|
||||||
memset(&connected_addr[event->disconnect.conn.conn_handle].val, 0, PEER_ADDR_VAL_SIZE);
|
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;
|
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);
|
peer_delete(event->disconnect.conn.conn_handle);
|
||||||
|
|
||||||
/* Resume scanning. */
|
/* Resume scanning. */
|
||||||
@@ -422,19 +442,39 @@ void ble_client_uart_task(void *pvParameters)
|
|||||||
}
|
}
|
||||||
memset(temp, 0x0, event.size);
|
memset(temp, 0x0, event.size);
|
||||||
uart_read_bytes(UART_NUM_0, temp, event.size, portMAX_DELAY);
|
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 (attribute_handle[i] != 0) {
|
||||||
#if MYNEWT_VAL(BLE_GATTC)
|
valid_conns[valid_count].conn_handle = i;
|
||||||
rc = ble_gattc_write_flat(i, attribute_handle[i], temp, event.size, NULL, NULL);
|
valid_conns[valid_count].attr_handle = attribute_handle[i];
|
||||||
if (rc == 0) {
|
valid_count++;
|
||||||
ESP_LOGI(tag, "Write in uart task success!");
|
|
||||||
} else {
|
|
||||||
ESP_LOGI(tag, "Error in writing characteristic rc=%d", rc);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
vTaskDelay(10);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
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);
|
free(temp);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@@ -484,6 +524,13 @@ app_main(void)
|
|||||||
return;
|
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 */
|
/* Initialize UART driver and start uart task */
|
||||||
ble_spp_uart_init();
|
ble_spp_uart_init();
|
||||||
|
|
||||||
|
|||||||
@@ -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);
|
ble_spp_server_print_conn_desc(&event->disconnect.conn);
|
||||||
MODLOG_DFLT(INFO, "\n");
|
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. */
|
/* Connection terminated; resume advertising. */
|
||||||
ble_spp_server_advertise();
|
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.cur_notify,
|
||||||
event->subscribe.prev_indicate,
|
event->subscribe.prev_indicate,
|
||||||
event->subscribe.cur_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;
|
return 0;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
@@ -360,6 +364,10 @@ void ble_server_uart_task(void *pvParameters)
|
|||||||
if (event.size) {
|
if (event.size) {
|
||||||
uint8_t *ntf;
|
uint8_t *ntf;
|
||||||
ntf = (uint8_t *)malloc(sizeof(uint8_t) * event.size);
|
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);
|
memset(ntf, 0x00, event.size);
|
||||||
uart_read_bytes(UART_NUM_0, ntf, event.size, portMAX_DELAY);
|
uart_read_bytes(UART_NUM_0, ntf, event.size, portMAX_DELAY);
|
||||||
|
|
||||||
|
|||||||
@@ -121,6 +121,10 @@ blecent_on_custom_write(uint16_t conn_handle,
|
|||||||
error->status, conn_handle, attr->handle);
|
error->status, conn_handle, attr->handle);
|
||||||
|
|
||||||
peer = peer_find(conn_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,
|
chr = peer_chr_find_uuid(peer,
|
||||||
remote_svc_uuid,
|
remote_svc_uuid,
|
||||||
remote_chr_uuid);
|
remote_chr_uuid);
|
||||||
@@ -257,6 +261,7 @@ blecent_on_subscribe(uint16_t conn_handle,
|
|||||||
if (peer == NULL) {
|
if (peer == NULL) {
|
||||||
MODLOG_DFLT(ERROR, "Error in finding peer, aborting...");
|
MODLOG_DFLT(ERROR, "Error in finding peer, aborting...");
|
||||||
ble_gap_terminate(conn_handle, BLE_ERR_REM_USER_CONN_TERM);
|
ble_gap_terminate(conn_handle, BLE_ERR_REM_USER_CONN_TERM);
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
/* Subscribe to, write to, and read the custom characteristic*/
|
/* Subscribe to, write to, and read the custom characteristic*/
|
||||||
blecent_custom_gatt_operations(peer);
|
blecent_custom_gatt_operations(peer);
|
||||||
@@ -286,7 +291,10 @@ blecent_on_write(uint16_t conn_handle,
|
|||||||
uint8_t value[2];
|
uint8_t value[2];
|
||||||
int rc;
|
int rc;
|
||||||
const struct peer *peer = peer_find(conn_handle);
|
const struct peer *peer = peer_find(conn_handle);
|
||||||
|
if (peer == NULL) {
|
||||||
|
MODLOG_DFLT(ERROR, "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,
|
dsc = peer_dsc_find_uuid(peer,
|
||||||
BLE_UUID16_DECLARE(BLECENT_SVC_ALERT_UUID),
|
BLE_UUID16_DECLARE(BLECENT_SVC_ALERT_UUID),
|
||||||
BLE_UUID16_DECLARE(BLECENT_CHR_UNR_ALERT_STAT_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];
|
uint8_t value[2];
|
||||||
int rc;
|
int rc;
|
||||||
const struct peer *peer = peer_find(conn_handle);
|
const struct peer *peer = peer_find(conn_handle);
|
||||||
|
if (peer == NULL) {
|
||||||
|
MODLOG_DFLT(ERROR, "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,
|
chr = peer_chr_find_uuid(peer,
|
||||||
BLE_UUID16_DECLARE(BLECENT_SVC_ALERT_UUID),
|
BLE_UUID16_DECLARE(BLECENT_SVC_ALERT_UUID),
|
||||||
BLE_UUID16_DECLARE(BLECENT_CHR_ALERT_NOT_CTRL_PT));
|
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.status,
|
||||||
(event->cache_assoc.cache_state == 0) ? "INVALID" : "LOADED");
|
(event->cache_assoc.cache_state == 0) ? "INVALID" : "LOADED");
|
||||||
/* Perform service discovery */
|
/* 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);
|
blecent_on_disc_complete, NULL);
|
||||||
if(rc != 0) {
|
if(rc != 0) {
|
||||||
MODLOG_DFLT(ERROR, "Failed to discover services; rc=%d\n", rc);
|
MODLOG_DFLT(ERROR, "Failed to discover services; rc=%d\n", rc);
|
||||||
|
|||||||
@@ -191,6 +191,9 @@ gatt_svr_chr_access_sc_control_point(uint16_t conn_handle,
|
|||||||
|
|
||||||
/* Allocate response buffer */
|
/* Allocate response buffer */
|
||||||
om_indication = ble_hs_mbuf_att_pkt();
|
om_indication = ble_hs_mbuf_att_pkt();
|
||||||
|
if (om_indication == NULL) {
|
||||||
|
return BLE_HS_ENOMEM;
|
||||||
|
}
|
||||||
|
|
||||||
switch(op_code){
|
switch(op_code){
|
||||||
#if (CSC_FEATURES & CSC_FEATURE_WHEEL_REV_DATA)
|
#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),
|
sizeof(new_cumulative_wheel_rev_arr),
|
||||||
new_cumulative_wheel_rev_arr);
|
new_cumulative_wheel_rev_arr);
|
||||||
if (rc != 0){
|
if (rc != 0){
|
||||||
|
os_mbuf_free_chain(om_indication);
|
||||||
return BLE_ATT_ERR_INVALID_ATTR_VALUE_LEN;
|
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*/
|
/* Read new sensor location value*/
|
||||||
rc = os_mbuf_copydata(ctxt->om, 1, 1, &new_sensor_location);
|
rc = os_mbuf_copydata(ctxt->om, 1, 1, &new_sensor_location);
|
||||||
if (rc != 0){
|
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));
|
rc = os_mbuf_append(om_indication, &response, sizeof(response));
|
||||||
|
|
||||||
if (rc != 0){
|
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)
|
#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){
|
if (op_code == SC_CP_OP_REQ_SUPPORTED_SENSOR_LOCATIONS){
|
||||||
rc = os_mbuf_append(om_indication, &csc_supported_sensor_locations,
|
rc = os_mbuf_append(om_indication, &csc_supported_sensor_locations,
|
||||||
sizeof(csc_supported_sensor_locations));
|
sizeof(csc_supported_sensor_locations));
|
||||||
}
|
if (rc != 0){
|
||||||
|
os_mbuf_free_chain(om_indication);
|
||||||
if (rc != 0){
|
return BLE_ATT_ERR_INSUFFICIENT_RES;
|
||||||
return BLE_ATT_ERR_INSUFFICIENT_RES;
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
rc = ble_gatts_indicate_custom(conn_handle, csc_control_point_handle,
|
rc = ble_gatts_indicate_custom(conn_handle, csc_control_point_handle,
|
||||||
om_indication);
|
om_indication);
|
||||||
|
if (rc != 0) {
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
|
||||||
return rc;
|
return rc;
|
||||||
|
|
||||||
|
done:
|
||||||
|
os_mbuf_free_chain(om_indication);
|
||||||
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
|
|||||||
@@ -200,6 +200,9 @@ blehr_gap_event(struct ble_gap_event *event, void *arg)
|
|||||||
case BLE_GAP_EVENT_DISCONNECT:
|
case BLE_GAP_EVENT_DISCONNECT:
|
||||||
MODLOG_DFLT(INFO, "disconnect; reason=%d\n", event->disconnect.reason);
|
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 */
|
/* Connection terminated; resume advertising */
|
||||||
blehr_advertise();
|
blehr_advertise();
|
||||||
break;
|
break;
|
||||||
|
|||||||
@@ -245,7 +245,9 @@ bleprph_gap_event(struct ble_gap_event *event, void *arg)
|
|||||||
}
|
}
|
||||||
|
|
||||||
#if MYNEWT_VAL(BLE_POWER_CONTROL)
|
#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
|
#endif
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
@@ -497,6 +499,7 @@ app_main(void)
|
|||||||
ret = nimble_port_init();
|
ret = nimble_port_init();
|
||||||
if (ret != ESP_OK) {
|
if (ret != ESP_OK) {
|
||||||
ESP_LOGE(tag, "Failed to init nimble %d ", ret);
|
ESP_LOGE(tag, "Failed to init nimble %d ", ret);
|
||||||
|
hci_uart_close();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
/* Initialize the NimBLE host configuration. */
|
/* Initialize the NimBLE host configuration. */
|
||||||
|
|||||||
@@ -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
|
* SPDX-License-Identifier: Unlicense OR CC0-1.0
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
#include <stdbool.h>
|
||||||
#include "freertos/FreeRTOS.h"
|
#include "freertos/FreeRTOS.h"
|
||||||
#include "freertos/task.h"
|
#include "freertos/task.h"
|
||||||
#include "freertos/queue.h"
|
#include "freertos/queue.h"
|
||||||
@@ -44,6 +45,7 @@ enum {
|
|||||||
};
|
};
|
||||||
|
|
||||||
TaskHandle_t s_rx_task_hdl;
|
TaskHandle_t s_rx_task_hdl;
|
||||||
|
static volatile bool s_shutdown_flag = false;
|
||||||
|
|
||||||
static void IRAM_ATTR hci_uart_rx_task(void *arg)
|
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;
|
uint32_t len_total_read = 0;
|
||||||
uint8_t rx_st = UART_RX_TYPE;
|
uint8_t rx_st = UART_RX_TYPE;
|
||||||
|
|
||||||
while (1) {
|
while (!s_shutdown_flag) {
|
||||||
len_now_read = uart_read_bytes(UART_NO, &buf[len_total_read], len_to_read, portMAX_DELAY);
|
// Use timeout instead of portMAX_DELAY to allow periodic shutdown flag check
|
||||||
assert(len_now_read == len_to_read);
|
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;
|
len_total_read += len_now_read;
|
||||||
|
|
||||||
switch (rx_st) {
|
switch (rx_st) {
|
||||||
@@ -130,6 +138,10 @@ static void IRAM_ATTR hci_uart_rx_task(void *arg)
|
|||||||
m = ble_transport_alloc_acl_from_ll();
|
m = ble_transport_alloc_acl_from_ll();
|
||||||
if (!m) {
|
if (!m) {
|
||||||
ESP_LOGE(TAG, "No buffers");
|
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) {
|
if ((rc = os_mbuf_append(m, &data[1], len_total_read - 1)) != 0) {
|
||||||
@@ -180,7 +192,7 @@ ble_transport_ll_init(void)
|
|||||||
void
|
void
|
||||||
ble_transport_ll_deinit(void)
|
ble_transport_ll_deinit(void)
|
||||||
{
|
{
|
||||||
|
hci_uart_close();
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
@@ -228,6 +240,7 @@ void hci_uart_open(void)
|
|||||||
intr_alloc_flags = ESP_INTR_FLAG_IRAM;
|
intr_alloc_flags = ESP_INTR_FLAG_IRAM;
|
||||||
#endif
|
#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_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_param_config(UART_NO, &uart_config));
|
||||||
ESP_ERROR_CHECK(uart_set_pin(UART_NO, UART_TX_PIN, UART_RX_PIN, -1, -1));
|
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)
|
void hci_uart_close(void)
|
||||||
{
|
{
|
||||||
if (s_rx_task_hdl) {
|
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);
|
uart_driver_delete(UART_NO);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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_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_SIZE, &recv_len, sizeof(recv_len));
|
||||||
esp_ping_get_profile(hdl, ESP_PING_PROF_TIMEGAP, &elapsed_time, sizeof(elapsed_time));
|
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",
|
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)
|
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;
|
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_SEQNO, &seqno, sizeof(seqno));
|
||||||
esp_ping_get_profile(hdl, ESP_PING_PROF_IPADDR, &target_addr, sizeof(target_addr));
|
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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -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
|
* 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) {
|
if (fields->name != NULL) {
|
||||||
assert(fields->name_len < sizeof s - 1);
|
size_t copy_len = fields->name_len;
|
||||||
memcpy(s, fields->name, fields->name_len);
|
if (copy_len >= sizeof(s)) {
|
||||||
s[fields->name_len] = '\0';
|
copy_len = sizeof(s) - 1;
|
||||||
|
}
|
||||||
|
memcpy(s, fields->name, copy_len);
|
||||||
|
s[copy_len] = '\0';
|
||||||
MODLOG_DFLT(DEBUG, " name(%scomplete)=%s\n",
|
MODLOG_DFLT(DEBUG, " name(%scomplete)=%s\n",
|
||||||
fields->name_is_complete ? "" : "in", s);
|
fields->name_is_complete ? "" : "in", s);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -40,7 +40,7 @@ chr_end_handle(const struct peer_svc *svc, const struct peer_chr *chr);
|
|||||||
int
|
int
|
||||||
chr_is_empty(const struct peer_svc *svc, const struct peer_chr *chr);
|
chr_is_empty(const struct peer_svc *svc, const struct peer_chr *chr);
|
||||||
static struct peer_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);
|
struct peer_chr **out_prev);
|
||||||
static void
|
static void
|
||||||
peer_disc_chrs(struct peer *peer);
|
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;
|
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) {
|
if (chr != NULL) {
|
||||||
/* Characteristic already discovered. */
|
/* Characteristic already discovered. */
|
||||||
return 0;
|
return 0;
|
||||||
|
|||||||
@@ -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
|
* SPDX-License-Identifier: Unlicense OR CC0-1.0
|
||||||
*/
|
*/
|
||||||
@@ -32,7 +32,7 @@ static int enter_passkey_handler(int argc, char *argv[])
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
sscanf(argv[1], "%s", pkey);
|
sscanf(argv[1], "%7s", pkey);
|
||||||
ESP_LOGI("You entered", "%s %s", argv[0], argv[1]);
|
ESP_LOGI("You entered", "%s %s", argv[0], argv[1]);
|
||||||
num = pkey[0];
|
num = pkey[0];
|
||||||
|
|
||||||
@@ -45,7 +45,9 @@ static int enter_passkey_handler(int argc, char *argv[])
|
|||||||
xQueueSend(cli_handle, &key, 0);
|
xQueueSend(cli_handle, &key, 0);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
sscanf(pkey, "%d", &key);
|
if (sscanf(pkey, "%d", &key) != 1) {
|
||||||
|
key = 0;
|
||||||
|
}
|
||||||
xQueueSend(cli_handle, &key, 0);
|
xQueueSend(cli_handle, &key, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -84,14 +86,14 @@ static void scli_task(void *arg)
|
|||||||
QueueHandle_t uart_queue;
|
QueueHandle_t uart_queue;
|
||||||
uart_event_t event;
|
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 */
|
/* Initialize the console */
|
||||||
esp_console_config_t console_config = {
|
esp_console_config_t console_config = {
|
||||||
.max_cmdline_args = 8,
|
.max_cmdline_args = 8,
|
||||||
.max_cmdline_length = 256,
|
.max_cmdline_length = 256,
|
||||||
};
|
};
|
||||||
|
|
||||||
esp_console_init(&console_config);
|
ESP_ERROR_CHECK(esp_console_init(&console_config));
|
||||||
|
|
||||||
while (!stop) {
|
while (!stop) {
|
||||||
i = 0;
|
i = 0;
|
||||||
@@ -107,6 +109,9 @@ static void scli_task(void *arg)
|
|||||||
}
|
}
|
||||||
if (event.type == UART_DATA) {
|
if (event.type == UART_DATA) {
|
||||||
while (uart_read_bytes(uart_num, (uint8_t *) &linebuf[i], 1, 0)) {
|
while (uart_read_bytes(uart_num, (uint8_t *) &linebuf[i], 1, 0)) {
|
||||||
|
if (i >= sizeof(linebuf) - 1) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
if (linebuf[i] == '\r') {
|
if (linebuf[i] == '\r') {
|
||||||
uart_write_bytes(uart_num, "\r\n", 2);
|
uart_write_bytes(uart_num, "\r\n", 2);
|
||||||
} else {
|
} else {
|
||||||
@@ -115,12 +120,16 @@ static void scli_task(void *arg)
|
|||||||
i++;
|
i++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} while ((i < 255) && linebuf[i - 1] != '\r');
|
|
||||||
|
} while ((i < 255) && (i == 0 || linebuf[i - 1] != '\r'));
|
||||||
if (stop) {
|
if (stop) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
/* Remove the truncating \r\n */
|
/* 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);
|
ret = esp_console_run((char *) linebuf, &cmd_ret);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
break;
|
break;
|
||||||
@@ -144,3 +153,40 @@ int scli_init(void)
|
|||||||
}
|
}
|
||||||
return ESP_OK;
|
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;
|
||||||
|
}
|
||||||
|
|||||||
@@ -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)
|
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);
|
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;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -227,15 +227,21 @@ bleprph_advertise(void)
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if MYNEWT_VAL(BLE_POWER_CONTROL)
|
#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;
|
int rc;
|
||||||
|
|
||||||
rc = ble_gap_read_remote_transmit_power_level(conn_handle, 0x01 ); // Attempting on LE 1M phy
|
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);
|
rc = ble_gap_set_transmit_power_reporting_enable(conn_handle, 0x1, 0x1);
|
||||||
assert (rc == 0);
|
if (rc != 0) {
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -317,10 +323,13 @@ bleprph_gap_event(struct ble_gap_event *event, void *arg)
|
|||||||
}
|
}
|
||||||
|
|
||||||
#if MYNEWT_VAL(BLE_POWER_CONTROL)
|
#if MYNEWT_VAL(BLE_POWER_CONTROL)
|
||||||
bleprph_power_control(event->connect.conn_handle);
|
if (event->connect.status == 0) {
|
||||||
|
rc = bleprph_power_control(event->connect.conn_handle);
|
||||||
ble_gap_event_listener_register(&power_control_event_listener,
|
if (rc == 0) {
|
||||||
bleprph_gap_power_event, NULL);
|
ble_gap_event_listener_register(&power_control_event_listener,
|
||||||
|
bleprph_gap_power_event, NULL);
|
||||||
|
}
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
|||||||
+13
-1
@@ -63,6 +63,7 @@ static int get_version(int argc, char **argv)
|
|||||||
{
|
{
|
||||||
esp_chip_info_t info;
|
esp_chip_info_t info;
|
||||||
uint32_t flash_size;
|
uint32_t flash_size;
|
||||||
|
const char *model_str;
|
||||||
esp_chip_info(&info);
|
esp_chip_info(&info);
|
||||||
if(esp_flash_get_size(NULL, &flash_size) != ESP_OK) {
|
if(esp_flash_get_size(NULL, &flash_size) != ESP_OK) {
|
||||||
printf("Get flash size failed");
|
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("IDF Version:%s\r\n", esp_get_idf_version());
|
||||||
printf("Chip info:\r\n");
|
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("\tcores:%d\r\n", info.cores);
|
||||||
printf("\tfeature:%s%s%s%s%" PRIu32 "%s\r\n",
|
printf("\tfeature:%s%s%s%s%" PRIu32 "%s\r\n",
|
||||||
info.features & CHIP_FEATURE_WIFI_BGN ? "/802.11bgn" : "",
|
info.features & CHIP_FEATURE_WIFI_BGN ? "/802.11bgn" : "",
|
||||||
|
|||||||
@@ -111,8 +111,8 @@ peer_find(uint16_t conn_handle);
|
|||||||
/* Console */
|
/* Console */
|
||||||
int scli_init(void);
|
int scli_init(void);
|
||||||
void ble_register_cli(void);
|
void ble_register_cli(void);
|
||||||
int scli_receive_key(int *key);
|
int scli_receive_key(int key[6]);
|
||||||
int cli_receive_key(int *key);
|
int cli_receive_key(int key[6]);
|
||||||
int scli_receive_yesno(bool *key);
|
int scli_receive_yesno(bool *key);
|
||||||
void scli_reset_queue(void);
|
void scli_reset_queue(void);
|
||||||
|
|
||||||
|
|||||||
@@ -58,9 +58,10 @@ static int blecent_gap_event(struct ble_gap_event *event, void *arg);
|
|||||||
static SemaphoreHandle_t xSemaphore;
|
static SemaphoreHandle_t xSemaphore;
|
||||||
static int mbuf_len_total;
|
static int mbuf_len_total;
|
||||||
static int failure_count;
|
static int failure_count;
|
||||||
|
static TaskHandle_t throughput_task_handle = NULL;
|
||||||
static int conn_params_def[] = {40, 40, 0, 500, 80, 80};
|
static int conn_params_def[] = {40, 40, 0, 500, 80, 80};
|
||||||
/* test_data accepts test_name and test_time from CLI */
|
/* 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 int mtu_def = 512;
|
||||||
static ble_addr_t conn_addr;
|
static ble_addr_t conn_addr;
|
||||||
static uint16_t handle;
|
static uint16_t handle;
|
||||||
@@ -225,6 +226,7 @@ static int blecent_read(uint16_t conn_handle, uint16_t val_handle,
|
|||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
err:
|
err:
|
||||||
|
xSemaphoreGive(xSemaphore);
|
||||||
/* Terminate the connection. */
|
/* Terminate the connection. */
|
||||||
vTaskDelay(100 / portTICK_PERIOD_MS);
|
vTaskDelay(100 / portTICK_PERIOD_MS);
|
||||||
return ble_gap_terminate(peer->conn_handle, BLE_ERR_REM_USER_CONN_TERM);
|
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;
|
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);
|
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) {
|
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 {
|
else {
|
||||||
ESP_LOGI(tag, "Requested PHY: 1M");
|
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;
|
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);
|
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) {
|
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 {
|
else {
|
||||||
ESP_LOGI(tag, "Requested PHY: 2M");
|
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;
|
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);
|
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) {
|
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 {
|
else {
|
||||||
ESP_LOGI(tag, "Requested PHY: Coded S2");
|
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;
|
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);
|
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) {
|
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 {
|
else {
|
||||||
ESP_LOGI(tag, "Requested PHY: Coded S8");
|
ESP_LOGI(tag, "Requested PHY: Coded S8");
|
||||||
@@ -294,9 +300,29 @@ static void throughput_task(void *arg)
|
|||||||
struct peer *peer = (struct peer *)arg;
|
struct peer *peer = (struct peer *)arg;
|
||||||
const struct peer_chr *chr;
|
const struct peer_chr *chr;
|
||||||
const struct peer_dsc *dsc;
|
const struct peer_dsc *dsc;
|
||||||
|
struct ble_gap_conn_desc desc;
|
||||||
|
uint16_t conn_handle;
|
||||||
int rc = 0;
|
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) {
|
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);
|
vTaskDelay(4000 / portTICK_PERIOD_MS);
|
||||||
ESP_LOGI(tag, "Format for throughput demo:: throughput read 100");
|
ESP_LOGI(tag, "Format for throughput demo:: throughput read 100");
|
||||||
printf(" ====================================================================================\n");
|
printf(" ====================================================================================\n");
|
||||||
@@ -329,12 +355,15 @@ static void throughput_task(void *arg)
|
|||||||
scli_reset_queue();
|
scli_reset_queue();
|
||||||
#if CONFIG_EXAMPLE_EXTENDED_ADV
|
#if CONFIG_EXAMPLE_EXTENDED_ADV
|
||||||
if(test_data[2] >= 0) {
|
if(test_data[2] >= 0) {
|
||||||
rc = update_phy(handle, test_data[2]);
|
rc = update_phy(conn_handle, test_data[2]);
|
||||||
if(rc != 0) {
|
if(rc != 0) {
|
||||||
ESP_LOGI(tag, "Failed to update phy.\n");
|
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 */
|
||||||
while (!current_phy_updated) {
|
} else {
|
||||||
vTaskDelay(100 / portTICK_PERIOD_MS);
|
/* Wait for PHY update event to complete */
|
||||||
|
while (!current_phy_updated) {
|
||||||
|
vTaskDelay(100 / portTICK_PERIOD_MS);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@@ -354,10 +383,17 @@ static void throughput_task(void *arg)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (test_data[1] > 0) {
|
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]);
|
blecent_repeat_read, (void *) peer, test_data[1]);
|
||||||
if (rc != 0) {
|
if (rc != 0) {
|
||||||
ESP_LOGE(tag, "Error while reading from GATTS; rc = %d", rc);
|
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 {
|
} else {
|
||||||
ESP_LOGE(tag, "Please enter non-zero value for test time in seconds!!");
|
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) {
|
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) {
|
if (rc != 0) {
|
||||||
ESP_LOGE(tag, "Error while writing data; rc = %d", rc);
|
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 {
|
} else {
|
||||||
ESP_LOGE(tag, "Please enter non-zero value for test time in seconds!!");
|
ESP_LOGE(tag, "Please enter non-zero value for test time in seconds!!");
|
||||||
@@ -403,10 +446,17 @@ static void throughput_task(void *arg)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
rc = blecent_notify(peer->conn_handle, dsc->dsc.handle,
|
rc = blecent_notify(conn_handle, dsc->dsc.handle,
|
||||||
NULL, (void *) peer, test_data[1]);
|
NULL, (void *) peer, test_data[1]);
|
||||||
if (rc != 0) {
|
if (rc != 0) {
|
||||||
ESP_LOGE(tag, "Subscribing to notification failed; rc = %d ", rc);
|
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 {
|
} else {
|
||||||
ESP_LOGI(tag, "Subscribed to notifications. Throughput number"
|
ESP_LOGI(tag, "Subscribed to notifications. Throughput number"
|
||||||
" can be seen on peripheral terminal after %d seconds",
|
" can be seen on peripheral terminal after %d seconds",
|
||||||
@@ -421,13 +471,20 @@ static void throughput_task(void *arg)
|
|||||||
|
|
||||||
vTaskDelay(5000 / portTICK_PERIOD_MS);
|
vTaskDelay(5000 / portTICK_PERIOD_MS);
|
||||||
}
|
}
|
||||||
vTaskDelete(NULL);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
blecent_read_write_subscribe(const struct peer *peer)
|
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;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -515,6 +572,7 @@ ext_blecent_should_connect(const struct ble_gap_ext_disc_desc *disc)
|
|||||||
uint8_t test_addr[6];
|
uint8_t test_addr[6];
|
||||||
uint32_t peer_addr[6];
|
uint32_t peer_addr[6];
|
||||||
uint8_t phy_uuid_found = 0;
|
uint8_t phy_uuid_found = 0;
|
||||||
|
|
||||||
if (disc->legacy_event_type != BLE_HCI_ADV_RPT_EVTYPE_ADV_IND &&
|
if (disc->legacy_event_type != BLE_HCI_ADV_RPT_EVTYPE_ADV_IND &&
|
||||||
disc->legacy_event_type != BLE_HCI_ADV_RPT_EVTYPE_DIR_IND) {
|
disc->legacy_event_type != BLE_HCI_ADV_RPT_EVTYPE_DIR_IND) {
|
||||||
return 0;
|
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[5], &peer_addr[4], &peer_addr[3],
|
||||||
&peer_addr[2], &peer_addr[1], &peer_addr[0]);
|
&peer_addr[2], &peer_addr[1], &peer_addr[0]);
|
||||||
|
|
||||||
/* Conversion */
|
/* Conversion */
|
||||||
for (int i=0; i<6; i++) {
|
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) {
|
if (memcmp(test_addr, disc->addr.val, sizeof(disc->addr.val)) != 0) {
|
||||||
return 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).
|
/* The device has to advertise support LE PHY UUID (0xABF2).
|
||||||
*/
|
*/
|
||||||
do {
|
do {
|
||||||
ad_struct_len = disc->data[offset];
|
if (offset + 1 >= (int)disc->length_data) { /* At least read length and type */
|
||||||
|
|
||||||
if (!ad_struct_len) {
|
|
||||||
break;
|
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) */
|
/* Search for Complete Local Name (AD type 0x09) */
|
||||||
if (disc->data[offset + 1] == 0x09 && phy_uuid_found) {
|
if (disc->data[offset + 1] == 0x09 && phy_uuid_found) {
|
||||||
int name_len = disc->data[offset] - 1; /* Length minus type byte */
|
int name_len = disc->data[offset] - 1; /* Length minus type byte */
|
||||||
char serv_name[] = "nimble_prph";
|
char serv_name[] = "nimble_prph";
|
||||||
if (name_len > 0) {
|
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) &&
|
if (name_len == strlen(serv_name) &&
|
||||||
memcmp(&disc->data[offset + 2], serv_name, name_len) == 0) {
|
memcmp(&disc->data[offset + 2], serv_name, name_len) == 0) {
|
||||||
ESP_LOGI(tag, "central connect to `nimble_prph` success");
|
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;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Search if LE PHY UUID is advertised */
|
/* Search if LE PHY UUID is advertised */
|
||||||
if (disc->data[offset] == 0x03 && disc->data[offset + 1] == 0x03) {
|
if (disc->data[offset] == 0x03 && disc->data[offset + 1] == 0x03 &&
|
||||||
if ( disc->data[offset + 2] == 0xAB && disc->data[offset + 3] == 0xF2 ) {
|
offset + 3 < (int)disc->length_data &&
|
||||||
phy_uuid_found = 1;
|
disc->data[offset + 2] == 0xAB && disc->data[offset + 3] == 0xF2) {
|
||||||
}
|
phy_uuid_found = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
offset += ad_struct_len + 1;
|
offset += ad_struct_len + 1;
|
||||||
|
|
||||||
} while ( offset < disc->length_data );
|
} while (offset < (int)disc->length_data);
|
||||||
|
|
||||||
return phy_uuid_found;
|
return phy_uuid_found;
|
||||||
}
|
}
|
||||||
@@ -788,6 +850,15 @@ blecent_gap_event(struct ble_gap_event *event, void *arg)
|
|||||||
print_conn_desc(&event->disconnect.conn);
|
print_conn_desc(&event->disconnect.conn);
|
||||||
ESP_LOGI(tag, " ");
|
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. */
|
/* Forget about peer. */
|
||||||
peer_delete(event->disconnect.conn.conn_handle);
|
peer_delete(event->disconnect.conn.conn_handle);
|
||||||
vTaskDelay(200);
|
vTaskDelay(200);
|
||||||
@@ -882,7 +953,9 @@ blecent_on_sync(void)
|
|||||||
if (scli_receive_yesno(&yes)) {
|
if (scli_receive_yesno(&yes)) {
|
||||||
if (yes) {
|
if (yes) {
|
||||||
ESP_LOGI(tag, " Enter preferred MTU, format:: `MTU 512` ");
|
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);
|
ESP_LOGI(tag, "MTU provided by user= %d", mtu_def);
|
||||||
} else {
|
} else {
|
||||||
ESP_LOGD(tag, "No input for setting MTU; use default mtu = %d", mtu_def);
|
ESP_LOGD(tag, "No input for setting MTU; use default mtu = %d", mtu_def);
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD
|
* SPDX-FileCopyrightText: 2015-2025 Espressif Systems (Shanghai) CO LTD
|
||||||
*
|
*
|
||||||
* SPDX-License-Identifier: Apache-2.0
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
*/
|
*/
|
||||||
@@ -131,9 +131,12 @@ print_adv_fields(const struct ble_hs_adv_fields *fields)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (fields->name != NULL) {
|
if (fields->name != NULL) {
|
||||||
assert(fields->name_len < sizeof s - 1);
|
size_t copy_len = fields->name_len;
|
||||||
memcpy(s, fields->name, fields->name_len);
|
if (copy_len >= sizeof(s)) {
|
||||||
s[fields->name_len] = '\0';
|
copy_len = sizeof(s) - 1;
|
||||||
|
}
|
||||||
|
memcpy(s, fields->name, copy_len);
|
||||||
|
s[copy_len] = '\0';
|
||||||
MODLOG_DFLT(DEBUG, " name(%scomplete)=%s\n",
|
MODLOG_DFLT(DEBUG, " name(%scomplete)=%s\n",
|
||||||
fields->name_is_complete ? "" : "in", s);
|
fields->name_is_complete ? "" : "in", s);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -358,7 +358,7 @@ peer_chr_add(struct peer *peer, uint16_t svc_start_handle,
|
|||||||
if (prev == NULL) {
|
if (prev == NULL) {
|
||||||
SLIST_INSERT_HEAD(&svc->chrs, chr, next);
|
SLIST_INSERT_HEAD(&svc->chrs, chr, next);
|
||||||
} else {
|
} else {
|
||||||
SLIST_NEXT(prev, next) = chr;
|
SLIST_INSERT_AFTER(prev, chr, next);
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
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);
|
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 */
|
/* Including the services into inlucding list */
|
||||||
|
|
||||||
cur_svc = peer_svc_find_range(peer, gatt_incl_svc->handle);
|
cur_svc = peer_svc_find_range(peer, gatt_incl_svc->handle);
|
||||||
|
|
||||||
if (cur_svc == NULL) {
|
if (cur_svc == NULL) {
|
||||||
@@ -533,11 +509,38 @@ peer_inc_add(struct peer *peer, uint16_t svc_start_handle,
|
|||||||
return 0;
|
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);
|
incl_svc = os_memblock_get(&peer_incl_svc_pool);
|
||||||
if (incl_svc == NULL) {
|
if (incl_svc == NULL) {
|
||||||
return BLE_HS_ENOMEM;
|
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;
|
incl_svc->svc = *gatt_incl_svc;
|
||||||
|
|
||||||
if (incl_svc_prev == NULL) {
|
if (incl_svc_prev == NULL) {
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD
|
* SPDX-FileCopyrightText: 2015-2025 Espressif Systems (Shanghai) CO LTD
|
||||||
*
|
*
|
||||||
* SPDX-License-Identifier: Apache-2.0
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
*/
|
*/
|
||||||
@@ -8,6 +8,7 @@
|
|||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
#include "esp_log.h"
|
#include "esp_log.h"
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
#include <strings.h>
|
||||||
#include <esp_log.h>
|
#include <esp_log.h>
|
||||||
#include <esp_console.h>
|
#include <esp_console.h>
|
||||||
#include "esp_vfs_dev.h"
|
#include "esp_vfs_dev.h"
|
||||||
@@ -22,9 +23,23 @@
|
|||||||
#define YES_NO_PARAM (5000 / portTICK_PERIOD_MS)
|
#define YES_NO_PARAM (5000 / portTICK_PERIOD_MS)
|
||||||
|
|
||||||
static QueueHandle_t cli_handle;
|
static QueueHandle_t cli_handle;
|
||||||
static int key[3];
|
|
||||||
static int conn_param[10];
|
#define CLI_CONN_PARAM_COUNT 6
|
||||||
static int mtu;
|
|
||||||
|
#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)
|
#define CONSOLE_PROMPT_LEN_MAX (32)
|
||||||
|
|
||||||
@@ -41,56 +56,77 @@ static int conn_param_handler(int argc, char *argv[])
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
sscanf(argv[1], "%d", &conn_param[0]);
|
struct cli_msg msg = {
|
||||||
sscanf(argv[2], "%d", &conn_param[1]);
|
.type = CLI_MSG_TYPE_CONN_PARAM,
|
||||||
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]);
|
|
||||||
|
|
||||||
ESP_LOGI("You entered", "%s %d %d %d %d %d %d", argv[0], conn_param[0], conn_param[1],
|
sscanf(argv[1], "%d", &msg.data.conn_param[0]);
|
||||||
conn_param[2], conn_param[3], conn_param[4], conn_param[5]);
|
sscanf(argv[2], "%d", &msg.data.conn_param[1]);
|
||||||
xQueueSend(cli_handle, &conn_param[0], 500 / portTICK_PERIOD_MS);
|
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;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int conn_mtu_handler(int argc, char *argv[])
|
static int conn_mtu_handler(int argc, char *argv[])
|
||||||
{
|
{
|
||||||
|
int ret;
|
||||||
|
int mtu;
|
||||||
ESP_LOGI("MTU Arguments entered", "%d", argc);
|
ESP_LOGI("MTU Arguments entered", "%d", argc);
|
||||||
if (argc != 2) {
|
if (argc != 2) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
sscanf(argv[1], "%d", &mtu);
|
ret = sscanf(argv[1], "%d", &mtu);
|
||||||
ESP_LOGI("You entered", "%s %d", argv[0], mtu);
|
if (ret != 1) {
|
||||||
xQueueSend(cli_handle, &mtu, 500 / portTICK_PERIOD_MS);
|
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;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int throughput_demo_handler(int argc, char *argv[])
|
static int throughput_demo_handler(int argc, char *argv[])
|
||||||
{
|
{
|
||||||
char pkey[8];
|
char pkey[8];
|
||||||
|
struct cli_msg msg = {
|
||||||
|
.type = CLI_MSG_TYPE_THROUGHPUT,
|
||||||
|
};
|
||||||
|
|
||||||
if (argc != 4) {
|
if (argc != 4) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
sscanf(argv[1], "%s", pkey);
|
sscanf(argv[1], "%7s", pkey);
|
||||||
|
|
||||||
if (strcmp(pkey, "read") == 0) {
|
if (strcmp(pkey, "read") == 0) {
|
||||||
key[0] = 1;
|
msg.data.key[0] = 1;
|
||||||
} else if (strcmp(pkey, "write") == 0) {
|
} else if (strcmp(pkey, "write") == 0) {
|
||||||
key[0] = 2;
|
msg.data.key[0] = 2;
|
||||||
} else if (strcmp(pkey, "notify") == 0) {
|
} else if (strcmp(pkey, "notify") == 0) {
|
||||||
key[0] = 3;
|
msg.data.key[0] = 3;
|
||||||
} else {
|
} else {
|
||||||
key[0] = 0;
|
msg.data.key[0] = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
sscanf(argv[2], "%d", &key[1]);
|
sscanf(argv[2], "%d", &msg.data.key[1]);
|
||||||
sscanf(argv[3], "%d", &key[2]);
|
sscanf(argv[3], "%d", &msg.data.key[2]);
|
||||||
ESP_LOGI("Throughput demo handler", "%s %s %d %d", argv[0], argv[1], key[1], 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, &key[0], 500 / portTICK_PERIOD_MS);
|
xQueueSend(cli_handle, &msg, 500 / portTICK_PERIOD_MS);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -104,32 +140,80 @@ static int yesno_handler(int argc, char *argv[])
|
|||||||
return -1;
|
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;
|
yes = 1;
|
||||||
} else {
|
} else if (strcmp(yesno, "No") == 0 || strcmp(yesno, "NO") == 0 || strcmp(yesno, "no") == 0) {
|
||||||
yes = 0;
|
yes = 0;
|
||||||
|
} else {
|
||||||
|
yes = 0; /* invalid input */
|
||||||
}
|
}
|
||||||
|
|
||||||
ESP_LOGI("User entered", "%s %s", argv[0], yesno);
|
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;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int scli_receive_yesno(bool *console_key)
|
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)
|
void scli_reset_queue(void)
|
||||||
@@ -169,7 +253,7 @@ void ble_register_cli(void)
|
|||||||
esp_console_cmd_register(&cmds[i]);
|
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) {
|
if (cli_handle == NULL) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -507,8 +507,11 @@ void app_main(void)
|
|||||||
ble_hs_cfg.store_status_cb = ble_store_util_status_rr;
|
ble_hs_cfg.store_status_cb = ble_store_util_status_rr;
|
||||||
|
|
||||||
/* Initialize Notify Task */
|
/* 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)
|
#if MYNEWT_VAL(BLE_GATTS)
|
||||||
rc = gatt_svr_init();
|
rc = gatt_svr_init();
|
||||||
assert(rc == 0);
|
assert(rc == 0);
|
||||||
|
|||||||
Reference in New Issue
Block a user