Skip to content

Commit f374508

Browse files
committed
fix(nimble): Fix crashes in Client
1 parent a147147 commit f374508

File tree

2 files changed

+54
-4
lines changed

2 files changed

+54
-4
lines changed

libraries/BLE/src/BLEClient.cpp

Lines changed: 50 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -488,16 +488,17 @@ bool BLEClient::connect(BLEAddress address, uint8_t type, uint32_t timeoutMs) {
488488

489489
/**
490490
* @brief Disconnect from the peer.
491-
* @return N/A.
491+
* @return error code from bluedroid, 0 = success.
492492
*/
493-
void BLEClient::disconnect() {
493+
int BLEClient::disconnect(uint8_t reason) {
494494
log_v(">> disconnect()");
495495
esp_err_t errRc = ::esp_ble_gattc_close(getGattcIf(), getConnId());
496496
if (errRc != ESP_OK) {
497497
log_e("esp_ble_gattc_close: rc=%d %s", errRc, GeneralUtils::errorToString(errRc));
498-
return;
498+
return errRc;
499499
}
500500
log_v("<< disconnect()");
501+
return ESP_OK;
501502
} // disconnect
502503

503504
/**
@@ -1241,6 +1242,52 @@ int BLEClient::handleGAPEvent(struct ble_gap_event *event, void *arg) {
12411242
return 0;
12421243
} // handleGAPEvent
12431244

1245+
/**
1246+
* @brief Disconnect from the peer.
1247+
* @return Error code from NimBLE stack, 0 = success.
1248+
*/
1249+
int BLEClient::disconnect(uint8_t reason) {
1250+
log_d(">> disconnect()");
1251+
int rc = 0;
1252+
if(isConnected()) {
1253+
// If the timer was already started, ignore this call.
1254+
if(ble_npl_callout_is_active(&m_dcTimer)) {
1255+
log_i("Already disconnecting, timer started");
1256+
return BLE_HS_EALREADY;
1257+
}
1258+
1259+
ble_gap_conn_desc desc;
1260+
if(ble_gap_conn_find(m_conn_id, &desc) != 0){
1261+
log_i("Connection ID not found");
1262+
return BLE_HS_EALREADY;
1263+
}
1264+
1265+
// We use a timer to detect a controller error in the event that it does
1266+
// not inform the stack when disconnection is complete.
1267+
// This is a common error in certain esp-idf versions.
1268+
// The disconnect timeout time is the supervison timeout time + 1 second.
1269+
// In the case that the event happenss shortly after the supervision timeout
1270+
// we don't want to prematurely reset the host.
1271+
ble_npl_time_t ticks;
1272+
ble_npl_time_ms_to_ticks((desc.supervision_timeout + 100) * 10, &ticks);
1273+
ble_npl_callout_reset(&m_dcTimer, ticks);
1274+
1275+
rc = ble_gap_terminate(m_conn_id, reason);
1276+
if (rc != 0) {
1277+
if(rc != BLE_HS_EALREADY) {
1278+
ble_npl_callout_stop(&m_dcTimer);
1279+
}
1280+
log_e("ble_gap_terminate failed: rc=%d %s", rc, BLEUtils::returnCodeToString(rc));
1281+
} else {
1282+
log_d("Not connected to any peers");
1283+
}
1284+
}
1285+
1286+
log_d("<< disconnect()");
1287+
m_lastErr = rc;
1288+
return rc;
1289+
} // disconnect
1290+
12441291
bool BLEClientCallbacks::onConnParamsUpdateRequest(BLEClient *pClient, const ble_gap_upd_params *params) {
12451292
log_d("BLEClientCallbacks", "onConnParamsUpdateRequest: default");
12461293
return true;

libraries/BLE/src/BLEClient.h

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,9 @@
3737

3838
#if defined(CONFIG_BLUEDROID_ENABLED)
3939
#include <esp_gattc_api.h>
40+
#ifndef BLE_ERR_REM_USER_CONN_TERM
41+
#define BLE_ERR_REM_USER_CONN_TERM 0x13
42+
#endif
4043
#endif
4144

4245
/***************************************************************************
@@ -87,7 +90,7 @@ class BLEClient {
8790
bool connectTimeout(BLEAdvertisedDevice *device, uint32_t timeoutMS = portMAX_DELAY);
8891
bool connect(BLEAddress address, uint8_t type = 0, uint32_t timeoutMS = portMAX_DELAY);
8992
bool secureConnection();
90-
void disconnect();
93+
int disconnect(uint8_t reason = BLE_ERR_REM_USER_CONN_TERM);
9194
BLEAddress getPeerAddress();
9295
int getRssi();
9396
std::map<std::string, BLERemoteService *> *getServices();

0 commit comments

Comments
 (0)