@@ -65,6 +65,8 @@ NimBLEClient::NimBLEClient(const NimBLEAddress& peerAddress)
6565 m_terminateFailCount{0 },
6666 m_deleteCallbacks{false },
6767 m_connEstablished{false },
68+ m_asyncConnect{false },
69+ m_exchangeMTU{true },
6870# if CONFIG_BT_NIMBLE_EXT_ADV
6971 m_phyMask{BLE_GAP_LE_PHY_1M_MASK | BLE_GAP_LE_PHY_2M_MASK | BLE_GAP_LE_PHY_CODED_MASK},
7072# endif
@@ -123,37 +125,54 @@ size_t NimBLEClient::deleteService(const NimBLEUUID& uuid) {
123125} // deleteServices
124126
125127/* *
126- * @brief Connect to the BLE Server.
128+ * @brief Connect to the BLE Server using the address of the last connected device, or the address\n
129+ * passed to the constructor.
127130 * @param [in] deleteAttributes If true this will delete any attribute objects this client may already\n
128- * have created and clears the vectors after successful connection.
129- * @return True on success.
131+ * have created when last connected.
132+ * @param [in] asyncConnect If true, the connection will be made asynchronously and this function will return immediately.\n
133+ * If false, this function will block until the connection is established or the connection attempt times out.
134+ * @param [in] exchangeMTU If true, the client will attempt to exchange MTU with the server after connection.\n
135+ * If false, the client will use the default MTU size and the application will need to call exchangeMTU() later.
136+ * @return true on success.
130137 */
131- bool NimBLEClient::connect (bool deleteAttributes) {
132- return connect (m_peerAddress, deleteAttributes);
138+ bool NimBLEClient::connect (bool deleteAttributes, bool asyncConnect, bool exchangeMTU ) {
139+ return connect (m_peerAddress, deleteAttributes, asyncConnect, exchangeMTU );
133140}
134141
135142/* *
136143 * @brief Connect to an advertising device.
137144 * @param [in] device The device to connect to.
138145 * @param [in] deleteAttributes If true this will delete any attribute objects this client may already\n
139- * have created and clears the vectors after successful connection.
140- * @return True on success.
146+ * have created when last connected.
147+ * @param [in] asyncConnect If true, the connection will be made asynchronously and this function will return immediately.\n
148+ * If false, this function will block until the connection is established or the connection attempt times out.
149+ * @param [in] exchangeMTU If true, the client will attempt to exchange MTU with the server after connection.\n
150+ * If false, the client will use the default MTU size and the application will need to call exchangeMTU() later.
151+ * @return true on success.
141152 */
142- bool NimBLEClient::connect (NimBLEAdvertisedDevice* device, bool deleteAttributes) {
153+ bool NimBLEClient::connect (NimBLEAdvertisedDevice* device, bool deleteAttributes, bool asyncConnect, bool exchangeMTU ) {
143154 NimBLEAddress address (device->getAddress ());
144- return connect (address, deleteAttributes);
155+ return connect (address, deleteAttributes, asyncConnect, exchangeMTU );
145156}
146157
147158/* *
148159 * @brief Connect to a BLE Server by address.
149160 * @param [in] address The address of the server.
150161 * @param [in] deleteAttributes If true this will delete any attribute objects this client may already\n
151- * have created and clears the vectors after successful connection.
152- * @return True on success.
162+ * have created when last connected.
163+ * @param [in] asyncConnect If true, the connection will be made asynchronously and this function will return immediately.\n
164+ * If false, this function will block until the connection is established or the connection attempt times out.
165+ * @param [in] exchangeMTU If true, the client will attempt to exchange MTU with the server after connection.\n
166+ * If false, the client will use the default MTU size and the application will need to call exchangeMTU() later.
167+ * @return true on success.
153168 */
154- bool NimBLEClient::connect (const NimBLEAddress& address, bool deleteAttributes) {
169+ bool NimBLEClient::connect (const NimBLEAddress& address, bool deleteAttributes, bool asyncConnect, bool exchangeMTU ) {
155170 NIMBLE_LOGD (LOG_TAG, " >> connect(%s)" , address.toString ().c_str ());
156171
172+ if (deleteAttributes) {
173+ deleteServices ();
174+ }
175+
157176 if (!NimBLEDevice::m_synced) {
158177 NIMBLE_LOGE (LOG_TAG, " Host reset, wait for sync." );
159178 return false ;
@@ -177,10 +196,14 @@ bool NimBLEClient::connect(const NimBLEAddress& address, bool deleteAttributes)
177196 m_peerAddress = address;
178197 }
179198
199+ int rc = 0 ;
200+ m_asyncConnect = asyncConnect;
201+ m_exchangeMTU = exchangeMTU;
180202 TaskHandle_t cur_task = xTaskGetCurrentTaskHandle ();
181203 BleTaskData taskData = {this , cur_task, 0 , nullptr };
182- m_pTaskData = &taskData;
183- int rc = 0 ;
204+ if (!asyncConnect) {
205+ m_pTaskData = &taskData;
206+ }
184207
185208 // Set the connection in progress flag to prevent a scan from starting while connecting.
186209 NimBLEDevice::setConnectionInProgress (true );
@@ -214,6 +237,7 @@ bool NimBLEClient::connect(const NimBLEAddress& address, bool deleteAttributes)
214237 if (!NimBLEDevice::getScan ()->stop ()) {
215238 rc = BLE_HS_EUNKNOWN;
216239 }
240+ ble_gap_disc_cancel (); // we call this in case the app restarted the scan in the callback.
217241 break ;
218242
219243 case BLE_HS_EDONE:
@@ -242,10 +266,15 @@ bool NimBLEClient::connect(const NimBLEAddress& address, bool deleteAttributes)
242266 NimBLEDevice::setConnectionInProgress (false );
243267 m_lastErr = rc;
244268 if (rc != 0 ) {
269+ m_lastErr = rc;
245270 m_pTaskData = nullptr ;
246271 return false ;
247272 }
248273
274+ if (m_asyncConnect) {
275+ return true ;
276+ }
277+
249278# ifdef ulTaskNotifyValueClear
250279 // Clear the task notification value to ensure we block
251280 ulTaskNotifyValueClear (cur_task, ULONG_MAX);
@@ -278,10 +307,6 @@ bool NimBLEClient::connect(const NimBLEAddress& address, bool deleteAttributes)
278307 NIMBLE_LOGI (LOG_TAG, " Connection established" );
279308 }
280309
281- if (deleteAttributes) {
282- deleteServices ();
283- }
284-
285310 m_connEstablished = true ;
286311 m_pClientCallbacks->onConnect (this );
287312
@@ -854,6 +879,41 @@ uint16_t NimBLEClient::getMTU() const {
854879 return ble_att_mtu (m_connHandle);
855880} // getMTU
856881
882+ /* *
883+ * @brief Callback for the MTU exchange API function.
884+ * @details When the MTU exchange is complete the API will call this and report the new MTU.
885+ */
886+ int NimBLEClient::exchangeMTUCb (uint16_t conn_handle, const ble_gatt_error* error, uint16_t mtu, void * arg) {
887+ NIMBLE_LOGD (LOG_TAG, " exchangeMTUCb: status=%d, mtu=%d" , error->status , mtu);
888+
889+ NimBLEClient* pClient = (NimBLEClient*)arg;
890+ if (pClient->getConnHandle () != conn_handle) {
891+ return 0 ;
892+ }
893+
894+ if (error->status != 0 ) {
895+ NIMBLE_LOGE (LOG_TAG, " exchangeMTUCb() rc=%d %s" , error->status , NimBLEUtils::returnCodeToString (error->status ));
896+ pClient->m_lastErr = error->status ;
897+ }
898+
899+ return 0 ;
900+ }
901+
902+ /* *
903+ * @brief Begin the MTU exchange process with the server.
904+ * @returns true if the request was sent successfully.
905+ */
906+ bool NimBLEClient::exchangeMTU () {
907+ int rc = ble_gattc_exchange_mtu (m_connHandle, NimBLEClient::exchangeMTUCb, this );
908+ if (rc != 0 ) {
909+ NIMBLE_LOGE (LOG_TAG, " MTU exchange error; rc=%d %s" , rc, NimBLEUtils::returnCodeToString (rc));
910+ m_lastErr = rc;
911+ return false ;
912+ }
913+
914+ return true ;
915+ } // exchangeMTU
916+
857917/* *
858918 * @brief Handle a received GAP event.
859919 * @param [in] event The event structure sent by the NimBLE stack.
@@ -908,7 +968,7 @@ int NimBLEClient::handleGapEvent(struct ble_gap_event* event, void* arg) {
908968
909969 case BLE_GAP_EVENT_CONNECT: {
910970 // If we aren't waiting for this connection response we should drop the connection immediately.
911- if (pClient->isConnected () || pClient->m_pTaskData == nullptr ) {
971+ if (pClient->isConnected () || (! pClient->m_asyncConnect && pClient-> m_pTaskData == nullptr ) ) {
912972 ble_gap_terminate (event->connect .conn_handle , BLE_ERR_REM_USER_CONN_TERM);
913973 return 0 ;
914974 }
@@ -918,19 +978,28 @@ int NimBLEClient::handleGapEvent(struct ble_gap_event* event, void* arg) {
918978 NIMBLE_LOGI (LOG_TAG, " Connected event" );
919979
920980 pClient->m_connHandle = event->connect .conn_handle ;
921-
922- rc = ble_gattc_exchange_mtu ( pClient->m_connHandle , NULL , NULL );
923- if ( rc != 0 ) {
924- NIMBLE_LOGE (LOG_TAG, " MTU exchange error; rc=%d %s " , rc, NimBLEUtils::returnCodeToString (rc)) ;
925- break ;
981+ if (pClient-> m_exchangeMTU ) {
982+ if (! pClient->exchangeMTU () && !pClient-> m_asyncConnect ) {
983+ rc = pClient-> m_lastErr ;
984+ break ;
985+ }
926986 }
927987
928988 // In the case of a multi-connecting device we ignore this device when
929989 // scanning since we are already connected to it
930990 NimBLEDevice::addIgnored (pClient->m_peerAddress );
931991 } else {
932992 pClient->m_connHandle = BLE_HS_CONN_HANDLE_NONE;
933- break ;
993+ if (!pClient->m_asyncConnect ) {
994+ break ;
995+ }
996+ }
997+
998+ if (pClient->m_asyncConnect ) {
999+ pClient->m_connEstablished = rc == 0 ;
1000+ pClient->m_pClientCallbacks ->onConnect (pClient);
1001+ } else if (!pClient->m_exchangeMTU ) {
1002+ break ; // not wating for MTU exchange so release the task now.
9341003 }
9351004
9361005 return 0 ;
@@ -1072,7 +1141,9 @@ int NimBLEClient::handleGapEvent(struct ble_gap_event* event, void* arg) {
10721141 if (pClient->m_connHandle != event->mtu .conn_handle ) {
10731142 return 0 ;
10741143 }
1075- NIMBLE_LOGI (LOG_TAG, " mtu update event; conn_handle=%d mtu=%d" , event->mtu .conn_handle , event->mtu .value );
1144+
1145+ NIMBLE_LOGI (LOG_TAG, " mtu update: mtu=%d" , event->mtu .value );
1146+ pClient->m_pClientCallbacks ->onMTUChange (pClient, event->mtu .value );
10761147 rc = 0 ;
10771148 break ;
10781149 } // BLE_GAP_EVENT_MTU
@@ -1204,4 +1275,8 @@ void NimBLEClientCallbacks::onConfirmPasskey(NimBLEConnInfo& connInfo, uint32_t
12041275 NimBLEDevice::injectConfirmPasskey (connInfo, true );
12051276}
12061277
1278+ void NimBLEClientCallbacks::onMTUChange (NimBLEClient* pClient, uint16_t mtu) {
1279+ NIMBLE_LOGD (CB_TAG, " onMTUChange: default" );
1280+ }
1281+
12071282#endif /* CONFIG_BT_ENABLED && CONFIG_BT_NIMBLE_ROLE_CENTRAL */
0 commit comments