@@ -98,6 +98,7 @@ BLEClient::BLEClient() {
98
98
m_connectTimeout = 30000 ;
99
99
m_pTaskData = nullptr ;
100
100
m_lastErr = 0 ;
101
+ m_terminateFailCount = 0 ;
101
102
102
103
m_pConnParams.scan_itvl = 16 ; // Scan interval in 0.625ms units (NimBLE Default)
103
104
m_pConnParams.scan_window = 16 ; // Scan window in 0.625ms units (NimBLE Default)
@@ -107,9 +108,6 @@ BLEClient::BLEClient() {
107
108
m_pConnParams.supervision_timeout = BLE_GAP_INITIAL_SUPERVISION_TIMEOUT; // timeout = 400*10ms = 4000ms
108
109
m_pConnParams.min_ce_len = BLE_GAP_INITIAL_CONN_MIN_CE_LEN; // Minimum length of connection event in 0.625ms units
109
110
m_pConnParams.max_ce_len = BLE_GAP_INITIAL_CONN_MAX_CE_LEN; // Maximum length of connection event in 0.625ms units
110
-
111
- memset (&m_dcTimer, 0 , sizeof (m_dcTimer));
112
- ble_npl_callout_init (&m_dcTimer, nimble_port_get_dflt_eventq (), BLEClient::dcTimerCb, this );
113
111
#endif
114
112
} // BLEClient
115
113
@@ -124,10 +122,6 @@ BLEClient::~BLEClient() {
124
122
}
125
123
m_servicesMap.clear ();
126
124
m_servicesMapByInstID.clear ();
127
-
128
- #if defined(CONFIG_NIMBLE_ENABLED)
129
- ble_npl_callout_deinit (&m_dcTimer);
130
- #endif
131
125
} // ~BLEClient
132
126
133
127
/* *
@@ -186,34 +180,27 @@ bool BLEClient::secureConnection() {
186
180
#endif
187
181
188
182
#if defined(CONFIG_NIMBLE_ENABLED)
189
- TaskHandle_t cur_task = xTaskGetCurrentTaskHandle ();
190
- ble_task_data_t taskData = {this , cur_task, 0 , nullptr };
191
-
192
183
int retryCount = 1 ;
184
+ BLETaskData taskData (const_cast <BLEClient*>(this ), BLE_HS_ENOTCONN);
185
+ m_pTaskData = &taskData;
193
186
194
187
do {
195
- m_pTaskData = &taskData;
196
-
197
- int rc = BLESecurity::startSecurity (m_conn_id);
198
- if (rc != 0 ) {
199
- m_lastErr = rc;
200
- m_pTaskData = nullptr ;
201
- return false ;
188
+ if (BLESecurity::startSecurity (m_conn_id)) {
189
+ BLEUtils::taskWait (taskData, BLE_NPL_TIME_FOREVER);
202
190
}
203
191
204
- #ifdef ulTaskNotifyValueClear
205
- // Clear the task notification value to ensure we block
206
- ulTaskNotifyValueClear (cur_task, ULONG_MAX);
207
- #endif
208
- ulTaskNotifyTake (pdTRUE, portMAX_DELAY);
209
- } while (taskData.rc == (BLE_HS_ERR_HCI_BASE + BLE_ERR_PINKEY_MISSING) && retryCount--);
192
+ } while (taskData.m_flags == (BLE_HS_ERR_HCI_BASE + BLE_ERR_PINKEY_MISSING) && retryCount--);
210
193
211
- if (taskData.rc != 0 ) {
212
- m_lastErr = taskData.rc ;
213
- return false ;
194
+ m_pTaskData = nullptr ;
195
+
196
+ if (taskData.m_flags == 0 ) {
197
+ log_d (" << secureConnection: success" );
198
+ return true ;
214
199
}
215
200
216
- return true ;
201
+ m_lastErr = taskData.m_flags ;
202
+ log_e (" secureConnection: failed rc=%d" , taskData.m_flags );
203
+ return false ;
217
204
#endif
218
205
} // secureConnection
219
206
@@ -376,7 +363,7 @@ bool BLEClient::setMTU(uint16_t mtu) {
376
363
#endif
377
364
378
365
#if defined(CONFIG_NIMBLE_ENABLED)
379
- err = ble_gattc_exchange_mtu (m_conn_id, nullptr , nullptr );
366
+ // err = ble_gattc_exchange_mtu(m_conn_id, nullptr, nullptr);
380
367
#endif
381
368
382
369
if (err != ESP_OK) {
@@ -799,9 +786,6 @@ bool BLEClient::connect(BLEAddress address, uint8_t type, uint32_t timeoutMs) {
799
786
m_appId = BLEDevice::m_appId++;
800
787
m_peerAddress = address;
801
788
802
- TaskHandle_t cur_task = xTaskGetCurrentTaskHandle ();
803
- ble_task_data_t taskData = {this , cur_task, 0 , nullptr };
804
- m_pTaskData = &taskData;
805
789
int rc = 0 ;
806
790
807
791
/* Try to connect the the advertiser. Allow 30 seconds (30000 ms) for
@@ -837,45 +821,34 @@ bool BLEClient::connect(BLEAddress address, uint8_t type, uint32_t timeoutMs) {
837
821
838
822
} while (rc == BLE_HS_EBUSY);
839
823
840
- m_lastErr = rc;
841
-
842
824
if (rc != 0 ) {
843
- m_pTaskData = nullptr ;
825
+ m_lastErr = rc ;
844
826
return false ;
845
827
}
846
828
847
- #ifdef ulTaskNotifyValueClear
848
- // Clear the task notification value to ensure we block
849
- ulTaskNotifyValueClear (cur_task, ULONG_MAX);
850
- #endif
829
+ BLETaskData taskData (this );
830
+ m_pTaskData = &taskData;
851
831
852
832
// Wait for the connect timeout time +1 second for the connection to complete
853
- if (ulTaskNotifyTake (pdTRUE, pdMS_TO_TICKS (m_connectTimeout + 1000 )) == pdFALSE) {
854
- m_pTaskData = nullptr ;
855
- // If a connection was made but no response from MTU exchange; disconnect
833
+ if (!BLEUtils::taskWait (taskData, m_connectTimeout + 1000 )) {
834
+ // If a connection was made but no response from MTU exchange proceed anyway
856
835
if (isConnected ()) {
857
- log_e (" Connect timeout - no response" );
858
- disconnect ();
836
+ taskData.m_flags = 0 ;
859
837
} else {
860
- // workaround; if the controller doesn't cancel the connection
861
- // at the timeout, cancel it here.
862
- log_e (" Connect timeout - canceling" );
838
+ // workaround; if the controller doesn't cancel the connection at the timeout, cancel it here.
839
+ log_e (" Connect timeout - cancelling" );
863
840
ble_gap_conn_cancel ();
841
+ taskData.m_flags = BLE_HS_ETIMEOUT;
864
842
}
843
+ }
865
844
866
- return false ;
845
+ m_pTaskData = nullptr ;
846
+ rc = taskData.m_flags ;
867
847
868
- } else if (taskData.rc != 0 ) {
869
- m_lastErr = taskData.rc ;
870
- log_e (" Connection failed; status=%d %s" , taskData.rc , BLEUtils::returnCodeToString (taskData.rc ));
871
- // If the failure was not a result of a disconnection
872
- // make sure we disconnect now to avoid dangling connections
873
- if (isConnected ()) {
874
- disconnect ();
875
- }
848
+ if (rc != 0 ) {
849
+ log_e (" Connection failed; status=%d %s" , rc, BLEUtils::returnCodeToString (rc));
850
+ m_lastErr = rc;
876
851
return false ;
877
- } else {
878
- log_i (" Connection established" );
879
852
}
880
853
881
854
m_isConnected = true ;
@@ -895,15 +868,16 @@ bool BLEClient::connect(BLEAddress address, uint8_t type, uint32_t timeoutMs) {
895
868
*/
896
869
int BLEClient::serviceDiscoveredCB (uint16_t conn_handle, const struct ble_gatt_error *error, const struct ble_gatt_svc *service, void *arg)
897
870
{
898
- if (error == nullptr || service == nullptr ) {
899
- log_e (" serviceDiscoveredCB: error or service is nullptr" );
900
- return 0 ;
901
- }
902
-
903
871
log_d (" Service Discovered >> status: %d handle: %d" , error->status , (error->status == 0 ) ? service->start_handle : -1 );
904
872
905
- ble_task_data_t *pTaskData = (ble_task_data_t *)arg;
906
- BLEClient *client = (BLEClient*)pTaskData->pATT ;
873
+ BLETaskData *pTaskData = (BLETaskData*)arg;
874
+ BLEClient *client = (BLEClient*)pTaskData->m_pInstance ;
875
+
876
+ if (error->status == BLE_HS_ENOTCONN) {
877
+ log_e (" << Service Discovered; Disconnected" );
878
+ BLEUtils::taskRelease (*pTaskData, error->status );
879
+ return error->status ;
880
+ }
907
881
908
882
// Make sure the service discovery is for this device
909
883
if (client->getConnId () != conn_handle){
@@ -918,53 +892,50 @@ int BLEClient::serviceDiscoveredCB(uint16_t conn_handle, const struct ble_gatt_e
918
892
return 0 ;
919
893
}
920
894
921
- if (error->status == BLE_HS_EDONE) {
922
- pTaskData->rc = 0 ;
923
- } else {
924
- log_e (" serviceDiscoveredCB() rc=%d %s" , error->status , BLEUtils::returnCodeToString (error->status ));
925
- pTaskData->rc = error->status ;
926
- }
927
-
928
- xTaskNotifyGive (pTaskData->task );
929
-
895
+ BLEUtils::taskRelease (*pTaskData, error->status );
930
896
log_d (" << Service Discovered" );
931
897
return error->status ;
932
898
}
933
899
934
900
std::map<std::string, BLERemoteService *> *BLEClient::getServices () {
935
- /*
936
- * Design
937
- * ------
938
- * We invoke esp_ble_gattc_search_service. This will request a list of the service exposed by the
939
- * peer BLE partner to be returned as events. Each event will be an an instance of ESP_GATTC_SEARCH_RES_EVT
940
- * and will culminate with an ESP_GATTC_SEARCH_CMPL_EVT when all have been received.
941
- */
942
901
log_v (" >> getServices" );
943
- // TODO implement retrieving services from cache
944
- // m_semaphoreSearchCmplEvt.take("getServices");
902
+
945
903
clearServices (); // Clear any services that may exist.
946
904
905
+ if (!isConnected ()) {
906
+ log_e (" Disconnected, could not retrieve services -aborting" );
907
+ return &m_servicesMap;
908
+ }
909
+
947
910
int errRc = 0 ;
948
- TaskHandle_t cur_task = xTaskGetCurrentTaskHandle ();
949
- ble_task_data_t taskData = {this , cur_task, 0 , nullptr };
911
+ BLETaskData taskData (this );
950
912
951
913
errRc = ble_gattc_disc_all_svcs (m_conn_id, BLEClient::serviceDiscoveredCB, &taskData);
914
+
952
915
if (errRc != 0 ) {
953
916
log_e (" ble_gattc_disc_all_svcs: rc=%d %s" , errRc, BLEUtils::returnCodeToString (errRc));
954
917
m_lastErr = errRc;
955
- // m_semaphoreSearchCmplEvt.give();
956
918
return &m_servicesMap;
957
919
}
958
- // If successful, remember that we now have services.
959
- m_haveServices = m_servicesMap.size () > 0 ;
960
- // m_semaphoreSearchCmplEvt.give();
961
- log_v (" << getServices" );
920
+
921
+ BLEUtils::taskWait (taskData, BLE_NPL_TIME_FOREVER);
922
+ errRc = taskData.m_flags ;
923
+ if (errRc == 0 || errRc == BLE_HS_EDONE) {
924
+ // If successful, remember that we now have services.
925
+ m_haveServices = m_servicesMap.size () > 0 ;
926
+ log_v (" << getServices" );
927
+ return &m_servicesMap;
928
+ }
929
+
930
+ m_lastErr = errRc;
931
+ log_e (" Could not retrieve services, rc=%d %s" , errRc, BLEUtils::returnCodeToString (errRc));
962
932
return &m_servicesMap;
963
933
} // getServices
964
934
965
935
int BLEClient::handleGAPEvent (struct ble_gap_event *event, void *arg) {
966
936
BLEClient *client = (BLEClient *)arg;
967
- int rc;
937
+ int rc = 0 ;
938
+ BLETaskData *pTaskData = client->m_pTaskData ;
968
939
969
940
log_d (" BLEClient" , " Got Client event %s" , BLEUtils::gapEventToString (event->type ));
970
941
@@ -979,7 +950,7 @@ int BLEClient::handleGAPEvent(struct ble_gap_event *event, void *arg) {
979
950
case BLE_HS_ETIMEOUT_HCI:
980
951
case BLE_HS_ENOTSYNCED:
981
952
case BLE_HS_EOS:
982
- log_d (" BLEClient" , " Disconnect - host reset, rc=%d" , rc);
953
+ log_e (" BLEClient" , " Disconnect - host reset, rc=%d" , rc);
983
954
BLEDevice::onReset (rc);
984
955
break ;
985
956
default :
@@ -990,14 +961,12 @@ int BLEClient::handleGAPEvent(struct ble_gap_event *event, void *arg) {
990
961
break ;
991
962
}
992
963
993
- // Stop the disconnect timer since we are now disconnected.
994
- ble_npl_callout_stop (&client->m_dcTimer );
995
-
996
964
// Remove the device from ignore list so we will scan it again
997
965
// BLEDevice::removeIgnored(client->m_peerAddress);
998
966
999
967
// No longer connected, clear the connection ID.
1000
968
client->m_conn_id = BLE_HS_CONN_HANDLE_NONE;
969
+ client->m_terminateFailCount = 0 ;
1001
970
1002
971
// If we received a connected event but did not get established (no PDU)
1003
972
// then a disconnect event will be sent but we should not send it to the
@@ -1028,11 +997,11 @@ int BLEClient::handleGAPEvent(struct ble_gap_event *event, void *arg) {
1028
997
1029
998
rc = event->connect .status ;
1030
999
if (rc == 0 ) {
1031
- log_i (" BLEClient" , " Connected event" );
1000
+ log_i (" BLEClient: Connected event. Handle: %d " , event-> connect . conn_handle );
1032
1001
1033
1002
client->m_conn_id = event->connect .conn_handle ;
1034
1003
1035
- rc = ble_gattc_exchange_mtu (client->m_conn_id , NULL , NULL );
1004
+ rc = ble_gattc_exchange_mtu (client->m_conn_id , nullptr , nullptr );
1036
1005
if (rc != 0 ) {
1037
1006
log_e (" BLEClient" , " MTU exchange error; rc=%d %s" , rc, BLEUtils::returnCodeToString (rc));
1038
1007
break ;
@@ -1049,6 +1018,20 @@ int BLEClient::handleGAPEvent(struct ble_gap_event *event, void *arg) {
1049
1018
return 0 ;
1050
1019
} // BLE_GAP_EVENT_CONNECT
1051
1020
1021
+ case BLE_GAP_EVENT_TERM_FAILURE: {
1022
+ if (client->m_conn_id != event->term_failure .conn_handle ) {
1023
+ return 0 ;
1024
+ }
1025
+
1026
+ log_e (" Connection termination failure; rc=%d - retrying" , event->term_failure .status );
1027
+ if (++client->m_terminateFailCount > 2 ) {
1028
+ ble_hs_sched_reset (BLE_HS_ECONTROLLER);
1029
+ } else {
1030
+ ble_gap_terminate (event->term_failure .conn_handle , BLE_ERR_REM_USER_CONN_TERM);
1031
+ }
1032
+ return 0 ;
1033
+ } // BLE_GAP_EVENT_TERM_FAILURE
1034
+
1052
1035
case BLE_GAP_EVENT_NOTIFY_RX:
1053
1036
{
1054
1037
if (client->m_conn_id != event->notify_rx .conn_handle ) {
@@ -1236,12 +1219,8 @@ int BLEClient::handleGAPEvent(struct ble_gap_event *event, void *arg) {
1236
1219
}
1237
1220
} // Switch
1238
1221
1239
- if (client->m_pTaskData != nullptr ) {
1240
- client->m_pTaskData ->rc = rc;
1241
- if (client->m_pTaskData ->task ) {
1242
- xTaskNotifyGive (client->m_pTaskData ->task );
1243
- }
1244
- client->m_pTaskData = nullptr ;
1222
+ if (pTaskData != nullptr ) {
1223
+ BLEUtils::taskRelease (*pTaskData, rc);
1245
1224
}
1246
1225
1247
1226
return 0 ;
@@ -1256,41 +1235,16 @@ int BLEClient::disconnect(uint8_t reason) {
1256
1235
int rc = 0 ;
1257
1236
1258
1237
if (isConnected ()) {
1259
- // If the timer was already started, ignore this call.
1260
- if (ble_npl_callout_is_active (&m_dcTimer)) {
1261
- log_i (" Already disconnecting, timer started" );
1262
- return BLE_HS_EALREADY;
1263
- }
1264
-
1265
- ble_gap_conn_desc desc;
1266
- if (ble_gap_conn_find (m_conn_id, &desc) != 0 ){
1267
- log_i (" Connection ID not found" );
1268
- return BLE_HS_EALREADY;
1269
- }
1270
-
1271
- // We use a timer to detect a controller error in the event that it does
1272
- // not inform the stack when disconnection is complete.
1273
- // This is a common error in certain esp-idf versions.
1274
- // The disconnect timeout time is the supervison timeout time + 1 second.
1275
- // In the case that the event happenss shortly after the supervision timeout
1276
- // we don't want to prematurely reset the host.
1277
- ble_npl_time_t ticks;
1278
- ble_npl_time_ms_to_ticks ((desc.supervision_timeout + 100 ) * 10 , &ticks);
1279
- ble_npl_callout_reset (&m_dcTimer, ticks);
1280
-
1281
1238
rc = ble_gap_terminate (m_conn_id, reason);
1282
- if (rc != 0 ) {
1283
- if (rc != BLE_HS_EALREADY) {
1284
- ble_npl_callout_stop (&m_dcTimer);
1285
- }
1239
+ if (rc != 0 && rc != BLE_HS_ENOTCONN && rc != BLE_HS_EALREADY) {
1240
+ m_lastErr = rc;
1286
1241
log_e (" ble_gap_terminate failed: rc=%d %s" , rc, BLEUtils::returnCodeToString (rc));
1287
1242
}
1288
1243
} else {
1289
1244
log_d (" Not connected to any peers" );
1290
1245
}
1291
1246
1292
1247
log_d (" << disconnect()" );
1293
- m_lastErr = rc;
1294
1248
return rc;
1295
1249
} // disconnect
1296
1250
0 commit comments