@@ -98,6 +98,7 @@ BLEClient::BLEClient() {
9898 m_connectTimeout = 30000 ;
9999 m_pTaskData = nullptr ;
100100 m_lastErr = 0 ;
101+ m_terminateFailCount = 0 ;
101102
102103 m_pConnParams.scan_itvl = 16 ; // Scan interval in 0.625ms units (NimBLE Default)
103104 m_pConnParams.scan_window = 16 ; // Scan window in 0.625ms units (NimBLE Default)
@@ -107,9 +108,6 @@ BLEClient::BLEClient() {
107108 m_pConnParams.supervision_timeout = BLE_GAP_INITIAL_SUPERVISION_TIMEOUT; // timeout = 400*10ms = 4000ms
108109 m_pConnParams.min_ce_len = BLE_GAP_INITIAL_CONN_MIN_CE_LEN; // Minimum length of connection event in 0.625ms units
109110 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 );
113111#endif
114112} // BLEClient
115113
@@ -124,10 +122,6 @@ BLEClient::~BLEClient() {
124122 }
125123 m_servicesMap.clear ();
126124 m_servicesMapByInstID.clear ();
127-
128- #if defined(CONFIG_NIMBLE_ENABLED)
129- ble_npl_callout_deinit (&m_dcTimer);
130- #endif
131125} // ~BLEClient
132126
133127/* *
@@ -186,34 +180,27 @@ bool BLEClient::secureConnection() {
186180#endif
187181
188182#if defined(CONFIG_NIMBLE_ENABLED)
189- TaskHandle_t cur_task = xTaskGetCurrentTaskHandle ();
190- ble_task_data_t taskData = {this , cur_task, 0 , nullptr };
191-
192183 int retryCount = 1 ;
184+ BLETaskData taskData (const_cast <BLEClient*>(this ), BLE_HS_ENOTCONN);
185+ m_pTaskData = &taskData;
193186
194187 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);
202190 }
203191
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--);
210193
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 ;
214199 }
215200
216- return true ;
201+ m_lastErr = taskData.m_flags ;
202+ log_e (" secureConnection: failed rc=%d" , taskData.m_flags );
203+ return false ;
217204#endif
218205} // secureConnection
219206
@@ -376,7 +363,7 @@ bool BLEClient::setMTU(uint16_t mtu) {
376363#endif
377364
378365#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);
380367#endif
381368
382369 if (err != ESP_OK) {
@@ -799,9 +786,6 @@ bool BLEClient::connect(BLEAddress address, uint8_t type, uint32_t timeoutMs) {
799786 m_appId = BLEDevice::m_appId++;
800787 m_peerAddress = address;
801788
802- TaskHandle_t cur_task = xTaskGetCurrentTaskHandle ();
803- ble_task_data_t taskData = {this , cur_task, 0 , nullptr };
804- m_pTaskData = &taskData;
805789 int rc = 0 ;
806790
807791 /* 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) {
837821
838822 } while (rc == BLE_HS_EBUSY);
839823
840- m_lastErr = rc;
841-
842824 if (rc != 0 ) {
843- m_pTaskData = nullptr ;
825+ m_lastErr = rc ;
844826 return false ;
845827 }
846828
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;
851831
852832 // 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
856835 if (isConnected ()) {
857- log_e (" Connect timeout - no response" );
858- disconnect ();
836+ taskData.m_flags = 0 ;
859837 } 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" );
863840 ble_gap_conn_cancel ();
841+ taskData.m_flags = BLE_HS_ETIMEOUT;
864842 }
843+ }
865844
866- return false ;
845+ m_pTaskData = nullptr ;
846+ rc = taskData.m_flags ;
867847
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;
876851 return false ;
877- } else {
878- log_i (" Connection established" );
879852 }
880853
881854 m_isConnected = true ;
@@ -895,15 +868,16 @@ bool BLEClient::connect(BLEAddress address, uint8_t type, uint32_t timeoutMs) {
895868 */
896869int BLEClient::serviceDiscoveredCB (uint16_t conn_handle, const struct ble_gatt_error *error, const struct ble_gatt_svc *service, void *arg)
897870{
898- if (error == nullptr || service == nullptr ) {
899- log_e (" serviceDiscoveredCB: error or service is nullptr" );
900- return 0 ;
901- }
902-
903871 log_d (" Service Discovered >> status: %d handle: %d" , error->status , (error->status == 0 ) ? service->start_handle : -1 );
904872
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+ }
907881
908882 // Make sure the service discovery is for this device
909883 if (client->getConnId () != conn_handle){
@@ -918,53 +892,50 @@ int BLEClient::serviceDiscoveredCB(uint16_t conn_handle, const struct ble_gatt_e
918892 return 0 ;
919893 }
920894
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 );
930896 log_d (" << Service Discovered" );
931897 return error->status ;
932898}
933899
934900std::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- */
942901 log_v (" >> getServices" );
943- // TODO implement retrieving services from cache
944- // m_semaphoreSearchCmplEvt.take("getServices");
902+
945903 clearServices (); // Clear any services that may exist.
946904
905+ if (!isConnected ()) {
906+ log_e (" Disconnected, could not retrieve services -aborting" );
907+ return &m_servicesMap;
908+ }
909+
947910 int errRc = 0 ;
948- TaskHandle_t cur_task = xTaskGetCurrentTaskHandle ();
949- ble_task_data_t taskData = {this , cur_task, 0 , nullptr };
911+ BLETaskData taskData (this );
950912
951913 errRc = ble_gattc_disc_all_svcs (m_conn_id, BLEClient::serviceDiscoveredCB, &taskData);
914+
952915 if (errRc != 0 ) {
953916 log_e (" ble_gattc_disc_all_svcs: rc=%d %s" , errRc, BLEUtils::returnCodeToString (errRc));
954917 m_lastErr = errRc;
955- // m_semaphoreSearchCmplEvt.give();
956918 return &m_servicesMap;
957919 }
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));
962932 return &m_servicesMap;
963933} // getServices
964934
965935int BLEClient::handleGAPEvent (struct ble_gap_event *event, void *arg) {
966936 BLEClient *client = (BLEClient *)arg;
967- int rc;
937+ int rc = 0 ;
938+ BLETaskData *pTaskData = client->m_pTaskData ;
968939
969940 log_d (" BLEClient" , " Got Client event %s" , BLEUtils::gapEventToString (event->type ));
970941
@@ -979,7 +950,7 @@ int BLEClient::handleGAPEvent(struct ble_gap_event *event, void *arg) {
979950 case BLE_HS_ETIMEOUT_HCI:
980951 case BLE_HS_ENOTSYNCED:
981952 case BLE_HS_EOS:
982- log_d (" BLEClient" , " Disconnect - host reset, rc=%d" , rc);
953+ log_e (" BLEClient" , " Disconnect - host reset, rc=%d" , rc);
983954 BLEDevice::onReset (rc);
984955 break ;
985956 default :
@@ -990,14 +961,12 @@ int BLEClient::handleGAPEvent(struct ble_gap_event *event, void *arg) {
990961 break ;
991962 }
992963
993- // Stop the disconnect timer since we are now disconnected.
994- ble_npl_callout_stop (&client->m_dcTimer );
995-
996964 // Remove the device from ignore list so we will scan it again
997965 // BLEDevice::removeIgnored(client->m_peerAddress);
998966
999967 // No longer connected, clear the connection ID.
1000968 client->m_conn_id = BLE_HS_CONN_HANDLE_NONE;
969+ client->m_terminateFailCount = 0 ;
1001970
1002971 // If we received a connected event but did not get established (no PDU)
1003972 // 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) {
1028997
1029998 rc = event->connect .status ;
1030999 if (rc == 0 ) {
1031- log_i (" BLEClient" , " Connected event" );
1000+ log_i (" BLEClient: Connected event. Handle: %d " , event-> connect . conn_handle );
10321001
10331002 client->m_conn_id = event->connect .conn_handle ;
10341003
1035- rc = ble_gattc_exchange_mtu (client->m_conn_id , NULL , NULL );
1004+ rc = ble_gattc_exchange_mtu (client->m_conn_id , nullptr , nullptr );
10361005 if (rc != 0 ) {
10371006 log_e (" BLEClient" , " MTU exchange error; rc=%d %s" , rc, BLEUtils::returnCodeToString (rc));
10381007 break ;
@@ -1049,6 +1018,20 @@ int BLEClient::handleGAPEvent(struct ble_gap_event *event, void *arg) {
10491018 return 0 ;
10501019 } // BLE_GAP_EVENT_CONNECT
10511020
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+
10521035 case BLE_GAP_EVENT_NOTIFY_RX:
10531036 {
10541037 if (client->m_conn_id != event->notify_rx .conn_handle ) {
@@ -1236,12 +1219,8 @@ int BLEClient::handleGAPEvent(struct ble_gap_event *event, void *arg) {
12361219 }
12371220 } // Switch
12381221
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);
12451224 }
12461225
12471226 return 0 ;
@@ -1256,41 +1235,16 @@ int BLEClient::disconnect(uint8_t reason) {
12561235 int rc = 0 ;
12571236
12581237 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-
12811238 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;
12861241 log_e (" ble_gap_terminate failed: rc=%d %s" , rc, BLEUtils::returnCodeToString (rc));
12871242 }
12881243 } else {
12891244 log_d (" Not connected to any peers" );
12901245 }
12911246
12921247 log_d (" << disconnect()" );
1293- m_lastErr = rc;
12941248 return rc;
12951249} // disconnect
12961250
0 commit comments