Fix for x86_64 build fail
[platform/upstream/connectedhomeip.git] / src / platform / ESP32 / nimble / BLEManagerImpl.cpp
1 /*
2  *
3  *    Copyright (c) 2020-2021 Project CHIP Authors
4  *    All rights reserved.
5  *
6  *    Licensed under the Apache License, Version 2.0 (the "License");
7  *    you may not use this file except in compliance with the License.
8  *    You may obtain a copy of the License at
9  *
10  *        http://www.apache.org/licenses/LICENSE-2.0
11  *
12  *    Unless required by applicable law or agreed to in writing, software
13  *    distributed under the License is distributed on an "AS IS" BASIS,
14  *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  *    See the License for the specific language governing permissions and
16  *    limitations under the License.
17  */
18
19 /**
20  *    @file
21  *          Provides an implementation of the BLEManager singleton object
22  *          for the ESP32 (NimBLE) platform.
23  */
24 /* this file behaves like a config.h, comes first */
25 #include <platform/internal/CHIPDeviceLayerInternal.h>
26
27 #if CHIP_DEVICE_CONFIG_ENABLE_CHIPOBLE
28
29 #include "sdkconfig.h"
30
31 #if CONFIG_BT_NIMBLE_ENABLED
32
33 #include <ble/CHIPBleServiceData.h>
34 #include <platform/internal/BLEManager.h>
35 #include <support/CodeUtils.h>
36 #include <support/logging/CHIPLogging.h>
37 #include <system/SystemTimer.h>
38
39 #include "esp_log.h"
40 #include "esp_nimble_hci.h"
41 #include "host/ble_hs.h"
42 #include "host/ble_hs_pvcy.h"
43 #include "host/ble_uuid.h"
44 #include "host/util/util.h"
45 #include "nimble/nimble_port.h"
46 #include "nimble/nimble_port_freertos.h"
47 #include "services/gap/ble_svc_gap.h"
48 #include "services/gatt/ble_svc_gatt.h"
49
50 #define MAX_ADV_DATA_LEN 31
51 #define CHIP_ADV_DATA_TYPE_FLAGS 0x01
52 #define CHIP_ADV_DATA_FLAGS 0x06
53 #define CHIP_ADV_DATA_TYPE_SERVICE_DATA 0x16
54
55 using namespace ::chip;
56 using namespace ::chip::Ble;
57
58 namespace chip {
59 namespace DeviceLayer {
60 namespace Internal {
61
62 namespace {
63
64 struct ESP32ChipServiceData
65 {
66     uint8_t ServiceUUID[2];
67     ChipBLEDeviceIdentificationInfo DeviceIdInfo;
68 };
69
70 const ble_uuid128_t UUID_CHIPoBLEService = {
71     BLE_UUID_TYPE_128, { 0xFB, 0x34, 0x9B, 0x5F, 0x80, 0x00, 0x00, 0x80, 0x00, 0x10, 0x00, 0x00, 0xAF, 0xFE, 0x00, 0x00 }
72 };
73 const ble_uuid16_t ShortUUID_CHIPoBLEService = { BLE_UUID_TYPE_16, 0xFEAF };
74
75 const ble_uuid128_t UUID128_CHIPoBLEChar_RX = {
76     BLE_UUID_TYPE_128, { 0x11, 0x9D, 0x9F, 0x42, 0x9C, 0x4F, 0x9F, 0x95, 0x59, 0x45, 0x3D, 0x26, 0xF5, 0x2E, 0xEE, 0x18 }
77 };
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 ble_uuid128_t UUID_CHIPoBLEChar_RX   = {
81     { BLE_UUID_TYPE_128 }, { 0x18, 0xEE, 0x2E, 0xF5, 0x26, 0x3D, 0x45, 0x59, 0x95, 0x9F, 0x4F, 0x9C, 0x42, 0x9F, 0x9D, 0x11 }
82 };
83
84 const ble_uuid128_t UUID128_CHIPoBLEChar_TX = {
85     BLE_UUID_TYPE_128, { 0x12, 0x9D, 0x9F, 0x42, 0x9C, 0x4F, 0x9F, 0x95, 0x59, 0x45, 0x3D, 0x26, 0xF5, 0x2E, 0xEE, 0x18 }
86 };
87 const ChipBleUUID chipUUID_CHIPoBLEChar_TX = { { 0x18, 0xEE, 0x2E, 0xF5, 0x26, 0x3D, 0x45, 0x59, 0x95, 0x9F, 0x4F, 0x9C, 0x42, 0x9F,
88                                                  0x9D, 0x12 } };
89 const ble_uuid128_t UUID_CHIPoBLEChar_TX   = {
90     { BLE_UUID_TYPE_128 }, { 0x12, 0x9D, 0x9F, 0x42, 0x9C, 0x4F, 0x9F, 0x95, 0x59, 0x45, 0x3D, 0x26, 0xF5, 0x2E, 0xEE, 0x18 }
91 };
92
93 } // unnamed namespace
94
95 BLEManagerImpl BLEManagerImpl::sInstance;
96
97 BLEManagerImpl::BLEManagerImpl() :
98     mAdvertiseTimerCallback(HandleAdvertisementTimer, this), mFastAdvertiseTimerCallback(HandleFastAdvertisementTimer, this)
99 {}
100
101 const struct ble_gatt_svc_def BLEManagerImpl::CHIPoBLEGATTAttrs[] = {
102     { .type = BLE_GATT_SVC_TYPE_PRIMARY,
103       .uuid = (ble_uuid_t *) (&ShortUUID_CHIPoBLEService),
104       .characteristics =
105           (struct ble_gatt_chr_def[]){
106               {
107                   .uuid       = (ble_uuid_t *) (&UUID128_CHIPoBLEChar_RX),
108                   .access_cb  = gatt_svr_chr_access,
109                   .flags      = BLE_GATT_CHR_F_WRITE,
110                   .val_handle = &sInstance.mRXCharAttrHandle,
111               },
112               {
113                   .uuid       = (ble_uuid_t *) (&UUID_CHIPoBLEChar_TX),
114                   .access_cb  = gatt_svr_chr_access,
115                   .flags      = BLE_GATT_CHR_F_READ | BLE_GATT_CHR_F_NOTIFY,
116                   .val_handle = &sInstance.mTXCharCCCDAttrHandle,
117               },
118               {
119                   0, /* No more characteristics in this service */
120               },
121           } },
122
123     {
124         0, /* No more services. */
125     },
126 };
127
128 CHIP_ERROR BLEManagerImpl::_Init()
129 {
130     CHIP_ERROR err;
131
132     // Initialize the Chip BleLayer.
133     err = BleLayer::Init(this, this, &SystemLayer);
134     SuccessOrExit(err);
135
136     mRXCharAttrHandle     = 0;
137     mTXCharCCCDAttrHandle = 0;
138     mFlags.ClearAll().Set(Flags::kAdvertisingEnabled, CHIP_DEVICE_CONFIG_CHIPOBLE_ENABLE_ADVERTISING_AUTOSTART);
139     mFlags.Set(Flags::kFastAdvertisingEnabled, true);
140     mNumGAPCons = 0;
141     memset(mCons, 0, sizeof(mCons));
142     mServiceMode = ConnectivityManager::kCHIPoBLEServiceMode_Enabled;
143     memset(mDeviceName, 0, sizeof(mDeviceName));
144
145     PlatformMgr().ScheduleWork(DriveBLEState, 0);
146
147 exit:
148     return err;
149 }
150
151 CHIP_ERROR BLEManagerImpl::_SetCHIPoBLEServiceMode(CHIPoBLEServiceMode val)
152 {
153     CHIP_ERROR err = CHIP_NO_ERROR;
154
155     VerifyOrExit(val != ConnectivityManager::kCHIPoBLEServiceMode_NotSupported, err = CHIP_ERROR_INVALID_ARGUMENT);
156     VerifyOrExit(mServiceMode != ConnectivityManager::kCHIPoBLEServiceMode_NotSupported, err = CHIP_ERROR_UNSUPPORTED_CHIP_FEATURE);
157
158     if (val != mServiceMode)
159     {
160         mServiceMode = val;
161         PlatformMgr().ScheduleWork(DriveBLEState, 0);
162     }
163
164 exit:
165     return err;
166 }
167
168 CHIP_ERROR BLEManagerImpl::_SetAdvertisingEnabled(bool val)
169 {
170     CHIP_ERROR err = CHIP_NO_ERROR;
171
172     VerifyOrExit(mServiceMode != ConnectivityManager::kCHIPoBLEServiceMode_NotSupported, err = CHIP_ERROR_UNSUPPORTED_CHIP_FEATURE);
173
174     if (val)
175     {
176         mAdvertiseStartTime = System::Timer::GetCurrentEpoch();
177         SystemLayer.StartTimer(kAdvertiseTimeout, &mAdvertiseTimerCallback);
178         SystemLayer.StartTimer(kFastAdvertiseTimeout, &mFastAdvertiseTimerCallback);
179     }
180
181     mFlags.Set(Flags::kFastAdvertisingEnabled, val);
182     mFlags.Set(Flags::kAdvertisingRefreshNeeded, 1);
183     mFlags.Set(Flags::kAdvertisingEnabled, val);
184     PlatformMgr().ScheduleWork(DriveBLEState, 0);
185
186 exit:
187     return err;
188 }
189
190 void BLEManagerImpl::HandleAdvertisementTimer(void * context)
191 {
192     static_cast<BLEManagerImpl *>(context)->HandleAdvertisementTimer();
193 }
194
195 void BLEManagerImpl::HandleAdvertisementTimer()
196 {
197     uint64_t currentTimestamp = System::Timer::GetCurrentEpoch();
198
199     if (currentTimestamp - mAdvertiseStartTime >= kAdvertiseTimeout)
200     {
201         mFlags.Set(Flags::kAdvertisingEnabled, 0);
202         PlatformMgr().ScheduleWork(DriveBLEState, 0);
203     }
204 }
205
206 void BLEManagerImpl::HandleFastAdvertisementTimer(void * context)
207 {
208     static_cast<BLEManagerImpl *>(context)->HandleFastAdvertisementTimer();
209 }
210
211 void BLEManagerImpl::HandleFastAdvertisementTimer()
212 {
213     uint64_t currentTimestamp = System::Timer::GetCurrentEpoch();
214
215     if (currentTimestamp - mAdvertiseStartTime >= kFastAdvertiseTimeout)
216     {
217         mFlags.Set(Flags::kFastAdvertisingEnabled, 0);
218         mFlags.Set(Flags::kAdvertisingRefreshNeeded, 1);
219         PlatformMgr().ScheduleWork(DriveBLEState, 0);
220     }
221 }
222
223 CHIP_ERROR BLEManagerImpl::_SetAdvertisingMode(BLEAdvertisingMode mode)
224 {
225     switch (mode)
226     {
227     case BLEAdvertisingMode::kFastAdvertising:
228         mFlags.Set(Flags::kFastAdvertisingEnabled, true);
229         break;
230     case BLEAdvertisingMode::kSlowAdvertising:
231         mFlags.Set(Flags::kFastAdvertisingEnabled, false);
232         break;
233     default:
234         return CHIP_ERROR_INVALID_ARGUMENT;
235     }
236     mFlags.Set(Flags::kAdvertisingRefreshNeeded);
237     PlatformMgr().ScheduleWork(DriveBLEState, 0);
238     return CHIP_NO_ERROR;
239 }
240
241 CHIP_ERROR BLEManagerImpl::_GetDeviceName(char * buf, size_t bufSize)
242 {
243     if (strlen(mDeviceName) >= bufSize)
244     {
245         return CHIP_ERROR_BUFFER_TOO_SMALL;
246     }
247     strcpy(buf, mDeviceName);
248     return CHIP_NO_ERROR;
249 }
250
251 CHIP_ERROR BLEManagerImpl::_SetDeviceName(const char * deviceName)
252 {
253     CHIP_ERROR err = CHIP_NO_ERROR;
254
255     VerifyOrExit(mServiceMode != ConnectivityManager::kCHIPoBLEServiceMode_NotSupported, err = CHIP_ERROR_UNSUPPORTED_CHIP_FEATURE);
256     if (deviceName != NULL && deviceName[0] != 0)
257     {
258         if (strlen(deviceName) >= kMaxDeviceNameLength)
259         {
260             return CHIP_ERROR_INVALID_ARGUMENT;
261         }
262         strcpy(mDeviceName, deviceName);
263         mFlags.Set(Flags::kUseCustomDeviceName);
264     }
265     else
266     {
267         mDeviceName[0] = 0;
268         mFlags.Clear(Flags::kUseCustomDeviceName);
269     }
270
271 exit:
272     return err;
273 }
274
275 void BLEManagerImpl::_OnPlatformEvent(const ChipDeviceEvent * event)
276 {
277     switch (event->Type)
278     {
279     case DeviceEventType::kCHIPoBLESubscribe:
280         HandleSubscribeReceived(event->CHIPoBLESubscribe.ConId, &CHIP_BLE_SVC_ID, &chipUUID_CHIPoBLEChar_TX);
281         {
282             ChipDeviceEvent connectionEvent;
283             connectionEvent.Type = DeviceEventType::kCHIPoBLEConnectionEstablished;
284             PlatformMgr().PostEvent(&connectionEvent);
285         }
286         break;
287
288     case DeviceEventType::kCHIPoBLEUnsubscribe:
289         HandleUnsubscribeReceived(event->CHIPoBLEUnsubscribe.ConId, &CHIP_BLE_SVC_ID, &chipUUID_CHIPoBLEChar_TX);
290         break;
291
292     case DeviceEventType::kCHIPoBLEWriteReceived:
293         HandleWriteReceived(event->CHIPoBLEWriteReceived.ConId, &CHIP_BLE_SVC_ID, &chipUUID_CHIPoBLEChar_RX,
294                             PacketBufferHandle::Adopt(event->CHIPoBLEWriteReceived.Data));
295         break;
296
297     case DeviceEventType::kCHIPoBLEIndicateConfirm:
298         HandleIndicationConfirmation(event->CHIPoBLEIndicateConfirm.ConId, &CHIP_BLE_SVC_ID, &chipUUID_CHIPoBLEChar_TX);
299         break;
300
301     case DeviceEventType::kCHIPoBLEConnectionError:
302         HandleConnectionError(event->CHIPoBLEConnectionError.ConId, event->CHIPoBLEConnectionError.Reason);
303         break;
304
305     case DeviceEventType::kFabricMembershipChange:
306     case DeviceEventType::kServiceProvisioningChange:
307     case DeviceEventType::kAccountPairingChange:
308     case DeviceEventType::kWiFiConnectivityChange:
309
310         // If CHIPOBLE_DISABLE_ADVERTISING_WHEN_PROVISIONED is enabled, and there is a change to the
311         // device's provisioning state, then automatically disable CHIPoBLE advertising if the device
312         // is now fully provisioned.
313 #if CHIP_DEVICE_CONFIG_CHIPOBLE_DISABLE_ADVERTISING_WHEN_PROVISIONED
314         if (ConfigurationMgr().IsFullyProvisioned())
315         {
316             mFlags.Clear(Flags::kAdvertisingEnabled);
317             ChipLogProgress(DeviceLayer, "CHIPoBLE advertising disabled because device is fully provisioned");
318         }
319 #endif // CHIP_DEVICE_CONFIG_CHIPOBLE_DISABLE_ADVERTISING_WHEN_PROVISIONED
320
321         // Force the advertising configuration to be refreshed to reflect new provisioning state.
322         ChipLogProgress(DeviceLayer, "Updating advertising data");
323         mFlags.Clear(Flags::kAdvertisingConfigured);
324         mFlags.Set(Flags::kAdvertisingRefreshNeeded);
325
326         DriveBLEState();
327         break;
328
329     default:
330         break;
331     }
332 }
333
334 bool BLEManagerImpl::SubscribeCharacteristic(BLE_CONNECTION_OBJECT conId, const ChipBleUUID * svcId, const ChipBleUUID * charId)
335 {
336     ChipLogProgress(DeviceLayer, "BLEManagerImpl::SubscribeCharacteristic() not supported");
337     return false;
338 }
339
340 bool BLEManagerImpl::UnsubscribeCharacteristic(BLE_CONNECTION_OBJECT conId, const ChipBleUUID * svcId, const ChipBleUUID * charId)
341 {
342     ChipLogProgress(DeviceLayer, "BLEManagerImpl::UnsubscribeCharacteristic() not supported");
343     return false;
344 }
345
346 bool BLEManagerImpl::CloseConnection(BLE_CONNECTION_OBJECT conId)
347 {
348     CHIP_ERROR err;
349
350     ChipLogProgress(DeviceLayer, "Closing BLE GATT connection (con %u)", conId);
351
352     // Signal the ESP BLE layer to close the conneecction.
353     err = ble_gap_terminate(conId, BLE_ERR_REM_USER_CONN_TERM);
354     if (err != CHIP_NO_ERROR)
355     {
356         ChipLogError(DeviceLayer, "ble_gap_terminate() failed: %s", ErrorStr(err));
357     }
358
359     // Force a refresh of the advertising state.
360     mFlags.Set(Flags::kAdvertisingRefreshNeeded);
361     mFlags.Clear(Flags::kAdvertisingConfigured);
362     PlatformMgr().ScheduleWork(DriveBLEState, 0);
363
364     return (err == CHIP_NO_ERROR);
365 }
366
367 uint16_t BLEManagerImpl::GetMTU(BLE_CONNECTION_OBJECT conId) const
368 {
369     return ble_att_mtu(conId);
370 }
371
372 bool BLEManagerImpl::SendIndication(BLE_CONNECTION_OBJECT conId, const ChipBleUUID * svcId, const ChipBleUUID * charId,
373                                     PacketBufferHandle data)
374 {
375     CHIP_ERROR err = CHIP_NO_ERROR;
376     struct os_mbuf * om;
377
378     VerifyOrExit(IsSubscribed(conId), err = CHIP_ERROR_INVALID_ARGUMENT);
379
380     ESP_LOGD(TAG, "Sending indication for CHIPoBLE TX characteristic (con %u, len %u)", conId, data->DataLength());
381
382     om = ble_hs_mbuf_from_flat(data->Start(), data->DataLength());
383     if (om == NULL)
384     {
385         ChipLogError(DeviceLayer, "ble_hs_mbuf_from_flat failed:");
386         err = CHIP_ERROR_NO_MEMORY;
387         ExitNow();
388     }
389
390     err = ble_gattc_notify_custom(conId, mTXCharCCCDAttrHandle, om);
391     if (err != CHIP_NO_ERROR)
392     {
393         ChipLogError(DeviceLayer, "ble_gattc_notify_custom() failed: %s", ErrorStr(err));
394         ExitNow();
395     }
396
397 exit:
398     if (err != CHIP_NO_ERROR)
399     {
400         ChipLogError(DeviceLayer, "BLEManagerImpl::SendIndication() failed: %s", ErrorStr(err));
401         return false;
402     }
403     return true;
404 }
405
406 bool BLEManagerImpl::SendWriteRequest(BLE_CONNECTION_OBJECT conId, const ChipBleUUID * svcId, const ChipBleUUID * charId,
407                                       PacketBufferHandle pBuf)
408 {
409     ChipLogError(DeviceLayer, "BLEManagerImpl::SendWriteRequest() not supported");
410     return false;
411 }
412
413 bool BLEManagerImpl::SendReadRequest(BLE_CONNECTION_OBJECT conId, const ChipBleUUID * svcId, const ChipBleUUID * charId,
414                                      PacketBufferHandle pBuf)
415 {
416     ChipLogError(DeviceLayer, "BLEManagerImpl::SendReadRequest() not supported");
417     return false;
418 }
419
420 bool BLEManagerImpl::SendReadResponse(BLE_CONNECTION_OBJECT conId, BLE_READ_REQUEST_CONTEXT requestContext,
421                                       const ChipBleUUID * svcId, const ChipBleUUID * charId)
422 {
423     ChipLogError(DeviceLayer, "BLEManagerImpl::SendReadResponse() not supported");
424     return false;
425 }
426
427 void BLEManagerImpl::NotifyChipConnectionClosed(BLE_CONNECTION_OBJECT conId) {}
428
429 void BLEManagerImpl::DriveBLEState(void)
430 {
431     int ret;
432     CHIP_ERROR err = CHIP_NO_ERROR;
433
434     // Perform any initialization actions that must occur after the Chip task is running.
435     if (!mFlags.Has(Flags::kAsyncInitCompleted))
436     {
437         mFlags.Set(Flags::kAsyncInitCompleted);
438
439         // If CHIP_DEVICE_CONFIG_CHIPOBLE_DISABLE_ADVERTISING_WHEN_PROVISIONED is enabled,
440         // disable CHIPoBLE advertising if the device is fully provisioned.
441 #if CHIP_DEVICE_CONFIG_CHIPOBLE_DISABLE_ADVERTISING_WHEN_PROVISIONED
442         if (ConfigurationMgr().IsFullyProvisioned())
443         {
444             mFlags.Clear(Flags::kAdvertisingEnabled);
445             ChipLogProgress(DeviceLayer, "CHIPoBLE advertising disabled because device is fully provisioned");
446         }
447 #endif // CHIP_DEVICE_CONFIG_CHIPOBLE_DISABLE_ADVERTISING_WHEN_PROVISIONED
448     }
449
450     // Initializes the ESP BLE layer if needed.
451     if (mServiceMode == ConnectivityManager::kCHIPoBLEServiceMode_Enabled && !mFlags.Has(Flags::kESPBLELayerInitialized))
452     {
453         err = InitESPBleLayer();
454         SuccessOrExit(err);
455
456         // Add delay of 500msec while NimBLE host task gets up and running
457         {
458             vTaskDelay(500 / portTICK_RATE_MS);
459         }
460     }
461
462     // If the application has enabled CHIPoBLE and BLE advertising...
463     if (mServiceMode == ConnectivityManager::kCHIPoBLEServiceMode_Enabled &&
464         mFlags.Has(Flags::kAdvertisingEnabled)
465 #if CHIP_DEVICE_CONFIG_CHIPOBLE_SINGLE_CONNECTION
466         // and no connections are active...
467         && (_NumConnections() == 0)
468 #endif
469     )
470     {
471         // Start/re-start advertising if not already advertising, or if the advertising state of the
472         // ESP BLE layer needs to be refreshed.
473         if (!mFlags.Has(Flags::kAdvertising) || mFlags.Has(Flags::kAdvertisingRefreshNeeded))
474         {
475             // Configure advertising data if it hasn't been done yet.  This is an asynchronous step which
476             // must complete before advertising can be started.  When that happens, this method will
477             // be called again, and execution will proceed to the code below.
478             if (!mFlags.Has(Flags::kAdvertisingConfigured))
479             {
480                 err = ConfigureAdvertisingData();
481                 if (err != CHIP_NO_ERROR)
482                 {
483                     ChipLogError(DeviceLayer, "Configure Adv Data failed: %s", ErrorStr(err));
484                     ExitNow();
485                 }
486             }
487
488             // Start advertising.  This is also an asynchronous step.
489             ESP_LOGD(TAG, "NimBLE start advertising...");
490             err = StartAdvertising();
491             if (err != CHIP_NO_ERROR)
492             {
493                 ChipLogError(DeviceLayer, "Start advertising failed: %s", ErrorStr(err));
494                 ExitNow();
495             }
496
497             mFlags.Clear(Flags::kAdvertisingRefreshNeeded);
498             // Transition to the Advertising state...
499             if (!mFlags.Has(Flags::kAdvertising))
500             {
501                 ChipLogProgress(DeviceLayer, "CHIPoBLE advertising started");
502
503                 mFlags.Set(Flags::kAdvertising);
504
505                 // Post a CHIPoBLEAdvertisingChange(Started) event.
506                 {
507                     ChipDeviceEvent advChange;
508                     advChange.Type                             = DeviceEventType::kCHIPoBLEAdvertisingChange;
509                     advChange.CHIPoBLEAdvertisingChange.Result = kActivity_Started;
510                     PlatformMgr().PostEvent(&advChange);
511                 }
512             }
513         }
514     }
515
516     // Otherwise stop advertising if needed...
517     else
518     {
519         if (mFlags.Has(Flags::kAdvertising))
520         {
521             ret = ble_gap_adv_stop();
522             if (ret != 0)
523             {
524                 err = CHIP_ERROR_INTERNAL;
525                 ChipLogError(DeviceLayer, "ble_gap_adv_stop() failed: %s", ErrorStr(err));
526                 ExitNow();
527             }
528
529             // mFlags.Clear(Flags::kAdvertisingRefreshNeeded);
530
531             // Transition to the not Advertising state...
532             if (mFlags.Has(Flags::kAdvertising))
533             {
534                 mFlags.Clear(Flags::kAdvertising);
535                 mFlags.Set(Flags::kFastAdvertisingEnabled, true);
536
537                 ChipLogProgress(DeviceLayer, "CHIPoBLE advertising stopped");
538
539                 // Directly inform the ThreadStackManager that CHIPoBLE advertising has stopped.
540 #if CHIP_DEVICE_CONFIG_ENABLE_THREAD
541                 ThreadStackMgr().OnCHIPoBLEAdvertisingStop();
542 #endif // CHIP_DEVICE_CONFIG_ENABLE_THREAD
543
544                 // Post a CHIPoBLEAdvertisingChange(Stopped) event.
545                 {
546                     ChipDeviceEvent advChange;
547                     advChange.Type                             = DeviceEventType::kCHIPoBLEAdvertisingChange;
548                     advChange.CHIPoBLEAdvertisingChange.Result = kActivity_Stopped;
549                     PlatformMgr().PostEvent(&advChange);
550                 }
551             }
552
553             ExitNow();
554         }
555     }
556
557     // Stop the CHIPoBLE GATT service if needed.
558     if (mServiceMode != ConnectivityManager::kCHIPoBLEServiceMode_Enabled && mFlags.Has(Flags::kGATTServiceStarted))
559     {
560         // TODO: Not supported
561     }
562
563 exit:
564     if (err != CHIP_NO_ERROR)
565     {
566         ChipLogError(DeviceLayer, "Disabling CHIPoBLE service due to error: %s", ErrorStr(err));
567         mServiceMode = ConnectivityManager::kCHIPoBLEServiceMode_Disabled;
568     }
569 }
570
571 void BLEManagerImpl::bleprph_on_reset(int reason)
572 {
573     ESP_LOGE(TAG, "Resetting state; reason=%d\n", reason);
574 }
575
576 void BLEManagerImpl::bleprph_on_sync(void)
577 {
578     sInstance.mFlags.Set(Flags::kESPBLELayerInitialized);
579     sInstance.mFlags.Set(Flags::kGATTServiceStarted);
580     ESP_LOGI(TAG, "BLE host-controller synced");
581 }
582
583 void BLEManagerImpl::bleprph_host_task(void * param)
584 {
585     ESP_LOGD(TAG, "BLE Host Task Started");
586     /* This function will return only when nimble_port_stop() is executed */
587     nimble_port_run();
588     nimble_port_freertos_deinit();
589 }
590
591 CHIP_ERROR BLEManagerImpl::InitESPBleLayer(void)
592 {
593     CHIP_ERROR err = CHIP_NO_ERROR;
594
595     VerifyOrExit(!mFlags.Has(Flags::kESPBLELayerInitialized), /* */);
596
597     for (int i = 0; i < kMaxConnections; i++)
598     {
599         mSubscribedConIds[i] = BLE_CONNECTION_UNINITIALIZED;
600     }
601
602     err = esp_nimble_hci_and_controller_init();
603     SuccessOrExit(err);
604
605     nimble_port_init();
606
607     /* Initialize the NimBLE host configuration. */
608     ble_hs_cfg.reset_cb          = bleprph_on_reset;
609     ble_hs_cfg.sync_cb           = bleprph_on_sync;
610     ble_hs_cfg.store_status_cb   = ble_store_util_status_rr;
611     ble_hs_cfg.sm_bonding        = 1;
612     ble_hs_cfg.sm_our_key_dist   = BLE_SM_PAIR_KEY_DIST_ENC | BLE_SM_PAIR_KEY_DIST_ID;
613     ble_hs_cfg.sm_their_key_dist = BLE_SM_PAIR_KEY_DIST_ENC | BLE_SM_PAIR_KEY_DIST_ID;
614
615     // Register the CHIPoBLE GATT attributes with the ESP BLE layer if needed.
616     if (mServiceMode == ConnectivityManager::kCHIPoBLEServiceMode_Enabled)
617     {
618         ble_svc_gap_init();
619         ble_svc_gatt_init();
620
621         err = ble_gatts_count_cfg(CHIPoBLEGATTAttrs);
622         if (err != CHIP_NO_ERROR)
623         {
624             ChipLogError(DeviceLayer, "ble_gatts_count_cfg failed: %s", ErrorStr(err));
625             ExitNow();
626         }
627
628         err = ble_gatts_add_svcs(CHIPoBLEGATTAttrs);
629         if (err != CHIP_NO_ERROR)
630         {
631             ChipLogError(DeviceLayer, "ble_gatts_add_svcs failed: %s", ErrorStr(err));
632             ExitNow();
633         }
634     }
635
636     nimble_port_freertos_init(bleprph_host_task);
637
638 exit:
639     return err;
640 }
641
642 CHIP_ERROR BLEManagerImpl::ConfigureAdvertisingData(void)
643 {
644     CHIP_ERROR err;
645     uint8_t advData[MAX_ADV_DATA_LEN];
646     uint8_t index = 0;
647
648     // If a custom device name has not been specified, generate a CHIP-standard name based on the
649     // bottom digits of the Chip device id.
650     uint16_t discriminator;
651     SuccessOrExit(err = ConfigurationMgr().GetSetupDiscriminator(discriminator));
652
653     if (!mFlags.Has(Flags::kUseCustomDeviceName))
654     {
655         snprintf(mDeviceName, sizeof(mDeviceName), "%s%04u", CHIP_DEVICE_CONFIG_BLE_DEVICE_NAME_PREFIX, discriminator);
656         mDeviceName[kMaxDeviceNameLength] = 0;
657     }
658
659     // Configure the BLE device name.
660     err = ble_svc_gap_device_name_set(mDeviceName);
661     if (err != CHIP_NO_ERROR)
662     {
663         ChipLogError(DeviceLayer, "ble_svc_gap_device_name_set() failed: %s", ErrorStr(err));
664         ExitNow();
665     }
666
667     memset(advData, 0, sizeof(advData));
668     advData[index++] = 0x02;                                                                // length
669     advData[index++] = CHIP_ADV_DATA_TYPE_FLAGS;                                            // AD type : flags
670     advData[index++] = CHIP_ADV_DATA_FLAGS;                                                 // AD value
671     advData[index++] = 0x0A;                                                                // length
672     advData[index++] = CHIP_ADV_DATA_TYPE_SERVICE_DATA;                                     // AD type: (Service Data - 16-bit UUID)
673     advData[index++] = static_cast<uint8_t>(ShortUUID_CHIPoBLEService.value & 0xFF);        // AD value
674     advData[index++] = static_cast<uint8_t>((ShortUUID_CHIPoBLEService.value >> 8) & 0xFF); // AD value
675
676     chip::Ble::ChipBLEDeviceIdentificationInfo deviceIdInfo;
677     err = ConfigurationMgr().GetBLEDeviceIdentificationInfo(deviceIdInfo);
678     if (err != CHIP_NO_ERROR)
679     {
680         ChipLogError(DeviceLayer, "GetBLEDeviceIdentificationInfo(): %s", ErrorStr(err));
681         ExitNow();
682     }
683
684     VerifyOrExit(index + sizeof(deviceIdInfo) <= sizeof(advData), err = BLE_ERROR_OUTBOUND_MESSAGE_TOO_BIG);
685     memcpy(&advData[index], &deviceIdInfo, sizeof(deviceIdInfo));
686     index = static_cast<uint8_t>(index + sizeof(deviceIdInfo));
687
688     // Construct the Chip BLE Service Data to be sent in the scan response packet.
689     err = ble_gap_adv_set_data(advData, sizeof(advData));
690     if (err != CHIP_NO_ERROR)
691     {
692         ChipLogError(DeviceLayer, "ble_gap_adv_set_data failed: %s %d", ErrorStr(err), discriminator);
693         ExitNow();
694     }
695
696 exit:
697     return err;
698 }
699
700 void BLEManagerImpl::HandleRXCharWrite(struct ble_gatt_char_context * param)
701 {
702     CHIP_ERROR err    = CHIP_NO_ERROR;
703     uint16_t data_len = 0;
704
705     ESP_LOGI(TAG, "Write request received for CHIPoBLE RX characteristic con %u %u", param->conn_handle, param->attr_handle);
706
707     // Copy the data to a packet buffer.
708     data_len               = OS_MBUF_PKTLEN(param->ctxt->om);
709     PacketBufferHandle buf = System::PacketBufferHandle::New(data_len, 0);
710     VerifyOrExit(!buf.IsNull(), err = CHIP_ERROR_NO_MEMORY);
711     VerifyOrExit(buf->AvailableDataLength() >= data_len, err = CHIP_ERROR_BUFFER_TOO_SMALL);
712     ble_hs_mbuf_to_flat(param->ctxt->om, buf->Start(), data_len, NULL);
713     buf->SetDataLength(data_len);
714
715     // Post an event to the Chip queue to deliver the data into the Chip stack.
716     {
717         ChipDeviceEvent event;
718         event.Type                        = DeviceEventType::kCHIPoBLEWriteReceived;
719         event.CHIPoBLEWriteReceived.ConId = param->conn_handle;
720         event.CHIPoBLEWriteReceived.Data  = std::move(buf).UnsafeRelease();
721         PlatformMgr().PostEvent(&event);
722     }
723
724 exit:
725     if (err != CHIP_NO_ERROR)
726     {
727         ChipLogError(DeviceLayer, "HandleRXCharWrite() failed: %s", ErrorStr(err));
728     }
729 }
730
731 void BLEManagerImpl::HandleTXCharRead(struct ble_gatt_char_context * param)
732 {
733     /* Not supported */
734     ChipLogError(DeviceLayer, "BLEManagerImpl::HandleTXCharRead() not supported");
735 }
736
737 void BLEManagerImpl::HandleTXCharCCCDRead(void * param)
738 {
739     /* Not Supported */
740     ChipLogError(DeviceLayer, "BLEManagerImpl::HandleTXCharCCCDRead() not supported");
741 }
742
743 void BLEManagerImpl::HandleTXCharCCCDWrite(struct ble_gap_event * gapEvent)
744 {
745     CHIP_ERROR err = CHIP_NO_ERROR;
746     bool indicationsEnabled;
747     bool notificationsEnabled;
748
749     ChipLogProgress(DeviceLayer,
750                     "Write request/command received for CHIPoBLE TX CCCD characteristic (con %" PRIu16
751                     " ) indicate = %d notify = %d",
752                     gapEvent->subscribe.conn_handle, gapEvent->subscribe.cur_indicate, gapEvent->subscribe.cur_notify);
753
754     // Determine if the client is enabling or disabling indications/notification.
755     indicationsEnabled   = gapEvent->subscribe.cur_indicate;
756     notificationsEnabled = gapEvent->subscribe.cur_notify;
757
758     // If the client has requested to enabled indications/notifications
759     if (indicationsEnabled || notificationsEnabled)
760     {
761         // If indications are not already enabled for the connection...
762         if (!IsSubscribed(gapEvent->subscribe.conn_handle))
763         {
764             // Record that indications have been enabled for this connection.  If this fails because
765             err = SetSubscribed(gapEvent->subscribe.conn_handle);
766             VerifyOrExit(err != CHIP_ERROR_NO_MEMORY, err = CHIP_NO_ERROR);
767             SuccessOrExit(err);
768         }
769     }
770
771     else
772     {
773         // If indications had previously been enabled for this connection, record that they are no longer
774         // enabled.
775         UnsetSubscribed(gapEvent->subscribe.conn_handle);
776     }
777
778     // Post an event to the Chip queue to process either a CHIPoBLE Subscribe or Unsubscribe based on
779     // whether the client is enabling or disabling indications.
780     {
781         ChipDeviceEvent event;
782         event.Type = (indicationsEnabled || notificationsEnabled) ? DeviceEventType::kCHIPoBLESubscribe
783                                                                   : DeviceEventType::kCHIPoBLEUnsubscribe;
784         event.CHIPoBLESubscribe.ConId = gapEvent->subscribe.conn_handle;
785         PlatformMgr().PostEvent(&event);
786     }
787
788     ChipLogProgress(DeviceLayer, "CHIPoBLE %s received",
789                     (indicationsEnabled || notificationsEnabled) ? "subscribe" : "unsubscribe");
790
791 exit:
792     if (err != CHIP_NO_ERROR)
793     {
794         ChipLogError(DeviceLayer, "HandleTXCharCCCDWrite() failed: %s", ErrorStr(err));
795         // TODO: fail connection???
796     }
797
798     return;
799 }
800
801 CHIP_ERROR BLEManagerImpl::HandleTXComplete(struct ble_gap_event * gapEvent)
802 {
803     ChipLogProgress(DeviceLayer, "Confirm received for CHIPoBLE TX characteristic indication (con %" PRIu16 ") status= %d ",
804                     gapEvent->notify_tx.conn_handle, gapEvent->notify_tx.status);
805
806     // Signal the BLE Layer that the outstanding indication is complete.
807     if (gapEvent->notify_tx.status == 0 || gapEvent->notify_tx.status == BLE_HS_EDONE)
808     {
809         // Post an event to the Chip queue to process the indicate confirmation.
810         ChipDeviceEvent event;
811         event.Type                          = DeviceEventType::kCHIPoBLEIndicateConfirm;
812         event.CHIPoBLEIndicateConfirm.ConId = gapEvent->notify_tx.conn_handle;
813         PlatformMgr().PostEvent(&event);
814     }
815
816     else
817     {
818         ChipDeviceEvent event;
819         event.Type                           = DeviceEventType::kCHIPoBLEConnectionError;
820         event.CHIPoBLEConnectionError.ConId  = gapEvent->notify_tx.conn_handle;
821         event.CHIPoBLEConnectionError.Reason = BLE_ERROR_CHIPOBLE_PROTOCOL_ABORT;
822         PlatformMgr().PostEvent(&event);
823     }
824
825     return CHIP_NO_ERROR;
826 }
827
828 uint16_t BLEManagerImpl::_NumConnections(void)
829 {
830     uint16_t numCons = 0;
831     for (uint16_t i = 0; i < kMaxConnections; i++)
832     {
833         if (mSubscribedConIds[i] != BLE_CONNECTION_UNINITIALIZED)
834         {
835             numCons++;
836         }
837     }
838
839     return numCons;
840 }
841
842 CHIP_ERROR BLEManagerImpl::HandleGAPConnect(struct ble_gap_event * gapEvent)
843 {
844     CHIP_ERROR err = CHIP_NO_ERROR;
845     ChipLogProgress(DeviceLayer, "BLE GAP connection established (con %" PRIu16 ")", gapEvent->connect.conn_handle);
846
847     // Track the number of active GAP connections.
848     mNumGAPCons++;
849     err = SetSubscribed(gapEvent->connect.conn_handle);
850     VerifyOrExit(err != CHIP_ERROR_NO_MEMORY, err = CHIP_NO_ERROR);
851     SuccessOrExit(err);
852
853     mFlags.Set(Flags::kAdvertisingRefreshNeeded);
854     mFlags.Clear(Flags::kAdvertisingConfigured);
855
856 exit:
857     return err;
858 }
859
860 CHIP_ERROR BLEManagerImpl::HandleGAPDisconnect(struct ble_gap_event * gapEvent)
861 {
862     ChipLogProgress(DeviceLayer, "BLE GAP connection terminated (con %" PRIu16, " reason 0x%02 " PRIx8 ")",
863                     gapEvent->disconnect.conn.conn_handle, gapEvent->disconnect.reason);
864
865     // Update the number of GAP connections.
866     if (mNumGAPCons > 0)
867     {
868         mNumGAPCons--;
869     }
870
871     if (UnsetSubscribed(gapEvent->disconnect.conn.conn_handle))
872     {
873         CHIP_ERROR disconReason;
874         switch (gapEvent->disconnect.reason)
875         {
876         case BLE_ERR_REM_USER_CONN_TERM:
877             disconReason = BLE_ERROR_REMOTE_DEVICE_DISCONNECTED;
878             break;
879         case BLE_ERR_CONN_TERM_LOCAL:
880             disconReason = BLE_ERROR_APP_CLOSED_CONNECTION;
881             break;
882         default:
883             disconReason = BLE_ERROR_CHIPOBLE_PROTOCOL_ABORT;
884             break;
885         }
886         HandleConnectionError(gapEvent->disconnect.conn.conn_handle, disconReason);
887     }
888
889     // Force a reconfiguration of advertising in case we switched to non-connectable mode when
890     // the BLE connection was established.
891     mFlags.Set(Flags::kAdvertisingRefreshNeeded);
892     mFlags.Clear(Flags::kAdvertisingConfigured);
893
894     return CHIP_NO_ERROR;
895 }
896
897 CHIP_ERROR BLEManagerImpl::SetSubscribed(uint16_t conId)
898 {
899     uint16_t freeIndex = kMaxConnections;
900
901     for (uint16_t i = 0; i < kMaxConnections; i++)
902     {
903         if (mSubscribedConIds[i] == conId)
904         {
905             return CHIP_NO_ERROR;
906         }
907         else if (mSubscribedConIds[i] == BLE_CONNECTION_UNINITIALIZED && i < freeIndex)
908         {
909             freeIndex = i;
910         }
911     }
912
913     if (freeIndex < kMaxConnections)
914     {
915         mSubscribedConIds[freeIndex] = conId;
916         return CHIP_NO_ERROR;
917     }
918     else
919     {
920         return CHIP_ERROR_NO_MEMORY;
921     }
922 }
923
924 bool BLEManagerImpl::UnsetSubscribed(uint16_t conId)
925 {
926     for (uint16_t i = 0; i < kMaxConnections; i++)
927     {
928         if (mSubscribedConIds[i] == conId)
929         {
930             mSubscribedConIds[i] = BLE_CONNECTION_UNINITIALIZED;
931             return true;
932         }
933     }
934     return false;
935 }
936
937 bool BLEManagerImpl::IsSubscribed(uint16_t conId)
938 {
939     if (conId != BLE_CONNECTION_UNINITIALIZED)
940     {
941         for (uint16_t i = 0; i < kMaxConnections; i++)
942         {
943             if (mSubscribedConIds[i] == conId)
944             {
945                 return true;
946             }
947         }
948     }
949     return false;
950 }
951
952 int BLEManagerImpl::ble_svr_gap_event(struct ble_gap_event * event, void * arg)
953 {
954     CHIP_ERROR err = CHIP_NO_ERROR;
955
956     switch (event->type)
957     {
958     case BLE_GAP_EVENT_CONNECT:
959         /* A new connection was established or a connection attempt failed */
960         err = sInstance.HandleGAPConnect(event);
961         SuccessOrExit(err);
962         break;
963
964     case BLE_GAP_EVENT_DISCONNECT:
965         err = sInstance.HandleGAPDisconnect(event);
966         SuccessOrExit(err);
967         break;
968
969     case BLE_GAP_EVENT_ADV_COMPLETE:
970         ESP_LOGD(TAG, "BLE_GAP_EVENT_ADV_COMPLETE event");
971         break;
972
973     case BLE_GAP_EVENT_SUBSCRIBE:
974         if (event->subscribe.attr_handle == sInstance.mTXCharCCCDAttrHandle)
975         {
976             sInstance.HandleTXCharCCCDWrite(event);
977         }
978
979         break;
980
981     case BLE_GAP_EVENT_NOTIFY_TX:
982         err = sInstance.HandleTXComplete(event);
983         SuccessOrExit(err);
984         break;
985
986     case BLE_GAP_EVENT_MTU:
987         ESP_LOGD(TAG, "BLE_GAP_EVENT_MTU = %d channel id = %d", event->mtu.value, event->mtu.channel_id);
988         break;
989
990     default:
991         break;
992     }
993
994 exit:
995     if (err != CHIP_NO_ERROR)
996     {
997         ChipLogError(DeviceLayer, "Disabling CHIPoBLE service due to error: %s", ErrorStr(err));
998         sInstance.mServiceMode = ConnectivityManager::kCHIPoBLEServiceMode_Disabled;
999     }
1000
1001     // Schedule DriveBLEState() to run.
1002     PlatformMgr().ScheduleWork(DriveBLEState, 0);
1003
1004     return err;
1005 }
1006
1007 int BLEManagerImpl::gatt_svr_chr_access(uint16_t conn_handle, uint16_t attr_handle, struct ble_gatt_access_ctxt * ctxt, void * arg)
1008 {
1009     struct ble_gatt_char_context param;
1010     CHIP_ERROR err = CHIP_NO_ERROR;
1011
1012     memset(&param, 0, sizeof(struct ble_gatt_char_context));
1013
1014     switch (ctxt->op)
1015     {
1016     case BLE_GATT_ACCESS_OP_READ_CHR:
1017
1018         param.conn_handle = conn_handle;
1019         param.attr_handle = attr_handle;
1020         param.ctxt        = ctxt;
1021         param.arg         = arg;
1022         sInstance.HandleTXCharRead(&param);
1023         break;
1024
1025     case BLE_GATT_ACCESS_OP_READ_DSC:
1026
1027         param.conn_handle = conn_handle;
1028         param.attr_handle = attr_handle;
1029         param.ctxt        = ctxt;
1030         param.arg         = arg;
1031         sInstance.HandleTXCharCCCDRead(&param);
1032         break;
1033
1034     case BLE_GATT_ACCESS_OP_WRITE_CHR:
1035         param.conn_handle = conn_handle;
1036         param.attr_handle = attr_handle;
1037         param.ctxt        = ctxt;
1038         param.arg         = arg;
1039         sInstance.HandleRXCharWrite(&param);
1040         break;
1041
1042     default:
1043         err = BLE_ATT_ERR_UNLIKELY;
1044         break;
1045     }
1046
1047     PlatformMgr().ScheduleWork(DriveBLEState, 0);
1048
1049     return err;
1050 }
1051
1052 CHIP_ERROR BLEManagerImpl::StartAdvertising(void)
1053 {
1054     int ret;
1055
1056     ble_gap_adv_params adv_params;
1057     memset(&adv_params, 0, sizeof(adv_params));
1058     uint8_t own_addr_type = BLE_OWN_ADDR_RANDOM;
1059
1060     adv_params.disc_mode = BLE_GAP_DISC_MODE_GEN;
1061
1062     // Inform the ThreadStackManager that CHIPoBLE advertising is about to start.
1063 #if CHIP_DEVICE_CONFIG_ENABLE_THREAD
1064     {
1065         ThreadStackMgr().OnCHIPoBLEAdvertisingStart();
1066     }
1067 #endif // CHIP_DEVICE_CONFIG_ENABLE_THREAD
1068
1069     mFlags.Clear(Flags::kAdvertisingRefreshNeeded);
1070
1071     // Advertise connectable if we haven't reached the maximum number of connections.
1072     size_t numCons       = _NumConnections();
1073     bool connectable     = (numCons < kMaxConnections);
1074     adv_params.conn_mode = connectable ? BLE_GAP_CONN_MODE_UND : BLE_GAP_CONN_MODE_NON;
1075
1076     // Advertise in fast mode if it is connectable advertisement and
1077     // the application has expressly requested fast advertising.
1078     if (connectable && mFlags.Has(Flags::kFastAdvertisingEnabled))
1079     {
1080         adv_params.itvl_min = CHIP_DEVICE_CONFIG_BLE_FAST_ADVERTISING_INTERVAL_MIN;
1081         adv_params.itvl_max = CHIP_DEVICE_CONFIG_BLE_FAST_ADVERTISING_INTERVAL_MAX;
1082     }
1083     else
1084     {
1085         adv_params.itvl_min = CHIP_DEVICE_CONFIG_BLE_SLOW_ADVERTISING_INTERVAL_MIN;
1086         adv_params.itvl_max = CHIP_DEVICE_CONFIG_BLE_SLOW_ADVERTISING_INTERVAL_MAX;
1087     }
1088
1089     ChipLogProgress(DeviceLayer, "Configuring CHIPoBLE advertising (interval %" PRIu32 " ms, %sconnectable, device name %s)",
1090                     (((uint32_t) adv_params.itvl_min) * 10) / 16, (connectable) ? "" : "non-", mDeviceName);
1091
1092     {
1093         if (ble_gap_adv_active())
1094         {
1095             /* Advertising is already active. Stop and restart with the new parameters */
1096             ChipLogProgress(DeviceLayer, "Device already advertising, stop active advertisement and restart");
1097             ret = ble_gap_adv_stop();
1098             if (ret != 0)
1099             {
1100                 ChipLogError(DeviceLayer, "ble_gap_adv_stop() failed: %d, cannot restart", ret);
1101                 return CHIP_ERROR_INTERNAL;
1102             }
1103         }
1104         else
1105         {
1106             ret = ble_hs_pvcy_rpa_config(NIMBLE_HOST_ENABLE_RPA);
1107             if (ret != 0)
1108             {
1109                 ChipLogError(DeviceLayer, "RPA not set: %d", ret);
1110                 return CHIP_ERROR_INTERNAL;
1111             }
1112         }
1113         ret = ble_gap_adv_start(own_addr_type, NULL, BLE_HS_FOREVER, &adv_params, ble_svr_gap_event, NULL);
1114
1115         if (ret == 0)
1116         {
1117             return CHIP_NO_ERROR;
1118         }
1119         else
1120         {
1121             ChipLogError(DeviceLayer, "ble_gap_adv_start() failed: %d", ret);
1122             return CHIP_ERROR_INTERNAL;
1123         }
1124     }
1125 }
1126
1127 void BLEManagerImpl::DriveBLEState(intptr_t arg)
1128 {
1129     sInstance.DriveBLEState();
1130 }
1131
1132 } // namespace Internal
1133 } // namespace DeviceLayer
1134 } // namespace chip
1135
1136 #endif // CONFIG_BT_NIMBLE_ENABLED
1137
1138 #endif // CHIP_DEVICE_CONFIG_ENABLE_CHIPOBLE