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