Skip to content

Commit

Permalink
[host] add SetThreadEnabled to ThreadHost APIs (#2542)
Browse files Browse the repository at this point in the history
This commit adds a new method `SetThreadEnabled` as a ThreadHost API.

The method is added so that the Android binder API can be easily
implemented without the need to handle NCP/RCP case. In this commit,
`RcpHost::SetThreadEnabled` is implemented and
`NcpHost::SetThreadEnabled` will be implemented later.
  • Loading branch information
Irving-cl authored Oct 17, 2024
1 parent 5ab0e93 commit 689483c
Show file tree
Hide file tree
Showing 5 changed files with 90 additions and 0 deletions.
8 changes: 8 additions & 0 deletions src/ncp/ncp_host.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,14 @@ void NcpHost::ScheduleMigration(const otOperationalDatasetTlvs &aPendingOpDatase
}
}

void NcpHost::SetThreadEnabled(bool aEnabled, const AsyncResultReceiver aReceiver)
{
OT_UNUSED_VARIABLE(aEnabled);

// TODO: Implement SetThreadEnabled under NCP mode.
mTaskRunner.Post([aReceiver](void) { aReceiver(OT_ERROR_NOT_IMPLEMENTED, "Not implemented!"); });
}

void NcpHost::Process(const MainloopContext &aMainloop)
{
mSpinelDriver.Process(&aMainloop);
Expand Down
1 change: 1 addition & 0 deletions src/ncp/ncp_host.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,7 @@ class NcpHost : public MainloopProcessor, public ThreadHost, public NcpNetworkPr
void Leave(const AsyncResultReceiver &aReceiver) override;
void ScheduleMigration(const otOperationalDatasetTlvs &aPendingOpDatasetTlvs,
const AsyncResultReceiver aReceiver) override;
void SetThreadEnabled(bool aEnabled, const AsyncResultReceiver aReceiver) override;
CoprocessorType GetCoprocessorType(void) override { return OT_COPROCESSOR_NCP; }
const char *GetCoprocessorVersion(void) override;
const char *GetInterfaceName(void) const override { return mConfig.mInterfaceName; }
Expand Down
52 changes: 52 additions & 0 deletions src/ncp/rcp_host.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -295,6 +295,8 @@ void RcpHost::Deinit(void)
OtNetworkProperties::SetInstance(nullptr);
mThreadStateChangedCallbacks.clear();
mResetHandlers.clear();

mSetThreadEnabledReceiver = nullptr;
}

void RcpHost::HandleStateChanged(otChangedFlags aFlags)
Expand Down Expand Up @@ -417,6 +419,56 @@ void RcpHost::ScheduleMigration(const otOperationalDatasetTlvs &aPendingOpDatase
mTaskRunner.Post([aReceiver](void) { aReceiver(OT_ERROR_NOT_IMPLEMENTED, "Not implemented!"); });
}

void RcpHost::SetThreadEnabled(bool aEnabled, const AsyncResultReceiver aReceiver)
{
otError error = OT_ERROR_NONE;
bool receiveResultHere = true;

VerifyOrExit(mInstance != nullptr, error = OT_ERROR_INVALID_STATE);
VerifyOrExit(mSetThreadEnabledReceiver == nullptr, error = OT_ERROR_BUSY);

if (aEnabled)
{
otOperationalDatasetTlvs datasetTlvs;

if (otDatasetGetActiveTlvs(mInstance, &datasetTlvs) != OT_ERROR_NOT_FOUND && datasetTlvs.mLength > 0 &&
otThreadGetDeviceRole(mInstance) == OT_DEVICE_ROLE_DISABLED)
{
SuccessOrExit(error = otIp6SetEnabled(mInstance, true));
SuccessOrExit(error = otThreadSetEnabled(mInstance, true));
}
}
else
{
SuccessOrExit(error = otThreadDetachGracefully(mInstance, DisableThreadAfterDetach, this));
mSetThreadEnabledReceiver = aReceiver;
receiveResultHere = false;
}

exit:
if (receiveResultHere)
{
mTaskRunner.Post([aReceiver, error](void) { aReceiver(error, ""); });
}
}

