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

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

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

parents 17f40c81 319ccccf
Loading
Loading
Loading
Loading
+64 −6
Original line number Original line Diff line number Diff line
@@ -33,6 +33,7 @@
#include <unistd.h>
#include <unistd.h>


#include <string>
#include <string>
#include <vector>


#include "common/code_utils.hpp"
#include "common/code_utils.hpp"
#include "openthread/openthread-system.h"
#include "openthread/openthread-system.h"
@@ -49,10 +50,8 @@ SocketInterface::SocketInterface(const ot::Url::Url& aRadioUrl)
    : mReceiveFrameCallback(nullptr),
    : mReceiveFrameCallback(nullptr),
      mReceiveFrameContext(nullptr),
      mReceiveFrameContext(nullptr),
      mReceiveFrameBuffer(nullptr),
      mReceiveFrameBuffer(nullptr),
      mSockFd(-1),
      mRadioUrl(aRadioUrl) {
      mRadioUrl(aRadioUrl) {
    memset(&mInterfaceMetrics, 0, sizeof(mInterfaceMetrics));
    ResetStates();
    mInterfaceMetrics.mRcpInterfaceType = kSpinelInterfaceTypeVendor;
}
}


otError SocketInterface::Init(ReceiveFrameCallback aCallback, void* aCallbackContext,
otError SocketInterface::Init(ReceiveFrameCallback aCallback, void* aCallbackContext,
@@ -120,13 +119,50 @@ otError SocketInterface::WaitForFrame(uint64_t aTimeoutUs) {
    } else if (rval == 0) {
    } else if (rval == 0) {
        ExitNow(error = OT_ERROR_RESPONSE_TIMEOUT);
        ExitNow(error = OT_ERROR_RESPONSE_TIMEOUT);
    } else {
    } else {
        DieNowWithMessage("wait response", OT_EXIT_FAILURE);
        DieNowWithMessage("Wait response", OT_EXIT_FAILURE);
    }
    }


exit:
exit:
    return error;
    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) {
void SocketInterface::UpdateFdSet(void* aMainloopContext) {
    otSysMainloopContext* context = reinterpret_cast<otSysMainloopContext*>(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) {
void SocketInterface::Read(void) {
    uint8_t buffer[kMaxFrameSize];
    uint8_t buffer[kMaxFrameSize];


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


void SocketInterface::Write(const uint8_t* aFrame, uint16_t aLength) {
void SocketInterface::Write(const uint8_t* aFrame, uint16_t aLength) {
    ssize_t rval = TEMP_FAILURE_RETRY(write(mSockFd, aFrame, 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);
    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 threadnetwork
}  // namespace hardware
}  // namespace hardware
}  // namespace android
}  // namespace android
+23 −4
Original line number Original line Diff line number Diff line
@@ -136,10 +136,10 @@ class SocketInterface : public ot::Spinel::SpinelInterface,
     * Hardware resets the RCP.
     * Hardware resets the RCP.
     *
     *
     * @retval OT_ERROR_NONE            Successfully reset 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.
     * Returns the RCP interface metrics.
@@ -237,9 +237,26 @@ class SocketInterface : public ot::Spinel::SpinelInterface,
     */
     */
    void WaitForSocketFileCreated(const char* aPath);
    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 {
    enum {
        kMaxSelectTimeMs = 2000,             ///< Maximum wait time in Milliseconds for file
        kMaxSelectTimeMs = 2000,             ///< Maximum wait time in Milliseconds for file
                                             ///< descriptor to become available.
                                             ///< descriptor to become available.
        kMaxRetriesForSocketCloseCheck = 3,  ///< Maximum retry times for checking
                                             ///< if socket is closed.
    };
    };


    ReceiveFrameCallback mReceiveFrameCallback;
    ReceiveFrameCallback mReceiveFrameCallback;
@@ -249,6 +266,8 @@ class SocketInterface : public ot::Spinel::SpinelInterface,
    int mSockFd;
    int mSockFd;
    const ot::Url::Url& mRadioUrl;
    const ot::Url::Url& mRadioUrl;


    bool mIsHardwareResetting;

    otRcpInterfaceMetrics mInterfaceMetrics;
    otRcpInterfaceMetrics mInterfaceMetrics;


    // Non-copyable, intentionally not implemented.
    // Non-copyable, intentionally not implemented.