Skip to content

Commit

Permalink
[Telink] add BLE PostEvent and fast/slow adv (project-chip#23116) (pr…
Browse files Browse the repository at this point in the history
  • Loading branch information
s07641069 authored Nov 4, 2022
1 parent a17c005 commit ff13388
Show file tree
Hide file tree
Showing 2 changed files with 154 additions and 36 deletions.
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

0 comments on commit ff13388

Please sign in to comment.