Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Linux] Add support for extended advertisement #31668

Merged
merged 16 commits into from
Feb 6, 2024
Merged
Show file tree
Hide file tree
Changes from 12 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 27 additions & 0 deletions docs/guides/BUILDING.md
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
4 changes: 2 additions & 2 deletions examples/lock-app/esp32/main/AppTask.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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();
Expand All @@ -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)
Expand Down
4 changes: 2 additions & 2 deletions examples/platform/silabs/BaseApplication.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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();
Expand All @@ -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();
Expand Down
2 changes: 1 addition & 1 deletion src/app/server/Dnssd.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -499,7 +499,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();
}

Expand Down
2 changes: 1 addition & 1 deletion src/lib/dnssd/minimal_mdns/tests/TestAdvertiser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -210,7 +210,7 @@ CommissionAdvertisingParameters commissionableNodeParamsEnhancedAsICDLIT =
.SetTcpSupported(chip::Optional<bool>(true))
.SetICDOperatingAsLIT(chip::Optional<bool>(true))
.SetLocalMRPConfig(Optional<ReliableMessageProtocolConfig>::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" };
Expand Down
2 changes: 1 addition & 1 deletion src/platform/Infineon/PSOC6/BLEManagerImpl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
108 changes: 73 additions & 35 deletions src/platform/Linux/BLEManagerImpl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,15 @@ 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);
arkq marked this conversation as resolved.
Show resolved Hide resolved
#endif

const ChipBleUUID ChipUUID_CHIPoBLEChar_RX = { { 0x18, 0xEE, 0x2E, 0xF5, 0x26, 0x3D, 0x45, 0x59, 0x95, 0x9F, 0x4F, 0x9C, 0x42, 0x9F,
0x9D, 0x11 } };
Expand Down Expand Up @@ -91,7 +100,7 @@ CHIP_ERROR BLEManagerImpl::_Init()

OnChipBleConnectReceived = HandleIncomingBleConnection;

PlatformMgr().ScheduleWork(DriveBLEState, 0);
DeviceLayer::SystemLayer().ScheduleLambda([this] { DriveBLEState(); });

exit:
return err;
Expand Down Expand Up @@ -119,7 +128,7 @@ CHIP_ERROR BLEManagerImpl::_SetAdvertisingEnabled(bool val)
mFlags.Set(Flags::kAdvertisingEnabled, val);
}

PlatformMgr().ScheduleWork(DriveBLEState, 0);
DeviceLayer::SystemLayer().ScheduleLambda([this] { DriveBLEState(); });

return err;
}
Expand All @@ -138,7 +147,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;
}

Expand Down Expand Up @@ -186,14 +195,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;
}

Expand Down Expand Up @@ -278,17 +282,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);
tehampson marked this conversation as resolved.
Show resolved Hide resolved
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))
Expand Down Expand Up @@ -595,15 +596,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));
SuccessOrExit(err = mBLEAdvertisement.Init(mEndpoint, mpBLEAdvUUID));
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();
}
}
}

Expand All @@ -627,11 +642,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");
Expand All @@ -641,6 +651,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<BLEManagerImpl *>(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
arkq marked this conversation as resolved.
Show resolved Hide resolved
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();
Expand Down Expand Up @@ -695,18 +738,13 @@ void BLEManagerImpl::CleanScanConfig()
mBLEScanConfig.mBleScanState = BleScanState::kNotScanning;
}

void BLEManagerImpl::InitiateScan(intptr_t arg)
{
sInstance.InitiateScan(static_cast<BleScanState>(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<intptr_t>(BleScanState::kScanForDiscriminator));
DeviceLayer::SystemLayer().ScheduleLambda([this] { InitiateScan(BleScanState::kScanForDiscriminator); });
}

CHIP_ERROR BLEManagerImpl::CancelConnection()
Expand Down
12 changes: 6 additions & 6 deletions src/platform/Linux/BLEManagerImpl.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand All @@ -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. */
Expand All @@ -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
Expand All @@ -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;
Expand All @@ -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;
Expand Down
Loading
Loading