Fix for x86_64 build fail
[platform/upstream/connectedhomeip.git] / src / platform / ESP32 / bluedroid / BLEManagerImpl.cpp
1 /*
2  *
3  *    Copyright (c) 2020-2021 Project CHIP Authors
4  *    Copyright (c) 2018 Nest Labs, Inc.
5  *    All rights reserved.
6  *
7  *    Licensed under the Apache License, Version 2.0 (the "License");
8  *    you may not use this file except in compliance with the License.
9  *    You may obtain a copy of the License at
10  *
11  *        http://www.apache.org/licenses/LICENSE-2.0
12  *
13  *    Unless required by applicable law or agreed to in writing, software
14  *    distributed under the License is distributed on an "AS IS" BASIS,
15  *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  *    See the License for the specific language governing permissions and
17  *    limitations under the License.
18  */
19
20 /**
21  *    @file
22  *          Provides an implementation of the BLEManager singleton object
23  *          for the ESP32 platform.
24  */
25 /* this file behaves like a config.h, comes first */
26 #include <platform/internal/CHIPDeviceLayerInternal.h>
27
28 #if CHIP_DEVICE_CONFIG_ENABLE_CHIPOBLE
29
30 #include "sdkconfig.h"
31
32 #if CONFIG_BT_BLUEDROID_ENABLED
33
34 #include <ble/CHIPBleServiceData.h>
35 #include <platform/internal/BLEManager.h>
36 #include <support/CodeUtils.h>
37 #include <support/logging/CHIPLogging.h>
38
39 #include "esp_bt.h"
40 #include "esp_bt_main.h"
41 #include "esp_gap_ble_api.h"
42 #include "esp_gatt_common_api.h"
43 #include "esp_gatts_api.h"
44 #include "esp_log.h"
45
46 #define MAX_ADV_DATA_LEN 31
47 #define CHIP_ADV_DATA_TYPE_FLAGS 0x01
48 #define CHIP_ADV_DATA_FLAGS 0x06
49 #define CHIP_ADV_DATA_TYPE_SERVICE_DATA 0x16
50
51 using namespace ::chip;
52 using namespace ::chip::Ble;
53
54 namespace chip {
55 namespace DeviceLayer {
56 namespace Internal {
57
58 namespace {
59
60 struct ESP32ChipServiceData
61 {
62     uint8_t ServiceUUID[2];
63     ChipBLEDeviceIdentificationInfo DeviceIdInfo;
64 };
65
66 const uint16_t CHIPoBLEAppId = 0x235A;
67
68 const uint8_t UUID_PrimaryService[]        = { 0x00, 0x28 };
69 const uint8_t UUID_CharDecl[]              = { 0x03, 0x28 };
70 const uint8_t UUID_ClientCharConfigDesc[]  = { 0x02, 0x29 };
71 const uint8_t UUID_CHIPoBLEService[]       = { 0xFB, 0x34, 0x9B, 0x5F, 0x80, 0x00, 0x00, 0x80,
72                                          0x00, 0x10, 0x00, 0x00, 0xAF, 0xFE, 0x00, 0x00 };
73 const uint8_t ShortUUID_CHIPoBLEService[]  = { 0xAF, 0xFE };
74 const uint8_t UUID_CHIPoBLEChar_RX[]       = { 0x11, 0x9D, 0x9F, 0x42, 0x9C, 0x4F, 0x9F, 0x95,
75                                          0x59, 0x45, 0x3D, 0x26, 0xF5, 0x2E, 0xEE, 0x18 };
76 const uint8_t UUID_CHIPoBLEChar_TX[]       = { 0x12, 0x9D, 0x9F, 0x42, 0x9C, 0x4F, 0x9F, 0x95,
77                                          0x59, 0x45, 0x3D, 0x26, 0xF5, 0x2E, 0xEE, 0x18 };
78 const ChipBleUUID ChipUUID_CHIPoBLEChar_RX = { { 0x18, 0xEE, 0x2E, 0xF5, 0x26, 0x3D, 0x45, 0x59, 0x95, 0x9F, 0x4F, 0x9C, 0x42, 0x9F,
79                                                  0x9D, 0x11 } };
80 const ChipBleUUID ChipUUID_CHIPoBLEChar_TX = { { 0x18, 0xEE, 0x2E, 0xF5, 0x26, 0x3D, 0x45, 0x59, 0x95, 0x9F, 0x4F, 0x9C, 0x42, 0x9F,
81                                                  0x9D, 0x12 } };
82
83 const uint8_t CharProps_ReadNotify = ESP_GATT_CHAR_PROP_BIT_READ | ESP_GATT_CHAR_PROP_BIT_NOTIFY;
84 const uint8_t CharProps_Write      = ESP_GATT_CHAR_PROP_BIT_WRITE;
85
86 // Offsets into CHIPoBLEGATTAttrs for specific attributes.
87 enum
88 {
89     kAttrIndex_ServiceDeclaration = 0,
90     kAttrIndex_RXCharValue        = 2,
91     kAttrIndex_TXCharValue        = 4,
92     kAttrIndex_TXCharCCCDValue    = 5,
93 };
94
95 // Table of attribute definitions for Chip over BLE GATT service.
96 const esp_gatts_attr_db_t CHIPoBLEGATTAttrs[] = {
97     // Service Declaration for Chip over BLE Service
98     { { ESP_GATT_AUTO_RSP },
99       { ESP_UUID_LEN_16, (uint8_t *) UUID_PrimaryService, ESP_GATT_PERM_READ, ESP_UUID_LEN_16, ESP_UUID_LEN_16,
100         (uint8_t *) ShortUUID_CHIPoBLEService } },
101
102     // ----- Chip over BLE RX Characteristic -----
103
104     // Characteristic declaration
105     { { ESP_GATT_AUTO_RSP },
106       { ESP_UUID_LEN_16, (uint8_t *) UUID_CharDecl, ESP_GATT_PERM_READ, 1, 1, (uint8_t *) &CharProps_Write } },
107     // Characteristic value
108     { { ESP_GATT_RSP_BY_APP }, { ESP_UUID_LEN_128, (uint8_t *) UUID_CHIPoBLEChar_RX, ESP_GATT_PERM_WRITE, 512, 0, NULL } },
109
110     // ----- Chip over BLE TX Characteristic -----
111
112     // Characteristic declaration
113     { { ESP_GATT_AUTO_RSP },
114       { ESP_UUID_LEN_16, (uint8_t *) UUID_CharDecl, ESP_GATT_PERM_READ, 1, 1, (uint8_t *) &CharProps_ReadNotify } },
115     // Characteristic value
116     { { ESP_GATT_RSP_BY_APP }, { ESP_UUID_LEN_128, (uint8_t *) UUID_CHIPoBLEChar_TX, ESP_GATT_PERM_READ, 512, 0, NULL } },
117     // Client characteristic configuration description (CCCD) value
118     { { ESP_GATT_RSP_BY_APP },
119       { ESP_UUID_LEN_16, (uint8_t *) UUID_ClientCharConfigDesc, ESP_GATT_PERM_READ | ESP_GATT_PERM_WRITE, 2, 0, NULL } },
120 };
121
122 const uint16_t CHIPoBLEGATTAttrCount = sizeof(CHIPoBLEGATTAttrs) / sizeof(CHIPoBLEGATTAttrs[0]);
123
124 } // unnamed namespace
125
126 BLEManagerImpl BLEManagerImpl::sInstance;
127
128 BLEManagerImpl::BLEManagerImpl() {}
129
130 CHIP_ERROR BLEManagerImpl::_Init()
131 {
132     CHIP_ERROR err;
133
134     // Initialize the Chip BleLayer.
135     err = BleLayer::Init(this, this, &SystemLayer);
136     SuccessOrExit(err);
137
138     memset(mCons, 0, sizeof(mCons));
139     mServiceMode          = ConnectivityManager::kCHIPoBLEServiceMode_Enabled;
140     mAppIf                = ESP_GATT_IF_NONE;
141     mServiceAttrHandle    = 0;
142     mRXCharAttrHandle     = 0;
143     mTXCharAttrHandle     = 0;
144     mTXCharCCCDAttrHandle = 0;
145     mFlags.ClearAll().Set(Flags::kAdvertisingEnabled, CHIP_DEVICE_CONFIG_CHIPOBLE_ENABLE_ADVERTISING_AUTOSTART);
146     mFlags.Set(Flags::kFastAdvertisingEnabled, true);
147     memset(mDeviceName, 0, sizeof(mDeviceName));
148
149     PlatformMgr().ScheduleWork(DriveBLEState, 0);
150
151 exit:
152     return err;
153 }
154
155 CHIP_ERROR BLEManagerImpl::_SetCHIPoBLEServiceMode(CHIPoBLEServiceMode val)
156 {
157     CHIP_ERROR err = CHIP_NO_ERROR;
158
159     VerifyOrExit(val != ConnectivityManager::kCHIPoBLEServiceMode_NotSupported, err = CHIP_ERROR_INVALID_ARGUMENT);
160     VerifyOrExit(mServiceMode != ConnectivityManager::kCHIPoBLEServiceMode_NotSupported, err = CHIP_ERROR_UNSUPPORTED_CHIP_FEATURE);
161
162     if (val != mServiceMode)
163     {
164         mServiceMode = val;
165         PlatformMgr().ScheduleWork(DriveBLEState, 0);
166     }
167
168 exit:
169     return err;
170 }
171
172 CHIP_ERROR BLEManagerImpl::_SetAdvertisingEnabled(bool val)
173 {
174     CHIP_ERROR err = CHIP_NO_ERROR;
175
176     VerifyOrExit(mServiceMode != ConnectivityManager::kCHIPoBLEServiceMode_NotSupported, err = CHIP_ERROR_UNSUPPORTED_CHIP_FEATURE);
177
178     if (mFlags.Has(Flags::kAdvertisingEnabled) != val)
179     {
180         mFlags.Set(Flags::kAdvertisingEnabled, val);
181         PlatformMgr().ScheduleWork(DriveBLEState, 0);
182     }
183
184 exit:
185     return err;
186 }
187
188 CHIP_ERROR BLEManagerImpl::_SetAdvertisingMode(BLEAdvertisingMode mode)
189 {
190     switch (mode)
191     {
192     case BLEAdvertisingMode::kFastAdvertising:
193         mFlags.Set(Flags::kFastAdvertisingEnabled, true);
194         break;
195     case BLEAdvertisingMode::kSlowAdvertising:
196         mFlags.Set(Flags::kFastAdvertisingEnabled, false);
197         break;
198     default:
199         return CHIP_ERROR_INVALID_ARGUMENT;
200     }
201     mFlags.Set(Flags::kAdvertisingRefreshNeeded);
202     PlatformMgr().ScheduleWork(DriveBLEState, 0);
203     return CHIP_NO_ERROR;
204 }
205
206 CHIP_ERROR BLEManagerImpl::_GetDeviceName(char * buf, size_t bufSize)
207 {
208     if (strlen(mDeviceName) >= bufSize)
209     {
210         return CHIP_ERROR_BUFFER_TOO_SMALL;
211     }
212     strcpy(buf, mDeviceName);
213     return CHIP_NO_ERROR;
214 }
215
216 CHIP_ERROR BLEManagerImpl::_SetDeviceName(const char * deviceName)
217 {
218     if (mServiceMode == ConnectivityManager::kCHIPoBLEServiceMode_NotSupported)
219     {
220         return CHIP_ERROR_UNSUPPORTED_CHIP_FEATURE;
221     }
222     if (deviceName != NULL && deviceName[0] != 0)
223     {
224         if (strlen(deviceName) >= kMaxDeviceNameLength)
225         {
226             return CHIP_ERROR_INVALID_ARGUMENT;
227         }
228         strcpy(mDeviceName, deviceName);
229         mFlags.Set(Flags::kUseCustomDeviceName);
230     }
231     else
232     {
233         mDeviceName[0] = 0;
234         mFlags.Clear(Flags::kUseCustomDeviceName);
235     }
236     return CHIP_NO_ERROR;
237 }
238
239 void BLEManagerImpl::_OnPlatformEvent(const ChipDeviceEvent * event)
240 {
241     switch (event->Type)
242     {
243     case DeviceEventType::kCHIPoBLESubscribe:
244         HandleSubscribeReceived(event->CHIPoBLESubscribe.ConId, &CHIP_BLE_SVC_ID, &ChipUUID_CHIPoBLEChar_TX);
245         {
246             ChipDeviceEvent connectionEvent;
247             connectionEvent.Type = DeviceEventType::kCHIPoBLEConnectionEstablished;
248             PlatformMgr().PostEvent(&connectionEvent);
249         }
250         break;
251
252     case DeviceEventType::kCHIPoBLEUnsubscribe:
253         HandleUnsubscribeReceived(event->CHIPoBLEUnsubscribe.ConId, &CHIP_BLE_SVC_ID, &ChipUUID_CHIPoBLEChar_TX);
254         break;
255
256     case DeviceEventType::kCHIPoBLEWriteReceived:
257         HandleWriteReceived(event->CHIPoBLEWriteReceived.ConId, &CHIP_BLE_SVC_ID, &ChipUUID_CHIPoBLEChar_RX,
258                             PacketBufferHandle::Adopt(event->CHIPoBLEWriteReceived.Data));
259         break;
260
261     case DeviceEventType::kCHIPoBLEIndicateConfirm:
262         HandleIndicationConfirmation(event->CHIPoBLEIndicateConfirm.ConId, &CHIP_BLE_SVC_ID, &ChipUUID_CHIPoBLEChar_TX);
263         break;
264
265     case DeviceEventType::kCHIPoBLEConnectionError:
266         HandleConnectionError(event->CHIPoBLEConnectionError.ConId, event->CHIPoBLEConnectionError.Reason);
267         break;
268
269     case DeviceEventType::kFabricMembershipChange:
270     case DeviceEventType::kServiceProvisioningChange:
271     case DeviceEventType::kAccountPairingChange:
272     case DeviceEventType::kWiFiConnectivityChange:
273         // If CHIPOBLE_DISABLE_ADVERTISING_WHEN_PROVISIONED is enabled, and there is a change to the
274         // device's provisioning state, then automatically disable CHIPoBLE advertising if the device
275         // is now fully provisioned.
276 #if CHIP_DEVICE_CONFIG_CHIPOBLE_DISABLE_ADVERTISING_WHEN_PROVISIONED
277         if (ConfigurationMgr().IsFullyProvisioned())
278         {
279             mFlags.Clear(Flags::kAdvertisingEnabled);
280             ChipLogProgress(DeviceLayer, "CHIPoBLE advertising disabled because device is fully provisioned");
281         }
282 #endif // CHIP_DEVICE_CONFIG_CHIPOBLE_DISABLE_ADVERTISING_WHEN_PROVISIONED
283
284         // Force the advertising configuration to be refreshed to reflect new provisioning state.
285         ChipLogProgress(DeviceLayer, "Updating advertising data");
286         mFlags.Clear(Flags::kAdvertisingConfigured);
287         mFlags.Set(Flags::kAdvertisingRefreshNeeded);
288
289         DriveBLEState();
290
291     default:
292         break;
293     }
294 }
295
296 bool BLEManagerImpl::SubscribeCharacteristic(BLE_CONNECTION_OBJECT conId, const ChipBleUUID * svcId, const ChipBleUUID * charId)
297 {
298     ChipLogProgress(DeviceLayer, "BLEManagerImpl::SubscribeCharacteristic() not supported");
299     return false;
300 }
301
302 bool BLEManagerImpl::UnsubscribeCharacteristic(BLE_CONNECTION_OBJECT conId, const ChipBleUUID * svcId, const ChipBleUUID * charId)
303 {
304     ChipLogProgress(DeviceLayer, "BLEManagerImpl::UnsubscribeCharacteristic() not supported");
305     return false;
306 }
307
308 bool BLEManagerImpl::CloseConnection(BLE_CONNECTION_OBJECT conId)
309 {
310     CHIP_ERROR err;
311
312     ChipLogProgress(DeviceLayer, "Closing BLE GATT connection (con %u)", conId);
313
314     // Signal the ESP BLE layer to close the conntion.
315     err = esp_ble_gatts_close(mAppIf, conId);
316     if (err != CHIP_NO_ERROR)
317     {
318         ChipLogError(DeviceLayer, "esp_ble_gatts_close() failed: %s", ErrorStr(err));
319     }
320
321     // Release the associated connection state record.
322     ReleaseConnectionState(conId);
323
324     // Force a refresh of the advertising state.
325     mFlags.Set(Flags::kAdvertisingRefreshNeeded);
326     mFlags.Clear(Flags::kAdvertisingConfigured);
327     PlatformMgr().ScheduleWork(DriveBLEState, 0);
328
329     return (err == CHIP_NO_ERROR);
330 }
331
332 uint16_t BLEManagerImpl::GetMTU(BLE_CONNECTION_OBJECT conId) const
333 {
334     CHIPoBLEConState * conState = const_cast<BLEManagerImpl *>(this)->GetConnectionState(conId);
335     return (conState != NULL) ? conState->MTU : 0;
336 }
337
338 bool BLEManagerImpl::SendIndication(BLE_CONNECTION_OBJECT conId, const ChipBleUUID * svcId, const ChipBleUUID * charId,
339                                     PacketBufferHandle data)
340 {
341     CHIP_ERROR err              = CHIP_NO_ERROR;
342     CHIPoBLEConState * conState = GetConnectionState(conId);
343
344     ESP_LOGD(TAG, "Sending indication for CHIPoBLE TX characteristic (con %u, len %u)", conId, data->DataLength());
345
346     VerifyOrExit(conState != NULL, err = CHIP_ERROR_INVALID_ARGUMENT);
347
348     VerifyOrExit(conState->PendingIndBuf.IsNull(), err = CHIP_ERROR_INCORRECT_STATE);
349
350     err = esp_ble_gatts_send_indicate(mAppIf, conId, mTXCharAttrHandle, data->DataLength(), data->Start(), false);
351     if (err != CHIP_NO_ERROR)
352     {
353         ChipLogError(DeviceLayer, "esp_ble_gatts_send_indicate() failed: %s", ErrorStr(err));
354         ExitNow();
355     }
356
357     // Save a reference to the buffer until we get a indication from the ESP BLE layer that it
358     // has been sent.
359     conState->PendingIndBuf = std::move(data);
360
361 exit:
362     if (err != CHIP_NO_ERROR)
363     {
364         ChipLogError(DeviceLayer, "BLEManagerImpl::SendIndication() failed: %s", ErrorStr(err));
365         return false;
366     }
367     return true;
368 }
369
370 bool BLEManagerImpl::SendWriteRequest(BLE_CONNECTION_OBJECT conId, const ChipBleUUID * svcId, const ChipBleUUID * charId,
371                                       PacketBufferHandle pBuf)
372 {
373     ChipLogError(DeviceLayer, "BLEManagerImpl::SendWriteRequest() not supported");
374     return false;
375 }
376
377 bool BLEManagerImpl::SendReadRequest(BLE_CONNECTION_OBJECT conId, const ChipBleUUID * svcId, const ChipBleUUID * charId,
378                                      PacketBufferHandle pBuf)
379 {
380     ChipLogError(DeviceLayer, "BLEManagerImpl::SendReadRequest() not supported");
381     return false;
382 }
383
384 bool BLEManagerImpl::SendReadResponse(BLE_CONNECTION_OBJECT conId, BLE_READ_REQUEST_CONTEXT requestContext,
385                                       const ChipBleUUID * svcId, const ChipBleUUID * charId)
386 {
387     ChipLogError(DeviceLayer, "BLEManagerImpl::SendReadResponse() not supported");
388     return false;
389 }
390
391 void BLEManagerImpl::NotifyChipConnectionClosed(BLE_CONNECTION_OBJECT conId) {}
392
393 void BLEManagerImpl::DriveBLEState(void)
394 {
395     CHIP_ERROR err = CHIP_NO_ERROR;
396
397     // Perform any initialization actions that must occur after the Chip task is running.
398     if (!mFlags.Has(Flags::kAsyncInitCompleted))
399     {
400         mFlags.Set(Flags::kAsyncInitCompleted);
401
402         // If CHIP_DEVICE_CONFIG_CHIPOBLE_DISABLE_ADVERTISING_WHEN_PROVISIONED is enabled,
403         // disable CHIPoBLE advertising if the device is fully provisioned.
404 #if CHIP_DEVICE_CONFIG_CHIPOBLE_DISABLE_ADVERTISING_WHEN_PROVISIONED
405         if (ConfigurationMgr().IsFullyProvisioned())
406         {
407             mFlags.Clear(Flags::kAdvertisingEnabled);
408             ChipLogProgress(DeviceLayer, "CHIPoBLE advertising disabled because device is fully provisioned");
409         }
410 #endif // CHIP_DEVICE_CONFIG_CHIPOBLE_DISABLE_ADVERTISING_WHEN_PROVISIONED
411     }
412
413     // If there's already a control operation in progress, wait until it completes.
414     VerifyOrExit(!mFlags.Has(Flags::kControlOpInProgress), /* */);
415
416     // Initializes the ESP BLE layer if needed.
417     if (mServiceMode == ConnectivityManager::kCHIPoBLEServiceMode_Enabled && !mFlags.Has(Flags::kESPBLELayerInitialized))
418     {
419         err = InitESPBleLayer();
420         SuccessOrExit(err);
421     }
422
423     // Register the CHIPoBLE application with the ESP BLE layer if needed.
424     if (mServiceMode == ConnectivityManager::kCHIPoBLEServiceMode_Enabled && !mFlags.Has(Flags::kAppRegistered))
425     {
426         err = esp_ble_gatts_app_register(CHIPoBLEAppId);
427         if (err != CHIP_NO_ERROR)
428         {
429             ChipLogError(DeviceLayer, "esp_ble_gatts_app_register() failed: %s", ErrorStr(err));
430             ExitNow();
431         }
432
433         mFlags.Set(Flags::kControlOpInProgress);
434
435         ExitNow();
436     }
437
438     // Register the CHIPoBLE GATT attributes with the ESP BLE layer if needed.
439     if (mServiceMode == ConnectivityManager::kCHIPoBLEServiceMode_Enabled && !mFlags.Has(Flags::kAttrsRegistered))
440     {
441         err = esp_ble_gatts_create_attr_tab(CHIPoBLEGATTAttrs, mAppIf, CHIPoBLEGATTAttrCount, 0);
442         if (err != CHIP_NO_ERROR)
443         {
444             ChipLogError(DeviceLayer, "esp_ble_gatts_create_attr_tab() failed: %s", ErrorStr(err));
445             ExitNow();
446         }
447
448         mFlags.Set(Flags::kControlOpInProgress);
449
450         ExitNow();
451     }
452
453     // Start the CHIPoBLE GATT service if needed.
454     if (mServiceMode == ConnectivityManager::kCHIPoBLEServiceMode_Enabled && !mFlags.Has(Flags::kGATTServiceStarted))
455     {
456         err = esp_ble_gatts_start_service(mServiceAttrHandle);
457         if (err != CHIP_NO_ERROR)
458         {
459             ChipLogError(DeviceLayer, "esp_ble_gatts_start_service() failed: %s", ErrorStr(err));
460             ExitNow();
461         }
462
463         mFlags.Set(Flags::kControlOpInProgress);
464
465         ExitNow();
466     }
467
468     // If the application has enabled CHIPoBLE and BLE advertising...
469     if (mServiceMode == ConnectivityManager::kCHIPoBLEServiceMode_Enabled &&
470         mFlags.Has(Flags::kAdvertisingEnabled)
471 #if CHIP_DEVICE_CONFIG_CHIPOBLE_SINGLE_CONNECTION
472         // and no connections are active...
473         && (_NumConnections() == 0)
474 #endif
475     )
476     {
477         // Start/re-start advertising if not already advertising, or if the advertising state of the
478         // ESP BLE layer needs to be refreshed.
479         if (!mFlags.Has(Flags::kAdvertising) || mFlags.Has(Flags::kAdvertisingRefreshNeeded))
480         {
481             // Configure advertising data if it hasn't been done yet.  This is an asynchronous step which
482             // must complete before advertising can be started.  When that happens, this method will
483             // be called again, and execution will proceed to the code below.
484             if (!mFlags.Has(Flags::kAdvertisingConfigured))
485             {
486                 err = ConfigureAdvertisingData();
487                 ExitNow();
488             }
489
490             // Start advertising.  This is also an asynchronous step.
491             err = StartAdvertising();
492             ExitNow();
493         }
494     }
495
496     // Otherwise stop advertising if needed...
497     else
498     {
499         if (mFlags.Has(Flags::kAdvertising))
500         {
501             err = esp_ble_gap_stop_advertising();
502             if (err != CHIP_NO_ERROR)
503             {
504                 ChipLogError(DeviceLayer, "esp_ble_gap_stop_advertising() failed: %s", ErrorStr(err));
505                 ExitNow();
506             }
507
508             mFlags.Set(Flags::kControlOpInProgress);
509
510             ExitNow();
511         }
512     }
513
514     // Stop the CHIPoBLE GATT service if needed.
515     if (mServiceMode != ConnectivityManager::kCHIPoBLEServiceMode_Enabled && mFlags.Has(Flags::kGATTServiceStarted))
516     {
517         // TODO: what to do about existing connections??
518
519         err = esp_ble_gatts_stop_service(mServiceAttrHandle);
520         if (err != CHIP_NO_ERROR)
521         {
522             ChipLogError(DeviceLayer, "esp_ble_gatts_stop_service() failed: %s", ErrorStr(err));
523             ExitNow();
524         }
525
526         mFlags.Set(Flags::kControlOpInProgress);
527
528         ExitNow();
529     }
530
531 exit:
532     if (err != CHIP_NO_ERROR)
533     {
534         ChipLogError(DeviceLayer, "Disabling CHIPoBLE service due to error: %s", ErrorStr(err));
535         mServiceMode = ConnectivityManager::kCHIPoBLEServiceMode_Disabled;
536     }
537 }
538
539 CHIP_ERROR BLEManagerImpl::InitESPBleLayer(void)
540 {
541     CHIP_ERROR err = CHIP_NO_ERROR;
542
543     VerifyOrExit(!mFlags.Has(Flags::kESPBLELayerInitialized), /* */);
544
545     // If the ESP Bluetooth controller has not been initialized...
546     if (esp_bt_controller_get_status() == ESP_BT_CONTROLLER_STATUS_IDLE)
547     {
548         // Since Chip only uses BLE, release memory held by ESP classic bluetooth stack.
549         err = esp_bt_controller_mem_release(ESP_BT_MODE_CLASSIC_BT);
550         if (err != CHIP_NO_ERROR)
551         {
552             ChipLogError(DeviceLayer, "esp_bt_controller_mem_release() failed: %s", ErrorStr(err));
553             ExitNow();
554         }
555
556         // Initialize the ESP Bluetooth controller.
557         esp_bt_controller_config_t bt_cfg = BT_CONTROLLER_INIT_CONFIG_DEFAULT();
558         err                               = esp_bt_controller_init(&bt_cfg);
559         if (err != CHIP_NO_ERROR)
560         {
561             ChipLogError(DeviceLayer, "esp_bt_controller_init() failed: %s", ErrorStr(err));
562             ExitNow();
563         }
564     }
565
566     // If the ESP Bluetooth controller has not been enabled, enable it now.
567     if (esp_bt_controller_get_status() != ESP_BT_CONTROLLER_STATUS_ENABLED)
568     {
569         err = esp_bt_controller_enable(ESP_BT_MODE_BLE);
570         if (err != CHIP_NO_ERROR)
571         {
572             ChipLogError(DeviceLayer, "esp_bt_controller_enable() failed: %s", ErrorStr(err));
573             ExitNow();
574         }
575     }
576
577     // If the ESP Bluedroid stack has not been initialized, initialize it now.
578     if (esp_bluedroid_get_status() == ESP_BLUEDROID_STATUS_UNINITIALIZED)
579     {
580         err = esp_bluedroid_init();
581         if (err != CHIP_NO_ERROR)
582         {
583             ChipLogError(DeviceLayer, "esp_bluedroid_init() failed: %s", ErrorStr(err));
584             ExitNow();
585         }
586     }
587
588     // If the ESP Bluedroid stack has not been enabled, enable it now.
589     if (esp_bluedroid_get_status() != ESP_BLUEDROID_STATUS_ENABLED)
590     {
591         err = esp_bluedroid_enable();
592         if (err != CHIP_NO_ERROR)
593         {
594             ChipLogError(DeviceLayer, "esp_bluedroid_enable() failed: %s", ErrorStr(err));
595             ExitNow();
596         }
597     }
598
599     // Register a callback to receive GATT events.
600     err = esp_ble_gatts_register_callback(HandleGATTEvent);
601     if (err != CHIP_NO_ERROR)
602     {
603         ChipLogError(DeviceLayer, "esp_ble_gatts_register_callback() failed: %s", ErrorStr(err));
604         ExitNow();
605     }
606
607     // Register a callback to receive GAP events.
608     err = esp_ble_gap_register_callback(HandleGAPEvent);
609     if (err != CHIP_NO_ERROR)
610     {
611         ChipLogError(DeviceLayer, "esp_ble_gap_register_callback() failed: %s", ErrorStr(err));
612         ExitNow();
613     }
614
615     // Set the maximum supported MTU size.
616     err = esp_ble_gatt_set_local_mtu(ESP_GATT_MAX_MTU_SIZE);
617     if (err != CHIP_NO_ERROR)
618     {
619         ChipLogError(DeviceLayer, "esp_ble_gatt_set_local_mtu() failed: %s", ErrorStr(err));
620     }
621     SuccessOrExit(err);
622
623     mFlags.Set(Flags::kESPBLELayerInitialized);
624
625 exit:
626     return err;
627 }
628
629 CHIP_ERROR BLEManagerImpl::ConfigureAdvertisingData(void)
630 {
631     CHIP_ERROR err;
632     uint8_t advData[MAX_ADV_DATA_LEN];
633     uint8_t index = 0;
634
635     // If a custom device name has not been specified, generate a CHIP-standard name based on the
636     // discriminator value
637     uint16_t discriminator;
638     SuccessOrExit(err = ConfigurationMgr().GetSetupDiscriminator(discriminator));
639
640     if (!mFlags.Has(Flags::kUseCustomDeviceName))
641     {
642         snprintf(mDeviceName, sizeof(mDeviceName), "%s%04u", CHIP_DEVICE_CONFIG_BLE_DEVICE_NAME_PREFIX, discriminator);
643         mDeviceName[kMaxDeviceNameLength] = 0;
644     }
645
646     // Configure the BLE device name.
647     err = esp_ble_gap_set_device_name(mDeviceName);
648     if (err != CHIP_NO_ERROR)
649     {
650         ChipLogError(DeviceLayer, "esp_ble_gap_set_device_name() failed: %s", ErrorStr(err));
651         ExitNow();
652     }
653
654     memset(advData, 0, sizeof(advData));
655     advData[index++] = 0x02;                            // length
656     advData[index++] = CHIP_ADV_DATA_TYPE_FLAGS;        // AD type : flags
657     advData[index++] = CHIP_ADV_DATA_FLAGS;             // AD value
658     advData[index++] = 0x0A;                            // length
659     advData[index++] = CHIP_ADV_DATA_TYPE_SERVICE_DATA; // AD type: (Service Data - 16-bit UUID)
660     advData[index++] = ShortUUID_CHIPoBLEService[0];    // AD value
661     advData[index++] = ShortUUID_CHIPoBLEService[1];    // AD value
662
663     chip::Ble::ChipBLEDeviceIdentificationInfo deviceIdInfo;
664     err = ConfigurationMgr().GetBLEDeviceIdentificationInfo(deviceIdInfo);
665     if (err != CHIP_NO_ERROR)
666     {
667         ChipLogError(DeviceLayer, "GetBLEDeviceIdentificationInfo(): ", ErrorStr(err));
668         ExitNow();
669     }
670
671     VerifyOrExit(index + sizeof(deviceIdInfo) <= sizeof(advData), err = BLE_ERROR_OUTBOUND_MESSAGE_TOO_BIG);
672     memcpy(&advData[index], &deviceIdInfo, sizeof(deviceIdInfo));
673     index = static_cast<uint8_t>(index + sizeof(deviceIdInfo));
674
675     // Construct the Chip BLE Service Data to be sent in the scan response packet.
676     err = esp_ble_gap_config_adv_data_raw(advData, sizeof(advData));
677     if (err != CHIP_NO_ERROR)
678     {
679         ChipLogError(DeviceLayer, "esp_ble_gap_config_adv_data_raw(<raw_data>) failed: %s", ErrorStr(err));
680         ExitNow();
681     }
682
683     mFlags.Set(Flags::kControlOpInProgress);
684
685 exit:
686     return err;
687 }
688
689 CHIP_ERROR BLEManagerImpl::StartAdvertising(void)
690 {
691     CHIP_ERROR err;
692     esp_ble_adv_params_t advertParams = {
693         0,                                 // adv_int_min
694         0,                                 // adv_int_max
695         ADV_TYPE_IND,                      // adv_type
696         BLE_ADDR_TYPE_PUBLIC,              // own_addr_type
697         { 0 },                             // peer_addr
698         BLE_ADDR_TYPE_RANDOM,              // peer_addr_type
699         ADV_CHNL_ALL,                      // channel_map
700         ADV_FILTER_ALLOW_SCAN_ANY_CON_ANY, // adv_filter_policy
701     };
702
703     // Inform the ThreadStackManager that CHIPoBLE advertising is about to start.
704 #if CHIP_DEVICE_CONFIG_ENABLE_THREAD
705     ThreadStackMgr().OnCHIPoBLEAdvertisingStart();
706 #endif // CHIP_DEVICE_CONFIG_ENABLE_THREAD
707
708     // Advertise connectable if we haven't reached the maximum number of connections.
709     size_t numCons        = NumConnections();
710     bool connectable      = (numCons < kMaxConnections);
711     advertParams.adv_type = connectable ? ADV_TYPE_IND : ADV_TYPE_NONCONN_IND;
712
713     // Advertise in fast mode if not fully provisioned and there are no CHIPoBLE connections, or
714     // if the application has expressly requested fast advertising.
715     if ((numCons == 0 && !ConfigurationMgr().IsPairedToAccount()) || mFlags.Has(Flags::kFastAdvertisingEnabled))
716     {
717         advertParams.adv_int_min = CHIP_DEVICE_CONFIG_BLE_FAST_ADVERTISING_INTERVAL_MIN;
718         advertParams.adv_int_max = CHIP_DEVICE_CONFIG_BLE_FAST_ADVERTISING_INTERVAL_MAX;
719     }
720     else
721     {
722         advertParams.adv_int_min = CHIP_DEVICE_CONFIG_BLE_SLOW_ADVERTISING_INTERVAL_MIN;
723         advertParams.adv_int_max = CHIP_DEVICE_CONFIG_BLE_SLOW_ADVERTISING_INTERVAL_MAX;
724     }
725
726     ChipLogProgress(DeviceLayer, "Configuring CHIPoBLE advertising (interval %" PRIu32 " ms, %sconnectable, device name %s)",
727                     (((uint32_t) advertParams.adv_int_min) * 10) / 16, (connectable) ? "" : "non-", mDeviceName);
728
729     err = esp_ble_gap_start_advertising(&advertParams);
730     if (err != CHIP_NO_ERROR)
731     {
732         ChipLogError(DeviceLayer, "esp_ble_gap_start_advertising() failed: %s", ErrorStr(err));
733         ExitNow();
734     }
735
736     mFlags.Set(Flags::kControlOpInProgress);
737
738 exit:
739     return err;
740 }
741
742 void BLEManagerImpl::HandleGATTControlEvent(esp_gatts_cb_event_t event, esp_gatt_if_t gatts_if, esp_ble_gatts_cb_param_t * param)
743 {
744     CHIP_ERROR err         = CHIP_NO_ERROR;
745     bool controlOpComplete = false;
746
747     // Ignore GATT control events that do not pertain to the CHIPoBLE application, except for ESP_GATTS_REG_EVT.
748     if (event != ESP_GATTS_REG_EVT && (!mFlags.Has(Flags::kAppRegistered) || gatts_if != mAppIf))
749     {
750         ExitNow();
751     }
752
753     switch (event)
754     {
755     case ESP_GATTS_REG_EVT:
756
757         if (param->reg.app_id == CHIPoBLEAppId)
758         {
759             if (param->reg.status != ESP_GATT_OK)
760             {
761                 ChipLogError(DeviceLayer, "ESP_GATTS_REG_EVT error: %d", (int) param->reg.status);
762                 ExitNow(err = ESP_ERR_INVALID_RESPONSE);
763             }
764
765             // Save the 'interface type' assigned to the CHIPoBLE application by the ESP BLE layer.
766             mAppIf = gatts_if;
767
768             mFlags.Set(Flags::kAppRegistered);
769             controlOpComplete = true;
770         }
771
772         break;
773
774     case ESP_GATTS_CREAT_ATTR_TAB_EVT:
775
776         if (param->add_attr_tab.status != ESP_GATT_OK)
777         {
778             ChipLogError(DeviceLayer, "ESP_GATTS_CREAT_ATTR_TAB_EVT error: %d", (int) param->add_attr_tab.status);
779             ExitNow(err = ESP_ERR_INVALID_RESPONSE);
780         }
781
782         // Save the attribute handles assigned by the ESP BLE layer to the CHIPoBLE attributes.
783         mServiceAttrHandle    = param->add_attr_tab.handles[kAttrIndex_ServiceDeclaration];
784         mRXCharAttrHandle     = param->add_attr_tab.handles[kAttrIndex_RXCharValue];
785         mTXCharAttrHandle     = param->add_attr_tab.handles[kAttrIndex_TXCharValue];
786         mTXCharCCCDAttrHandle = param->add_attr_tab.handles[kAttrIndex_TXCharCCCDValue];
787
788         mFlags.Set(Flags::kAttrsRegistered);
789         controlOpComplete = true;
790
791         break;
792
793     case ESP_GATTS_START_EVT:
794
795         if (param->start.status != ESP_GATT_OK)
796         {
797             ChipLogError(DeviceLayer, "ESP_GATTS_START_EVT error: %d", (int) param->start.status);
798             ExitNow(err = ESP_ERR_INVALID_RESPONSE);
799         }
800
801         ChipLogProgress(DeviceLayer, "CHIPoBLE GATT service started");
802
803         mFlags.Set(Flags::kGATTServiceStarted);
804         controlOpComplete = true;
805
806         break;
807
808     case ESP_GATTS_STOP_EVT:
809
810         if (param->stop.status != ESP_GATT_OK)
811         {
812             ChipLogError(DeviceLayer, "ESP_GATTS_STOP_EVT error: %d", (int) param->stop.status);
813             ExitNow(err = ESP_ERR_INVALID_RESPONSE);
814         }
815
816         ChipLogProgress(DeviceLayer, "CHIPoBLE GATT service stopped");
817
818         mFlags.Clear(Flags::kGATTServiceStarted);
819         controlOpComplete = true;
820
821         break;
822
823     case ESP_GATTS_RESPONSE_EVT:
824         ESP_LOGD(TAG, "ESP_GATTS_RESPONSE_EVT (handle %u, status %d)", param->rsp.handle, (int) param->rsp.status);
825         break;
826
827     default:
828         // Ignore all other event types.
829         break;
830     }
831
832 exit:
833     if (err != CHIP_NO_ERROR)
834     {
835         ChipLogError(DeviceLayer, "Disabling CHIPoBLE service due to error: %s", ErrorStr(err));
836         mServiceMode = ConnectivityManager::kCHIPoBLEServiceMode_Disabled;
837     }
838     if (controlOpComplete)
839     {
840         mFlags.Clear(Flags::kControlOpInProgress);
841         PlatformMgr().ScheduleWork(DriveBLEState, 0);
842     }
843 }
844
845 void BLEManagerImpl::HandleGATTCommEvent(esp_gatts_cb_event_t event, esp_gatt_if_t gatts_if, esp_ble_gatts_cb_param_t * param)
846 {
847     // Ignore the event if the CHIPoBLE service hasn't been started, or if the event is for a different
848     // BLE application.
849     if (!sInstance.mFlags.Has(Flags::kGATTServiceStarted) || gatts_if != sInstance.mAppIf)
850     {
851         return;
852     }
853
854     switch (event)
855     {
856     case ESP_GATTS_CONNECT_EVT:
857         ChipLogProgress(DeviceLayer, "BLE GATT connection established (con %u)", param->connect.conn_id);
858
859         // Allocate a connection state record for the new connection.
860         GetConnectionState(param->mtu.conn_id, true);
861
862         // Receiving a connection stops the advertising processes.  So force a refresh of the advertising
863         // state.
864         mFlags.Set(Flags::kAdvertisingRefreshNeeded);
865         mFlags.Clear(Flags::kAdvertisingConfigured);
866         PlatformMgr().ScheduleWork(DriveBLEState, 0);
867
868         break;
869
870     case ESP_GATTS_DISCONNECT_EVT:
871         HandleDisconnect(param);
872         break;
873
874     case ESP_GATTS_READ_EVT:
875         if (param->read.handle == mTXCharAttrHandle)
876         {
877             HandleTXCharRead(param);
878         }
879         if (param->read.handle == mTXCharCCCDAttrHandle)
880         {
881             HandleTXCharCCCDRead(param);
882         }
883         break;
884
885     case ESP_GATTS_WRITE_EVT:
886         if (param->write.handle == mRXCharAttrHandle)
887         {
888             HandleRXCharWrite(param);
889         }
890         if (param->write.handle == mTXCharCCCDAttrHandle)
891         {
892             HandleTXCharCCCDWrite(param);
893         }
894         break;
895
896     case ESP_GATTS_CONF_EVT: {
897         CHIPoBLEConState * conState = GetConnectionState(param->conf.conn_id);
898         if (conState != NULL)
899         {
900             HandleTXCharConfirm(conState, param);
901         }
902     }
903     break;
904
905     case ESP_GATTS_MTU_EVT: {
906         ESP_LOGD(TAG, "MTU for con %u: %u", param->mtu.conn_id, param->mtu.mtu);
907         CHIPoBLEConState * conState = GetConnectionState(param->mtu.conn_id);
908         if (conState != NULL)
909         {
910             // conState->MTU is a 10-bit field inside a uint16_t.  We're
911             // assigning to it from a uint16_t, and compilers warn about
912             // possibly not fitting.  There's no way to suppress that warning
913             // via explicit cast; we have to disable the warning around the
914             // assignment.
915             //
916             // TODO: https://github.com/project-chip/connectedhomeip/issues/2569
917             // tracks making this safe with a check or explaining why no check
918             // is needed.
919 #pragma GCC diagnostic push
920 #pragma GCC diagnostic ignored "-Wconversion"
921             conState->MTU = param->mtu.mtu;
922 #pragma GCC diagnostic pop
923         }
924     }
925     break;
926
927     default:
928         break;
929     }
930 }
931
932 void BLEManagerImpl::HandleRXCharWrite(esp_ble_gatts_cb_param_t * param)
933 {
934     CHIP_ERROR err = CHIP_NO_ERROR;
935     bool needResp  = param->write.need_rsp;
936     PacketBufferHandle buf;
937
938     ESP_LOGD(TAG, "Write request received for CHIPoBLE RX characteristic (con %u, len %u)", param->write.conn_id, param->write.len);
939
940     // Disallow long writes.
941     VerifyOrExit(param->write.is_prep == false, err = CHIP_ERROR_INVALID_ARGUMENT);
942
943     // Copy the data to a packet buffer.
944     buf = System::PacketBufferHandle::NewWithData(param->write.value, param->write.len, 0, 0);
945     VerifyOrExit(!buf.IsNull(), err = CHIP_ERROR_NO_MEMORY);
946
947     // Send a response if requested.
948     if (needResp)
949     {
950         esp_ble_gatts_send_response(mAppIf, param->write.conn_id, param->write.trans_id, ESP_GATT_OK, NULL);
951         needResp = false;
952     }
953
954     // Post an event to the Chip queue to deliver the data into the Chip stack.
955     {
956         ChipDeviceEvent event;
957         event.Type                        = DeviceEventType::kCHIPoBLEWriteReceived;
958         event.CHIPoBLEWriteReceived.ConId = param->write.conn_id;
959         event.CHIPoBLEWriteReceived.Data  = std::move(buf).UnsafeRelease();
960         PlatformMgr().PostEvent(&event);
961     }
962
963 exit:
964     if (err != CHIP_NO_ERROR)
965     {
966         ChipLogError(DeviceLayer, "HandleRXCharWrite() failed: %s", ErrorStr(err));
967         if (needResp)
968         {
969             esp_ble_gatts_send_response(mAppIf, param->write.conn_id, param->write.trans_id, ESP_GATT_INTERNAL_ERROR, NULL);
970         }
971         // TODO: fail connection???
972     }
973 }
974
975 void BLEManagerImpl::HandleTXCharRead(esp_ble_gatts_cb_param_t * param)
976 {
977     CHIP_ERROR err;
978     esp_gatt_rsp_t rsp;
979
980     ESP_LOGD(TAG, "Read request received for CHIPoBLE TX characteristic (con %u)", param->read.conn_id);
981
982     // Send a zero-length response.
983     memset(&rsp, 0, sizeof(esp_gatt_rsp_t));
984     rsp.attr_value.handle = param->read.handle;
985     err                   = esp_ble_gatts_send_response(mAppIf, param->read.conn_id, param->read.trans_id, ESP_GATT_OK, &rsp);
986     if (err != CHIP_NO_ERROR)
987     {
988         ChipLogError(DeviceLayer, "esp_ble_gatts_send_response() failed: %s", ErrorStr(err));
989     }
990 }
991
992 void BLEManagerImpl::HandleTXCharCCCDRead(esp_ble_gatts_cb_param_t * param)
993 {
994     CHIP_ERROR err;
995     CHIPoBLEConState * conState;
996     esp_gatt_rsp_t rsp;
997
998     ESP_LOGD(TAG, "Read request received for CHIPoBLE TX characteristic CCCD (con %u)", param->read.conn_id);
999
1000     // Find the connection state record.
1001     conState = GetConnectionState(param->read.conn_id);
1002
1003     // Send current CCCD value, or an error if we failed to allocate a connection state object.
1004     memset(&rsp, 0, sizeof(esp_gatt_rsp_t));
1005     rsp.attr_value.handle = param->read.handle;
1006     if (conState != NULL)
1007     {
1008         rsp.attr_value.len      = 2;
1009         rsp.attr_value.value[0] = conState->Subscribed ? 1 : 0;
1010     }
1011     err = esp_ble_gatts_send_response(mAppIf, param->read.conn_id, param->read.trans_id,
1012                                       (conState != NULL) ? ESP_GATT_OK : ESP_GATT_INTERNAL_ERROR, &rsp);
1013     if (err != CHIP_NO_ERROR)
1014     {
1015         ChipLogError(DeviceLayer, "esp_ble_gatts_send_response() failed: %s", ErrorStr(err));
1016     }
1017 }
1018
1019 void BLEManagerImpl::HandleTXCharCCCDWrite(esp_ble_gatts_cb_param_t * param)
1020 {
1021     CHIP_ERROR err = CHIP_NO_ERROR;
1022     CHIPoBLEConState * conState;
1023     bool needResp = param->write.need_rsp;
1024     bool indicationsEnabled;
1025
1026     ESP_LOGD(TAG, "Write request received for CHIPoBLE TX characteristic CCCD (con %u, len %u)", param->write.conn_id,
1027              param->write.len);
1028
1029     // Find the connection state record.
1030     conState = GetConnectionState(param->read.conn_id);
1031     VerifyOrExit(conState != NULL, err = CHIP_ERROR_NO_MEMORY);
1032
1033     // Disallow long writes.
1034     VerifyOrExit(param->write.is_prep == false, err = CHIP_ERROR_INVALID_ARGUMENT);
1035
1036     // Determine if the client is enabling or disabling indications.
1037     indicationsEnabled = (param->write.len > 0 && (param->write.value[0] != 0));
1038
1039     // Send a response to the Write if requested.
1040     if (needResp)
1041     {
1042         esp_ble_gatts_send_response(mAppIf, param->write.conn_id, param->write.trans_id, ESP_GATT_OK, NULL);
1043         needResp = false;
1044     }
1045
1046     // Post an event to the Chip queue to process either a CHIPoBLE Subscribe or Unsubscribe based on
1047     // whether the client is enabling or disabling indications.
1048     {
1049         ChipDeviceEvent event;
1050         event.Type = (indicationsEnabled) ? DeviceEventType::kCHIPoBLESubscribe : DeviceEventType::kCHIPoBLEUnsubscribe;
1051         event.CHIPoBLESubscribe.ConId = param->write.conn_id;
1052         PlatformMgr().PostEvent(&event);
1053     }
1054
1055     ChipLogProgress(DeviceLayer, "CHIPoBLE %s received", indicationsEnabled ? "subscribe" : "unsubscribe");
1056
1057 exit:
1058     if (err != CHIP_NO_ERROR)
1059     {
1060         ChipLogError(DeviceLayer, "HandleTXCharCCCDWrite() failed: %s", ErrorStr(err));
1061         if (needResp)
1062         {
1063             esp_ble_gatts_send_response(mAppIf, param->write.conn_id, param->write.trans_id, ESP_GATT_INTERNAL_ERROR, NULL);
1064         }
1065         // TODO: fail connection???
1066     }
1067 }
1068
1069 void BLEManagerImpl::HandleTXCharConfirm(CHIPoBLEConState * conState, esp_ble_gatts_cb_param_t * param)
1070 {
1071     ESP_LOGD(TAG, "Confirm received for CHIPoBLE TX characteristic indication (con %u, status %u)", param->conf.conn_id,
1072              param->conf.status);
1073
1074     // If there is a pending indication buffer for the connection, release it now.
1075     conState->PendingIndBuf = nullptr;
1076
1077     // If the confirmation was successful...
1078     if (param->conf.status == ESP_GATT_OK)
1079     {
1080         // Post an event to the Chip queue to process the indicate confirmation.
1081         ChipDeviceEvent event;
1082         event.Type                          = DeviceEventType::kCHIPoBLEIndicateConfirm;
1083         event.CHIPoBLEIndicateConfirm.ConId = param->conf.conn_id;
1084         PlatformMgr().PostEvent(&event);
1085     }
1086
1087     else
1088     {
1089         ChipDeviceEvent event;
1090         event.Type                           = DeviceEventType::kCHIPoBLEConnectionError;
1091         event.CHIPoBLEConnectionError.ConId  = param->disconnect.conn_id;
1092         event.CHIPoBLEConnectionError.Reason = BLE_ERROR_CHIPOBLE_PROTOCOL_ABORT;
1093         PlatformMgr().PostEvent(&event);
1094     }
1095 }
1096
1097 void BLEManagerImpl::HandleDisconnect(esp_ble_gatts_cb_param_t * param)
1098 {
1099     ChipLogProgress(DeviceLayer, "BLE GATT connection closed (con %u, reason %u)", param->disconnect.conn_id,
1100                     param->disconnect.reason);
1101
1102     // If this was a CHIPoBLE connection, release the associated connection state record
1103     // and post an event to deliver a connection error to the CHIPoBLE layer.
1104     if (ReleaseConnectionState(param->disconnect.conn_id))
1105     {
1106         ChipDeviceEvent event;
1107         event.Type                          = DeviceEventType::kCHIPoBLEConnectionError;
1108         event.CHIPoBLEConnectionError.ConId = param->disconnect.conn_id;
1109         switch (param->disconnect.reason)
1110         {
1111         case ESP_GATT_CONN_TERMINATE_PEER_USER:
1112             event.CHIPoBLEConnectionError.Reason = BLE_ERROR_REMOTE_DEVICE_DISCONNECTED;
1113             break;
1114         case ESP_GATT_CONN_TERMINATE_LOCAL_HOST:
1115             event.CHIPoBLEConnectionError.Reason = BLE_ERROR_APP_CLOSED_CONNECTION;
1116             break;
1117         default:
1118             event.CHIPoBLEConnectionError.Reason = BLE_ERROR_CHIPOBLE_PROTOCOL_ABORT;
1119             break;
1120         }
1121         PlatformMgr().PostEvent(&event);
1122
1123         // Force a refresh of the advertising state.
1124         mFlags.Set(Flags::kAdvertisingRefreshNeeded);
1125         mFlags.Clear(Flags::kAdvertisingConfigured);
1126         PlatformMgr().ScheduleWork(DriveBLEState, 0);
1127     }
1128 }
1129
1130 BLEManagerImpl::CHIPoBLEConState * BLEManagerImpl::GetConnectionState(uint16_t conId, bool allocate)
1131 {
1132     uint16_t freeIndex = kMaxConnections;
1133
1134     for (uint16_t i = 0; i < kMaxConnections; i++)
1135     {
1136         if (mCons[i].Allocated == 1)
1137         {
1138             if (mCons[i].ConId == conId)
1139             {
1140                 return &mCons[i];
1141             }
1142         }
1143
1144         else if (i < freeIndex)
1145         {
1146             freeIndex = i;
1147         }
1148     }
1149
1150     if (allocate)
1151     {
1152         if (freeIndex < kMaxConnections)
1153         {
1154             mCons[freeIndex].Set(conId);
1155             return &mCons[freeIndex];
1156         }
1157
1158         ChipLogError(DeviceLayer, "Failed to allocate CHIPoBLEConState");
1159     }
1160
1161     return NULL;
1162 }
1163
1164 bool BLEManagerImpl::ReleaseConnectionState(uint16_t conId)
1165 {
1166     for (uint16_t i = 0; i < kMaxConnections; i++)
1167     {
1168         if (mCons[i].Allocated && mCons[i].ConId == conId)
1169         {
1170             mCons[i].Reset();
1171             return true;
1172         }
1173     }
1174
1175     return false;
1176 }
1177
1178 uint16_t BLEManagerImpl::_NumConnections(void)
1179 {
1180     uint16_t numCons = 0;
1181     for (uint16_t i = 0; i < kMaxConnections; i++)
1182     {
1183         if (mCons[i].Allocated)
1184         {
1185             numCons++;
1186         }
1187     }
1188
1189     return numCons;
1190 }
1191
1192 void BLEManagerImpl::HandleGATTEvent(esp_gatts_cb_event_t event, esp_gatt_if_t gatts_if, esp_ble_gatts_cb_param_t * param)
1193 {
1194     ESP_LOGV(TAG, "GATT Event: %d (if %d)", (int) event, (int) gatts_if);
1195
1196     // This method is invoked on the ESP BLE thread.  Therefore we must hold a lock
1197     // on the Chip stack while processing the event.
1198     PlatformMgr().LockChipStack();
1199
1200     sInstance.HandleGATTControlEvent(event, gatts_if, param);
1201     sInstance.HandleGATTCommEvent(event, gatts_if, param);
1202
1203     PlatformMgr().UnlockChipStack();
1204 }
1205
1206 void BLEManagerImpl::HandleGAPEvent(esp_gap_ble_cb_event_t event, esp_ble_gap_cb_param_t * param)
1207 {
1208     CHIP_ERROR err = CHIP_NO_ERROR;
1209
1210     ESP_LOGV(TAG, "GAP Event: %d", (int) event);
1211
1212     // This method is invoked on the ESP BLE thread.  Therefore we must hold a lock
1213     // on the Chip stack while processing the event.
1214     PlatformMgr().LockChipStack();
1215
1216     switch (event)
1217     {
1218     case ESP_GAP_BLE_ADV_DATA_RAW_SET_COMPLETE_EVT:
1219
1220         if (param->adv_data_cmpl.status != ESP_BT_STATUS_SUCCESS)
1221         {
1222             ChipLogError(DeviceLayer, "ESP_GAP_BLE_ADV_DATA_SET_COMPLETE_EVT error: %d", (int) param->adv_data_cmpl.status);
1223             ExitNow(err = ESP_ERR_INVALID_RESPONSE);
1224         }
1225
1226         sInstance.mFlags.Set(Flags::kAdvertisingConfigured);
1227         sInstance.mFlags.Clear(Flags::kControlOpInProgress);
1228
1229         break;
1230
1231     case ESP_GAP_BLE_ADV_START_COMPLETE_EVT:
1232
1233         if (param->adv_start_cmpl.status != ESP_BT_STATUS_SUCCESS)
1234         {
1235             ChipLogError(DeviceLayer, "ESP_GAP_BLE_ADV_START_COMPLETE_EVT error: %d", (int) param->adv_start_cmpl.status);
1236             ExitNow(err = ESP_ERR_INVALID_RESPONSE);
1237         }
1238
1239         sInstance.mFlags.Clear(Flags::kControlOpInProgress);
1240         sInstance.mFlags.Clear(Flags::kAdvertisingRefreshNeeded);
1241
1242         // Transition to the Advertising state...
1243         if (!sInstance.mFlags.Has(Flags::kAdvertising))
1244         {
1245             ChipLogProgress(DeviceLayer, "CHIPoBLE advertising started");
1246
1247             sInstance.mFlags.Set(Flags::kAdvertising);
1248
1249             // Post a CHIPoBLEAdvertisingChange(Started) event.
1250             {
1251                 ChipDeviceEvent advChange;
1252                 advChange.Type                             = DeviceEventType::kCHIPoBLEAdvertisingChange;
1253                 advChange.CHIPoBLEAdvertisingChange.Result = kActivity_Started;
1254                 PlatformMgr().PostEvent(&advChange);
1255             }
1256         }
1257
1258         break;
1259
1260     case ESP_GAP_BLE_ADV_STOP_COMPLETE_EVT:
1261
1262         if (param->adv_stop_cmpl.status != ESP_BT_STATUS_SUCCESS)
1263         {
1264             ChipLogError(DeviceLayer, "ESP_GAP_BLE_ADV_STOP_COMPLETE_EVT error: %d", (int) param->adv_stop_cmpl.status);
1265             ExitNow(err = ESP_ERR_INVALID_RESPONSE);
1266         }
1267
1268         sInstance.mFlags.Clear(Flags::kControlOpInProgress);
1269         sInstance.mFlags.Clear(Flags::kAdvertisingRefreshNeeded);
1270
1271         // Transition to the not Advertising state...
1272         if (sInstance.mFlags.Has(Flags::kAdvertising))
1273         {
1274             sInstance.mFlags.Clear(Flags::kAdvertising);
1275             sInstance.mFlags.Set(Flags::kFastAdvertisingEnabled, true);
1276
1277             ChipLogProgress(DeviceLayer, "CHIPoBLE advertising stopped");
1278
1279             // Directly inform the ThreadStackManager that CHIPoBLE advertising has stopped.
1280 #if CHIP_DEVICE_CONFIG_ENABLE_THREAD
1281             ThreadStackMgr().OnCHIPoBLEAdvertisingStop();
1282 #endif // CHIP_DEVICE_CONFIG_ENABLE_THREAD
1283
1284             // Post a CHIPoBLEAdvertisingChange(Stopped) event.
1285             {
1286                 ChipDeviceEvent advChange;
1287                 advChange.Type                             = DeviceEventType::kCHIPoBLEAdvertisingChange;
1288                 advChange.CHIPoBLEAdvertisingChange.Result = kActivity_Stopped;
1289                 PlatformMgr().PostEvent(&advChange);
1290             }
1291         }
1292
1293         break;
1294
1295     default:
1296         break;
1297     }
1298
1299 exit:
1300     if (err != CHIP_NO_ERROR)
1301     {
1302         ChipLogError(DeviceLayer, "Disabling CHIPoBLE service due to error: %s", ErrorStr(err));
1303         sInstance.mServiceMode = ConnectivityManager::kCHIPoBLEServiceMode_Disabled;
1304     }
1305     PlatformMgr().ScheduleWork(DriveBLEState, 0);
1306     PlatformMgr().UnlockChipStack();
1307 }
1308
1309 void BLEManagerImpl::DriveBLEState(intptr_t arg)
1310 {
1311     sInstance.DriveBLEState();
1312 }
1313
1314 } // namespace Internal
1315 } // namespace DeviceLayer
1316 } // namespace chip
1317
1318 #endif // CONFIG_BT_BLUEDROID_ENABLED
1319
1320 #endif // CHIP_DEVICE_CONFIG_ENABLE_CHIPOBLE