From 28c453e61b4b7504f0ce29cdb1c5b5fd0640f494 Mon Sep 17 00:00:00 2001 From: shihchienc Date: Wed, 19 Jun 2024 07:45:58 +0000 Subject: [PATCH] [Thread] Implement hardware reset To implement hardware reset sent from radio spinel. Bug: 347138417 Test: atest VtsHalThreadNetworkTargetTest Test: manual hardware reset Change-Id: I937d73b7964448becc5b49499683b3e65332fb0b --- .../aidl/default/socket_interface.cpp | 70 +++++++++++++++++-- .../aidl/default/socket_interface.hpp | 27 +++++-- 2 files changed, 87 insertions(+), 10 deletions(-) diff --git a/threadnetwork/aidl/default/socket_interface.cpp b/threadnetwork/aidl/default/socket_interface.cpp index 0544502ea9..339fd6b7e0 100644 --- a/threadnetwork/aidl/default/socket_interface.cpp +++ b/threadnetwork/aidl/default/socket_interface.cpp @@ -33,6 +33,7 @@ #include #include +#include #include "common/code_utils.hpp" #include "openthread/openthread-system.h" @@ -49,10 +50,8 @@ SocketInterface::SocketInterface(const ot::Url::Url& aRadioUrl) : mReceiveFrameCallback(nullptr), mReceiveFrameContext(nullptr), mReceiveFrameBuffer(nullptr), - mSockFd(-1), mRadioUrl(aRadioUrl) { - memset(&mInterfaceMetrics, 0, sizeof(mInterfaceMetrics)); - mInterfaceMetrics.mRcpInterfaceType = kSpinelInterfaceTypeVendor; + ResetStates(); } otError SocketInterface::Init(ReceiveFrameCallback aCallback, void* aCallbackContext, @@ -120,13 +119,50 @@ otError SocketInterface::WaitForFrame(uint64_t aTimeoutUs) { } else if (rval == 0) { ExitNow(error = OT_ERROR_RESPONSE_TIMEOUT); } else { - DieNowWithMessage("wait response", OT_EXIT_FAILURE); + DieNowWithMessage("Wait response", OT_EXIT_FAILURE); } exit: return error; } +otError SocketInterface::WaitForHardwareResetCompletion(uint32_t aTimeoutMs) { + otError error = OT_ERROR_NONE; + int retries = 0; + int rval; + + while (mIsHardwareResetting && retries++ < kMaxRetriesForSocketCloseCheck) { + struct timeval timeout; + timeout.tv_sec = static_cast(aTimeoutMs / MS_PER_S); + timeout.tv_usec = static_cast((aTimeoutMs % MS_PER_S) * MS_PER_S); + + fd_set readFds; + + FD_ZERO(&readFds); + FD_SET(mSockFd, &readFds); + + rval = TEMP_FAILURE_RETRY(select(mSockFd + 1, &readFds, nullptr, nullptr, &timeout)); + + if (rval > 0) { + Read(); + } else if (rval < 0) { + DieNowWithMessage("Wait response", OT_EXIT_ERROR_ERRNO); + } else { + LogInfo("Waiting for hardware reset, retry attempt: %d, max attempt: %d", retries, + kMaxRetriesForSocketCloseCheck); + } + } + + VerifyOrExit(!mIsHardwareResetting, error = OT_ERROR_FAILED); + + WaitForSocketFileCreated(mRadioUrl.GetPath()); + mSockFd = OpenFile(mRadioUrl); + VerifyOrExit(mSockFd != -1, error = OT_ERROR_FAILED); + +exit: + return error; +} + void SocketInterface::UpdateFdSet(void* aMainloopContext) { otSysMainloopContext* context = reinterpret_cast(aMainloopContext); @@ -150,6 +186,16 @@ void SocketInterface::Process(const void* aMainloopContext) { } } +otError SocketInterface::HardwareReset(void) { + otError error = OT_ERROR_NONE; + std::vector resetCommand = {SPINEL_HEADER_FLAG, SPINEL_CMD_RESET, 0x04}; + + mIsHardwareResetting = true; + SendFrame(resetCommand.data(), resetCommand.size()); + + return WaitForHardwareResetCompletion(kMaxSelectTimeMs); +} + void SocketInterface::Read(void) { uint8_t buffer[kMaxFrameSize]; @@ -160,8 +206,13 @@ void SocketInterface::Read(void) { } else if (rval < 0) { DieNow(OT_EXIT_ERROR_ERRNO); } else { - LogCrit("Socket connection is closed by remote."); - exit(OT_EXIT_FAILURE); + if (mIsHardwareResetting) { + LogInfo("Socket connection is closed due to hardware reset."); + ResetStates(); + } else { + LogCrit("Socket connection is closed by remote."); + exit(OT_EXIT_FAILURE); + } } } @@ -298,6 +349,13 @@ bool SocketInterface::IsSocketFileExisted(const char* aPath) { return stat(aPath, &st) == 0 && S_ISSOCK(st.st_mode); } +void SocketInterface::ResetStates() { + mSockFd = -1; + mIsHardwareResetting = false; + memset(&mInterfaceMetrics, 0, sizeof(mInterfaceMetrics)); + mInterfaceMetrics.mRcpInterfaceType = kSpinelInterfaceTypeVendor; +} + } // namespace threadnetwork } // namespace hardware } // namespace android diff --git a/threadnetwork/aidl/default/socket_interface.hpp b/threadnetwork/aidl/default/socket_interface.hpp index 6f3be7fdf8..494d76ad5a 100644 --- a/threadnetwork/aidl/default/socket_interface.hpp +++ b/threadnetwork/aidl/default/socket_interface.hpp @@ -136,10 +136,10 @@ class SocketInterface : public ot::Spinel::SpinelInterface, * Hardware resets the RCP. * * @retval OT_ERROR_NONE Successfully reset the RCP. - * @retval OT_ERROR_NOT_IMPLEMENT The hardware reset is not implemented. + * @retval OT_ERROR_FAILED Hardware reset is failed. * */ - otError HardwareReset(void) { return OT_ERROR_NOT_IMPLEMENTED; } + otError HardwareReset(void); /** * Returns the RCP interface metrics. @@ -237,9 +237,26 @@ class SocketInterface : public ot::Spinel::SpinelInterface, */ void WaitForSocketFileCreated(const char* aPath); + /** + * Wait for the hardware reset completion signal. + * + * @retval OT_ERROR_NONE Hardware reset is successfully. + * @retval OT_ERROR_FAILED Hardware reset is failed. + * + */ + otError WaitForHardwareResetCompletion(uint32_t aTimeoutMs); + + /** + * Reset socket interface to intitial state. + * + */ + void ResetStates(void); + enum { - kMaxSelectTimeMs = 2000, ///< Maximum wait time in Milliseconds for file - ///< descriptor to become available. + kMaxSelectTimeMs = 2000, ///< Maximum wait time in Milliseconds for file + ///< descriptor to become available. + kMaxRetriesForSocketCloseCheck = 3, ///< Maximum retry times for checking + ///< if socket is closed. }; ReceiveFrameCallback mReceiveFrameCallback; @@ -249,6 +266,8 @@ class SocketInterface : public ot::Spinel::SpinelInterface, int mSockFd; const ot::Url::Url& mRadioUrl; + bool mIsHardwareResetting; + otRcpInterfaceMetrics mInterfaceMetrics; // Non-copyable, intentionally not implemented.