diff --git a/src/app/server/CommissioningWindowManager.cpp b/src/app/server/CommissioningWindowManager.cpp index 6faeb9ad73..b6e5cac3dd 100644 --- a/src/app/server/CommissioningWindowManager.cpp +++ b/src/app/server/CommissioningWindowManager.cpp @@ -287,6 +287,20 @@ CHIP_ERROR CommissioningWindowManager::AdvertiseAndListenForPASE() return CHIP_NO_ERROR; } +System::Clock::Seconds32 CommissioningWindowManager::MaxCommissioningTimeout() const +{ +#if CHIP_DEVICE_CONFIG_EXT_ADVERTISING + /* Allow for extended announcement only if the device is uncomissioned. */ + if (mServer->GetFabricTable().FabricCount() == 0) + { + // Specification section 2.3.1 - Extended Announcement Duration up to 48h + return System::Clock::Seconds32(60 * 60 * 48); + } +#endif + // Specification section 5.4.2.3. Announcement Duration says 15 minutes. + return System::Clock::Seconds32(15 * 60); +} + CHIP_ERROR CommissioningWindowManager::OpenBasicCommissioningWindow(Seconds32 commissioningTimeout, CommissioningWindowAdvertisement advertisementMode) { diff --git a/src/app/server/CommissioningWindowManager.h b/src/app/server/CommissioningWindowManager.h index 3f0f7d036a..8455152b00 100644 --- a/src/app/server/CommissioningWindowManager.h +++ b/src/app/server/CommissioningWindowManager.h @@ -57,16 +57,7 @@ class CommissioningWindowManager : public Messaging::UnsolicitedMessageHandler, return CHIP_NO_ERROR; } - static constexpr System::Clock::Seconds32 MaxCommissioningTimeout() - { -#if CHIP_DEVICE_CONFIG_BLE_EXT_ADVERTISING - // Specification section 2.3.1 - Extended Announcement Duration up to 48h - return System::Clock::Seconds32(60 * 60 * 48); -#else - // Specification section 5.4.2.3. Announcement Duration says 15 minutes. - return System::Clock::Seconds32(15 * 60); -#endif - } + System::Clock::Seconds32 MaxCommissioningTimeout() const; System::Clock::Seconds32 MinCommissioningTimeout() const { diff --git a/src/include/platform/CHIPDeviceConfig.h b/src/include/platform/CHIPDeviceConfig.h index 0dd5e4e978..4e8644211c 100644 --- a/src/include/platform/CHIPDeviceConfig.h +++ b/src/include/platform/CHIPDeviceConfig.h @@ -631,18 +631,18 @@ #endif /** - * CHIP_DEVICE_CONFIG_BLE_EXT_ADVERTISING + * CHIP_DEVICE_CONFIG_EXT_ADVERTISING * * Optional configuration to enable Extended Announcement Duration up to 48h. * Should be used together with extending CHIP_DEVICE_CONFIG_DISCOVERY_TIMEOUT_SECS past 15 minutes. * Disabled by default. */ -#ifndef CHIP_DEVICE_CONFIG_BLE_EXT_ADVERTISING -#define CHIP_DEVICE_CONFIG_BLE_EXT_ADVERTISING 0 +#ifndef CHIP_DEVICE_CONFIG_EXT_ADVERTISING +#define CHIP_DEVICE_CONFIG_EXT_ADVERTISING 0 #endif -#if CHIP_DEVICE_CONFIG_BLE_EXT_ADVERTISING +#if CHIP_DEVICE_CONFIG_EXT_ADVERTISING /** * CHIP_DEVICE_CONFIG_BLE_EXT_ADVERTISING_INTERVAL_CHANGE_TIME_MS @@ -726,18 +726,18 @@ static_assert(CHIP_DEVICE_CONFIG_BLE_EXT_ADVERTISING_INTERVAL_MIN <= CHIP_DEVICE * Time in seconds that a factory new device will advertise commissionable node discovery. */ #ifndef CHIP_DEVICE_CONFIG_DISCOVERY_TIMEOUT_SECS -#if CHIP_DEVICE_CONFIG_BLE_EXT_ADVERTISING +#if CHIP_DEVICE_CONFIG_EXT_ADVERTISING /** * By default, the extended announcement, when enabled, starts its extended advertising 15 mins * after the standard slow advertisement. Time at which the default discovery time would close the * commissioning window and stop the BLE. - * Therefore, when CHIP_DEVICE_CONFIG_BLE_EXT_ADVERTISING is enabled bump the default Discovery timeout + * Therefore, when CHIP_DEVICE_CONFIG_EXT_ADVERTISING is enabled bump the default Discovery timeout * to the maximum allowed by the spec. 48h. */ #define CHIP_DEVICE_CONFIG_DISCOVERY_TIMEOUT_SECS (60 * 60 * 48) #else #define CHIP_DEVICE_CONFIG_DISCOVERY_TIMEOUT_SECS (15 * 60) -#endif // CHIP_DEVICE_CONFIG_BLE_EXT_ADVERTISING +#endif // CHIP_DEVICE_CONFIG_EXT_ADVERTISING #endif // CHIP_DEVICE_CONFIG_DISCOVERY_TIMEOUT_SECS /** diff --git a/src/platform/ESP32/CHIPDevicePlatformConfig.h b/src/platform/ESP32/CHIPDevicePlatformConfig.h index 5e97b4e7eb..b90637595f 100644 --- a/src/platform/ESP32/CHIPDevicePlatformConfig.h +++ b/src/platform/ESP32/CHIPDevicePlatformConfig.h @@ -106,7 +106,12 @@ #define CHIP_DEVICE_CONFIG_DISCOVERY_TIMEOUT_SECS CONFIG_CHIP_DISCOVERY_TIMEOUT_SECS #define CHIP_DEVICE_CONFIG_ENABLE_BOTH_COMMISSIONER_AND_COMMISSIONEE CONFIG_ENABLE_ESP32_BLE_CONTROLLER #define CHIP_DEVICE_CONFIG_ENABLE_PAIRING_AUTOSTART CONFIG_CHIP_ENABLE_PAIRING_AUTOSTART -#define CHIP_DEVICE_CONFIG_BLE_EXT_ADVERTISING CONFIG_ENABLE_BLE_EXT_ANNOUNCEMENT + +#ifdef CONFIG_ENABLE_BLE_EXT_ANNOUNCEMENT +#define CHIP_DEVICE_CONFIG_EXT_ADVERTISING CONFIG_ENABLE_BLE_EXT_ANNOUNCEMENT +#else +#define CHIP_DEVICE_CONFIG_EXT_ADVERTISING 0 +#endif // Options for background chip task #define CHIP_DEVICE_CONFIG_ENABLE_BG_EVENT_PROCESSING CONFIG_ENABLE_BG_EVENT_PROCESSING diff --git a/src/platform/ESP32/nimble/BLEManagerImpl.cpp b/src/platform/ESP32/nimble/BLEManagerImpl.cpp index 9ee4476c39..2f31e20806 100644 --- a/src/platform/ESP32/nimble/BLEManagerImpl.cpp +++ b/src/platform/ESP32/nimble/BLEManagerImpl.cpp @@ -302,13 +302,13 @@ void BLEManagerImpl::BleAdvTimeoutHandler(TimerHandle_t xTimer) BLEMgrImpl().mFlags.Set(Flags::kFastAdvertisingEnabled, 0); BLEMgrImpl().mFlags.Set(Flags::kAdvertisingRefreshNeeded, 1); -#if CHIP_DEVICE_CONFIG_BLE_EXT_ADVERTISING +#if CHIP_DEVICE_CONFIG_EXT_ADVERTISING BLEMgrImpl().mFlags.Clear(Flags::kExtAdvertisingEnabled); BLEMgrImpl().StartBleAdvTimeoutTimer(CHIP_DEVICE_CONFIG_BLE_EXT_ADVERTISING_INTERVAL_CHANGE_TIME_MS); #endif PlatformMgr().ScheduleWork(DriveBLEState, 0); } -#if CHIP_DEVICE_CONFIG_BLE_EXT_ADVERTISING +#if CHIP_DEVICE_CONFIG_EXT_ADVERTISING else { ChipLogProgress(DeviceLayer, "bleAdv Timeout : Start extended advertisement"); @@ -1094,7 +1094,7 @@ CHIP_ERROR BLEManagerImpl::ConfigureAdvertisingData(void) ExitNow(); } -#if CHIP_DEVICE_CONFIG_BLE_EXT_ADVERTISING +#if CHIP_DEVICE_CONFIG_EXT_ADVERTISING // Check for extended advertisement interval and redact VID/PID if past the initial period. if (mFlags.Has(Flags::kExtAdvertisingEnabled)) { @@ -1699,7 +1699,7 @@ CHIP_ERROR BLEManagerImpl::StartAdvertising(void) } else { -#if CHIP_DEVICE_CONFIG_BLE_EXT_ADVERTISING +#if CHIP_DEVICE_CONFIG_EXT_ADVERTISING if (!mFlags.Has(Flags::kExtAdvertisingEnabled)) { adv_params.itvl_min = CHIP_DEVICE_CONFIG_BLE_SLOW_ADVERTISING_INTERVAL_MIN; diff --git a/src/platform/Linux/BLEManagerImpl.cpp b/src/platform/Linux/BLEManagerImpl.cpp index 36b7430863..2653df5900 100644 --- a/src/platform/Linux/BLEManagerImpl.cpp +++ b/src/platform/Linux/BLEManagerImpl.cpp @@ -61,7 +61,7 @@ static constexpr System::Clock::Timeout kNewConnectionScanTimeout = System::Cloc static constexpr System::Clock::Timeout kConnectTimeout = System::Clock::Seconds16(20); static constexpr System::Clock::Timeout kFastAdvertiseTimeout = System::Clock::Milliseconds32(CHIP_DEVICE_CONFIG_BLE_ADVERTISING_INTERVAL_CHANGE_TIME); -#if CHIP_DEVICE_CONFIG_BLE_EXT_ADVERTISING +#if CHIP_DEVICE_CONFIG_EXT_ADVERTISING // The CHIP_DEVICE_CONFIG_BLE_EXT_ADVERTISING_INTERVAL_CHANGE_TIME_MS specifies the transition time // starting from advertisement commencement. Since the extended advertisement timer is started after // the fast-to-slow transition, we have to subtract the time spent in fast advertising. @@ -629,7 +629,7 @@ void BLEManagerImpl::DriveBLEState() // Setup service data for advertising. auto serviceDataFlags = BluezAdvertisement::kServiceDataNone; -#if CHIP_DEVICE_CONFIG_BLE_EXT_ADVERTISING +#if CHIP_DEVICE_CONFIG_EXT_ADVERTISING if (mFlags.Has(Flags::kExtAdvertisingEnabled)) serviceDataFlags |= BluezAdvertisement::kServiceDataExtendedAnnouncement; #endif @@ -698,7 +698,7 @@ BluezAdvertisement::AdvertisingIntervals BLEManagerImpl::GetAdvertisingIntervals { if (mFlags.Has(Flags::kFastAdvertisingEnabled)) return { CHIP_DEVICE_CONFIG_BLE_FAST_ADVERTISING_INTERVAL_MIN, CHIP_DEVICE_CONFIG_BLE_FAST_ADVERTISING_INTERVAL_MAX }; -#if CHIP_DEVICE_CONFIG_BLE_EXT_ADVERTISING +#if CHIP_DEVICE_CONFIG_EXT_ADVERTISING if (mFlags.Has(Flags::kExtAdvertisingEnabled)) return { CHIP_DEVICE_CONFIG_BLE_EXT_ADVERTISING_INTERVAL_MIN, CHIP_DEVICE_CONFIG_BLE_EXT_ADVERTISING_INTERVAL_MAX }; #endif @@ -713,7 +713,7 @@ void BLEManagerImpl::HandleAdvertisingTimer(chip::System::Layer *, void * appSta { ChipLogDetail(DeviceLayer, "bleAdv Timeout : Start slow advertisement"); self->_SetAdvertisingMode(BLEAdvertisingMode::kSlowAdvertising); -#if CHIP_DEVICE_CONFIG_BLE_EXT_ADVERTISING +#if CHIP_DEVICE_CONFIG_EXT_ADVERTISING self->mFlags.Clear(Flags::kExtAdvertisingEnabled); DeviceLayer::SystemLayer().StartTimer(kSlowAdvertiseTimeout, HandleAdvertisingTimer, self); } diff --git a/src/platform/Linux/bluez/BluezAdvertisement.cpp b/src/platform/Linux/bluez/BluezAdvertisement.cpp index aa5135d00b..2483b01076 100644 --- a/src/platform/Linux/bluez/BluezAdvertisement.cpp +++ b/src/platform/Linux/bluez/BluezAdvertisement.cpp @@ -160,7 +160,7 @@ CHIP_ERROR BluezAdvertisement::SetupServiceData(ServiceDataFlags aFlags) deviceInfo.SetAdditionalDataFlag(true); #endif -#if CHIP_DEVICE_CONFIG_BLE_EXT_ADVERTISING +#if CHIP_DEVICE_CONFIG_EXT_ADVERTISING if (aFlags & kServiceDataExtendedAnnouncement) { deviceInfo.SetExtendedAnnouncementFlag(true); diff --git a/src/platform/NuttX/BLEManagerImpl.cpp b/src/platform/NuttX/BLEManagerImpl.cpp new file mode 100644 index 0000000000..6672b5d4bd --- /dev/null +++ b/src/platform/NuttX/BLEManagerImpl.cpp @@ -0,0 +1,870 @@ +/* + * + * Copyright (c) 2020-2021 Project CHIP Authors + * Copyright (c) 2018 Nest Labs, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * @file + * Provides an implementation of the BLEManager singleton object + * for Linux platforms. + */ + +/** + * Note: BLEManager requires ConnectivityManager to be defined beforehand, + * otherwise we will face circular dependency between them. */ +#include + +/** + * Note: Use public include for BLEManager which includes our local + * platform//BLEManagerImpl.h after defining interface class. */ +#include "platform/internal/BLEManager.h" + +#include +#include + +#include +#include +#include +#include +#include + +#include "bluez/BluezEndpoint.h" + +#if !CHIP_DEVICE_CONFIG_SUPPORTS_CONCURRENT_CONNECTION +#include +#endif + +using namespace ::nl; +using namespace ::chip::Ble; + +namespace chip { +namespace DeviceLayer { +namespace Internal { + +namespace { + +static constexpr System::Clock::Timeout kNewConnectionScanTimeout = System::Clock::Seconds16(20); +static constexpr System::Clock::Timeout kConnectTimeout = System::Clock::Seconds16(20); +static constexpr System::Clock::Timeout kFastAdvertiseTimeout = + System::Clock::Milliseconds32(CHIP_DEVICE_CONFIG_BLE_ADVERTISING_INTERVAL_CHANGE_TIME); +#if CHIP_DEVICE_CONFIG_EXT_ADVERTISING +// The CHIP_DEVICE_CONFIG_BLE_EXT_ADVERTISING_INTERVAL_CHANGE_TIME_MS specifies the transition time +// starting from advertisement commencement. Since the extended advertisement timer is started after +// the fast-to-slow transition, we have to subtract the time spent in fast advertising. +static constexpr System::Clock::Timeout kSlowAdvertiseTimeout = System::Clock::Milliseconds32( + CHIP_DEVICE_CONFIG_BLE_EXT_ADVERTISING_INTERVAL_CHANGE_TIME_MS - CHIP_DEVICE_CONFIG_BLE_ADVERTISING_INTERVAL_CHANGE_TIME); +static_assert(CHIP_DEVICE_CONFIG_BLE_EXT_ADVERTISING_INTERVAL_CHANGE_TIME_MS >= + CHIP_DEVICE_CONFIG_BLE_ADVERTISING_INTERVAL_CHANGE_TIME, + "The extended advertising interval change time must be greater than the fast advertising interval change time"); +#endif + +void HandleConnectTimeout(chip::System::Layer *, void * apEndpoint) +{ + VerifyOrDie(apEndpoint != nullptr); + static_cast(apEndpoint)->CancelConnect(); + BLEManagerImpl::HandleConnectFailed(CHIP_ERROR_TIMEOUT); +} + +} // namespace + +BLEManagerImpl BLEManagerImpl::sInstance; + +void HandleIncomingBleConnection(BLEEndPoint * bleEP) +{ + ChipLogProgress(DeviceLayer, "CHIPoBluez con rcvd"); +} + +CHIP_ERROR BLEManagerImpl::_Init() +{ + CHIP_ERROR err; + + err = BleLayer::Init(this, this, this, &DeviceLayer::SystemLayer()); + SuccessOrExit(err); + + mServiceMode = ConnectivityManager::kCHIPoBLEServiceMode_Enabled; + mFlags.ClearAll().Set(Flags::kAdvertisingEnabled, CHIP_DEVICE_CONFIG_CHIPOBLE_ENABLE_ADVERTISING_AUTOSTART && !mIsCentral); + mFlags.Set(Flags::kFastAdvertisingEnabled, true); + + memset(mDeviceName, 0, sizeof(mDeviceName)); + + OnChipBleConnectReceived = HandleIncomingBleConnection; + + DeviceLayer::SystemLayer().ScheduleLambda([this] { DriveBLEState(); }); + +exit: + return err; +} + +void BLEManagerImpl::_Shutdown() +{ + // Ensure scan resources are cleared (e.g. timeout timers). + mDeviceScanner.Shutdown(); + // Stop advertising and free resources. + mBLEAdvertisement.Shutdown(); + // Make sure that the endpoint is not used by the timer. + DeviceLayer::SystemLayer().CancelTimer(HandleConnectTimeout, &mEndpoint); + // Release BLE connection resources (unregister from BlueZ). + mEndpoint.Shutdown(); + mFlags.Clear(Flags::kBluezBLELayerInitialized); +} + +CHIP_ERROR BLEManagerImpl::_SetAdvertisingEnabled(bool val) +{ + CHIP_ERROR err = CHIP_NO_ERROR; + + if (mFlags.Has(Flags::kAdvertisingEnabled) != val) + { + mFlags.Set(Flags::kAdvertisingEnabled, val); + } + + DeviceLayer::SystemLayer().ScheduleLambda([this] { DriveBLEState(); }); + + return err; +} + +CHIP_ERROR BLEManagerImpl::_SetAdvertisingMode(BLEAdvertisingMode mode) +{ + switch (mode) + { + case BLEAdvertisingMode::kFastAdvertising: + mFlags.Set(Flags::kFastAdvertisingEnabled, true); + break; + case BLEAdvertisingMode::kSlowAdvertising: + mFlags.Set(Flags::kFastAdvertisingEnabled, false); + break; + default: + return CHIP_ERROR_INVALID_ARGUMENT; + } + mFlags.Set(Flags::kAdvertisingRefreshNeeded); + DeviceLayer::SystemLayer().ScheduleLambda([this] { DriveBLEState(); }); + return CHIP_NO_ERROR; +} + +CHIP_ERROR BLEManagerImpl::_GetDeviceName(char * buf, size_t bufSize) +{ + if (strlen(mDeviceName) >= bufSize) + { + return CHIP_ERROR_BUFFER_TOO_SMALL; + } + strcpy(buf, mDeviceName); + + return CHIP_NO_ERROR; +} + +CHIP_ERROR BLEManagerImpl::_SetDeviceName(const char * deviceName) +{ + CHIP_ERROR err = CHIP_NO_ERROR; + + VerifyOrExit(mServiceMode != ConnectivityManager::kCHIPoBLEServiceMode_NotSupported, err = CHIP_ERROR_UNSUPPORTED_CHIP_FEATURE); + + if (deviceName != nullptr && deviceName[0] != 0) + { + VerifyOrExit(strlen(deviceName) < kMaxDeviceNameLength, err = CHIP_ERROR_INVALID_ARGUMENT); + strcpy(mDeviceName, deviceName); + mFlags.Set(Flags::kUseCustomDeviceName); + } + else + { + uint16_t discriminator; + SuccessOrExit(err = GetCommissionableDataProvider()->GetSetupDiscriminator(discriminator)); + snprintf(mDeviceName, sizeof(mDeviceName), "%s%04u", CHIP_DEVICE_CONFIG_BLE_DEVICE_NAME_PREFIX, discriminator); + mDeviceName[kMaxDeviceNameLength] = 0; + mFlags.Clear(Flags::kUseCustomDeviceName); + } + +exit: + return err; +} + +uint16_t BLEManagerImpl::_NumConnections() +{ + uint16_t numCons = 0; + return numCons; +} + +CHIP_ERROR BLEManagerImpl::ConfigureBle(uint32_t aAdapterId, bool aIsCentral) +{ + mAdapterId = aAdapterId; + mIsCentral = aIsCentral; + mpBLEAdvUUID = "0xFFF6"; + return CHIP_NO_ERROR; +} + +void BLEManagerImpl::_OnPlatformEvent(const ChipDeviceEvent * event) +{ + switch (event->Type) + { + case DeviceEventType::kCHIPoBLESubscribe: + HandleSubscribeReceived(event->CHIPoBLESubscribe.ConId, &CHIP_BLE_SVC_ID, &Ble::CHIP_BLE_CHAR_2_UUID); + { + ChipDeviceEvent connectionEvent; + connectionEvent.Type = DeviceEventType::kCHIPoBLEConnectionEstablished; + PlatformMgr().PostEventOrDie(&connectionEvent); + } + break; + + case DeviceEventType::kCHIPoBLEUnsubscribe: + HandleUnsubscribeReceived(event->CHIPoBLEUnsubscribe.ConId, &CHIP_BLE_SVC_ID, &Ble::CHIP_BLE_CHAR_2_UUID); + break; + + case DeviceEventType::kCHIPoBLEWriteReceived: + HandleWriteReceived(event->CHIPoBLEWriteReceived.ConId, &CHIP_BLE_SVC_ID, &Ble::CHIP_BLE_CHAR_1_UUID, + PacketBufferHandle::Adopt(event->CHIPoBLEWriteReceived.Data)); + break; + + case DeviceEventType::kCHIPoBLEIndicateConfirm: + HandleIndicationConfirmation(event->CHIPoBLEIndicateConfirm.ConId, &CHIP_BLE_SVC_ID, &Ble::CHIP_BLE_CHAR_2_UUID); + break; + + case DeviceEventType::kCHIPoBLEConnectionError: + HandleConnectionError(event->CHIPoBLEConnectionError.ConId, event->CHIPoBLEConnectionError.Reason); + break; + case DeviceEventType::kServiceProvisioningChange: + // Force the advertising configuration to be refreshed to reflect new provisioning state. + mFlags.Clear(Flags::kAdvertisingConfigured); + + DriveBLEState(); + break; + default: + HandlePlatformSpecificBLEEvent(event); + break; + } +} + +void BLEManagerImpl::HandlePlatformSpecificBLEEvent(const ChipDeviceEvent * apEvent) +{ + CHIP_ERROR err = CHIP_NO_ERROR; + bool controlOpComplete = false; + ChipLogDetail(DeviceLayer, "HandlePlatformSpecificBLEEvent %d", apEvent->Type); + switch (apEvent->Type) + { + case DeviceEventType::kPlatformLinuxBLECentralConnected: + if (mBLEScanConfig.mBleScanState == BleScanState::kConnecting) + { + BleConnectionDelegate::OnConnectionComplete(mBLEScanConfig.mAppState, + apEvent->Platform.BLECentralConnected.mConnection); + CleanScanConfig(); + } + break; + case DeviceEventType::kPlatformLinuxBLECentralConnectFailed: + if (mBLEScanConfig.mBleScanState == BleScanState::kConnecting) + { + BleConnectionDelegate::OnConnectionError(mBLEScanConfig.mAppState, apEvent->Platform.BLECentralConnectFailed.mError); + CleanScanConfig(); + } + break; + case DeviceEventType::kPlatformLinuxBLEWriteComplete: + HandleWriteConfirmation(apEvent->Platform.BLEWriteComplete.mConnection, &CHIP_BLE_SVC_ID, &Ble::CHIP_BLE_CHAR_1_UUID); + break; + case DeviceEventType::kPlatformLinuxBLESubscribeOpComplete: + if (apEvent->Platform.BLESubscribeOpComplete.mIsSubscribed) + HandleSubscribeComplete(apEvent->Platform.BLESubscribeOpComplete.mConnection, &CHIP_BLE_SVC_ID, + &Ble::CHIP_BLE_CHAR_2_UUID); + else + HandleUnsubscribeComplete(apEvent->Platform.BLESubscribeOpComplete.mConnection, &CHIP_BLE_SVC_ID, + &Ble::CHIP_BLE_CHAR_2_UUID); + break; + case DeviceEventType::kPlatformLinuxBLEIndicationReceived: + HandleIndicationReceived(apEvent->Platform.BLEIndicationReceived.mConnection, &CHIP_BLE_SVC_ID, &Ble::CHIP_BLE_CHAR_2_UUID, + PacketBufferHandle::Adopt(apEvent->Platform.BLEIndicationReceived.mData)); + break; + case DeviceEventType::kPlatformLinuxBLEPeripheralAdvStartComplete: + SuccessOrExit(err = apEvent->Platform.BLEPeripheralAdvStartComplete.mError); + sInstance.mFlags.Clear(Flags::kControlOpInProgress).Clear(Flags::kAdvertisingRefreshNeeded); + // Do not restart the timer if it is still active. This is to avoid the timer from being restarted + // if the advertising is stopped due to a premature release. + if (!DeviceLayer::SystemLayer().IsTimerActive(HandleAdvertisingTimer, this)) + { + // Start a timer to make sure that the fast advertising is stopped after specified timeout. + SuccessOrExit(err = DeviceLayer::SystemLayer().StartTimer(kFastAdvertiseTimeout, HandleAdvertisingTimer, this)); + } + sInstance.mFlags.Set(Flags::kAdvertising); + break; + case DeviceEventType::kPlatformLinuxBLEPeripheralAdvStopComplete: + SuccessOrExit(err = apEvent->Platform.BLEPeripheralAdvStopComplete.mError); + sInstance.mFlags.Clear(Flags::kControlOpInProgress).Clear(Flags::kAdvertisingRefreshNeeded); + DeviceLayer::SystemLayer().CancelTimer(HandleAdvertisingTimer, this); + + // Transition to the not Advertising state... + if (sInstance.mFlags.Has(Flags::kAdvertising)) + { + sInstance.mFlags.Clear(Flags::kAdvertising); + ChipLogProgress(DeviceLayer, "CHIPoBLE advertising stopped"); + } + break; + case DeviceEventType::kPlatformLinuxBLEPeripheralAdvReleased: + // If the advertising was stopped due to a premature release, check if it needs to be restarted. + sInstance.mFlags.Clear(Flags::kAdvertising); + DriveBLEState(); + break; + case DeviceEventType::kPlatformLinuxBLEPeripheralRegisterAppComplete: + SuccessOrExit(err = apEvent->Platform.BLEPeripheralRegisterAppComplete.mError); + mFlags.Set(Flags::kAppRegistered); + controlOpComplete = true; + break; + default: + break; + } + +exit: + if (err != CHIP_NO_ERROR) + { + ChipLogError(DeviceLayer, "Disabling CHIPoBLE service due to error: %s", ErrorStr(err)); + mServiceMode = ConnectivityManager::kCHIPoBLEServiceMode_Disabled; + DeviceLayer::SystemLayer().CancelTimer(HandleAdvertisingTimer, this); + sInstance.mFlags.Clear(Flags::kControlOpInProgress); + } + + if (controlOpComplete) + { + mFlags.Clear(Flags::kControlOpInProgress); + DriveBLEState(); + } +} + +uint16_t BLEManagerImpl::GetMTU(BLE_CONNECTION_OBJECT conId) const +{ + uint16_t mtu = 0; + VerifyOrExit(conId != BLE_CONNECTION_UNINITIALIZED, + ChipLogError(DeviceLayer, "BLE connection is not initialized in %s", __func__)); + mtu = conId->GetMTU(); +exit: + return mtu; +} + +CHIP_ERROR BLEManagerImpl::SubscribeCharacteristic(BLE_CONNECTION_OBJECT conId, const ChipBleUUID * svcId, + const ChipBleUUID * charId) +{ + CHIP_ERROR err = BLE_ERROR_GATT_SUBSCRIBE_FAILED; + + VerifyOrExit(conId != BLE_CONNECTION_UNINITIALIZED, + ChipLogError(DeviceLayer, "BLE connection is not initialized in %s", __func__)); + VerifyOrExit(Ble::UUIDsMatch(svcId, &CHIP_BLE_SVC_ID), + ChipLogError(DeviceLayer, "SubscribeCharacteristic() called with invalid service ID")); + VerifyOrExit(Ble::UUIDsMatch(charId, &Ble::CHIP_BLE_CHAR_2_UUID), + ChipLogError(DeviceLayer, "SubscribeCharacteristic() called with invalid characteristic ID")); + err = conId->SubscribeCharacteristic(); + +exit: + return err; +} + +CHIP_ERROR BLEManagerImpl::UnsubscribeCharacteristic(BLE_CONNECTION_OBJECT conId, const ChipBleUUID * svcId, + const ChipBleUUID * charId) +{ + CHIP_ERROR err = BLE_ERROR_GATT_UNSUBSCRIBE_FAILED; + + VerifyOrExit(conId != BLE_CONNECTION_UNINITIALIZED, + ChipLogError(DeviceLayer, "BLE connection is not initialized in %s", __func__)); + VerifyOrExit(Ble::UUIDsMatch(svcId, &CHIP_BLE_SVC_ID), + ChipLogError(DeviceLayer, "UnsubscribeCharacteristic() called with invalid service ID")); + VerifyOrExit(Ble::UUIDsMatch(charId, &Ble::CHIP_BLE_CHAR_2_UUID), + ChipLogError(DeviceLayer, "UnsubscribeCharacteristic() called with invalid characteristic ID")); + err = conId->UnsubscribeCharacteristic(); + +exit: + return err; +} + +CHIP_ERROR BLEManagerImpl::CloseConnection(BLE_CONNECTION_OBJECT conId) +{ + CHIP_ERROR err = CHIP_ERROR_INTERNAL; + + VerifyOrExit(conId != BLE_CONNECTION_UNINITIALIZED, + ChipLogError(DeviceLayer, "BLE connection is not initialized in %s", __func__)); + ChipLogProgress(DeviceLayer, "Closing BLE GATT connection (con %p)", conId); + err = conId->CloseConnection(); + +exit: + return err; +} + +CHIP_ERROR BLEManagerImpl::SendIndication(BLE_CONNECTION_OBJECT conId, const ChipBleUUID * svcId, const Ble::ChipBleUUID * charId, + chip::System::PacketBufferHandle pBuf) +{ + CHIP_ERROR err = BLE_ERROR_GATT_INDICATE_FAILED; + + VerifyOrExit(conId != BLE_CONNECTION_UNINITIALIZED, + ChipLogError(DeviceLayer, "BLE connection is not initialized in %s", __func__)); + err = conId->SendIndication(std::move(pBuf)); + +exit: + return err; +} + +CHIP_ERROR BLEManagerImpl::SendWriteRequest(BLE_CONNECTION_OBJECT conId, const Ble::ChipBleUUID * svcId, + const Ble::ChipBleUUID * charId, chip::System::PacketBufferHandle pBuf) +{ + CHIP_ERROR err = BLE_ERROR_GATT_WRITE_FAILED; + + VerifyOrExit(conId != BLE_CONNECTION_UNINITIALIZED, + ChipLogError(DeviceLayer, "BLE connection is not initialized in %s", __func__)); + VerifyOrExit(Ble::UUIDsMatch(svcId, &CHIP_BLE_SVC_ID), + ChipLogError(DeviceLayer, "SendWriteRequest() called with invalid service ID")); + VerifyOrExit(Ble::UUIDsMatch(charId, &Ble::CHIP_BLE_CHAR_1_UUID), + ChipLogError(DeviceLayer, "SendWriteRequest() called with invalid characteristic ID")); + err = conId->SendWriteRequest(std::move(pBuf)); + +exit: + return err; +} + +void BLEManagerImpl::HandleNewConnection(BLE_CONNECTION_OBJECT conId) +{ + if (sInstance.mIsCentral) + { + ChipDeviceEvent event; + event.Type = DeviceEventType::kPlatformLinuxBLECentralConnected; + event.Platform.BLECentralConnected.mConnection = conId; + PlatformMgr().PostEventOrDie(&event); + } +} + +void BLEManagerImpl::HandleConnectFailed(CHIP_ERROR error) +{ + if (sInstance.mIsCentral) + { + ChipDeviceEvent event; + event.Type = DeviceEventType::kPlatformLinuxBLECentralConnectFailed; + event.Platform.BLECentralConnectFailed.mError = error; + PlatformMgr().PostEventOrDie(&event); + } +} + +void BLEManagerImpl::HandleWriteComplete(BLE_CONNECTION_OBJECT conId) +{ + ChipDeviceEvent event; + event.Type = DeviceEventType::kPlatformLinuxBLEWriteComplete; + event.Platform.BLEWriteComplete.mConnection = conId; + PlatformMgr().PostEventOrDie(&event); +} + +void BLEManagerImpl::HandleSubscribeOpComplete(BLE_CONNECTION_OBJECT conId, bool subscribed) +{ + ChipDeviceEvent event; + event.Type = DeviceEventType::kPlatformLinuxBLESubscribeOpComplete; + event.Platform.BLESubscribeOpComplete.mConnection = conId; + event.Platform.BLESubscribeOpComplete.mIsSubscribed = subscribed; + PlatformMgr().PostEventOrDie(&event); +} + +void BLEManagerImpl::HandleTXCharChanged(BLE_CONNECTION_OBJECT conId, const uint8_t * value, size_t len) +{ + CHIP_ERROR err = CHIP_NO_ERROR; + System::PacketBufferHandle buf = System::PacketBufferHandle::NewWithData(value, len); + + ChipLogDetail(DeviceLayer, "Indication received, conn = %p", conId); + + VerifyOrExit(!buf.IsNull(), err = CHIP_ERROR_NO_MEMORY); + + ChipDeviceEvent event; + event.Type = DeviceEventType::kPlatformLinuxBLEIndicationReceived; + event.Platform.BLEIndicationReceived.mConnection = conId; + event.Platform.BLEIndicationReceived.mData = std::move(buf).UnsafeRelease(); + PlatformMgr().PostEventOrDie(&event); + +exit: + if (err != CHIP_NO_ERROR) + ChipLogError(DeviceLayer, "HandleTXCharChanged() failed: %s", ErrorStr(err)); +} + +void BLEManagerImpl::HandleRXCharWrite(BLE_CONNECTION_OBJECT conId, const uint8_t * value, size_t len) +{ + CHIP_ERROR err = CHIP_NO_ERROR; + System::PacketBufferHandle buf; + + // Copy the data to a packet buffer. + buf = System::PacketBufferHandle::NewWithData(value, len); + VerifyOrExit(!buf.IsNull(), err = CHIP_ERROR_NO_MEMORY); + + // Post an event to the Chip queue to deliver the data into the Chip stack. + { + ChipDeviceEvent event; + event.Type = DeviceEventType::kCHIPoBLEWriteReceived; + ChipLogProgress(Ble, "Write request received debug %p", conId); + event.CHIPoBLEWriteReceived.ConId = conId; + event.CHIPoBLEWriteReceived.Data = std::move(buf).UnsafeRelease(); + PlatformMgr().PostEventOrDie(&event); + } + +exit: + if (err != CHIP_NO_ERROR) + { + ChipLogError(DeviceLayer, "HandleRXCharWrite() failed: %s", ErrorStr(err)); + } +} + +void BLEManagerImpl::CHIPoBluez_ConnectionClosed(BLE_CONNECTION_OBJECT conId) +{ + ChipLogProgress(DeviceLayer, "Bluez notify CHIPoBluez connection disconnected"); + + // If this was a CHIPoBLE connection, post an event to deliver a connection error to the CHIPoBLE layer. + { + ChipDeviceEvent event; + event.Type = DeviceEventType::kCHIPoBLEConnectionError; + event.CHIPoBLEConnectionError.ConId = conId; + event.CHIPoBLEConnectionError.Reason = BLE_ERROR_REMOTE_DEVICE_DISCONNECTED; + PlatformMgr().PostEventOrDie(&event); + } +} + +void BLEManagerImpl::HandleTXCharCCCDWrite(BLE_CONNECTION_OBJECT conId) +{ + VerifyOrReturn(conId != BLE_CONNECTION_UNINITIALIZED, + ChipLogError(DeviceLayer, "BLE connection is not initialized in %s", __func__)); + + // Post an event to the Chip queue to process either a CHIPoBLE Subscribe or Unsubscribe based on + // whether the client is enabling or disabling indications. + ChipDeviceEvent event; + event.Type = conId->IsNotifyAcquired() ? DeviceEventType::kCHIPoBLESubscribe : DeviceEventType::kCHIPoBLEUnsubscribe; + event.CHIPoBLESubscribe.ConId = conId; + PlatformMgr().PostEventOrDie(&event); + + ChipLogProgress(DeviceLayer, "CHIPoBLE %s received", + (event.Type == DeviceEventType::kCHIPoBLESubscribe) ? "subscribe" : "unsubscribe"); +} + +void BLEManagerImpl::HandleTXComplete(BLE_CONNECTION_OBJECT conId) +{ + // Post an event to the Chip queue to process the indicate confirmation. + ChipDeviceEvent event; + event.Type = DeviceEventType::kCHIPoBLEIndicateConfirm; + event.CHIPoBLEIndicateConfirm.ConId = conId; + PlatformMgr().PostEventOrDie(&event); +} + +void BLEManagerImpl::DriveBLEState() +{ + CHIP_ERROR err = CHIP_NO_ERROR; + + // Perform any initialization actions that must occur after the Chip task is running. + if (!mFlags.Has(Flags::kAsyncInitCompleted)) + { + mFlags.Set(Flags::kAsyncInitCompleted); + ExitNow(); + } + + // If there's already a control operation in progress, wait until it completes. + VerifyOrExit(!mFlags.Has(Flags::kControlOpInProgress), /* */); + + // Initializes the Bluez BLE layer if needed. + if (mServiceMode == ConnectivityManager::kCHIPoBLEServiceMode_Enabled && !mFlags.Has(Flags::kBluezBLELayerInitialized)) + { + SuccessOrExit(err = mEndpoint.Init(mIsCentral, mAdapterId)); + mFlags.Set(Flags::kBluezBLELayerInitialized); + } + + // Register the CHIPoBLE application with the Bluez BLE layer if needed. + if (!mIsCentral && mServiceMode == ConnectivityManager::kCHIPoBLEServiceMode_Enabled && !mFlags.Has(Flags::kAppRegistered)) + { + SuccessOrExit(err = mEndpoint.RegisterGattApplication()); + mFlags.Set(Flags::kControlOpInProgress); + ExitNow(); + } + + // If the application has enabled CHIPoBLE and BLE advertising... + if (mServiceMode == ConnectivityManager::kCHIPoBLEServiceMode_Enabled && mFlags.Has(Flags::kAdvertisingEnabled)) + { + // Start/re-start advertising if not already advertising, or if the advertising state of the + // Bluez BLE layer needs to be refreshed. + if (!mFlags.Has(Flags::kAdvertising) || mFlags.Has(Flags::kAdvertisingRefreshNeeded)) + { + mFlags.Clear(Flags::kAdvertisingRefreshNeeded); + + // Configure advertising data if it hasn't been done yet. + if (!mFlags.Has(Flags::kAdvertisingConfigured)) + { + SuccessOrExit(err = mBLEAdvertisement.Init(mEndpoint, mpBLEAdvUUID, mDeviceName)); + mFlags.Set(Flags::kAdvertisingConfigured); + } + + // Setup service data for advertising. + auto serviceDataFlags = BluezAdvertisement::kServiceDataNone; +#if CHIP_DEVICE_CONFIG_EXT_ADVERTISING + if (mFlags.Has(Flags::kExtAdvertisingEnabled)) + serviceDataFlags |= BluezAdvertisement::kServiceDataExtendedAnnouncement; +#endif + SuccessOrExit(err = mBLEAdvertisement.SetupServiceData(serviceDataFlags)); + + // Set or update the advertising intervals. + SuccessOrExit(err = mBLEAdvertisement.SetIntervals(GetAdvertisingIntervals())); + + if (!mFlags.Has(Flags::kAdvertising)) + { + // Start advertising. This is an asynchronous step. BLE manager will be notified of + // advertising start completion via a call to NotifyBLEPeripheralAdvStartComplete. + SuccessOrExit(err = mBLEAdvertisement.Start()); + mFlags.Set(Flags::kControlOpInProgress); + ExitNow(); + } + } + } + + // Otherwise stop advertising if needed... + else + { + if (mFlags.Has(Flags::kAdvertising)) + { + SuccessOrExit(err = mBLEAdvertisement.Stop()); + mFlags.Set(Flags::kControlOpInProgress); + + ExitNow(); + } + } + +exit: + if (err != CHIP_NO_ERROR) + { + ChipLogError(DeviceLayer, "Disabling CHIPoBLE service due to error: %s", ErrorStr(err)); + DeviceLayer::SystemLayer().CancelTimer(HandleAdvertisingTimer, this); + mServiceMode = ConnectivityManager::kCHIPoBLEServiceMode_Disabled; + } +} + +void BLEManagerImpl::NotifyChipConnectionClosed(BLE_CONNECTION_OBJECT conId) +{ + ChipLogProgress(Ble, "Got notification regarding chip connection closure"); +#if CHIP_DEVICE_CONFIG_ENABLE_WPA && !CHIP_DEVICE_CONFIG_SUPPORTS_CONCURRENT_CONNECTION + if (mState == kState_NotInitialized) + { + // Close BLE GATT connections to disconnect BlueZ + CloseConnection(conId); + // In Non-Concurrent mode start the Wi-Fi, as BLE has been stopped + DeviceLayer::ConnectivityMgrImpl().StartNonConcurrentWiFiManagement(); + } +#endif // CHIP_DEVICE_CONFIG_SUPPORTS_CONCURRENT_CONNECTION +} + +void BLEManagerImpl::CheckNonConcurrentBleClosing() +{ +#if CHIP_DEVICE_CONFIG_ENABLE_WPA && !CHIP_DEVICE_CONFIG_SUPPORTS_CONCURRENT_CONNECTION + if (mState == kState_Disconnecting) + { + DeviceLayer::DeviceControlServer::DeviceControlSvr().PostCloseAllBLEConnectionsToOperationalNetworkEvent(); + } +#endif +} + +BluezAdvertisement::AdvertisingIntervals BLEManagerImpl::GetAdvertisingIntervals() const +{ + if (mFlags.Has(Flags::kFastAdvertisingEnabled)) + return { CHIP_DEVICE_CONFIG_BLE_FAST_ADVERTISING_INTERVAL_MIN, CHIP_DEVICE_CONFIG_BLE_FAST_ADVERTISING_INTERVAL_MAX }; +#if CHIP_DEVICE_CONFIG_EXT_ADVERTISING + if (mFlags.Has(Flags::kExtAdvertisingEnabled)) + return { CHIP_DEVICE_CONFIG_BLE_EXT_ADVERTISING_INTERVAL_MIN, CHIP_DEVICE_CONFIG_BLE_EXT_ADVERTISING_INTERVAL_MAX }; +#endif + return { CHIP_DEVICE_CONFIG_BLE_SLOW_ADVERTISING_INTERVAL_MIN, CHIP_DEVICE_CONFIG_BLE_SLOW_ADVERTISING_INTERVAL_MAX }; +} + +void BLEManagerImpl::HandleAdvertisingTimer(chip::System::Layer *, void * appState) +{ + auto * self = static_cast(appState); + + if (self->mFlags.Has(Flags::kFastAdvertisingEnabled)) + { + ChipLogDetail(DeviceLayer, "bleAdv Timeout : Start slow advertisement"); + self->_SetAdvertisingMode(BLEAdvertisingMode::kSlowAdvertising); +#if CHIP_DEVICE_CONFIG_EXT_ADVERTISING + self->mFlags.Clear(Flags::kExtAdvertisingEnabled); + DeviceLayer::SystemLayer().StartTimer(kSlowAdvertiseTimeout, HandleAdvertisingTimer, self); + } + else + { + ChipLogDetail(DeviceLayer, "bleAdv Timeout : Start extended advertisement"); + self->mFlags.Set(Flags::kExtAdvertisingEnabled); + // This will trigger advertising intervals update in the DriveBLEState() function. + self->_SetAdvertisingMode(BLEAdvertisingMode::kSlowAdvertising); +#endif + } +} + +void BLEManagerImpl::InitiateScan(BleScanState scanType) +{ + DriveBLEState(); + + if (scanType == BleScanState::kNotScanning) + { + BleConnectionDelegate::OnConnectionError(mBLEScanConfig.mAppState, CHIP_ERROR_INCORRECT_STATE); + ChipLogError(Ble, "Invalid scan type requested"); + return; + } + + if (!mFlags.Has(Flags::kBluezBLELayerInitialized)) + { + BleConnectionDelegate::OnConnectionError(mBLEScanConfig.mAppState, CHIP_ERROR_INCORRECT_STATE); + ChipLogError(Ble, "BLE Layer is not yet initialized"); + return; + } + + if (mEndpoint.GetAdapter() == nullptr) + { + BleConnectionDelegate::OnConnectionError(mBLEScanConfig.mAppState, CHIP_ERROR_INCORRECT_STATE); + ChipLogError(Ble, "No adapter available for new connection establishment"); + return; + } + + mBLEScanConfig.mBleScanState = scanType; + + CHIP_ERROR err = mDeviceScanner.Init(mEndpoint.GetAdapter(), this); + if (err != CHIP_NO_ERROR) + { + mBLEScanConfig.mBleScanState = BleScanState::kNotScanning; + BleConnectionDelegate::OnConnectionError(mBLEScanConfig.mAppState, CHIP_ERROR_INTERNAL); + ChipLogError(Ble, "Failed to create a BLE device scanner"); + return; + } + + err = mDeviceScanner.StartScan(kNewConnectionScanTimeout); + if (err != CHIP_NO_ERROR) + { + mBLEScanConfig.mBleScanState = BleScanState::kNotScanning; + ChipLogError(Ble, "Failed to start a BLE can: %s", chip::ErrorStr(err)); + BleConnectionDelegate::OnConnectionError(mBLEScanConfig.mAppState, err); + return; + } +} + +void BLEManagerImpl::CleanScanConfig() +{ + if (mBLEScanConfig.mBleScanState == BleScanState::kConnecting) + DeviceLayer::SystemLayer().CancelTimer(HandleConnectTimeout, &mEndpoint); + + mBLEScanConfig.mBleScanState = BleScanState::kNotScanning; +} + +void BLEManagerImpl::NewConnection(BleLayer * bleLayer, void * appState, const SetupDiscriminator & connDiscriminator) +{ + mBLEScanConfig.mDiscriminator = connDiscriminator; + mBLEScanConfig.mAppState = appState; + + // Scan initiation performed async, to ensure that the BLE subsystem is initialized. + DeviceLayer::SystemLayer().ScheduleLambda([this] { InitiateScan(BleScanState::kScanForDiscriminator); }); +} + +CHIP_ERROR BLEManagerImpl::CancelConnection() +{ + if (mBLEScanConfig.mBleScanState == BleScanState::kConnecting) + mEndpoint.CancelConnect(); + // If in discovery mode, stop scan. + else if (mBLEScanConfig.mBleScanState != BleScanState::kNotScanning) + mDeviceScanner.StopScan(); + return CHIP_NO_ERROR; +} + +void BLEManagerImpl::NotifyBLEPeripheralRegisterAppComplete(CHIP_ERROR error) +{ + ChipDeviceEvent event; + event.Type = DeviceEventType::kPlatformLinuxBLEPeripheralRegisterAppComplete; + event.Platform.BLEPeripheralRegisterAppComplete.mError = error; + PlatformMgr().PostEventOrDie(&event); +} + +void BLEManagerImpl::NotifyBLEPeripheralAdvStartComplete(CHIP_ERROR error) +{ + ChipDeviceEvent event; + event.Type = DeviceEventType::kPlatformLinuxBLEPeripheralAdvStartComplete; + event.Platform.BLEPeripheralAdvStartComplete.mError = error; + PlatformMgr().PostEventOrDie(&event); +} + +void BLEManagerImpl::NotifyBLEPeripheralAdvStopComplete(CHIP_ERROR error) +{ + ChipDeviceEvent event; + event.Type = DeviceEventType::kPlatformLinuxBLEPeripheralAdvStopComplete; + event.Platform.BLEPeripheralAdvStopComplete.mError = error; + PlatformMgr().PostEventOrDie(&event); +} + +void BLEManagerImpl::NotifyBLEPeripheralAdvReleased() +{ + ChipDeviceEvent event; + event.Type = DeviceEventType::kPlatformLinuxBLEPeripheralAdvReleased; + PlatformMgr().PostEventOrDie(&event); +} + +void BLEManagerImpl::OnDeviceScanned(BluezDevice1 & device, const chip::Ble::ChipBLEDeviceIdentificationInfo & info) +{ + const char * address = bluez_device1_get_address(&device); + ChipLogProgress(Ble, "New device scanned: %s", address); + + if (mBLEScanConfig.mBleScanState == BleScanState::kScanForDiscriminator) + { + auto isMatch = mBLEScanConfig.mDiscriminator.MatchesLongDiscriminator(info.GetDeviceDiscriminator()); + VerifyOrReturn( + isMatch, + ChipLogError(Ble, "Skip connection: Device discriminator does not match: %u != %u", info.GetDeviceDiscriminator(), + mBLEScanConfig.mDiscriminator.IsShortDiscriminator() ? mBLEScanConfig.mDiscriminator.GetShortValue() + : mBLEScanConfig.mDiscriminator.GetLongValue())); + ChipLogProgress(Ble, "Device discriminator match. Attempting to connect."); + } + else if (mBLEScanConfig.mBleScanState == BleScanState::kScanForAddress) + { + auto isMatch = strcmp(address, mBLEScanConfig.mAddress.c_str()) == 0; + VerifyOrReturn(isMatch, + ChipLogError(Ble, "Skip connection: Device address does not match: %s != %s", address, + mBLEScanConfig.mAddress.c_str())); + ChipLogProgress(Ble, "Device address match. Attempting to connect."); + } + else + { + // Internal consistency error + ChipLogError(Ble, "Unknown discovery type. Ignoring scanned device."); + return; + } + + mBLEScanConfig.mBleScanState = BleScanState::kConnecting; + + chip::DeviceLayer::PlatformMgr().LockChipStack(); + // We StartScan in the ChipStack thread. + // StopScan should also be performed in the ChipStack thread. + // At the same time, the scan timer also needs to be canceled in the ChipStack thread. + mDeviceScanner.StopScan(); + // Stop scanning and then start connecting timer + DeviceLayer::SystemLayer().StartTimer(kConnectTimeout, HandleConnectTimeout, &mEndpoint); + chip::DeviceLayer::PlatformMgr().UnlockChipStack(); + + CHIP_ERROR err = mEndpoint.ConnectDevice(device); + VerifyOrReturn(err == CHIP_NO_ERROR, ChipLogError(Ble, "Device connection failed: %" CHIP_ERROR_FORMAT, err.Format())); + + ChipLogProgress(Ble, "New device connected: %s", address); +} + +void BLEManagerImpl::OnScanComplete() +{ + switch (mBLEScanConfig.mBleScanState) + { + case BleScanState::kNotScanning: + ChipLogProgress(Ble, "Scan complete notification without an active scan."); + break; + case BleScanState::kScanForAddress: + case BleScanState::kScanForDiscriminator: + mBLEScanConfig.mBleScanState = BleScanState::kNotScanning; + ChipLogProgress(Ble, "Scan complete. No matching device found."); + break; + case BleScanState::kConnecting: + break; + } +} + +void BLEManagerImpl::OnScanError(CHIP_ERROR err) +{ + BleConnectionDelegate::OnConnectionError(mBLEScanConfig.mAppState, err); + ChipLogError(Ble, "BLE scan error: %" CHIP_ERROR_FORMAT, err.Format()); +} + +} // namespace Internal +} // namespace DeviceLayer +} // namespace chip diff --git a/src/platform/Zephyr/BLEManagerImpl.cpp b/src/platform/Zephyr/BLEManagerImpl.cpp index c46a922696..598f87c924 100644 --- a/src/platform/Zephyr/BLEManagerImpl.cpp +++ b/src/platform/Zephyr/BLEManagerImpl.cpp @@ -300,7 +300,7 @@ inline CHIP_ERROR BLEManagerImpl::PrepareAdvertisingRequest() Encoding::LittleEndian::Put16(serviceData.uuid, UUID16_CHIPoBLEService.val); ReturnErrorOnFailure(ConfigurationMgr().GetBLEDeviceIdentificationInfo(serviceData.deviceIdInfo)); -#if CHIP_DEVICE_CONFIG_BLE_EXT_ADVERTISING +#if CHIP_DEVICE_CONFIG_EXT_ADVERTISING if (mFlags.Has(Flags::kExtendedAdvertisingEnabled)) { serviceData.deviceIdInfo.SetVendorId(DEVICE_HANDLE_NULL); @@ -321,7 +321,7 @@ inline CHIP_ERROR BLEManagerImpl::PrepareAdvertisingRequest() mAdvertisingRequest.minInterval = CHIP_DEVICE_CONFIG_BLE_FAST_ADVERTISING_INTERVAL_MIN; mAdvertisingRequest.maxInterval = CHIP_DEVICE_CONFIG_BLE_FAST_ADVERTISING_INTERVAL_MAX; } -#if CHIP_DEVICE_CONFIG_BLE_EXT_ADVERTISING +#if CHIP_DEVICE_CONFIG_EXT_ADVERTISING else if (mFlags.Has(Flags::kExtendedAdvertisingEnabled)) { mAdvertisingRequest.minInterval = CHIP_DEVICE_CONFIG_BLE_EXT_ADVERTISING_INTERVAL_MIN; @@ -426,7 +426,7 @@ CHIP_ERROR BLEManagerImpl::StartAdvertising() System::Clock::Milliseconds32(CHIP_DEVICE_CONFIG_BLE_ADVERTISING_INTERVAL_CHANGE_TIME), HandleSlowBLEAdvertisementInterval, this); -#if CHIP_DEVICE_CONFIG_BLE_EXT_ADVERTISING +#if CHIP_DEVICE_CONFIG_EXT_ADVERTISING // Start timer to schedule start of the extended advertising DeviceLayer::SystemLayer().StartTimer( System::Clock::Milliseconds32(CHIP_DEVICE_CONFIG_BLE_EXT_ADVERTISING_INTERVAL_CHANGE_TIME_MS), @@ -448,7 +448,7 @@ CHIP_ERROR BLEManagerImpl::StopAdvertising() mFlags.Clear(Flags::kAdvertising); mFlags.Set(Flags::kFastAdvertisingEnabled, true); -#if CHIP_DEVICE_CONFIG_BLE_EXT_ADVERTISING +#if CHIP_DEVICE_CONFIG_EXT_ADVERTISING mFlags.Clear(Flags::kExtendedAdvertisingEnabled); #endif diff --git a/src/platform/Zephyr/CHIPDevicePlatformConfig.h b/src/platform/Zephyr/CHIPDevicePlatformConfig.h index e7622f60dd..f2efef53cc 100644 --- a/src/platform/Zephyr/CHIPDevicePlatformConfig.h +++ b/src/platform/Zephyr/CHIPDevicePlatformConfig.h @@ -132,7 +132,7 @@ #endif // CONFIG_CHIP_EXTENDED_DISCOVERY #ifdef CONFIG_CHIP_BLE_EXT_ADVERTISING -#define CHIP_DEVICE_CONFIG_BLE_EXT_ADVERTISING 1 +#define CHIP_DEVICE_CONFIG_EXT_ADVERTISING 1 #endif // CONFIG_CHIP_BLE_EXT_ADVERTISING #define CHIP_DEVICE_CONFIG_DISCOVERY_TIMEOUT_SECS (CONFIG_CHIP_BLE_ADVERTISING_DURATION * 60) diff --git a/src/platform/nrfconnect/CHIPDevicePlatformConfig.h b/src/platform/nrfconnect/CHIPDevicePlatformConfig.h index 98e28ac98f..dad506be2d 100644 --- a/src/platform/nrfconnect/CHIPDevicePlatformConfig.h +++ b/src/platform/nrfconnect/CHIPDevicePlatformConfig.h @@ -233,7 +233,7 @@ #endif // CONFIG_CHIP_EXTENDED_DISCOVERY #ifdef CONFIG_CHIP_BLE_EXT_ADVERTISING -#define CHIP_DEVICE_CONFIG_BLE_EXT_ADVERTISING 1 +#define CHIP_DEVICE_CONFIG_EXT_ADVERTISING 1 #endif // CONFIG_CHIP_BLE_EXT_ADVERTISING #define CHIP_DEVICE_CONFIG_DISCOVERY_TIMEOUT_SECS (CONFIG_CHIP_BLE_ADVERTISING_DURATION * 60) diff --git a/src/platform/silabs/CHIPDevicePlatformConfig.h b/src/platform/silabs/CHIPDevicePlatformConfig.h index e8601e5fee..ae9f5b5ffb 100644 --- a/src/platform/silabs/CHIPDevicePlatformConfig.h +++ b/src/platform/silabs/CHIPDevicePlatformConfig.h @@ -140,7 +140,7 @@ #define CHIP_DEVICE_CONFIG_MAX_EVENT_QUEUE_SIZE 25 -#define CHIP_DEVICE_CONFIG_BLE_EXT_ADVERTISING SL_MATTER_BLE_EXTENDED_ADV +#define CHIP_DEVICE_CONFIG_EXT_ADVERTISING SL_MATTER_BLE_EXTENDED_ADV /* ICD Configuration Defines diff --git a/src/platform/silabs/efr32/BLEManagerImpl.cpp b/src/platform/silabs/efr32/BLEManagerImpl.cpp index db9939819b..d53eb2a496 100644 --- a/src/platform/silabs/efr32/BLEManagerImpl.cpp +++ b/src/platform/silabs/efr32/BLEManagerImpl.cpp @@ -459,7 +459,7 @@ CHIP_ERROR BLEManagerImpl::ConfigureAdvertisingData(void) advData[index++] = ShortUUID_CHIPoBLEService[0]; // AD value advData[index++] = ShortUUID_CHIPoBLEService[1]; -#if CHIP_DEVICE_CONFIG_BLE_EXT_ADVERTISING +#if CHIP_DEVICE_CONFIG_EXT_ADVERTISING // Check for extended advertisement interval and redact VID/PID if past the initial period. if (mFlags.Has(Flags::kExtAdvertisingEnabled)) { @@ -562,7 +562,7 @@ CHIP_ERROR BLEManagerImpl::StartAdvertising(void) } else { -#if CHIP_DEVICE_CONFIG_BLE_EXT_ADVERTISING +#if CHIP_DEVICE_CONFIG_EXT_ADVERTISING if (!mFlags.Has(Flags::kExtAdvertisingEnabled)) { interval_min = CHIP_DEVICE_CONFIG_BLE_SLOW_ADVERTISING_INTERVAL_MIN; @@ -978,12 +978,12 @@ void BLEManagerImpl::BleAdvTimeoutHandler(TimerHandle_t xTimer) ChipLogDetail(DeviceLayer, "bleAdv Timeout : Start slow advertisement"); BLEMgrImpl().mFlags.Set(Flags::kAdvertising); BLEMgr().SetAdvertisingMode(BLEAdvertisingMode::kSlowAdvertising); -#if CHIP_DEVICE_CONFIG_BLE_EXT_ADVERTISING +#if CHIP_DEVICE_CONFIG_EXT_ADVERTISING BLEMgrImpl().mFlags.Clear(Flags::kExtAdvertisingEnabled); BLEMgrImpl().StartBleAdvTimeoutTimer(CHIP_DEVICE_CONFIG_BLE_EXT_ADVERTISING_INTERVAL_CHANGE_TIME_MS); #endif } -#if CHIP_DEVICE_CONFIG_BLE_EXT_ADVERTISING +#if CHIP_DEVICE_CONFIG_EXT_ADVERTISING else { ChipLogDetail(DeviceLayer, "bleAdv Timeout : Start extended advertisement");