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

[Telink] add BLE PostEvent and fast/slow adv (Cherry-pick #23116) #23465

Merged
Show file tree
Hide file tree
Changes from all 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
186 changes: 151 additions & 35 deletions src/platform/telink/BLEManagerImpl.cpp
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/*
*
* Copyright (c) 2020-2021 Project CHIP Authors
* Copyright (c) 2020-2022 Project CHIP Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand Down Expand Up @@ -167,28 +167,72 @@ K_THREAD_DEFINE(chipBleThread, CHIP_BLE_THREAD_STACK_SIZE, BLEManagerImpl::BleEn

CHIP_ERROR BLEManagerImpl::_Init()
{
CHIP_ERROR err = CHIP_NO_ERROR;

ThreadConnectivityReady = false;

/* Initialize the CHIP BleLayer. */
err = BleLayer::Init(this, this, &DeviceLayer::SystemLayer());
SuccessOrExit(err);

/* Set number of connections to zero */
mNumConnections = 0;
mServiceMode = ConnectivityManager::kCHIPoBLEServiceMode_Enabled;
mFlags.ClearAll().Set(Flags::kAdvertisingEnabled, CHIP_DEVICE_CONFIG_CHIPOBLE_ENABLE_ADVERTISING_AUTOSTART);
mFlags.Set(Flags::kFastAdvertisingEnabled, true);
mGAPConns = 0;

/* Unsubscribe all connections */
memset(mSubscribedConns, 0, sizeof(mSubscribedConns));

/* Enable CHIP over BLE service */
mServiceMode = ConnectivityManager::kCHIPoBLEServiceMode_Enabled;
// Initialize the CHIP BleLayer.
ReturnErrorOnFailure(BleLayer::Init(this, this, &DeviceLayer::SystemLayer()));

/* Suspend BLE Task */
// Suspend BLE Task
k_thread_suspend(chipBleThread);

return CHIP_NO_ERROR;
}

void BLEManagerImpl::DriveBLEState(intptr_t arg)
{
BLEMgrImpl().DriveBLEState();
}

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);
}

// If the application has enabled CHIPoBLE and BLE advertising...
if (mServiceMode == ConnectivityManager::kCHIPoBLEServiceMode_Enabled &&
mFlags.Has(Flags::kAdvertisingEnabled)
#if CHIP_DEVICE_CONFIG_CHIPOBLE_SINGLE_CONNECTION
// and no connections are active...
&& (NumConnections() == 0)
#endif
)
{
// Start/re-start advertising if not already advertising, or if the
// advertising state needs to be refreshed.
if (!mFlags.Has(Flags::kAdvertising) || mFlags.Has(Flags::kAdvertisingRefreshNeeded))
{
mFlags.Clear(Flags::kAdvertisingRefreshNeeded);
err = StartAdvertising();
SuccessOrExit(err);
}
}
else
{
if (mFlags.Has(Flags::kAdvertising))
{
err = StopAdvertising();
SuccessOrExit(err);
}
}

exit:
return err;
if (err != CHIP_NO_ERROR)
{
ChipLogError(DeviceLayer, "Disabling CHIPoBLE service due to error: %" CHIP_ERROR_FORMAT, err.Format());
mServiceMode = ConnectivityManager::kCHIPoBLEServiceMode_Disabled;
}
}

int BLEManagerImpl::RxWriteCallback(uint16_t connHandle, void * p)
Expand Down Expand Up @@ -543,13 +587,15 @@ CHIP_ERROR BLEManagerImpl::_SetAdvertisingEnabled(bool val)
{
CHIP_ERROR err = CHIP_NO_ERROR;

if (val)
{
err = StartAdvertising();
}
else
VerifyOrReturnError(mServiceMode != ConnectivityManager::kCHIPoBLEServiceMode_NotSupported,
CHIP_ERROR_UNSUPPORTED_CHIP_FEATURE);

if (mFlags.Has(Flags::kAdvertisingEnabled) != val)
{
err = StopAdvertising();
ChipLogDetail(DeviceLayer, "CHIPoBLE advertising set to %s", val ? "on" : "off");

mFlags.Set(Flags::kAdvertisingEnabled, val);
PlatformMgr().ScheduleWork(DriveBLEState, 0);
}

return err;
Expand Down Expand Up @@ -616,7 +662,29 @@ CHIP_ERROR BLEManagerImpl::StartAdvertising(void)
return CHIP_ERROR_INCORRECT_STATE;
}

