3 * Copyright (c) 2020-2021 Project CHIP Authors
4 * Copyright (c) 2018 Nest Labs, Inc.
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
10 * http://www.apache.org/licenses/LICENSE-2.0
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.
21 * Provides an implementation of the BLEManager singleton object
22 * for Linux platforms.
24 #include <platform/internal/CHIPDeviceLayerInternal.h>
26 #include <ble/CHIPBleServiceData.h>
28 #include <platform/internal/BLEManager.h>
29 #include <support/CodeUtils.h>
30 #include <support/SafeInt.h>
33 #include <type_traits>
36 #if CHIP_DEVICE_CONFIG_ENABLE_CHIPOBLE
38 #include "bluez/Helper.h"
41 using namespace ::chip::Ble;
44 namespace DeviceLayer {
49 static constexpr unsigned kNewConnectionScanTimeoutMs = 10000;
50 static constexpr unsigned kConnectTimeoutMs = 5000;
52 const ChipBleUUID ChipUUID_CHIPoBLEChar_RX = { { 0x18, 0xEE, 0x2E, 0xF5, 0x26, 0x3D, 0x45, 0x59, 0x95, 0x9F, 0x4F, 0x9C, 0x42, 0x9F,
54 const ChipBleUUID ChipUUID_CHIPoBLEChar_TX = { { 0x18, 0xEE, 0x2E, 0xF5, 0x26, 0x3D, 0x45, 0x59, 0x95, 0x9F, 0x4F, 0x9C, 0x42, 0x9F,
57 void HandleConnectTimeout(chip::System::Layer *, void * apEndpoint, chip::System::Error)
59 assert(apEndpoint != nullptr);
61 CancelConnect(static_cast<BluezEndpoint *>(apEndpoint));
62 BLEManagerImpl::HandleConnectFailed(CHIP_ERROR_TIMEOUT);
67 BLEManagerImpl BLEManagerImpl::sInstance;
69 void HandleIncomingBleConnection(BLEEndPoint * bleEP)
71 ChipLogProgress(DeviceLayer, "CHIPoBluez con rcvd");
74 CHIP_ERROR BLEManagerImpl::_Init()
78 err = BleLayer::Init(this, this, this, &SystemLayer);
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);
86 memset(mDeviceName, 0, sizeof(mDeviceName));
88 OnChipBleConnectReceived = HandleIncomingBleConnection;
90 PlatformMgr().ScheduleWork(DriveBLEState, 0);
96 CHIP_ERROR BLEManagerImpl::_SetCHIPoBLEServiceMode(CHIPoBLEServiceMode val)
98 CHIP_ERROR err = CHIP_NO_ERROR;
100 VerifyOrExit(val != ConnectivityManager::kCHIPoBLEServiceMode_NotSupported, err = CHIP_ERROR_INVALID_ARGUMENT);
101 VerifyOrExit(mServiceMode == ConnectivityManager::kCHIPoBLEServiceMode_NotSupported, err = CHIP_ERROR_UNSUPPORTED_CHIP_FEATURE);
103 if (val != mServiceMode)
106 PlatformMgr().ScheduleWork(DriveBLEState, 0);
113 CHIP_ERROR BLEManagerImpl::_SetAdvertisingEnabled(bool val)
115 CHIP_ERROR err = CHIP_NO_ERROR;
117 if (mFlags.Has(Flags::kAdvertisingEnabled) != val)
119 mFlags.Set(Flags::kAdvertisingEnabled, val);
122 PlatformMgr().ScheduleWork(DriveBLEState, 0);
127 CHIP_ERROR BLEManagerImpl::_SetAdvertisingMode(BLEAdvertisingMode mode)
131 case BLEAdvertisingMode::kFastAdvertising:
132 mFlags.Set(Flags::kFastAdvertisingEnabled, true);
134 case BLEAdvertisingMode::kSlowAdvertising:
135 mFlags.Set(Flags::kFastAdvertisingEnabled, false);
138 return CHIP_ERROR_INVALID_ARGUMENT;
140 mFlags.Set(Flags::kAdvertisingRefreshNeeded);
141 PlatformMgr().ScheduleWork(DriveBLEState, 0);
142 return CHIP_NO_ERROR;
145 CHIP_ERROR BLEManagerImpl::_GetDeviceName(char * buf, size_t bufSize)
147 if (strlen(mDeviceName) >= bufSize)
149 return CHIP_ERROR_BUFFER_TOO_SMALL;
151 strcpy(buf, mDeviceName);
153 return CHIP_NO_ERROR;
156 CHIP_ERROR BLEManagerImpl::_SetDeviceName(const char * deviceName)
158 CHIP_ERROR err = CHIP_NO_ERROR;
160 VerifyOrExit(mServiceMode != ConnectivityManager::kCHIPoBLEServiceMode_NotSupported, err = CHIP_ERROR_UNSUPPORTED_CHIP_FEATURE);
162 if (deviceName != nullptr && deviceName[0] != 0)
164 VerifyOrExit(strlen(deviceName) < kMaxDeviceNameLength, err = CHIP_ERROR_INVALID_ARGUMENT);
165 strcpy(mDeviceName, deviceName);
166 mFlags.Set(Flags::kUseCustomDeviceName);
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);
181 uint16_t BLEManagerImpl::_NumConnections()
183 uint16_t numCons = 0;
187 CHIP_ERROR BLEManagerImpl::ConfigureBle(uint32_t aAdapterId, bool aIsCentral)
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";
202 mIsCentral = aIsCentral;
207 CHIP_ERROR BLEManagerImpl::StartBLEAdvertising()
209 return StartBluezAdv(mpEndpoint);
212 CHIP_ERROR BLEManagerImpl::StopBLEAdvertising()
214 return StopBluezAdv(mpEndpoint);
217 void BLEManagerImpl::_OnPlatformEvent(const ChipDeviceEvent * event)
221 case DeviceEventType::kCHIPoBLESubscribe:
222 HandleSubscribeReceived(event->CHIPoBLESubscribe.ConId, &CHIP_BLE_SVC_ID, &ChipUUID_CHIPoBLEChar_TX);
224 ChipDeviceEvent connectionEvent;
225 connectionEvent.Type = DeviceEventType::kCHIPoBLEConnectionEstablished;
226 PlatformMgr().PostEvent(&connectionEvent);
230 case DeviceEventType::kCHIPoBLEUnsubscribe:
231 HandleUnsubscribeReceived(event->CHIPoBLEUnsubscribe.ConId, &CHIP_BLE_SVC_ID, &ChipUUID_CHIPoBLEChar_TX);
234 case DeviceEventType::kCHIPoBLEWriteReceived:
235 HandleWriteReceived(event->CHIPoBLEWriteReceived.ConId, &CHIP_BLE_SVC_ID, &ChipUUID_CHIPoBLEChar_RX,
236 PacketBufferHandle::Adopt(event->CHIPoBLEWriteReceived.Data));
239 case DeviceEventType::kCHIPoBLEIndicateConfirm:
240 HandleIndicationConfirmation(event->CHIPoBLEIndicateConfirm.ConId, &CHIP_BLE_SVC_ID, &ChipUUID_CHIPoBLEChar_TX);
243 case DeviceEventType::kCHIPoBLEConnectionError:
244 HandleConnectionError(event->CHIPoBLEConnectionError.ConId, event->CHIPoBLEConnectionError.Reason);
246 case DeviceEventType::kFabricMembershipChange:
247 case DeviceEventType::kServiceProvisioningChange:
248 case DeviceEventType::kAccountPairingChange:
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())
256 mFlags.Clear(Flags::kAdvertisingEnabled);
257 ChipLogProgress(DeviceLayer, "CHIPoBLE advertising disabled because device is fully provisioned");
259 #endif // CHIP_DEVICE_CONFIG_CHIPOBLE_DISABLE_ADVERTISING_WHEN_PROVISIONED
261 // Force the advertising configuration to be refreshed to reflect new provisioning state.
262 mFlags.Clear(Flags::kAdvertisingConfigured);
267 HandlePlatformSpecificBLEEvent(event);
272 void BLEManagerImpl::HandlePlatformSpecificBLEEvent(const ChipDeviceEvent * apEvent)
274 CHIP_ERROR err = CHIP_NO_ERROR;
275 bool controlOpComplete = false;
276 ChipLogProgress(DeviceLayer, "HandlePlatformSpecificBLEEvent %d", apEvent->Type);
277 switch (apEvent->Type)
279 case DeviceEventType::kPlatformLinuxBLECentralConnected:
280 if (mBLEScanConfig.mBleScanState == BleScanState::kConnecting)
282 OnConnectionComplete(mBLEScanConfig.mAppState, apEvent->Platform.BLECentralConnected.mConnection);
286 case DeviceEventType::kPlatformLinuxBLECentralConnectFailed:
287 if (mBLEScanConfig.mBleScanState == BleScanState::kConnecting)
289 OnConnectionError(mBLEScanConfig.mAppState, apEvent->Platform.BLECentralConnectFailed.mError);
293 case DeviceEventType::kPlatformLinuxBLEWriteComplete:
294 HandleWriteConfirmation(apEvent->Platform.BLEWriteComplete.mConnection, &CHIP_BLE_SVC_ID, &ChipUUID_CHIPoBLEChar_RX);
296 case DeviceEventType::kPlatformLinuxBLESubscribeOpComplete:
297 if (apEvent->Platform.BLESubscribeOpComplete.mIsSubscribed)
298 HandleSubscribeComplete(apEvent->Platform.BLESubscribeOpComplete.mConnection, &CHIP_BLE_SVC_ID,
299 &ChipUUID_CHIPoBLEChar_TX);
301 HandleUnsubscribeComplete(apEvent->Platform.BLESubscribeOpComplete.mConnection, &CHIP_BLE_SVC_ID,
302 &ChipUUID_CHIPoBLEChar_TX);
304 case DeviceEventType::kPlatformLinuxBLEIndicationReceived:
305 HandleIndicationReceived(apEvent->Platform.BLEIndicationReceived.mConnection, &CHIP_BLE_SVC_ID, &ChipUUID_CHIPoBLEChar_TX,
306 PacketBufferHandle::Adopt(apEvent->Platform.BLEIndicationReceived.mData));
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");
314 case DeviceEventType::kPlatformLinuxBLEPeripheralAdvStartComplete:
315 VerifyOrExit(apEvent->Platform.BLEPeripheralAdvStartComplete.mIsSuccess, err = CHIP_ERROR_INCORRECT_STATE);
316 sInstance.mFlags.Clear(Flags::kControlOpInProgress).Clear(Flags::kAdvertisingRefreshNeeded);
318 if (!sInstance.mFlags.Has(Flags::kAdvertising))
320 sInstance.mFlags.Set(Flags::kAdvertising);
324 case DeviceEventType::kPlatformLinuxBLEPeripheralAdvStopComplete:
325 VerifyOrExit(apEvent->Platform.BLEPeripheralAdvStopComplete.mIsSuccess, err = CHIP_ERROR_INCORRECT_STATE);
327 sInstance.mFlags.Clear(Flags::kControlOpInProgress).Clear(Flags::kAdvertisingRefreshNeeded);
329 // Transition to the not Advertising state...
330 if (sInstance.mFlags.Has(Flags::kAdvertising))
332 sInstance.mFlags.Clear(Flags::kAdvertising);
333 ChipLogProgress(DeviceLayer, "CHIPoBLE advertising stopped");
336 case DeviceEventType::kPlatformLinuxBLEPeripheralRegisterAppComplete:
337 VerifyOrExit(apEvent->Platform.BLEPeripheralRegisterAppComplete.mIsSuccess, err = CHIP_ERROR_INCORRECT_STATE);
338 mFlags.Set(Flags::kAppRegistered);
339 controlOpComplete = true;
346 if (err != CHIP_NO_ERROR)
348 ChipLogError(DeviceLayer, "Disabling CHIPoBLE service due to error: %s", ErrorStr(err));
349 mServiceMode = ConnectivityManager::kCHIPoBLEServiceMode_Disabled;
350 sInstance.mFlags.Clear(Flags::kControlOpInProgress);
353 if (controlOpComplete)
355 mFlags.Clear(Flags::kControlOpInProgress);
360 uint16_t BLEManagerImpl::GetMTU(BLE_CONNECTION_OBJECT conId) const
362 BluezConnection * connection = static_cast<BluezConnection *>(conId);
363 return (connection != nullptr) ? connection->mMtu : 0;
366 bool BLEManagerImpl::SubscribeCharacteristic(BLE_CONNECTION_OBJECT conId, const ChipBleUUID * svcId, const ChipBleUUID * charId)
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"));
375 result = BluezSubscribeCharacteristic(conId);
380 bool BLEManagerImpl::UnsubscribeCharacteristic(BLE_CONNECTION_OBJECT conId, const ChipBleUUID * svcId, const ChipBleUUID * charId)
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"));
389 result = BluezUnsubscribeCharacteristic(conId);
394 bool BLEManagerImpl::CloseConnection(BLE_CONNECTION_OBJECT conId)
396 ChipLogProgress(DeviceLayer, "Closing BLE GATT connection (con %p)", conId);
397 return CloseBluezConnection(conId);
400 bool BLEManagerImpl::SendIndication(BLE_CONNECTION_OBJECT conId, const ChipBleUUID * svcId, const Ble::ChipBleUUID * charId,
401 chip::System::PacketBufferHandle pBuf)
403 return SendBluezIndication(conId, std::move(pBuf));
406 bool BLEManagerImpl::SendWriteRequest(BLE_CONNECTION_OBJECT conId, const Ble::ChipBleUUID * svcId, const Ble::ChipBleUUID * charId,
407 chip::System::PacketBufferHandle pBuf)
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"));
416 result = BluezSendWriteRequest(conId, std::move(pBuf));
421 bool BLEManagerImpl::SendReadRequest(BLE_CONNECTION_OBJECT conId, const Ble::ChipBleUUID * svcId, const Ble::ChipBleUUID * charId,
422 chip::System::PacketBufferHandle pBuf)
424 ChipLogError(Ble, "SendReadRequest: Not implemented");
428 bool BLEManagerImpl::SendReadResponse(BLE_CONNECTION_OBJECT conId, BLE_READ_REQUEST_CONTEXT requestContext,
429 const Ble::ChipBleUUID * svcId, const Ble::ChipBleUUID * charId)
431 ChipLogError(Ble, "SendReadRBluezonse: Not implemented");
435 void BLEManagerImpl::HandleNewConnection(BLE_CONNECTION_OBJECT conId)
437 if (sInstance.mIsCentral)
439 ChipDeviceEvent event;
440 event.Type = DeviceEventType::kPlatformLinuxBLECentralConnected;
441 event.Platform.BLECentralConnected.mConnection = conId;
442 PlatformMgr().PostEvent(&event);
446 void BLEManagerImpl::HandleConnectFailed(CHIP_ERROR error)
448 if (sInstance.mIsCentral)
450 ChipDeviceEvent event;
451 event.Type = DeviceEventType::kPlatformLinuxBLECentralConnectFailed;
452 event.Platform.BLECentralConnectFailed.mError = error;
453 PlatformMgr().PostEvent(&event);
457 void BLEManagerImpl::HandleWriteComplete(BLE_CONNECTION_OBJECT conId)
459 ChipDeviceEvent event;
460 event.Type = DeviceEventType::kPlatformLinuxBLEWriteComplete;
461 event.Platform.BLEWriteComplete.mConnection = conId;
462 PlatformMgr().PostEvent(&event);
465 void BLEManagerImpl::HandleSubscribeOpComplete(BLE_CONNECTION_OBJECT conId, bool subscribed)
467 ChipDeviceEvent event;
468 event.Type = DeviceEventType::kPlatformLinuxBLESubscribeOpComplete;
469 event.Platform.BLESubscribeOpComplete.mConnection = conId;
470 event.Platform.BLESubscribeOpComplete.mIsSubscribed = subscribed;
471 PlatformMgr().PostEvent(&event);
474 void BLEManagerImpl::HandleTXCharChanged(BLE_CONNECTION_OBJECT conId, const uint8_t * value, size_t len)
476 CHIP_ERROR err = CHIP_NO_ERROR;
477 System::PacketBufferHandle buf = System::PacketBufferHandle::NewWithData(value, len);
479 ChipLogProgress(DeviceLayer, "Indication received, conn = %p", conId);
481 VerifyOrExit(!buf.IsNull(), err = CHIP_ERROR_NO_MEMORY);
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);
490 if (err != CHIP_NO_ERROR)
491 ChipLogError(DeviceLayer, "HandleTXCharChanged() failed: %s", ErrorStr(err));
494 void BLEManagerImpl::HandleRXCharWrite(BLE_CONNECTION_OBJECT conId, const uint8_t * value, size_t len)
496 CHIP_ERROR err = CHIP_NO_ERROR;
497 System::PacketBufferHandle buf;
499 // Copy the data to a packet buffer.
500 buf = System::PacketBufferHandle::NewWithData(value, len);
501 VerifyOrExit(!buf.IsNull(), err = CHIP_ERROR_NO_MEMORY);
503 // Post an event to the Chip queue to deliver the data into the Chip stack.
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);
514 if (err != CHIP_NO_ERROR)
516 ChipLogError(DeviceLayer, "HandleRXCharWrite() failed: %s", ErrorStr(err));
520 void BLEManagerImpl::CHIPoBluez_ConnectionClosed(BLE_CONNECTION_OBJECT conId)
522 ChipLogProgress(DeviceLayer, "Bluez notify CHIPoBluez connection disconnected");
524 // If this was a CHIPoBLE connection, post an event to deliver a connection error to the CHIPoBLE layer.
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);
534 void BLEManagerImpl::HandleTXCharCCCDWrite(BLE_CONNECTION_OBJECT conId)
536 CHIP_ERROR err = CHIP_NO_ERROR;
538 BluezConnection * connection = static_cast<BluezConnection *>(conId);
540 VerifyOrExit(connection != nullptr, ChipLogError(DeviceLayer, "Connection is NULL in HandleTXCharCCCDWrite"));
541 VerifyOrExit(connection->mpC2 != nullptr, ChipLogError(DeviceLayer, "C2 is NULL in HandleTXCharCCCDWrite"));
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.
546 ChipDeviceEvent event;
547 event.Type = connection->mIsNotify ? DeviceEventType::kCHIPoBLESubscribe : DeviceEventType::kCHIPoBLEUnsubscribe;
548 event.CHIPoBLESubscribe.ConId = connection;
549 PlatformMgr().PostEvent(&event);
552 ChipLogProgress(DeviceLayer, "CHIPoBLE %s received", connection->mIsNotify ? "subscribe" : "unsubscribe");
555 if (err != CHIP_NO_ERROR)
557 ChipLogError(DeviceLayer, "HandleTXCharCCCDWrite() failed: %s", ErrorStr(err));
558 // TODO: fail connection
562 void BLEManagerImpl::HandleTXComplete(BLE_CONNECTION_OBJECT conId)
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);
571 void BLEManagerImpl::DriveBLEState()
573 CHIP_ERROR err = CHIP_NO_ERROR;
575 // Perform any initialization actions that must occur after the Chip task is running.
576 if (!mFlags.Has(Flags::kAsyncInitCompleted))
578 mFlags.Set(Flags::kAsyncInitCompleted);
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())
585 mFlags.Clear(Flags::kAdvertisingEnabled);
586 ChipLogProgress(DeviceLayer, "CHIPoBLE advertising disabled because device is fully provisioned");
588 #endif // CHIP_DEVICE_CONFIG_CHIPOBLE_DISABLE_ADVERTISING_WHEN_PROVISIONED
592 // If there's already a control operation in progress, wait until it completes.
593 VerifyOrExit(!mFlags.Has(Flags::kControlOpInProgress), /* */);
595 // Initializes the Bluez BLE layer if needed.
596 if (mServiceMode == ConnectivityManager::kCHIPoBLEServiceMode_Enabled && !mFlags.Has(Flags::kBluezBLELayerInitialized))
598 err = InitBluezBleLayer(mIsCentral, nullptr, mBLEAdvConfig, mpEndpoint);
600 mFlags.Set(Flags::kBluezBLELayerInitialized);
603 // Register the CHIPoBLE application with the Bluez BLE layer if needed.
604 if (!mIsCentral && mServiceMode == ConnectivityManager::kCHIPoBLEServiceMode_Enabled && !mFlags.Has(Flags::kAppRegistered))
606 err = BluezGattsAppRegister(mpEndpoint);
607 mFlags.Set(Flags::kControlOpInProgress);
611 // If the application has enabled CHIPoBLE and BLE advertising...
612 if (mServiceMode == ConnectivityManager::kCHIPoBLEServiceMode_Enabled && mFlags.Has(Flags::kAdvertisingEnabled))
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))
618 mFlags.Clear(Flags::kAdvertisingRefreshNeeded);
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))
625 err = BluezAdvertisementSetup(mpEndpoint);
629 // Start advertising. This is also an asynchronous step.
630 err = StartBLEAdvertising();
633 sInstance.mFlags.Set(Flags::kAdvertising);
638 // Otherwise stop advertising if needed...
641 if (mFlags.Has(Flags::kAdvertising))
643 err = StopBLEAdvertising();
645 mFlags.Set(Flags::kControlOpInProgress);
652 if (err != CHIP_NO_ERROR)
654 ChipLogError(DeviceLayer, "Disabling CHIPoBLE service due to error: %s", ErrorStr(err));
655 mServiceMode = ConnectivityManager::kCHIPoBLEServiceMode_Disabled;
659 void BLEManagerImpl::DriveBLEState(intptr_t arg)
661 sInstance.DriveBLEState();
664 void BLEManagerImpl::NotifyChipConnectionClosed(BLE_CONNECTION_OBJECT conId)
666 ChipLogProgress(Ble, "Got notification regarding chip connection closure");
669 void BLEManagerImpl::InitiateScan(BleScanState scanType)
673 if (scanType == BleScanState::kNotScanning)
675 OnConnectionError(mBLEScanConfig.mAppState, CHIP_ERROR_INCORRECT_STATE);
676 ChipLogError(Ble, "Invalid scan type requested");
680 if (mpEndpoint == nullptr)
682 OnConnectionError(mBLEScanConfig.mAppState, CHIP_ERROR_INCORRECT_STATE);
683 ChipLogError(Ble, "BLE Layer is not yet initialized");
687 if (mpEndpoint->mpAdapter == nullptr)
689 OnConnectionError(mBLEScanConfig.mAppState, CHIP_ERROR_INCORRECT_STATE);
690 ChipLogError(Ble, "No adapter available for new connection establishment");
694 mDeviceScanner = Internal::ChipDeviceScanner::Create(mpEndpoint->mpAdapter, this);
695 mBLEScanConfig.mBleScanState = scanType;
699 mBLEScanConfig.mBleScanState = BleScanState::kNotScanning;
700 OnConnectionError(mBLEScanConfig.mAppState, CHIP_ERROR_INTERNAL);
701 ChipLogError(Ble, "Failed to create a BLE device scanner");
705 CHIP_ERROR err = mDeviceScanner->StartScan(kNewConnectionScanTimeoutMs);
706 if (err != CHIP_NO_ERROR)
708 mBLEScanConfig.mBleScanState = BleScanState::kNotScanning;
709 ChipLogError(Ble, "Failed to start a BLE can: %s", chip::ErrorStr(err));
710 OnConnectionError(mBLEScanConfig.mAppState, err);
715 void BLEManagerImpl::CleanScanConfig()
717 if (mBLEScanConfig.mBleScanState == BleScanState::kConnecting)
718 DeviceLayer::SystemLayer.CancelTimer(HandleConnectTimeout, mpEndpoint);
720 mBLEScanConfig.mBleScanState = BleScanState::kNotScanning;
723 void BLEManagerImpl::InitiateScan(intptr_t arg)
725 sInstance.InitiateScan(static_cast<BleScanState>(arg));
728 void BLEManagerImpl::NewConnection(BleLayer * bleLayer, void * appState, const uint16_t connDiscriminator)
730 mBLEScanConfig.mDiscriminator = connDiscriminator;
731 mBLEScanConfig.mAppState = appState;
733 // Scan initiation performed async, to ensure that the BLE subsystem is initialized.
734 PlatformMgr().ScheduleWork(InitiateScan, static_cast<intptr_t>(BleScanState::kScanForDiscriminator));
737 BLE_ERROR BLEManagerImpl::CancelConnection()
739 return BLE_ERROR_NOT_IMPLEMENTED;
742 void BLEManagerImpl::NotifyBLEPeripheralRegisterAppComplete(bool aIsSuccess, void * apAppstate)
744 ChipDeviceEvent event;
745 event.Type = DeviceEventType::kPlatformLinuxBLEPeripheralRegisterAppComplete;
746 event.Platform.BLEPeripheralRegisterAppComplete.mIsSuccess = aIsSuccess;
747 event.Platform.BLEPeripheralRegisterAppComplete.mpAppstate = apAppstate;
748 PlatformMgr().PostEvent(&event);
751 void BLEManagerImpl::NotifyBLEPeripheralAdvConfiguredComplete(bool aIsSuccess, void * apAppstate)
753 ChipDeviceEvent event;
754 event.Type = DeviceEventType::kPlatformLinuxBLEPeripheralAdvConfiguredComplete;
755 event.Platform.BLEPeripheralAdvConfiguredComplete.mIsSuccess = aIsSuccess;
756 event.Platform.BLEPeripheralAdvConfiguredComplete.mpAppstate = apAppstate;
757 PlatformMgr().PostEvent(&event);
760 void BLEManagerImpl::NotifyBLEPeripheralAdvStartComplete(bool aIsSuccess, void * apAppstate)
762 ChipDeviceEvent event;
763 event.Type = DeviceEventType::kPlatformLinuxBLEPeripheralAdvStartComplete;
764 event.Platform.BLEPeripheralAdvStartComplete.mIsSuccess = aIsSuccess;
765 event.Platform.BLEPeripheralAdvStartComplete.mpAppstate = apAppstate;
766 PlatformMgr().PostEvent(&event);
769 void BLEManagerImpl::NotifyBLEPeripheralAdvStopComplete(bool aIsSuccess, void * apAppstate)
771 ChipDeviceEvent event;
772 event.Type = DeviceEventType::kPlatformLinuxBLEPeripheralAdvStopComplete;
773 event.Platform.BLEPeripheralAdvStopComplete.mIsSuccess = aIsSuccess;
774 event.Platform.BLEPeripheralAdvStopComplete.mpAppstate = apAppstate;
775 PlatformMgr().PostEvent(&event);
778 void BLEManagerImpl::OnDeviceScanned(BluezDevice1 * device, const chip::Ble::ChipBLEDeviceIdentificationInfo & info)
780 ChipLogProgress(Ble, "New device scanned: %s", bluez_device1_get_address(device));
782 if (mBLEScanConfig.mBleScanState == BleScanState::kScanForDiscriminator)
784 if (info.GetDeviceDiscriminator() != mBLEScanConfig.mDiscriminator)
788 ChipLogProgress(Ble, "Device discriminator match. Attempting to connect.");
790 else if (mBLEScanConfig.mBleScanState == BleScanState::kScanForAddress)
792 if (strcmp(bluez_device1_get_address(device), mBLEScanConfig.mAddress.c_str()) != 0)
796 ChipLogProgress(Ble, "Device address match. Attempting to connect.");
800 // Internal consistency eerror
801 ChipLogError(Ble, "Unknown discovery type. Ignoring scanned device.");
805 mBLEScanConfig.mBleScanState = BleScanState::kConnecting;
806 DeviceLayer::SystemLayer.StartTimer(kConnectTimeoutMs, HandleConnectTimeout, mpEndpoint);
807 mDeviceScanner->StopScan();
809 ConnectDevice(device, mpEndpoint);
812 void BLEManagerImpl::OnScanComplete()
814 if (mBLEScanConfig.mBleScanState != BleScanState::kScanForDiscriminator &&
815 mBLEScanConfig.mBleScanState != BleScanState::kScanForAddress)
817 ChipLogProgress(Ble, "Scan complete notification without an active scan.");
821 OnConnectionError(mBLEScanConfig.mAppState, CHIP_ERROR_TIMEOUT);
822 mBLEScanConfig.mBleScanState = BleScanState::kNotScanning;
825 } // namespace Internal
826 } // namespace DeviceLayer
829 #endif // CHIP_DEVICE_CONFIG_ENABLE_CHIPOBLE