diff --git a/components/protocomm/src/simple_ble/simple_ble.c b/components/protocomm/src/simple_ble/simple_ble.c index 48d23874ad..e59f05ec18 100644 --- a/components/protocomm/src/simple_ble/simple_ble.c +++ b/components/protocomm/src/simple_ble/simple_ble.c @@ -23,6 +23,7 @@ static simple_ble_cfg_t *g_ble_cfg_p; static uint16_t *g_gatt_table_map; static uint8_t adv_config_done; +static esp_bd_addr_t s_cached_remote_bda = {0x0,}; #define adv_config_flag (1 << 0) #define scan_rsp_config_flag (1 << 1) @@ -133,6 +134,7 @@ static void gatts_profile_event_handler(esp_gatts_cb_event_t event, esp_gatt_if_ g_ble_cfg_p->connect_fn(event, gatts_if, param); esp_ble_conn_update_params_t conn_params = {0}; memcpy(conn_params.bda, param->connect.remote_bda, sizeof(esp_bd_addr_t)); + memcpy(s_cached_remote_bda, param->connect.remote_bda, sizeof(esp_bd_addr_t)); /* For the iOS system, please refer the official Apple documents about BLE connection parameters restrictions. */ conn_params.latency = 0; conn_params.max_int = 0x20; // max_int = 0x20*1.25ms = 40ms @@ -143,6 +145,7 @@ static void gatts_profile_event_handler(esp_gatts_cb_event_t event, esp_gatt_if_ case ESP_GATTS_DISCONNECT_EVT: ESP_LOGD(TAG, "ESP_GATTS_DISCONNECT_EVT, reason = %d", param->disconnect.reason); g_ble_cfg_p->disconnect_fn(event, gatts_if, param); + memset(s_cached_remote_bda, 0, sizeof(esp_bd_addr_t)); esp_ble_gap_start_advertising(&g_ble_cfg_p->adv_params); break; case ESP_GATTS_CREAT_ATTR_TAB_EVT: { @@ -320,3 +323,10 @@ esp_err_t simple_ble_stop(void) ESP_LOGD(TAG, "Free mem at end of simple_ble_stop %d", esp_get_free_heap_size()); return ESP_OK; } + +#ifdef CONFIG_WIFI_PROV_DISCONNECT_AFTER_PROV +esp_err_t simple_ble_disconnect(void) +{ + return esp_ble_gap_disconnect(s_cached_remote_bda); +} +#endif diff --git a/components/protocomm/src/simple_ble/simple_ble.h b/components/protocomm/src/simple_ble/simple_ble.h index 8f09adcb1e..78fe930379 100644 --- a/components/protocomm/src/simple_ble/simple_ble.h +++ b/components/protocomm/src/simple_ble/simple_ble.h @@ -104,4 +104,13 @@ esp_err_t simple_ble_stop(void); */ const uint8_t *simple_ble_get_uuid128(uint16_t handle); +#ifdef CONFIG_WIFI_PROV_DISCONNECT_AFTER_PROV +/** Terminates connection + * + * This API is called to initiate disconnection + * + * @return ESP_OK on success, and appropriate error code for failure + */ +esp_err_t simple_ble_disconnect(void); +#endif #endif /* _SIMPLE_BLE_ */ diff --git a/components/protocomm/src/transports/protocomm_ble.c b/components/protocomm/src/transports/protocomm_ble.c index b9f2953975..0d2fe1416d 100644 --- a/components/protocomm/src/transports/protocomm_ble.c +++ b/components/protocomm/src/transports/protocomm_ble.c @@ -318,6 +318,15 @@ static void transport_simple_ble_disconnect(esp_gatts_cb_event_t event, esp_gatt { esp_err_t ret; ESP_LOGD(TAG, "Inside disconnect w/ session - %d", param->disconnect.conn_id); + +#ifdef CONFIG_WIFI_PROV_KEEP_BLE_ON_AFTER_PROV + /* Ignore BLE events received after protocomm layer is stopped */ + if (protoble_internal == NULL) { + ESP_LOGI(TAG,"Protocomm layer has already stopped"); + return; + } +#endif + if (protoble_internal->pc_ble->sec && protoble_internal->pc_ble->sec->close_transport_session) { ret = protoble_internal->pc_ble->sec->close_transport_session(protoble_internal->pc_ble->sec_inst, @@ -572,11 +581,24 @@ esp_err_t protocomm_ble_stop(protocomm_t *pc) (protoble_internal != NULL ) && (pc == protoble_internal->pc_ble)) { esp_err_t ret = ESP_OK; + +#ifndef CONFIG_WIFI_PROV_KEEP_BLE_ON_AFTER_PROV + /* If flag is not enabled, stop the stack. */ ret = simple_ble_stop(); if (ret) { ESP_LOGE(TAG, "BLE stop failed"); } - simple_ble_deinit(); +#else +#ifdef CONFIG_WIFI_PROV_DISCONNECT_AFTER_PROV + /* Keep BT stack on, but terminate the connection after provisioning */ + ret = simple_ble_disconnect(); + if (ret) { + ESP_LOGE(TAG, "BLE disconnect failed"); + } + simple_ble_deinit(); +#endif // CONFIG_WIFI_PROV_DISCONNECT_AFTER_PROV +#endif // CONFIG_WIFI_PROV_KEEP_BLE_ON_AFTER_PROV + protocomm_ble_cleanup(); return ret; } diff --git a/components/protocomm/src/transports/protocomm_nimble.c b/components/protocomm/src/transports/protocomm_nimble.c index f0367c4ba5..574647bb3d 100644 --- a/components/protocomm/src/transports/protocomm_nimble.c +++ b/components/protocomm/src/transports/protocomm_nimble.c @@ -27,6 +27,7 @@ static const char *TAG = "protocomm_nimble"; int ble_uuid_flat(const ble_uuid_t *, void *); static uint8_t ble_uuid_base[BLE_UUID128_VAL_LENGTH]; static int num_chr_dsc; +static uint16_t s_cached_conn_handle; /* Standard 16 bit UUID for characteristic User Description*/ #define BLE_GATT_UUID_CHAR_DSC 0x2901 @@ -227,6 +228,7 @@ simple_ble_gap_event(struct ble_gap_event *event, void *arg) ESP_LOGE(TAG, "No open connection with the specified handle"); return rc; } + s_cached_conn_handle = event->connect.conn_handle; } else { /* Connection failed; resume advertising. */ simple_ble_advertise(); @@ -236,7 +238,7 @@ simple_ble_gap_event(struct ble_gap_event *event, void *arg) case BLE_GAP_EVENT_DISCONNECT: ESP_LOGD(TAG, "disconnect; reason=%d ", event->disconnect.reason); transport_simple_ble_disconnect(event, arg); - + s_cached_conn_handle = 0; /* Clear conn_handle value */ /* Connection terminated; resume advertising. */ simple_ble_advertise(); return 0; @@ -539,6 +541,14 @@ static void transport_simple_ble_disconnect(struct ble_gap_event *event, void *a esp_err_t ret; ESP_LOGD(TAG, "Inside disconnect w/ session - %d", event->disconnect.conn.conn_handle); + +#ifdef CONFIG_WIFI_PROV_KEEP_BLE_ON_AFTER_PROV + /* Ignore BLE events received after protocomm layer is stopped */ + if (protoble_internal == NULL) { + ESP_LOGI(TAG,"Protocomm layer has already stopped"); + return; + } +#endif if (protoble_internal->pc_ble->sec && protoble_internal->pc_ble->sec->close_transport_session) { ret = @@ -951,6 +961,8 @@ esp_err_t protocomm_ble_stop(protocomm_t *pc) rc); } +#ifndef CONFIG_WIFI_PROV_KEEP_BLE_ON_AFTER_PROV + /* If flag is enabled, don't stop the stack. User application can start a new advertising to perform its BT activities */ ret = nimble_port_stop(); if (ret == 0) { nimble_port_deinit(); @@ -959,8 +971,17 @@ esp_err_t protocomm_ble_stop(protocomm_t *pc) ESP_LOGE(TAG, "esp_nimble_hci_and_controller_deinit() failed with error: %d", ret); } } +#else +#ifdef CONFIG_WIFI_PROV_DISCONNECT_AFTER_PROV + /* Keep BT stack on, but terminate the connection after provisioning */ + rc = ble_gap_terminate(s_cached_conn_handle, BLE_ERR_REM_USER_CONN_TERM); + if (rc) { + ESP_LOGI(TAG, "Error in terminating connection rc = %d",rc); + } + free_gatt_ble_misc_memory(ble_cfg_p); +#endif // CONFIG_WIFI_PROV_DISCONNECT_AFTER_PROV +#endif // CONFIG_WIFI_PROV_KEEP_BLE_ON_AFTER_PROV - free_gatt_ble_misc_memory(ble_cfg_p); protocomm_ble_cleanup(); return ret; } diff --git a/components/wifi_provisioning/Kconfig b/components/wifi_provisioning/Kconfig index ad6e6f7386..ecffba9051 100644 --- a/components/wifi_provisioning/Kconfig +++ b/components/wifi_provisioning/Kconfig @@ -38,4 +38,13 @@ menu "Wi-Fi Provisioning Manager" help Used to enforce link encryption when attempting to read / write characteristic + config WIFI_PROV_KEEP_BLE_ON_AFTER_PROV + bool "Keep BT on after provisioning is done" + depends on BT_ENABLED + + config WIFI_PROV_DISCONNECT_AFTER_PROV + bool "Terminate connection after provisioning is done" + depends on WIFI_PROV_KEEP_BLE_ON_AFTER_PROV + default y + endmenu diff --git a/components/wifi_provisioning/src/scheme_ble.c b/components/wifi_provisioning/src/scheme_ble.c index a133592f92..4714a77436 100644 --- a/components/wifi_provisioning/src/scheme_ble.c +++ b/components/wifi_provisioning/src/scheme_ble.c @@ -207,6 +207,7 @@ void wifi_prov_scheme_ble_event_cb_free_btdm(void *user_data, wifi_prov_cb_event break; case WIFI_PROV_DEINIT: +#ifndef CONFIG_WIFI_PROV_KEEP_BLE_ON_AFTER_PROV /* Release memory used by BLE and Bluedroid host stack */ err = esp_bt_mem_release(ESP_BT_MODE_BTDM); if (err != ESP_OK) { @@ -214,6 +215,7 @@ void wifi_prov_scheme_ble_event_cb_free_btdm(void *user_data, wifi_prov_cb_event } else { ESP_LOGI(TAG, "BTDM memory released"); } +#endif break; default: @@ -247,6 +249,7 @@ void wifi_prov_scheme_ble_event_cb_free_ble(void *user_data, wifi_prov_cb_event_ esp_err_t err; switch (event) { case WIFI_PROV_DEINIT: +#ifndef CONFIG_WIFI_PROV_KEEP_BLE_ON_AFTER_PROV /* Release memory used by BLE stack */ err = esp_bt_mem_release(ESP_BT_MODE_BLE); if (err != ESP_OK) { @@ -254,6 +257,7 @@ void wifi_prov_scheme_ble_event_cb_free_ble(void *user_data, wifi_prov_cb_event_ } else { ESP_LOGI(TAG, "BLE memory released"); } +#endif break; default: