Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 319ccccf authored by Treehugger Robot's avatar Treehugger Robot Committed by Automerger Merge Worker
Browse files

Merge "[Thread] Implement hardware reset" into main am: 8e3aaa2f

parents 470826b2 8e3aaa2f
Loading
Loading
Loading
Loading
+64 −6
Original line number Diff line number Diff line
@@ -33,6 +33,7 @@
#include <unistd.h>

#include <string>
#include <vector>

#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<time_t>(aTimeoutMs / MS_PER_S);
        timeout.tv_usec = static_cast<suseconds_t>((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<otSysMainloopContext*>(aMainloopContext);

@@ -150,6 +186,16 @@ void SocketInterface::Process(const void* aMainloopContext) {
    }
}

otError SocketInterface::HardwareReset(void) {
    otError error = OT_ERROR_NONE;
    std::vector<uint8_t> 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];

@@ -159,11 +205,16 @@ void SocketInterface::Read(void) {
        ProcessReceivedData(buffer, static_cast<uint16_t>(rval));
    } else if (rval < 0) {
        DieNow(OT_EXIT_ERROR_ERRNO);
    } else {
        if (mIsHardwareResetting) {
            LogInfo("Socket connection is closed due to hardware reset.");
            ResetStates();
        } else {
            LogCrit("Socket connection is closed by remote.");
            exit(OT_EXIT_FAILURE);
        }
    }
}

void SocketInterface::Write(const uint8_t* aFrame, uint16_t aLength) {
    ssize_t rval = TEMP_FAILURE_RETRY(write(mSockFd, aFrame, aLength));
@@ -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
+23 −4
Original line number Diff line number Diff line
@@ -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.
        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.