void RcpHost::DisableThreadAfterDetach(void *aContext)
{
static_cast<RcpHost *>(aContext)->DisableThreadAfterDetach();
}

void RcpHost::DisableThreadAfterDetach(void)
{
otError error = OT_ERROR_NONE;
std::string errorMsg;

SuccessOrExit(error = otThreadSetEnabled(mInstance, false), errorMsg = "Failed to disable Thread stack");
SuccessOrExit(error = otIp6SetEnabled(mInstance, false), errorMsg = "Failed to disable Thread interface");

exit:
SafeInvokeAndClear(mSetThreadEnabledReceiver, error, errorMsg);
}

/*
* Provide, if required an "otPlatLog()" function
*/
Expand Down
15 changes: 15 additions & 0 deletions src/ncp/rcp_host.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -207,6 +207,7 @@ class RcpHost : public MainloopProcessor, public ThreadHost, public OtNetworkPro
void Leave(const AsyncResultReceiver &aRecevier) override;
void ScheduleMigration(const otOperationalDatasetTlvs &aPendingOpDatasetTlvs,
const AsyncResultReceiver aReceiver) override;
void SetThreadEnabled(bool aEnabled, const AsyncResultReceiver aReceiver) override;

CoprocessorType GetCoprocessorType(void) override
{
Expand All @@ -219,6 +220,15 @@ class RcpHost : public MainloopProcessor, public ThreadHost, public OtNetworkPro
}

private:
static void SafeInvokeAndClear(AsyncResultReceiver &aReceiver, otError aError, const std::string &aErrorInfo = "")
{
if (aReceiver)
{
aReceiver(aError, aErrorInfo);
aReceiver = nullptr;
}
}

static void HandleStateChanged(otChangedFlags aFlags, void *aContext)
{
static_cast<RcpHost *>(aContext)->HandleStateChanged(aFlags);
Expand All @@ -238,6 +248,9 @@ class RcpHost : public MainloopProcessor, public ThreadHost, public OtNetworkPro
void HandleBackboneRouterNdProxyEvent(otBackboneRouterNdProxyEvent aEvent, const otIp6Address *aAddress);
#endif

static void DisableThreadAfterDetach(void *aContext);
void DisableThreadAfterDetach(void);

bool IsAutoAttachEnabled(void);
void DisableAutoAttach(void);

Expand All @@ -252,6 +265,8 @@ class RcpHost : public MainloopProcessor, public ThreadHost, public OtNetworkPro
std::vector<ThreadStateChangedCallback> mThreadStateChangedCallbacks;
bool mEnableAutoAttach = false;

AsyncResultReceiver mSetThreadEnabledReceiver;

#if OTBR_ENABLE_FEATURE_FLAGS
// The applied FeatureFlagList in ApplyFeatureFlagList call, used for debugging purpose.
std::string mAppliedFeatureFlagListBytes;
Expand Down
14 changes: 14 additions & 0 deletions src/ncp/thread_host.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,20 @@ class ThreadHost : virtual public NetworkProperties
virtual void ScheduleMigration(const otOperationalDatasetTlvs &aPendingOpDatasetTlvs,
const AsyncResultReceiver aReceiver) = 0;

/**
* This method enables/disables the Thread network.
*
* 1. If there is an ongoing 'SetThreadEnabled' operation, no action will be taken and @p aReceiver
* will be invoked with error OT_ERROR_BUSY.
* 2. If the host hasn't been initialized, @p aReceiver will be invoked with error OT_ERROR_INVALID_STATE.
* 3. When @p aEnabled is false, this method will first trigger a graceful detach and then disable Thread
* network interface and the stack.
*
* @param[in] aEnabled true to enable and false to disable.
* @param[in] aReceiver A receiver to get the async result of this operation.
*/
virtual void SetThreadEnabled(bool aEnabled, const AsyncResultReceiver aReceiver) = 0;

/**
* Returns the co-processor type.
*/
Expand Down

0 comments on commit 689483c

Please sign in to comment.