mFlags.Set(Flags::kAdvertising);
// Transition to the Advertising state...
if (!mFlags.Has(Flags::kAdvertising))
{
ChipLogProgress(DeviceLayer, "CHIPoBLE advertising started");

mFlags.Set(Flags::kAdvertising);

// Post a CHIPoBLEAdvertisingChange(Started) event.
{
ChipDeviceEvent advChange;
advChange.Type = DeviceEventType::kCHIPoBLEAdvertisingChange;
advChange.CHIPoBLEAdvertisingChange.Result = kActivity_Started;
ReturnErrorOnFailure(PlatformMgr().PostEvent(&advChange));
}

if (mFlags.Has(Flags::kFastAdvertisingEnabled))
{
// Start timer to change advertising interval.
DeviceLayer::SystemLayer().StartTimer(
System::Clock::Milliseconds32(CHIP_DEVICE_CONFIG_BLE_ADVERTISING_INTERVAL_CHANGE_TIME),
HandleBLEAdvertisementIntervalChange, this);
}
}

/* Start BLE Task */
k_thread_resume(chipBleThread);
Expand All @@ -632,7 +700,7 @@ CHIP_ERROR BLEManagerImpl::StopAdvertising(void)
{
ChipLogProgress(DeviceLayer, "Thread provisioned. Advertisement already stopped at this stage");

return CHIP_NO_ERROR;
return CHIP_ERROR_INCORRECT_STATE;
}

/* Disable advertisement */
Expand All @@ -644,14 +712,44 @@ CHIP_ERROR BLEManagerImpl::StopAdvertising(void)
return CHIP_ERROR_INCORRECT_STATE;
}

mFlags.Clear(Flags::kAdvertising);
// Transition to the not Advertising state...
if (mFlags.Has(Flags::kAdvertising))
{
mFlags.Clear(Flags::kAdvertising);
mFlags.Set(Flags::kFastAdvertisingEnabled, true);

ChipLogProgress(DeviceLayer, "CHIPoBLE advertising stopped");

// Post a CHIPoBLEAdvertisingChange(Stopped) event.
{
ChipDeviceEvent advChange;
advChange.Type = DeviceEventType::kCHIPoBLEAdvertisingChange;
advChange.CHIPoBLEAdvertisingChange.Result = kActivity_Stopped;
ReturnErrorOnFailure(PlatformMgr().PostEvent(&advChange));
}

// Cancel timer event changing CHIPoBLE advertisement interval
DeviceLayer::SystemLayer().CancelTimer(HandleBLEAdvertisementIntervalChange, this);
}

return CHIP_NO_ERROR;
}

/// @todo: implementation
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);
PlatformMgr().ScheduleWork(DriveBLEState, 0);
return CHIP_NO_ERROR;
}

Expand Down Expand Up @@ -698,6 +796,12 @@ CHIP_ERROR BLEManagerImpl::_SetDeviceName(const char * devName)
return CHIP_NO_ERROR;
}

void BLEManagerImpl::HandleBLEAdvertisementIntervalChange(System::Layer * layer, void * param)
{
BLEMgr().SetAdvertisingMode(BLEAdvertisingMode::kSlowAdvertising);
ChipLogProgress(DeviceLayer, "CHIPoBLE advertising mode changed to slow");
}

void BLEManagerImpl::_OnPlatformEvent(const ChipDeviceEvent * event)
{
CHIP_ERROR err = CHIP_NO_ERROR;
Expand Down Expand Up @@ -747,6 +851,8 @@ void BLEManagerImpl::_OnPlatformEvent(const ChipDeviceEvent * event)
if (err != CHIP_NO_ERROR)
{
ChipLogError(DeviceLayer, "Fail to handle 0x%04x event. Error: %s", event->Type, ErrorStr(err));
mServiceMode = ConnectivityManager::kCHIPoBLEServiceMode_Disabled;
PlatformMgr().ScheduleWork(DriveBLEState, 0);
}
}

Expand Down Expand Up @@ -822,7 +928,7 @@ void BLEManagerImpl::SwitchToIeee802154(void)
ChipLogProgress(DeviceLayer, "BLEManagerImpl::Switch to IEEE802154");

