From bd6c4aba209923587717ec195fc8f9446e6b0d23 Mon Sep 17 00:00:00 2001 From: Arkadiusz Bokowy Date: Tue, 6 Feb 2024 08:57:29 +0100 Subject: [PATCH] [Linux] Add support for extended advertisement (#31668) * Use ScheduleLambda() instead of ScheduleWork * Set min/max advertisement interval * Matter BLE advertisement type shall be peripheral * Allow intervals to be set after initialization * Keep BlueZ default for adv slicing duration * Allow to update intervals on the fly - fast/slow * Transition to slow advertising after timeout * Fix advertisement typos in all places in the codebase * Do not specify advertisement timeout in BlueZ * Add support for extended advertisement * Post review changes - add manual how to enable experimental features in BlueZ * Restyled by prettier-markdown * Assert that extended adv interval is >= fast adv interval * Cancel HandleAdvertisingTimer timer in case of error --------- Co-authored-by: Restyled.io --- docs/guides/BUILDING.md | 27 +++++ examples/lock-app/esp32/main/AppTask.cpp | 4 +- examples/platform/silabs/BaseApplication.cpp | 4 +- src/app/server/Dnssd.cpp | 2 +- .../minimal_mdns/tests/TestAdvertiser.cpp | 2 +- .../Infineon/PSOC6/BLEManagerImpl.cpp | 2 +- src/platform/Linux/BLEManagerImpl.cpp | 112 ++++++++++++------ src/platform/Linux/BLEManagerImpl.h | 12 +- .../Linux/bluez/BluezAdvertisement.cpp | 95 +++++++++------ src/platform/Linux/bluez/BluezAdvertisement.h | 22 ++-- src/platform/Linux/bluez/Types.h | 17 --- src/platform/Linux/dbus/bluez/DbusBluez.xml | 6 +- src/platform/mt793x/BLEManagerImpl.cpp | 2 +- src/platform/silabs/efr32/BLEManagerImpl.cpp | 6 +- src/platform/silabs/rs911x/BLEManagerImpl.cpp | 4 +- src/platform/stm32/BLEManagerImpl.cpp | 4 +- 16 files changed, 201 insertions(+), 120 deletions(-) diff --git a/docs/guides/BUILDING.md b/docs/guides/BUILDING.md index 89e657f834a350..8e32d6dc4a3c66 100644 --- a/docs/guides/BUILDING.md +++ b/docs/guides/BUILDING.md @@ -94,6 +94,33 @@ Complete the following steps: 1. Reboot your Raspberry Pi after installing `pi-bluetooth`. +#### Enable experimental Bluetooth support in BlueZ + +The Matter application on Linux uses BlueZ to communicate with the Bluetooth +controller. The BlueZ version that comes with Ubuntu 22.04 does not support all +the features required by the Matter application by default. To enable these +features, you need to enable experimental Bluetooth support in BlueZ. + +1. Edit the `bluetooth.service` unit by running the following command: + + ```sh + sudo systemctl edit bluetooth.service + ``` + +1. Add the following content to the override file: + + ```ini + [Service] + ExecStart= + ExecStart=/usr/lib/bluetooth/bluetoothd -E + ``` + +1. Restart the Bluetooth service by running the following command: + + ```sh + sudo systemctl restart bluetooth.service + ``` + #### Configuring wpa_supplicant for storing permanent changes By default, wpa_supplicant is not allowed to update (overwrite) configuration. diff --git a/examples/lock-app/esp32/main/AppTask.cpp b/examples/lock-app/esp32/main/AppTask.cpp index 52650e5c2d2652..e6a8519b782c18 100644 --- a/examples/lock-app/esp32/main/AppTask.cpp +++ b/examples/lock-app/esp32/main/AppTask.cpp @@ -322,7 +322,7 @@ void AppTask::FunctionHandler(AppEvent * aEvent) } else { - // If the button was released before factory reset got initiated, start BLE advertissement in fast mode + // If the button was released before factory reset got initiated, start BLE advertisement in fast mode if (sAppTask.mFunctionTimerActive && sAppTask.mFunction == kFunction_StartBleAdv) { sAppTask.CancelTimer(); @@ -336,7 +336,7 @@ void AppTask::FunctionHandler(AppEvent * aEvent) } else { - ESP_LOGI(TAG, "Network is already provisioned, Ble advertissement not enabled"); + ESP_LOGI(TAG, "Network is already provisioned, Ble advertisement not enabled"); } } else if (sAppTask.mFunctionTimerActive && sAppTask.mFunction == kFunction_FactoryReset) diff --git a/examples/platform/silabs/BaseApplication.cpp b/examples/platform/silabs/BaseApplication.cpp index 5870de2aeb947d..d2c6266a58382b 100644 --- a/examples/platform/silabs/BaseApplication.cpp +++ b/examples/platform/silabs/BaseApplication.cpp @@ -453,7 +453,7 @@ void BaseApplication::ButtonHandler(AppEvent * aEvent) { // The factory reset sequence was not initiated, // Press and Release: - // - Open the commissioning window and start BLE advertissement in fast mode when not commissioned + // - Open the commissioning window and start BLE advertisement in fast mode when not commissioned // - Output qr code in logs // - Cycle LCD screen CancelFunctionTimer(); @@ -477,7 +477,7 @@ void BaseApplication::ButtonHandler(AppEvent * aEvent) } else { - SILABS_LOG("Network is already provisioned, Ble advertissement not enabled"); + SILABS_LOG("Network is already provisioned, Ble advertisement not enabled"); #if CHIP_CONFIG_ENABLE_ICD_SERVER // Temporarily claim network activity, until we implement a "user trigger" reason for ICD wakeups. PlatformMgr().LockChipStack(); diff --git a/src/app/server/Dnssd.cpp b/src/app/server/Dnssd.cpp index ce3a94ef790336..dfb1fc4d6062a4 100644 --- a/src/app/server/Dnssd.cpp +++ b/src/app/server/Dnssd.cpp @@ -496,7 +496,7 @@ CHIP_ERROR DnssdServer::GenerateRotatingDeviceId(char rotatingDeviceIdHexBuffer[ void DnssdServer::OnICDModeChange() { // ICDMode changed, restart DNS-SD advertising, because SII and ICD key are affected by this change. - // StartServer will take care of setting the operational and commissionable advertissements + // StartServer will take care of setting the operational and commissionable advertisements StartServer(); } diff --git a/src/lib/dnssd/minimal_mdns/tests/TestAdvertiser.cpp b/src/lib/dnssd/minimal_mdns/tests/TestAdvertiser.cpp index aa6fcf0c04b815..8f3e39c026eb6d 100644 --- a/src/lib/dnssd/minimal_mdns/tests/TestAdvertiser.cpp +++ b/src/lib/dnssd/minimal_mdns/tests/TestAdvertiser.cpp @@ -210,7 +210,7 @@ CommissionAdvertisingParameters commissionableNodeParamsEnhancedAsICDLIT = .SetTcpSupported(chip::Optional(true)) .SetICDOperatingAsLIT(chip::Optional(true)) .SetLocalMRPConfig(Optional::Value(3600000_ms32, 3600000_ms32, 65535_ms16)); -// With ICD Operation as LIT, SII key will not be added to the advertissement +// With ICD Operation as LIT, SII key will not be added to the advertisement QNamePart txtCommissionableNodeParamsEnhancedAsICDLITParts[] = { "D=22", "VP=555+897", "CM=2", "DT=70000", "DN=testy-test", "PI=Pair me", "PH=3", "SAI=3600000", "SAT=65535", "T=1", "ICD=1" }; diff --git a/src/platform/Infineon/PSOC6/BLEManagerImpl.cpp b/src/platform/Infineon/PSOC6/BLEManagerImpl.cpp index 9d380a7124ae8a..917cdc267e4d24 100644 --- a/src/platform/Infineon/PSOC6/BLEManagerImpl.cpp +++ b/src/platform/Infineon/PSOC6/BLEManagerImpl.cpp @@ -426,7 +426,7 @@ void BLEManagerImpl::DriveBLEState(void) ChipLogProgress(DeviceLayer, "CHIPoBLE stop advertising"); wiced_bt_start_advertisements(BTM_BLE_ADVERT_OFF, BLE_ADDR_PUBLIC, NULL); - /* Delete the heap allocated during BLE Advertisment Stop */ + /* Delete the heap allocated during BLE Advertisement Stop */ if (p_heap) { wiced_bt_delete_heap(p_heap); diff --git a/src/platform/Linux/BLEManagerImpl.cpp b/src/platform/Linux/BLEManagerImpl.cpp index 12232bc0fd36e4..a98a52de9721e1 100644 --- a/src/platform/Linux/BLEManagerImpl.cpp +++ b/src/platform/Linux/BLEManagerImpl.cpp @@ -54,6 +54,18 @@ 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_BLE_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 const ChipBleUUID ChipUUID_CHIPoBLEChar_RX = { { 0x18, 0xEE, 0x2E, 0xF5, 0x26, 0x3D, 0x45, 0x59, 0x95, 0x9F, 0x4F, 0x9C, 0x42, 0x9F, 0x9D, 0x11 } }; @@ -91,7 +103,7 @@ CHIP_ERROR BLEManagerImpl::_Init() OnChipBleConnectReceived = HandleIncomingBleConnection; - PlatformMgr().ScheduleWork(DriveBLEState, 0); + DeviceLayer::SystemLayer().ScheduleLambda([this] { DriveBLEState(); }); exit: return err; @@ -119,7 +131,7 @@ CHIP_ERROR BLEManagerImpl::_SetAdvertisingEnabled(bool val) mFlags.Set(Flags::kAdvertisingEnabled, val); } - PlatformMgr().ScheduleWork(DriveBLEState, 0); + DeviceLayer::SystemLayer().ScheduleLambda([this] { DriveBLEState(); }); return err; } @@ -138,7 +150,7 @@ CHIP_ERROR BLEManagerImpl::_SetAdvertisingMode(BLEAdvertisingMode mode) return CHIP_ERROR_INVALID_ARGUMENT; } mFlags.Set(Flags::kAdvertisingRefreshNeeded); - PlatformMgr().ScheduleWork(DriveBLEState, 0); + DeviceLayer::SystemLayer().ScheduleLambda([this] { DriveBLEState(); }); return CHIP_NO_ERROR; } @@ -186,14 +198,9 @@ uint16_t BLEManagerImpl::_NumConnections() CHIP_ERROR BLEManagerImpl::ConfigureBle(uint32_t aAdapterId, bool aIsCentral) { - - mAdapterId = aAdapterId; - mIsCentral = aIsCentral; - - mBLEAdvType = ChipAdvType::BLUEZ_ADV_TYPE_UNDIRECTED_CONNECTABLE_SCANNABLE; - mBLEAdvDurationMs = 2; - mpBLEAdvUUID = "0xFFF6"; - + mAdapterId = aAdapterId; + mIsCentral = aIsCentral; + mpBLEAdvUUID = "0xFFF6"; return CHIP_NO_ERROR; } @@ -278,17 +285,14 @@ void BLEManagerImpl::HandlePlatformSpecificBLEEvent(const ChipDeviceEvent * apEv case DeviceEventType::kPlatformLinuxBLEPeripheralAdvStartComplete: VerifyOrExit(apEvent->Platform.BLEPeripheralAdvStartComplete.mIsSuccess, err = CHIP_ERROR_INCORRECT_STATE); sInstance.mFlags.Clear(Flags::kControlOpInProgress).Clear(Flags::kAdvertisingRefreshNeeded); - - if (!sInstance.mFlags.Has(Flags::kAdvertising)) - { - sInstance.mFlags.Set(Flags::kAdvertising); - } - + // 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: VerifyOrExit(apEvent->Platform.BLEPeripheralAdvStopComplete.mIsSuccess, err = CHIP_ERROR_INCORRECT_STATE); - 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)) @@ -311,6 +315,7 @@ void BLEManagerImpl::HandlePlatformSpecificBLEEvent(const ChipDeviceEvent * apEv { 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); } @@ -595,15 +600,29 @@ void BLEManagerImpl::DriveBLEState() // Configure advertising data if it hasn't been done yet. if (!mFlags.Has(Flags::kAdvertisingConfigured)) { - SuccessOrExit(err = mBLEAdvertisement.Init(mEndpoint, mBLEAdvType, mpBLEAdvUUID, mBLEAdvDurationMs, mDeviceName)); + SuccessOrExit(err = mBLEAdvertisement.Init(mEndpoint, mpBLEAdvUUID, mDeviceName)); mFlags.Set(Flags::kAdvertisingConfigured); } - // 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(); + // Setup service data for advertising. + auto serviceDataFlags = BluezAdvertisement::kServiceDataNone; +#if CHIP_DEVICE_CONFIG_BLE_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(); + } } } @@ -627,11 +646,6 @@ void BLEManagerImpl::DriveBLEState() } } -void BLEManagerImpl::DriveBLEState(intptr_t arg) -{ - sInstance.DriveBLEState(); -} - void BLEManagerImpl::NotifyChipConnectionClosed(BLE_CONNECTION_OBJECT conId) { ChipLogProgress(Ble, "Got notification regarding chip connection closure"); @@ -641,6 +655,39 @@ void BLEManagerImpl::NotifyChipConnectionClosed(BLE_CONNECTION_OBJECT conId) #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_BLE_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_BLE_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(); @@ -695,18 +742,13 @@ void BLEManagerImpl::CleanScanConfig() mBLEScanConfig.mBleScanState = BleScanState::kNotScanning; } -void BLEManagerImpl::InitiateScan(intptr_t arg) -{ - sInstance.InitiateScan(static_cast(arg)); -} - 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. - PlatformMgr().ScheduleWork(InitiateScan, static_cast(BleScanState::kScanForDiscriminator)); + DeviceLayer::SystemLayer().ScheduleLambda([this] { InitiateScan(BleScanState::kScanForDiscriminator); }); } CHIP_ERROR BLEManagerImpl::CancelConnection() diff --git a/src/platform/Linux/BLEManagerImpl.h b/src/platform/Linux/BLEManagerImpl.h index 5cd3ed2460adf9..1441f2e6573573 100644 --- a/src/platform/Linux/BLEManagerImpl.h +++ b/src/platform/Linux/BLEManagerImpl.h @@ -141,6 +141,7 @@ class BLEManagerImpl final : public BLEManager, CHIP_ERROR CancelConnection() override; // ===== Members that implement virtual methods on ChipDeviceScannerDelegate + void OnDeviceScanned(BluezDevice1 & device, const chip::Ble::ChipBLEDeviceIdentificationInfo & info) override; void OnScanComplete() override; @@ -152,6 +153,7 @@ class BLEManagerImpl final : public BLEManager, static BLEManagerImpl sInstance; // ===== Private members reserved for use by this class only. + enum class Flags : uint16_t { kAsyncInitCompleted = 0x0001, /**< One-time asynchronous initialization actions have been performed. */ @@ -164,6 +166,7 @@ class BLEManagerImpl final : public BLEManager, kFastAdvertisingEnabled = 0x0080, /**< The application has enabled fast advertising. */ kUseCustomDeviceName = 0x0100, /**< The application has configured a custom BLE device name. */ kAdvertisingRefreshNeeded = 0x0200, /**< The advertising configuration/state in BLE layer needs to be updated. */ + kExtAdvertisingEnabled = 0x0400, /**< The application has enabled CHIPoBLE extended advertising. */ }; enum @@ -174,10 +177,9 @@ class BLEManagerImpl final : public BLEManager, }; void DriveBLEState(); - static void DriveBLEState(intptr_t arg); - + BluezAdvertisement::AdvertisingIntervals GetAdvertisingIntervals() const; + static void HandleAdvertisingTimer(chip::System::Layer *, void * appState); void InitiateScan(BleScanState scanType); - static void InitiateScan(intptr_t arg); void CleanScanConfig(); CHIPoBLEServiceMode mServiceMode; @@ -189,9 +191,7 @@ class BLEManagerImpl final : public BLEManager, BluezEndpoint mEndpoint; BluezAdvertisement mBLEAdvertisement; - ChipAdvType mBLEAdvType = ChipAdvType::BLUEZ_ADV_TYPE_UNDIRECTED_CONNECTABLE_SCANNABLE; - uint16_t mBLEAdvDurationMs = 20; - const char * mpBLEAdvUUID = nullptr; + const char * mpBLEAdvUUID = nullptr; ChipDeviceScanner mDeviceScanner; BLEScanConfig mBLEScanConfig; diff --git a/src/platform/Linux/bluez/BluezAdvertisement.cpp b/src/platform/Linux/bluez/BluezAdvertisement.cpp index ab6b5ddc6b0751..db74da8bec1ec4 100644 --- a/src/platform/Linux/bluez/BluezAdvertisement.cpp +++ b/src/platform/Linux/bluez/BluezAdvertisement.cpp @@ -42,52 +42,36 @@ BluezLEAdvertisement1 * BluezAdvertisement::CreateLEAdvertisement() { BluezLEAdvertisement1 * adv; BluezObjectSkeleton * object; - GVariant * serviceData; GVariant * serviceUUID; - GVariantBuilder serviceDataBuilder; GVariantBuilder serviceUUIDsBuilder; - GAutoPtr debugStr; ChipLogDetail(DeviceLayer, "Create BLE adv object at %s", mpAdvPath); object = bluez_object_skeleton_new(mpAdvPath); adv = bluez_leadvertisement1_skeleton_new(); - g_variant_builder_init(&serviceDataBuilder, G_VARIANT_TYPE("a{sv}")); g_variant_builder_init(&serviceUUIDsBuilder, G_VARIANT_TYPE("as")); - - g_variant_builder_add(&serviceDataBuilder, "{sv}", mpAdvUUID, - g_variant_new_fixed_array(G_VARIANT_TYPE_BYTE, &mDeviceIdInfo, sizeof(mDeviceIdInfo), sizeof(uint8_t))); g_variant_builder_add(&serviceUUIDsBuilder, "s", mpAdvUUID); - serviceData = g_variant_builder_end(&serviceDataBuilder); serviceUUID = g_variant_builder_end(&serviceUUIDsBuilder); - debugStr = GAutoPtr(g_variant_print(serviceData, TRUE)); - ChipLogDetail(DeviceLayer, "SET service data to %s", StringOrNullMarker(debugStr.get())); - - bluez_leadvertisement1_set_type_(adv, (mAdvType & BLUEZ_ADV_TYPE_CONNECTABLE) ? "peripheral" : "broadcast"); + bluez_leadvertisement1_set_type_(adv, "peripheral"); + bluez_leadvertisement1_set_service_uuids(adv, serviceUUID); // empty manufacturer data // empty solicit UUIDs - bluez_leadvertisement1_set_service_data(adv, serviceData); // empty data // Setting "Discoverable" to False on the adapter and to True on the advertisement convinces // Bluez to set "BR/EDR Not Supported" flag. Bluez doesn't provide API to do that explicitly // and the flag is necessary to force using LE transport. - bluez_leadvertisement1_set_discoverable(adv, (mAdvType & BLUEZ_ADV_TYPE_SCANNABLE) ? TRUE : FALSE); - if (mAdvType & BLUEZ_ADV_TYPE_SCANNABLE) - bluez_leadvertisement1_set_discoverable_timeout(adv, UINT16_MAX); + bluez_leadvertisement1_set_discoverable(adv, TRUE); + bluez_leadvertisement1_set_discoverable_timeout(adv, 0 /* infinite */); + // empty includes bluez_leadvertisement1_set_local_name(adv, mAdvName); - bluez_leadvertisement1_set_service_uuids(adv, serviceUUID); - - // 0xffff means no appearance - bluez_leadvertisement1_set_appearance(adv, 0xffff); - - bluez_leadvertisement1_set_duration(adv, mAdvDurationMs); - // empty duration, we don't have a clear notion what it would mean to timeslice between toble and anyone else - bluez_leadvertisement1_set_timeout(adv, 0); + bluez_leadvertisement1_set_appearance(adv, 0xffff /* no appearance */); + // empty duration + // empty timeout // empty secondary channel for now bluez_object_skeleton_set_leadvertisement1(object, adv); @@ -123,8 +107,7 @@ CHIP_ERROR BluezAdvertisement::InitImpl() return CHIP_NO_ERROR; } -CHIP_ERROR BluezAdvertisement::Init(const BluezEndpoint & aEndpoint, ChipAdvType aAdvType, const char * aAdvUUID, - uint32_t aAdvDurationMs, const char * aAdvName) +CHIP_ERROR BluezAdvertisement::Init(const BluezEndpoint & aEndpoint, const char * aAdvUUID, const char * aAdvName) { GAutoPtr rootPath; CHIP_ERROR err; @@ -136,10 +119,8 @@ CHIP_ERROR BluezAdvertisement::Init(const BluezEndpoint & aEndpoint, ChipAdvType mpAdapter = reinterpret_cast(g_object_ref(aEndpoint.GetAdapter())); g_object_get(G_OBJECT(mpRoot), "object-path", &MakeUniquePointerReceiver(rootPath).Get(), nullptr); - mpAdvPath = g_strdup_printf("%s/advertising", rootPath.get()); - mAdvType = aAdvType; - mpAdvUUID = g_strdup(aAdvUUID); - mAdvDurationMs = aAdvDurationMs; + mpAdvPath = g_strdup_printf("%s/advertising", rootPath.get()); + mpAdvUUID = g_strdup(aAdvUUID); if (aAdvName != nullptr) { @@ -151,13 +132,6 @@ CHIP_ERROR BluezAdvertisement::Init(const BluezEndpoint & aEndpoint, ChipAdvType g_snprintf(mAdvName, sizeof(mAdvName), "%s%04x", CHIP_DEVICE_CONFIG_BLE_DEVICE_NAME_PREFIX, getpid() & 0xffff); } - err = ConfigurationMgr().GetBLEDeviceIdentificationInfo(mDeviceIdInfo); - ReturnErrorOnFailure(err); - -#if CHIP_ENABLE_ADDITIONAL_DATA_ADVERTISING - mDeviceIdInfo.SetAdditionalDataFlag(true); -#endif - err = PlatformMgrImpl().GLibMatterContextInvokeSync( +[](BluezAdvertisement * self) { return self->InitImpl(); }, this); VerifyOrReturnError(err == CHIP_NO_ERROR, CHIP_ERROR_INCORRECT_STATE, @@ -169,6 +143,53 @@ CHIP_ERROR BluezAdvertisement::Init(const BluezEndpoint & aEndpoint, ChipAdvType return err; } +CHIP_ERROR BluezAdvertisement::SetIntervals(AdvertisingIntervals aAdvIntervals) +{ + VerifyOrReturnError(mpAdv != nullptr, CHIP_ERROR_UNINITIALIZED); + // If the advertisement is already running, BlueZ will update the intervals + // automatically. There is no need to stop and restart the advertisement. + bluez_leadvertisement1_set_min_interval(mpAdv, aAdvIntervals.first * 0.625); + bluez_leadvertisement1_set_max_interval(mpAdv, aAdvIntervals.second * 0.625); + return CHIP_NO_ERROR; +} + +CHIP_ERROR BluezAdvertisement::SetupServiceData(ServiceDataFlags aFlags) +{ + VerifyOrReturnError(mpAdv != nullptr, CHIP_ERROR_UNINITIALIZED); + + Ble::ChipBLEDeviceIdentificationInfo deviceInfo; + ReturnErrorOnFailure(ConfigurationMgr().GetBLEDeviceIdentificationInfo(deviceInfo)); + +#if CHIP_ENABLE_ADDITIONAL_DATA_ADVERTISING + deviceInfo.SetAdditionalDataFlag(true); +#endif + +#if CHIP_DEVICE_CONFIG_BLE_EXT_ADVERTISING + if (aFlags & kServiceDataExtendedAnnouncement) + { + deviceInfo.SetExtendedAnnouncementFlag(true); + // In case of extended advertisement, specification requires that + // the vendor ID and product ID are set to 0. + deviceInfo.SetVendorId(0); + deviceInfo.SetProductId(0); + } +#endif + + GVariantBuilder serviceDataBuilder; + g_variant_builder_init(&serviceDataBuilder, G_VARIANT_TYPE("a{sv}")); + g_variant_builder_add(&serviceDataBuilder, "{sv}", mpAdvUUID, + g_variant_new_fixed_array(G_VARIANT_TYPE_BYTE, &deviceInfo, sizeof(deviceInfo), sizeof(uint8_t))); + + GVariant * serviceData = g_variant_builder_end(&serviceDataBuilder); + + GAutoPtr debugStr(g_variant_print(serviceData, TRUE)); + ChipLogDetail(DeviceLayer, "SET service data to %s", StringOrNullMarker(debugStr.get())); + + bluez_leadvertisement1_set_service_data(mpAdv, serviceData); + + return CHIP_NO_ERROR; +} + void BluezAdvertisement::Shutdown() { VerifyOrReturn(mIsInitialized); diff --git a/src/platform/Linux/bluez/BluezAdvertisement.h b/src/platform/Linux/bluez/BluezAdvertisement.h index 3e14f18bccecd7..11fe51c8e7cdb9 100644 --- a/src/platform/Linux/bluez/BluezAdvertisement.h +++ b/src/platform/Linux/bluez/BluezAdvertisement.h @@ -18,6 +18,7 @@ #pragma once #include +#include #include #include @@ -38,11 +39,19 @@ class BluezEndpoint; class BluezAdvertisement { public: + using ServiceDataFlags = uint16_t; + // Minimum and maximum advertising intervals in units of 0.625ms. + using AdvertisingIntervals = std::pair; + + static constexpr ServiceDataFlags kServiceDataNone = 0; + static constexpr ServiceDataFlags kServiceDataExtendedAnnouncement = 1 << 0; + BluezAdvertisement() = default; ~BluezAdvertisement() { Shutdown(); } - CHIP_ERROR Init(const BluezEndpoint & aEndpoint, ChipAdvType aAdvType, const char * aAdvUUID, uint32_t aAdvDurationMs, - const char * aAdvName); + CHIP_ERROR Init(const BluezEndpoint & aEndpoint, const char * aAdvUUID, const char * aAdvName); + CHIP_ERROR SetupServiceData(ServiceDataFlags aFlags); + CHIP_ERROR SetIntervals(AdvertisingIntervals aAdvIntervals); void Shutdown(); /// Start BLE advertising. @@ -77,12 +86,9 @@ class BluezAdvertisement bool mIsInitialized = false; bool mIsAdvertising = false; - Ble::ChipBLEDeviceIdentificationInfo mDeviceIdInfo; - char * mpAdvPath = nullptr; - char * mpAdvUUID = nullptr; - ChipAdvType mAdvType; - uint16_t mAdvDurationMs = 0; - char mAdvName[32] = ""; + char * mpAdvPath = nullptr; + char * mpAdvUUID = nullptr; + char mAdvName[32] = ""; }; } // namespace Internal diff --git a/src/platform/Linux/bluez/Types.h b/src/platform/Linux/bluez/Types.h index 0153492b5b0e32..f7be4d858d079a 100644 --- a/src/platform/Linux/bluez/Types.h +++ b/src/platform/Linux/bluez/Types.h @@ -63,23 +63,6 @@ struct GAutoPtrDeleter namespace DeviceLayer { namespace Internal { -enum ChipAdvType -{ - BLUEZ_ADV_TYPE_CONNECTABLE = 0x01, - BLUEZ_ADV_TYPE_SCANNABLE = 0x02, - BLUEZ_ADV_TYPE_DIRECTED = 0x04, - - BLUEZ_ADV_TYPE_UNDIRECTED_NONCONNECTABLE_NONSCANNABLE = 0, - BLUEZ_ADV_TYPE_UNDIRECTED_CONNECTABLE_NONSCANNABLE = BLUEZ_ADV_TYPE_CONNECTABLE, - BLUEZ_ADV_TYPE_UNDIRECTED_NONCONNECTABLE_SCANNABLE = BLUEZ_ADV_TYPE_SCANNABLE, - BLUEZ_ADV_TYPE_UNDIRECTED_CONNECTABLE_SCANNABLE = BLUEZ_ADV_TYPE_CONNECTABLE | BLUEZ_ADV_TYPE_SCANNABLE, - - BLUEZ_ADV_TYPE_DIRECTED_NONCONNECTABLE_NONSCANNABLE = BLUEZ_ADV_TYPE_DIRECTED, - BLUEZ_ADV_TYPE_DIRECTED_CONNECTABLE_NONSCANNABLE = BLUEZ_ADV_TYPE_DIRECTED | BLUEZ_ADV_TYPE_CONNECTABLE, - BLUEZ_ADV_TYPE_DIRECTED_NONCONNECTABLE_SCANNABLE = BLUEZ_ADV_TYPE_DIRECTED | BLUEZ_ADV_TYPE_SCANNABLE, - BLUEZ_ADV_TYPE_DIRECTED_CONNECTABLE_SCANNABLE = BLUEZ_ADV_TYPE_DIRECTED | BLUEZ_ADV_TYPE_CONNECTABLE | BLUEZ_ADV_TYPE_SCANNABLE, -}; - #define BLUEZ_ADDRESS_SIZE 6 ///< BLE address size (in bytes) #define BLUEZ_PATH "/org/bluez" #define BLUEZ_INTERFACE "org.bluez" diff --git a/src/platform/Linux/dbus/bluez/DbusBluez.xml b/src/platform/Linux/dbus/bluez/DbusBluez.xml index ac0952bcc30284..00887dc5e147a9 100644 --- a/src/platform/Linux/dbus/bluez/DbusBluez.xml +++ b/src/platform/Linux/dbus/bluez/DbusBluez.xml @@ -187,9 +187,11 @@ - - + + + + diff --git a/src/platform/mt793x/BLEManagerImpl.cpp b/src/platform/mt793x/BLEManagerImpl.cpp index d1f92e1b2977ac..f1ac9bfa707b88 100644 --- a/src/platform/mt793x/BLEManagerImpl.cpp +++ b/src/platform/mt793x/BLEManagerImpl.cpp @@ -656,7 +656,7 @@ void BLEManagerImpl::BleAdvTimeoutHandler(TimerHandle_t xTimer) else if (BLEMgrImpl().mFlags.Has(Flags::kAdvertising)) { // Advertisement time expired. Stop advertising - ChipLogDetail(DeviceLayer, "bleAdv Timeout : Stop advertissement"); + ChipLogDetail(DeviceLayer, "bleAdv Timeout : Stop advertisement"); BLEMgr().SetAdvertisingEnabled(false); } } diff --git a/src/platform/silabs/efr32/BLEManagerImpl.cpp b/src/platform/silabs/efr32/BLEManagerImpl.cpp index 193d15bb018d6b..bd4aee39cf8160 100644 --- a/src/platform/silabs/efr32/BLEManagerImpl.cpp +++ b/src/platform/silabs/efr32/BLEManagerImpl.cpp @@ -545,7 +545,7 @@ CHIP_ERROR BLEManagerImpl::StartAdvertising(void) } else { - ChipLogDetail(DeviceLayer, "Start BLE advertissement"); + ChipLogDetail(DeviceLayer, "Start BLE advertisement"); } const uint8_t kResolvableRandomAddrType = 2; // Private resolvable random address type @@ -976,7 +976,7 @@ void BLEManagerImpl::BleAdvTimeoutHandler(TimerHandle_t xTimer) { if (BLEMgrImpl().mFlags.Has(Flags::kFastAdvertisingEnabled)) { - ChipLogDetail(DeviceLayer, "bleAdv Timeout : Start slow advertissment"); + ChipLogDetail(DeviceLayer, "bleAdv Timeout : Start slow advertisement"); BLEMgrImpl().mFlags.Set(Flags::kAdvertising); BLEMgr().SetAdvertisingMode(BLEAdvertisingMode::kSlowAdvertising); #if CHIP_DEVICE_CONFIG_BLE_EXT_ADVERTISING @@ -987,7 +987,7 @@ void BLEManagerImpl::BleAdvTimeoutHandler(TimerHandle_t xTimer) #if CHIP_DEVICE_CONFIG_BLE_EXT_ADVERTISING else { - ChipLogDetail(DeviceLayer, "bleAdv Timeout : Start extended advertisment"); + ChipLogDetail(DeviceLayer, "bleAdv Timeout : Start extended advertisement"); BLEMgrImpl().mFlags.Set(Flags::kAdvertising); BLEMgrImpl().mFlags.Set(Flags::kExtAdvertisingEnabled); BLEMgr().SetAdvertisingMode(BLEAdvertisingMode::kSlowAdvertising); diff --git a/src/platform/silabs/rs911x/BLEManagerImpl.cpp b/src/platform/silabs/rs911x/BLEManagerImpl.cpp index a32d46b30f2715..d7e79f59dc8318 100644 --- a/src/platform/silabs/rs911x/BLEManagerImpl.cpp +++ b/src/platform/silabs/rs911x/BLEManagerImpl.cpp @@ -672,7 +672,7 @@ CHIP_ERROR BLEManagerImpl::StartAdvertising(void) } else { - ChipLogDetail(DeviceLayer, "Start BLE advertissement"); + ChipLogDetail(DeviceLayer, "Start BLE advertisement"); } if (!(mFlags.Has(Flags::kAdvertising))) @@ -1072,7 +1072,7 @@ void BLEManagerImpl::BleAdvTimeoutHandler(TimerHandle_t xTimer) { if (BLEMgrImpl().mFlags.Has(Flags::kFastAdvertisingEnabled)) { - ChipLogDetail(DeviceLayer, "bleAdv Timeout : Start slow advertissment"); + ChipLogDetail(DeviceLayer, "bleAdv Timeout : Start slow advertisement"); BLEMgr().SetAdvertisingMode(BLEAdvertisingMode::kSlowAdvertising); } } diff --git a/src/platform/stm32/BLEManagerImpl.cpp b/src/platform/stm32/BLEManagerImpl.cpp index 1cffd11b783487..60863a2da6a698 100644 --- a/src/platform/stm32/BLEManagerImpl.cpp +++ b/src/platform/stm32/BLEManagerImpl.cpp @@ -702,14 +702,14 @@ void BLEManagerImpl::BleAdvTimeoutHandler(TimerHandle_t xTimer) if (BLEMgrImpl().mFlags.Has(Flags::kFastAdvertisingEnabled)) { /* Stop advertising and defer restart for when stop confirmation is received from the stack */ - ChipLogDetail(DeviceLayer, "bleAdv Timeout : Stop advertissement"); + ChipLogDetail(DeviceLayer, "bleAdv Timeout : Stop advertisement"); sInstance.StopAdvertising(); sInstance.mFlags.Set(Flags::kRestartAdvertising); } else if (BLEMgrImpl().mFlags.Has(Flags::kAdvertising)) { // Advertisement time expired. Stop advertising - ChipLogDetail(DeviceLayer, "bleAdv Timeout : Stop advertissement"); + ChipLogDetail(DeviceLayer, "bleAdv Timeout : Stop advertisement"); BLEMgr().SetAdvertisingEnabled(false); } }