From 7c2da28fd9c21ff4b5dd0aa027aff249d87dc526 Mon Sep 17 00:00:00 2001 From: Kamil Kasperczyk <66371704+kkasperczyk-no@users.noreply.github.com> Date: Mon, 16 Sep 2024 08:11:37 +0200 Subject: [PATCH] [nrf fromtree] Fix max timeout for open commissioning window (#35507) Commissioning window can be opened using timeout exceeding the maximum value of 900 s defined by the spec. This can happen if selected transport is IP, but the device uses BLE extended announcement feature. Added checking if device is commissioned to be able to determine what max timeout should be used for the particular scenario. Renamed CHIP_DEVICE_CONFIG_BLE_EXT_ADVERTISING to the CHIP_DEVICE_CONFIG_EXT_ADVERTISING, as config name sounds misleading and it seems it relates only to BLE. Fixes: #35505 --- src/app/server/CommissioningWindowManager.cpp | 14 + src/app/server/CommissioningWindowManager.h | 11 +- src/include/platform/CHIPDeviceConfig.h | 14 +- src/platform/ESP32/CHIPDevicePlatformConfig.h | 7 +- src/platform/ESP32/nimble/BLEManagerImpl.cpp | 8 +- src/platform/Linux/BLEManagerImpl.cpp | 8 +- .../Linux/bluez/BluezAdvertisement.cpp | 2 +- src/platform/NuttX/BLEManagerImpl.cpp | 870 ++++++++++++++++++ src/platform/Zephyr/BLEManagerImpl.cpp | 8 +- .../Zephyr/CHIPDevicePlatformConfig.h | 2 +- .../nrfconnect/CHIPDevicePlatformConfig.h | 2 +- .../silabs/CHIPDevicePlatformConfig.h | 2 +- src/platform/silabs/efr32/BLEManagerImpl.cpp | 8 +- 13 files changed, 918 insertions(+), 38 deletions(-) create mode 100644 src/platform/NuttX/BLEManagerImpl.cpp 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");