/* Stop BLE */
StopAdvertising();
_SetAdvertisingEnabled(false);

/* Stop BLE task */
k_thread_suspend(chipBleThread);
Expand All @@ -845,7 +951,7 @@ void BLEManagerImpl::NotifyChipConnectionClosed(BLE_CONNECTION_OBJECT conId) {}

uint16_t BLEManagerImpl::_NumConnections(void)
{
return mNumConnections;
return mGAPConns;
}

/// @todo implement multicinnection subscription
Expand Down Expand Up @@ -876,36 +982,41 @@ CHIP_ERROR BLEManagerImpl::HandleGAPConnect(const ChipDeviceEvent * event)
{
const BleConnEventType * connEvent = &event->Platform.BleConnEvent;

/* Increase number of connections */
mNumConnections++;

ChipLogProgress(DeviceLayer, "BLE connection established (ConnId: 0x%02x)", connEvent->connHandle);
mGAPConns++;
ChipLogProgress(DeviceLayer, "Current number of connections: %u/%u", NumConnections(), kMaxConnections);

mFlags.Set(Flags::kAdvertisingRefreshNeeded);
PlatformMgr().ScheduleWork(DriveBLEState, 0);

return CHIP_NO_ERROR;
}

CHIP_ERROR BLEManagerImpl::HandleGAPDisconnect(const ChipDeviceEvent * event)
{
const BleConnEventType * connEvent = &event->Platform.BleConnEvent;
ChipDeviceEvent disconnectEvent;

/* Decrease number of connections */
mNumConnections--;

ChipLogProgress(DeviceLayer, "BLE GAP connection terminated (reason 0x%02x)", connEvent->HciResult);

mGAPConns--;

ChipLogProgress(DeviceLayer, "Current number of connections: %u/%u", NumConnections(), kMaxConnections);

/* Unsubscribe */
// Unsubscribe
if (UnsetSubscribed(connEvent->connHandle))
{
HandleUnsubscribeReceived(connEvent->connHandle, &CHIP_BLE_SVC_ID, &chipUUID_CHIPoBLEChar_TX);
}

/* Send Connection close event */
ChipDeviceEvent disconnectEvent;
disconnectEvent.Type = DeviceEventType::kCHIPoBLEConnectionClosed;
ReturnErrorOnFailure(PlatformMgr().PostEvent(&disconnectEvent));

// Force a reconfiguration of advertising in case we switched to non-connectable mode when
// the BLE connection was established.
mFlags.Set(Flags::kAdvertisingRefreshNeeded);
PlatformMgr().ScheduleWork(DriveBLEState, 0);

return CHIP_NO_ERROR;
}

Expand All @@ -926,6 +1037,11 @@ CHIP_ERROR BLEManagerImpl::HandleDisconnectRequest(const ChipDeviceEvent * event
return CHIP_ERROR_INCORRECT_STATE;
}

// Force a reconfiguration of advertising in case we switched to non-connectable mode when
// the BLE connection was established.
mFlags.Set(Flags::kAdvertisingRefreshNeeded);
PlatformMgr().ScheduleWork(DriveBLEState, 0);

return CHIP_NO_ERROR;
}

Expand Down
4 changes: 3 additions & 1 deletion src/platform/telink/BLEManagerImpl.h
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,7 @@ class BLEManagerImpl final : public BLEManager, private BleLayer, private BlePla
CHIPoBLEServiceMode mServiceMode;
BitFlags<Flags> mFlags;
char mDeviceName[kMaxDeviceNameLength + 1];
uint16_t mNumConnections;
uint16_t mGAPConns;
bool mSubscribedConns[kMaxConnections];
uint8_t mAdvDataBuf[kMaxAdvertisementDataSetSize];
uint8_t mScanRespDataBuf[kMaxAdvertisementDataSetSize];
Expand Down Expand Up @@ -144,6 +144,8 @@ class BLEManagerImpl final : public BLEManager, private BleLayer, private BlePla
/* Callbacks from BLE stack*/
static void DriveBLEState(intptr_t arg);

static void HandleBLEAdvertisementIntervalChange(System::Layer * layer, void * param);

/* Handlers for stack events */
static void CancelBleAdvTimeoutTimer(void);
static void StartBleAdvTimeoutTimer(uint32_t aTimeoutInMs);
Expand Down