Apply Upstream code (2021-03-15)
[platform/upstream/connectedhomeip.git] / src / platform / Linux / BLEManagerImpl.cpp
1 /*
2  *
3  *    Copyright (c) 2020-2021 Project CHIP Authors
4  *    Copyright (c) 2018 Nest Labs, Inc.
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 Linux platforms.
23  */
24 #include <platform/internal/CHIPDeviceLayerInternal.h>
25
26 #include <ble/CHIPBleServiceData.h>
27 #include <new>
28 #include <platform/internal/BLEManager.h>
29 #include <support/CodeUtils.h>
30 #include <support/SafeInt.h>
31
32 #include <type_traits>
33 #include <utility>
34
35 #if CHIP_DEVICE_CONFIG_ENABLE_CHIPOBLE
36
37 #include "bluez/Helper.h"
38
39 using namespace ::nl;
40 using namespace ::chip::Ble;
41
42 namespace chip {
43 namespace DeviceLayer {
44 namespace Internal {
45
46 namespace {
47
48 static constexpr unsigned kNewConnectionScanTimeoutMs = 10000;
49
50 const ChipBleUUID ChipUUID_CHIPoBLEChar_RX = { { 0x18, 0xEE, 0x2E, 0xF5, 0x26, 0x3D, 0x45, 0x59, 0x95, 0x9F, 0x4F, 0x9C, 0x42, 0x9F,
51                                                  0x9D, 0x11 } };
52 const ChipBleUUID ChipUUID_CHIPoBLEChar_TX = { { 0x18, 0xEE, 0x2E, 0xF5, 0x26, 0x3D, 0x45, 0x59, 0x95, 0x9F, 0x4F, 0x9C, 0x42, 0x9F,
53                                                  0x9D, 0x12 } };
54
55 } // namespace
56
57 BLEManagerImpl BLEManagerImpl::sInstance;
58
59 void HandleIncomingBleConnection(BLEEndPoint * bleEP)
60 {
61     ChipLogProgress(DeviceLayer, "CHIPoBluez con rcvd");
62 }
63
64 CHIP_ERROR BLEManagerImpl::_Init()
65 {
66     CHIP_ERROR err;
67
68     err = BleLayer::Init(this, this, this, &SystemLayer);
69     SuccessOrExit(err);
70
71     mServiceMode = ConnectivityManager::kCHIPoBLEServiceMode_Enabled;
72     mFlags.ClearAll().Set(Flags::kAdvertisingEnabled, CHIP_DEVICE_CONFIG_CHIPOBLE_ENABLE_ADVERTISING_AUTOSTART && !mIsCentral);
73     mAppState = nullptr;
74
75     memset(mDeviceName, 0, sizeof(mDeviceName));
76
77     OnChipBleConnectReceived = HandleIncomingBleConnection;
78
79     PlatformMgr().ScheduleWork(DriveBLEState, 0);
80
81 exit:
82     return err;
83 }
84
85 CHIP_ERROR BLEManagerImpl::_SetCHIPoBLEServiceMode(CHIPoBLEServiceMode val)
86 {
87     CHIP_ERROR err = CHIP_NO_ERROR;
88
89     VerifyOrExit(val != ConnectivityManager::kCHIPoBLEServiceMode_NotSupported, err = CHIP_ERROR_INVALID_ARGUMENT);
90     VerifyOrExit(mServiceMode == ConnectivityManager::kCHIPoBLEServiceMode_NotSupported, err = CHIP_ERROR_UNSUPPORTED_CHIP_FEATURE);
91
92     if (val != mServiceMode)
93     {
94         mServiceMode = val;
95         PlatformMgr().ScheduleWork(DriveBLEState, 0);
96     }
97
98 exit:
99     return err;
100 }
101
102 CHIP_ERROR BLEManagerImpl::_SetAdvertisingEnabled(bool val)
103 {
104     CHIP_ERROR err = CHIP_NO_ERROR;
105
106     if (mFlags.Has(Flags::kAdvertisingEnabled) != val)
107     {
108         mFlags.Set(Flags::kAdvertisingEnabled, val);
109     }
110
111     PlatformMgr().ScheduleWork(DriveBLEState, 0);
112
113     return err;
114 }
115
116 CHIP_ERROR BLEManagerImpl::_SetFastAdvertisingEnabled(bool val)
117 {
118     CHIP_ERROR err = CHIP_NO_ERROR;
119
120     VerifyOrExit(mServiceMode == ConnectivityManager::kCHIPoBLEServiceMode_NotSupported, err = CHIP_ERROR_UNSUPPORTED_CHIP_FEATURE);
121
122     if (mFlags.Has(Flags::kFastAdvertisingEnabled) != val)
123     {
124         mFlags.Set(Flags::kFastAdvertisingEnabled, val);
125         PlatformMgr().ScheduleWork(DriveBLEState, 0);
126     }
127
128 exit:
129     return err;
130 }
131
132 CHIP_ERROR BLEManagerImpl::_GetDeviceName(char * buf, size_t bufSize)
133 {
134     if (strlen(mDeviceName) >= bufSize)
135     {
136         return CHIP_ERROR_BUFFER_TOO_SMALL;
137     }
138     strcpy(buf, mDeviceName);
139
140     return CHIP_NO_ERROR;
141 }
142
143 CHIP_ERROR BLEManagerImpl::_SetDeviceName(const char * deviceName)
144 {
145     CHIP_ERROR err = CHIP_NO_ERROR;
146
147     VerifyOrExit(mServiceMode != ConnectivityManager::kCHIPoBLEServiceMode_NotSupported, err = CHIP_ERROR_UNSUPPORTED_CHIP_FEATURE);
148
149     if (deviceName != nullptr && deviceName[0] != 0)
150     {
151         VerifyOrExit(strlen(deviceName) < kMaxDeviceNameLength, err = CHIP_ERROR_INVALID_ARGUMENT);
152         strcpy(mDeviceName, deviceName);
153         mFlags.Set(Flags::kUseCustomDeviceName);
154     }
155     else
156     {
157         uint16_t discriminator;
158         SuccessOrExit(err = ConfigurationMgr().GetSetupDiscriminator(discriminator));
159         snprintf(mDeviceName, sizeof(mDeviceName), "%s%04u", CHIP_DEVICE_CONFIG_BLE_DEVICE_NAME_PREFIX, discriminator);
160         mDeviceName[kMaxDeviceNameLength] = 0;
161         mFlags.Clear(Flags::kUseCustomDeviceName);
162     }
163
164 exit:
165     return err;
166 }
167
168 uint16_t BLEManagerImpl::_NumConnections()
169 {
170     uint16_t numCons = 0;
171     return numCons;
172 }
173
174 CHIP_ERROR BLEManagerImpl::ConfigureBle(uint32_t aAdapterId, bool aIsCentral)
175 {
176     CHIP_ERROR err                  = CHIP_NO_ERROR;
177     mBLEAdvConfig.mpBleName         = mDeviceName;
178     mBLEAdvConfig.mAdapterId        = aAdapterId;
179     mBLEAdvConfig.mMajor            = 1;
180     mBLEAdvConfig.mMinor            = 1;
181     mBLEAdvConfig.mVendorId         = 1;
182     mBLEAdvConfig.mProductId        = 1;
183     mBLEAdvConfig.mDeviceId         = 1;
184     mBLEAdvConfig.mDuration         = 2;
185     mBLEAdvConfig.mPairingStatus    = 0;
186     mBLEAdvConfig.mType             = ChipAdvType::BLUEZ_ADV_TYPE_UNDIRECTED_CONNECTABLE_SCANNABLE;
187     mBLEAdvConfig.mpAdvertisingUUID = "0xFEAF";
188
189     mIsCentral = aIsCentral;
190
191     return err;
192 }
193
194 CHIP_ERROR BLEManagerImpl::StartBLEAdvertising()
195 {
196     return StartBluezAdv(mpEndpoint);
197 }
198
199 CHIP_ERROR BLEManagerImpl::StopBLEAdvertising()
200 {
201     return StopBluezAdv(mpEndpoint);
202 }
203
204 void BLEManagerImpl::_OnPlatformEvent(const ChipDeviceEvent * event)
205 {
206     switch (event->Type)
207     {
208     case DeviceEventType::kCHIPoBLESubscribe:
209         HandleSubscribeReceived(event->CHIPoBLESubscribe.ConId, &CHIP_BLE_SVC_ID, &ChipUUID_CHIPoBLEChar_TX);
210         {
211             ChipDeviceEvent connectionEvent;
212             connectionEvent.Type = DeviceEventType::kCHIPoBLEConnectionEstablished;
213             PlatformMgr().PostEvent(&connectionEvent);
214         }
215         break;
216
217     case DeviceEventType::kCHIPoBLEUnsubscribe:
218         HandleUnsubscribeReceived(event->CHIPoBLEUnsubscribe.ConId, &CHIP_BLE_SVC_ID, &ChipUUID_CHIPoBLEChar_TX);
219         break;
220
221     case DeviceEventType::kCHIPoBLEWriteReceived:
222         HandleWriteReceived(event->CHIPoBLEWriteReceived.ConId, &CHIP_BLE_SVC_ID, &ChipUUID_CHIPoBLEChar_RX,
223                             PacketBufferHandle::Adopt(event->CHIPoBLEWriteReceived.Data));
224         break;
225
226     case DeviceEventType::kCHIPoBLEIndicateConfirm:
227         HandleIndicationConfirmation(event->CHIPoBLEIndicateConfirm.ConId, &CHIP_BLE_SVC_ID, &ChipUUID_CHIPoBLEChar_TX);
228         break;
229
230     case DeviceEventType::kCHIPoBLEConnectionError:
231         HandleConnectionError(event->CHIPoBLEConnectionError.ConId, event->CHIPoBLEConnectionError.Reason);
232         break;
233     case DeviceEventType::kFabricMembershipChange:
234     case DeviceEventType::kServiceProvisioningChange:
235     case DeviceEventType::kAccountPairingChange:
236
237         // If CHIPOBLE_DISABLE_ADVERTISING_WHEN_PROVISIONED is enabled, and there is a change to the
238         // device's provisioning state, then automatically disable CHIPoBLE advertising if the device
239         // is now fully provisioned.
240 #if CHIP_DEVICE_CONFIG_CHIPOBLE_DISABLE_ADVERTISING_WHEN_PROVISIONED
241         if (ConfigurationMgr().IsFullyProvisioned())
242         {
243             mFlags.Clear(Flags::kAdvertisingEnabled);
244             ChipLogProgress(DeviceLayer, "CHIPoBLE advertising disabled because device is fully provisioned");
245         }
246 #endif // CHIP_DEVICE_CONFIG_CHIPOBLE_DISABLE_ADVERTISING_WHEN_PROVISIONED
247
248         // Force the advertising configuration to be refreshed to reflect new provisioning state.
249         mFlags.Clear(Flags::kAdvertisingConfigured);
250
251         DriveBLEState();
252         break;
253     default:
254         HandlePlatformSpecificBLEEvent(event);
255         break;
256     }
257 }
258
259 void BLEManagerImpl::HandlePlatformSpecificBLEEvent(const ChipDeviceEvent * apEvent)
260 {
261     CHIP_ERROR err         = CHIP_NO_ERROR;
262     bool controlOpComplete = false;
263     ChipLogProgress(DeviceLayer, "HandlePlatformSpecificBLEEvent %d", apEvent->Type);
264     switch (apEvent->Type)
265     {
266     case DeviceEventType::kPlatformLinuxBLECentralConnected:
267         if (OnConnectionComplete != nullptr)
268             OnConnectionComplete(mBLEScanConfig.mAppState, apEvent->Platform.BLECentralConnected.mConnection);
269         break;
270     case DeviceEventType::kPlatformLinuxBLEWriteComplete:
271         HandleWriteConfirmation(apEvent->Platform.BLEWriteComplete.mConnection, &CHIP_BLE_SVC_ID, &ChipUUID_CHIPoBLEChar_RX);
272         break;
273     case DeviceEventType::kPlatformLinuxBLESubscribeOpComplete:
274         if (apEvent->Platform.BLESubscribeOpComplete.mIsSubscribed)
275             HandleSubscribeComplete(apEvent->Platform.BLESubscribeOpComplete.mConnection, &CHIP_BLE_SVC_ID,
276                                     &ChipUUID_CHIPoBLEChar_TX);
277         else
278             HandleUnsubscribeComplete(apEvent->Platform.BLESubscribeOpComplete.mConnection, &CHIP_BLE_SVC_ID,
279                                       &ChipUUID_CHIPoBLEChar_TX);
280         break;
281     case DeviceEventType::kPlatformLinuxBLEIndicationReceived:
282         HandleIndicationReceived(apEvent->Platform.BLEIndicationReceived.mConnection, &CHIP_BLE_SVC_ID, &ChipUUID_CHIPoBLEChar_TX,
283                                  PacketBufferHandle::Adopt(apEvent->Platform.BLEIndicationReceived.mData));
284         break;
285     case DeviceEventType::kPlatformLinuxBLEPeripheralAdvConfiguredComplete:
286         VerifyOrExit(apEvent->Platform.BLEPeripheralAdvConfiguredComplete.mIsSuccess, err = CHIP_ERROR_INCORRECT_STATE);
287         sInstance.mFlags.Set(Flags::kAdvertisingConfigured).Clear(Flags::kControlOpInProgress);
288         controlOpComplete = true;
289         ChipLogProgress(DeviceLayer, "CHIPoBLE advertising config complete");
290         break;
291     case DeviceEventType::kPlatformLinuxBLEPeripheralAdvStartComplete:
292         VerifyOrExit(apEvent->Platform.BLEPeripheralAdvStartComplete.mIsSuccess, err = CHIP_ERROR_INCORRECT_STATE);
293         sInstance.mFlags.Clear(Flags::kControlOpInProgress).Clear(Flags::kAdvertisingRefreshNeeded);
294
295         if (!sInstance.mFlags.Has(Flags::kAdvertising))
296         {
297             sInstance.mFlags.Set(Flags::kAdvertising);
298         }
299
300         break;
301     case DeviceEventType::kPlatformLinuxBLEPeripheralAdvStopComplete:
302         VerifyOrExit(apEvent->Platform.BLEPeripheralAdvStopComplete.mIsSuccess, err = CHIP_ERROR_INCORRECT_STATE);
303
304         sInstance.mFlags.Clear(Flags::kControlOpInProgress).Clear(Flags::kAdvertisingRefreshNeeded);
305
306         // Transition to the not Advertising state...
307         if (sInstance.mFlags.Has(Flags::kAdvertising))
308         {
309             sInstance.mFlags.Clear(Flags::kAdvertising);
310             ChipLogProgress(DeviceLayer, "CHIPoBLE advertising stopped");
311         }
312         break;
313     case DeviceEventType::kPlatformLinuxBLEPeripheralRegisterAppComplete:
314         VerifyOrExit(apEvent->Platform.BLEPeripheralRegisterAppComplete.mIsSuccess, err = CHIP_ERROR_INCORRECT_STATE);
315         mFlags.Set(Flags::kAppRegistered);
316         controlOpComplete = true;
317         break;
318     default:
319         break;
320     }
321
322 exit:
323     if (err != CHIP_NO_ERROR)
324     {
325         ChipLogError(DeviceLayer, "Disabling CHIPoBLE service due to error: %s", ErrorStr(err));
326         mServiceMode = ConnectivityManager::kCHIPoBLEServiceMode_Disabled;
327         sInstance.mFlags.Clear(Flags::kControlOpInProgress);
328     }
329
330     if (controlOpComplete)
331     {
332         mFlags.Clear(Flags::kControlOpInProgress);
333         DriveBLEState();
334     }
335 }
336
337 uint16_t BLEManagerImpl::GetMTU(BLE_CONNECTION_OBJECT conId) const
338 {
339     BluezConnection * connection = static_cast<BluezConnection *>(conId);
340     return (connection != nullptr) ? connection->mMtu : 0;
341 }
342
343 bool BLEManagerImpl::SubscribeCharacteristic(BLE_CONNECTION_OBJECT conId, const ChipBleUUID * svcId, const ChipBleUUID * charId)
344 {
345     bool result = false;
346
347     VerifyOrExit(Ble::UUIDsMatch(svcId, &CHIP_BLE_SVC_ID),
348                  ChipLogError(DeviceLayer, "SubscribeCharacteristic() called with invalid service ID"));
349     VerifyOrExit(Ble::UUIDsMatch(charId, &ChipUUID_CHIPoBLEChar_TX),
350                  ChipLogError(DeviceLayer, "SubscribeCharacteristic() called with invalid characteristic ID"));
351
352     result = BluezSubscribeCharacteristic(conId);
353 exit:
354     return result;
355 }
356
357 bool BLEManagerImpl::UnsubscribeCharacteristic(BLE_CONNECTION_OBJECT conId, const ChipBleUUID * svcId, const ChipBleUUID * charId)
358 {
359     bool result = false;
360
361     VerifyOrExit(Ble::UUIDsMatch(svcId, &CHIP_BLE_SVC_ID),
362                  ChipLogError(DeviceLayer, "UnsubscribeCharacteristic() called with invalid service ID"));
363     VerifyOrExit(Ble::UUIDsMatch(charId, &ChipUUID_CHIPoBLEChar_TX),
364                  ChipLogError(DeviceLayer, "UnsubscribeCharacteristic() called with invalid characteristic ID"));
365
366     result = BluezUnsubscribeCharacteristic(conId);
367 exit:
368     return result;
369 }
370
371 bool BLEManagerImpl::CloseConnection(BLE_CONNECTION_OBJECT conId)
372 {
373     ChipLogProgress(DeviceLayer, "Closing BLE GATT connection (con %p)", conId);
374     return CloseBluezConnection(conId);
375 }
376
377 bool BLEManagerImpl::SendIndication(BLE_CONNECTION_OBJECT conId, const ChipBleUUID * svcId, const Ble::ChipBleUUID * charId,
378                                     chip::System::PacketBufferHandle pBuf)
379 {
380     return SendBluezIndication(conId, std::move(pBuf));
381 }
382
383 bool BLEManagerImpl::SendWriteRequest(BLE_CONNECTION_OBJECT conId, const Ble::ChipBleUUID * svcId, const Ble::ChipBleUUID * charId,
384                                       chip::System::PacketBufferHandle pBuf)
385 {
386     bool result = false;
387
388     VerifyOrExit(Ble::UUIDsMatch(svcId, &CHIP_BLE_SVC_ID),
389                  ChipLogError(DeviceLayer, "SendWriteRequest() called with invalid service ID"));
390     VerifyOrExit(Ble::UUIDsMatch(charId, &ChipUUID_CHIPoBLEChar_RX),
391                  ChipLogError(DeviceLayer, "SendWriteRequest() called with invalid characteristic ID"));
392
393     result = BluezSendWriteRequest(conId, std::move(pBuf));
394 exit:
395     return result;
396 }
397
398 bool BLEManagerImpl::SendReadRequest(BLE_CONNECTION_OBJECT conId, const Ble::ChipBleUUID * svcId, const Ble::ChipBleUUID * charId,
399                                      chip::System::PacketBufferHandle pBuf)
400 {
401     ChipLogError(Ble, "SendReadRequest: Not implemented");
402     return true;
403 }
404
405 bool BLEManagerImpl::SendReadResponse(BLE_CONNECTION_OBJECT conId, BLE_READ_REQUEST_CONTEXT requestContext,
406                                       const Ble::ChipBleUUID * svcId, const Ble::ChipBleUUID * charId)
407 {
408     ChipLogError(Ble, "SendReadRBluezonse: Not implemented");
409     return true;
410 }
411
412 void BLEManagerImpl::HandleNewConnection(BLE_CONNECTION_OBJECT conId)
413 {
414     if (sInstance.mIsCentral)
415     {
416         ChipDeviceEvent event;
417         event.Type                                     = DeviceEventType::kPlatformLinuxBLECentralConnected;
418         event.Platform.BLECentralConnected.mConnection = conId;
419         PlatformMgr().PostEvent(&event);
420     }
421 }
422
423 void BLEManagerImpl::HandleWriteComplete(BLE_CONNECTION_OBJECT conId)
424 {
425     ChipDeviceEvent event;
426     event.Type                                  = DeviceEventType::kPlatformLinuxBLEWriteComplete;
427     event.Platform.BLEWriteComplete.mConnection = conId;
428     PlatformMgr().PostEvent(&event);
429 }
430
431 void BLEManagerImpl::HandleSubscribeOpComplete(BLE_CONNECTION_OBJECT conId, bool subscribed)
432 {
433     ChipDeviceEvent event;
434     event.Type                                          = DeviceEventType::kPlatformLinuxBLESubscribeOpComplete;
435     event.Platform.BLESubscribeOpComplete.mConnection   = conId;
436     event.Platform.BLESubscribeOpComplete.mIsSubscribed = subscribed;
437     PlatformMgr().PostEvent(&event);
438 }
439
440 void BLEManagerImpl::HandleTXCharChanged(BLE_CONNECTION_OBJECT conId, const uint8_t * value, size_t len)
441 {
442     CHIP_ERROR err                 = CHIP_NO_ERROR;
443     System::PacketBufferHandle buf = System::PacketBufferHandle::NewWithData(value, len);
444
445     ChipLogProgress(DeviceLayer, "Indication received, conn = %p", conId);
446
447     VerifyOrExit(!buf.IsNull(), err = CHIP_ERROR_NO_MEMORY);
448
449     ChipDeviceEvent event;
450     event.Type                                       = DeviceEventType::kPlatformLinuxBLEIndicationReceived;
451     event.Platform.BLEIndicationReceived.mConnection = conId;
452     event.Platform.BLEIndicationReceived.mData       = std::move(buf).UnsafeRelease();
453     PlatformMgr().PostEvent(&event);
454
455 exit:
456     if (err != CHIP_NO_ERROR)
457         ChipLogError(DeviceLayer, "HandleTXCharChanged() failed: %s", ErrorStr(err));
458 }
459
460 void BLEManagerImpl::HandleRXCharWrite(BLE_CONNECTION_OBJECT conId, const uint8_t * value, size_t len)
461 {
462     CHIP_ERROR err = CHIP_NO_ERROR;
463     System::PacketBufferHandle buf;
464
465     // Copy the data to a packet buffer.
466     buf = System::PacketBufferHandle::NewWithData(value, len);
467     VerifyOrExit(!buf.IsNull(), err = CHIP_ERROR_NO_MEMORY);
468
469     // Post an event to the Chip queue to deliver the data into the Chip stack.
470     {
471         ChipDeviceEvent event;
472         event.Type = DeviceEventType::kCHIPoBLEWriteReceived;
473         ChipLogProgress(Ble, "Write request received debug %p", conId);
474         event.CHIPoBLEWriteReceived.ConId = conId;
475         event.CHIPoBLEWriteReceived.Data  = std::move(buf).UnsafeRelease();
476         PlatformMgr().PostEvent(&event);
477     }
478
479 exit:
480     if (err != CHIP_NO_ERROR)
481     {
482         ChipLogError(DeviceLayer, "HandleRXCharWrite() failed: %s", ErrorStr(err));
483     }
484 }
485
486 void BLEManagerImpl::CHIPoBluez_ConnectionClosed(BLE_CONNECTION_OBJECT conId)
487 {
488     ChipLogProgress(DeviceLayer, "Bluez notify CHIPoBluez connection disconnected");
489
490     // If this was a CHIPoBLE connection, post an event to deliver a connection error to the CHIPoBLE layer.
491     {
492         ChipDeviceEvent event;
493         event.Type                           = DeviceEventType::kCHIPoBLEConnectionError;
494         event.CHIPoBLEConnectionError.ConId  = conId;
495         event.CHIPoBLEConnectionError.Reason = BLE_ERROR_REMOTE_DEVICE_DISCONNECTED;
496         PlatformMgr().PostEvent(&event);
497     }
498 }
499
500 void BLEManagerImpl::HandleTXCharCCCDWrite(BLE_CONNECTION_OBJECT conId)
501 {
502     CHIP_ERROR err = CHIP_NO_ERROR;
503
504     BluezConnection * connection = static_cast<BluezConnection *>(conId);
505
506     VerifyOrExit(connection != nullptr, ChipLogError(DeviceLayer, "Connection is NULL in HandleTXCharCCCDWrite"));
507     VerifyOrExit(connection->mpC2 != nullptr, ChipLogError(DeviceLayer, "C2 is NULL in HandleTXCharCCCDWrite"));
508
509     // Post an event to the Chip queue to process either a CHIPoBLE Subscribe or Unsubscribe based on
510     // whether the client is enabling or disabling indications.
511     {
512         ChipDeviceEvent event;
513         event.Type = connection->mIsNotify ? DeviceEventType::kCHIPoBLESubscribe : DeviceEventType::kCHIPoBLEUnsubscribe;
514         event.CHIPoBLESubscribe.ConId = connection;
515         PlatformMgr().PostEvent(&event);
516     }
517
518     ChipLogProgress(DeviceLayer, "CHIPoBLE %s received", connection->mIsNotify ? "subscribe" : "unsubscribe");
519
520 exit:
521     if (err != CHIP_NO_ERROR)
522     {
523         ChipLogError(DeviceLayer, "HandleTXCharCCCDWrite() failed: %s", ErrorStr(err));
524         // TODO: fail connection
525     }
526 }
527
528 void BLEManagerImpl::HandleTXComplete(BLE_CONNECTION_OBJECT conId)
529 {
530     // Post an event to the Chip queue to process the indicate confirmation.
531     ChipDeviceEvent event;
532     event.Type                          = DeviceEventType::kCHIPoBLEIndicateConfirm;
533     event.CHIPoBLEIndicateConfirm.ConId = conId;
534     PlatformMgr().PostEvent(&event);
535 }
536
537 void BLEManagerImpl::DriveBLEState()
538 {
539     CHIP_ERROR err = CHIP_NO_ERROR;
540
541     // Perform any initialization actions that must occur after the Chip task is running.
542     if (!mFlags.Has(Flags::kAsyncInitCompleted))
543     {
544         mFlags.Set(Flags::kAsyncInitCompleted);
545
546         // If CHIP_DEVICE_CONFIG_CHIPOBLE_DISABLE_ADVERTISING_WHEN_PROVISIONED is enabled,
547         // disable CHIPoBLE advertising if the device is fully provisioned.
548 #if CHIP_DEVICE_CONFIG_CHIPOBLE_DISABLE_ADVERTISING_WHEN_PROVISIONED
549         if (ConfigurationMgr().IsFullyProvisioned())
550         {
551             mFlags.Clear(Flags::kAdvertisingEnabled);
552             ChipLogProgress(DeviceLayer, "CHIPoBLE advertising disabled because device is fully provisioned");
553         }
554 #endif // CHIP_DEVICE_CONFIG_CHIPOBLE_DISABLE_ADVERTISING_WHEN_PROVISIONED
555         ExitNow();
556     }
557
558     // If there's already a control operation in progress, wait until it completes.
559     VerifyOrExit(!mFlags.Has(Flags::kControlOpInProgress), /* */);
560
561     // Initializes the Bluez BLE layer if needed.
562     if (mServiceMode == ConnectivityManager::kCHIPoBLEServiceMode_Enabled && !mFlags.Has(Flags::kBluezBLELayerInitialized))
563     {
564         err = InitBluezBleLayer(mIsCentral, nullptr, mBLEAdvConfig, mpEndpoint);
565         SuccessOrExit(err);
566         mFlags.Set(Flags::kBluezBLELayerInitialized);
567     }
568
569     // Register the CHIPoBLE application with the Bluez BLE layer if needed.
570     if (!mIsCentral && mServiceMode == ConnectivityManager::kCHIPoBLEServiceMode_Enabled && !mFlags.Has(Flags::kAppRegistered))
571     {
572         err = BluezGattsAppRegister(mpEndpoint);
573         mFlags.Set(Flags::kControlOpInProgress);
574         ExitNow();
575     }
576
577     // If the application has enabled CHIPoBLE and BLE advertising...
578     if (mServiceMode == ConnectivityManager::kCHIPoBLEServiceMode_Enabled && mFlags.Has(Flags::kAdvertisingEnabled))
579     {
580         // Start/re-start advertising if not already advertising, or if the advertising state of the
581         // Bluez BLE layer needs to be refreshed.
582         if (!mFlags.Has(Flags::kAdvertising) || mFlags.Has(Flags::kAdvertisingRefreshNeeded))
583         {
584             // Configure advertising data if it hasn't been done yet.  This is an asynchronous step which
585             // must complete before advertising can be started.  When that happens, this method will
586             // be called again, and execution will proceed to the code below.
587             if (!mFlags.Has(Flags::kAdvertisingConfigured))
588             {
589                 err = BluezAdvertisementSetup(mpEndpoint);
590                 ExitNow();
591             }
592
593             // Start advertising.  This is also an asynchronous step.
594             err = StartBLEAdvertising();
595             SuccessOrExit(err);
596
597             sInstance.mFlags.Set(Flags::kAdvertising);
598             ExitNow();
599         }
600     }
601
602     // Otherwise stop advertising if needed...
603     else
604     {
605         if (mFlags.Has(Flags::kAdvertising))
606         {
607             err = StopBLEAdvertising();
608             SuccessOrExit(err);
609             mFlags.Set(Flags::kControlOpInProgress);
610
611             ExitNow();
612         }
613     }
614
615 exit:
616     if (err != CHIP_NO_ERROR)
617     {
618         ChipLogError(DeviceLayer, "Disabling CHIPoBLE service due to error: %s", ErrorStr(err));
619         mServiceMode = ConnectivityManager::kCHIPoBLEServiceMode_Disabled;
620     }
621 }
622
623 void BLEManagerImpl::DriveBLEState(intptr_t arg)
624 {
625     sInstance.DriveBLEState();
626 }
627
628 void BLEManagerImpl::NotifyChipConnectionClosed(BLE_CONNECTION_OBJECT conId)
629 {
630     ChipLogProgress(Ble, "Got notification regarding chip connection closure");
631 }
632
633 void BLEManagerImpl::InitiateScan(BleScanState scanType)
634 {
635     DriveBLEState();
636
637     if (scanType == BleScanState::kNotScanning)
638     {
639         OnConnectionError(mBLEScanConfig.mAppState, CHIP_ERROR_INCORRECT_STATE);
640         ChipLogError(Ble, "Invalid scan type requested");
641         return;
642     }
643
644     if (mpEndpoint == nullptr)
645     {
646         OnConnectionError(mBLEScanConfig.mAppState, CHIP_ERROR_INCORRECT_STATE);
647         ChipLogError(Ble, "BLE Layer is not yet initialized");
648         return;
649     }
650
651     if (mpEndpoint->mpAdapter == nullptr)
652     {
653         OnConnectionError(mBLEScanConfig.mAppState, CHIP_ERROR_INCORRECT_STATE);
654         ChipLogError(Ble, "No adapter available for new connection establishment");
655         return;
656     }
657
658     mDeviceScanner = Internal::ChipDeviceScanner::Create(mpEndpoint->mpAdapter, this);
659
660     mBLEScanConfig.bleScanState = BleScanState::kScanForDiscriminator;
661
662     if (!mDeviceScanner)
663     {
664         mBLEScanConfig.bleScanState = BleScanState::kNotScanning;
665         OnConnectionError(mBLEScanConfig.mAppState, CHIP_ERROR_INTERNAL);
666         ChipLogError(Ble, "Failed to create a BLE device scanner");
667         return;
668     }
669
670     CHIP_ERROR err = mDeviceScanner->StartScan(kNewConnectionScanTimeoutMs);
671     if (err != CHIP_NO_ERROR)
672     {
673         mBLEScanConfig.bleScanState = BleScanState::kNotScanning;
674         ChipLogError(Ble, "Failed to start a BLE can: %s", chip::ErrorStr(err));
675         OnConnectionError(mBLEScanConfig.mAppState, err);
676         return;
677     }
678 }
679
680 void BLEManagerImpl::InitiateScan(intptr_t arg)
681 {
682     sInstance.InitiateScan(static_cast<BleScanState>(arg));
683 }
684
685 void BLEManagerImpl::NewConnection(BleLayer * bleLayer, void * appState, const uint16_t connDiscriminator)
686 {
687     mBLEScanConfig.mDiscriminator = connDiscriminator;
688     mBLEScanConfig.mAppState      = appState;
689
690     // Scan initiation performed async, to ensure that the BLE subsystem is initialized.
691     PlatformMgr().ScheduleWork(InitiateScan, static_cast<intptr_t>(BleScanState::kScanForDiscriminator));
692 }
693
694 void BLEManagerImpl::NotifyBLEPeripheralRegisterAppComplete(bool aIsSuccess, void * apAppstate)
695 {
696     ChipDeviceEvent event;
697     event.Type                                                 = DeviceEventType::kPlatformLinuxBLEPeripheralRegisterAppComplete;
698     event.Platform.BLEPeripheralRegisterAppComplete.mIsSuccess = aIsSuccess;
699     event.Platform.BLEPeripheralRegisterAppComplete.mpAppstate = apAppstate;
700     PlatformMgr().PostEvent(&event);
701 }
702
703 void BLEManagerImpl::NotifyBLEPeripheralAdvConfiguredComplete(bool aIsSuccess, void * apAppstate)
704 {
705     ChipDeviceEvent event;
706     event.Type = DeviceEventType::kPlatformLinuxBLEPeripheralAdvConfiguredComplete;
707     event.Platform.BLEPeripheralAdvConfiguredComplete.mIsSuccess = aIsSuccess;
708     event.Platform.BLEPeripheralAdvConfiguredComplete.mpAppstate = apAppstate;
709     PlatformMgr().PostEvent(&event);
710 }
711
712 void BLEManagerImpl::NotifyBLEPeripheralAdvStartComplete(bool aIsSuccess, void * apAppstate)
713 {
714     ChipDeviceEvent event;
715     event.Type                                              = DeviceEventType::kPlatformLinuxBLEPeripheralAdvStartComplete;
716     event.Platform.BLEPeripheralAdvStartComplete.mIsSuccess = aIsSuccess;
717     event.Platform.BLEPeripheralAdvStartComplete.mpAppstate = apAppstate;
718     PlatformMgr().PostEvent(&event);
719 }
720
721 void BLEManagerImpl::NotifyBLEPeripheralAdvStopComplete(bool aIsSuccess, void * apAppstate)
722 {
723     ChipDeviceEvent event;
724     event.Type                                             = DeviceEventType::kPlatformLinuxBLEPeripheralAdvStopComplete;
725     event.Platform.BLEPeripheralAdvStopComplete.mIsSuccess = aIsSuccess;
726     event.Platform.BLEPeripheralAdvStopComplete.mpAppstate = apAppstate;
727     PlatformMgr().PostEvent(&event);
728 }
729
730 void BLEManagerImpl::OnDeviceScanned(BluezDevice1 * device, const chip::Ble::ChipBLEDeviceIdentificationInfo & info)
731 {
732     ChipLogProgress(Ble, "New device scanned: %s", bluez_device1_get_address(device));
733
734     if (mBLEScanConfig.bleScanState == BleScanState::kScanForDiscriminator)
735     {
736         if (info.GetDeviceDiscriminator() != mBLEScanConfig.mDiscriminator)
737         {
738             return;
739         }
740         ChipLogProgress(Ble, "Device discriminator match. Attempting to connect.");
741     }
742     else if (mBLEScanConfig.bleScanState == BleScanState::kScanForAddress)
743     {
744         if (strcmp(bluez_device1_get_address(device), mBLEScanConfig.mAddress.c_str()) != 0)
745         {
746             return;
747         }
748         ChipLogProgress(Ble, "Device address match. Attempting to connect.");
749     }
750     else
751     {
752         // Internal consistency eerror
753         ChipLogError(Ble, "Unknown discovery type. Ignoring scanned device.");
754         return;
755     }
756
757     mBLEScanConfig.bleScanState = BleScanState::kNotScanning;
758     mDeviceScanner->StopScan();
759
760     ConnectDevice(device);
761 }
762
763 void BLEManagerImpl::OnScanComplete()
764 {
765     if (mBLEScanConfig.bleScanState == BleScanState::kNotScanning)
766     {
767         ChipLogError(Ble, "Scan complete notification without an active scan.");
768         return;
769     }
770
771     OnConnectionError(mBLEScanConfig.mAppState, CHIP_ERROR_TIMEOUT);
772     mBLEScanConfig.bleScanState = BleScanState::kNotScanning;
773 }
774
775 } // namespace Internal
776 } // namespace DeviceLayer
777 } // namespace chip
778
779 #endif // CHIP_DEVICE_CONFIG_ENABLE_CHIPOBLE