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

Commit 7ae6d6f4 authored by Zhanglong Xia's avatar Zhanglong Xia
Browse files

add Spinel SPI interface support

This commit enables the Thread Network HAL to support the Spinel
SPI interface.

Bug: 277286756
Test: Build and run otbr-agent on the emulator.
Change-Id: I6726eead5686f0afb33e5e2035ebc9021eca5afa
parent 59b01867
Loading
Loading
Loading
Loading
+2 −0
Original line number Original line Diff line number Diff line
@@ -29,6 +29,7 @@ cc_defaults {
        "openthread-hdlc",
        "openthread-hdlc",
        "openthread-platform",
        "openthread-platform",
        "openthread-posix",
        "openthread-posix",
        "openthread-spi",
        "openthread-url",
        "openthread-url",
    ],
    ],


@@ -68,6 +69,7 @@ cc_fuzz {
        "openthread-hdlc",
        "openthread-hdlc",
        "openthread-platform",
        "openthread-platform",
        "openthread-posix",
        "openthread-posix",
        "openthread-spi",
        "openthread-url",
        "openthread-url",
    ],
    ],


+32 −13
Original line number Original line Diff line number Diff line
@@ -21,17 +21,36 @@
#include <android/binder_process.h>
#include <android/binder_process.h>
#include <utils/Log.h>
#include <utils/Log.h>


#include "hdlc_interface.hpp"
#include "spi_interface.hpp"

namespace aidl {
namespace aidl {
namespace android {
namespace android {
namespace hardware {
namespace hardware {
namespace threadnetwork {
namespace threadnetwork {


ThreadChip::ThreadChip(char* url)
ThreadChip::ThreadChip(char* url) : mUrl(), mRxFrameBuffer(), mCallback(nullptr) {
    : mUrl(),
    static const char kHdlcProtocol[] = "spinel+hdlc";
      mInterface(handleReceivedFrame, this, mRxFrameBuffer),
    static const char kSpiProtocol[] = "spinel+spi";
      mRxFrameBuffer(),
    const char* protocol;
      mCallback(nullptr) {

    CHECK_EQ(mUrl.Init(url), 0);
    CHECK_EQ(mUrl.Init(url), 0);

    protocol = mUrl.GetProtocol();
    CHECK_NE(protocol, nullptr);

    if (memcmp(protocol, kSpiProtocol, strlen(kSpiProtocol)) == 0) {
        mSpinelInterface = std::make_shared<ot::Posix::SpiInterface>(handleReceivedFrameJump, this,
                                                                     mRxFrameBuffer);
    } else if (memcmp(protocol, kHdlcProtocol, strlen(kHdlcProtocol)) == 0) {
        mSpinelInterface = std::make_shared<ot::Posix::HdlcInterface>(handleReceivedFrameJump, this,
                                                                      mRxFrameBuffer);
    } else {
        ALOGE("The protocol \"%s\" is not supported!", protocol);
        exit(1);
    }

    CHECK_NE(mSpinelInterface, nullptr);
}
}


void ThreadChip::clientDeathCallback(void* context) {
void ThreadChip::clientDeathCallback(void* context) {
@@ -43,7 +62,7 @@ void ThreadChip::clientDeathCallback(void) {
    close();
    close();
}
}


void ThreadChip::handleReceivedFrame(void* context) {
void ThreadChip::handleReceivedFrameJump(void* context) {
    static_cast<ThreadChip*>(context)->handleReceivedFrame();
    static_cast<ThreadChip*>(context)->handleReceivedFrame();
}
}


@@ -70,7 +89,7 @@ ndk::ScopedAStatus ThreadChip::open(const std::shared_ptr<IThreadChipCallback>&
    mBinderDeathRecipient = AIBinder_DeathRecipient_new(clientDeathCallback);
    mBinderDeathRecipient = AIBinder_DeathRecipient_new(clientDeathCallback);
    VerifyOrExit(AIBinder_linkToDeath(binder, mBinderDeathRecipient, this) == STATUS_OK,
    VerifyOrExit(AIBinder_linkToDeath(binder, mBinderDeathRecipient, this) == STATUS_OK,
                 status = errorStatus(ERROR_FAILED, "Failed to link the binder to death"));
                 status = errorStatus(ERROR_FAILED, "Failed to link the binder to death"));
    VerifyOrExit(mInterface.Init(mUrl) == OT_ERROR_NONE,
    VerifyOrExit(mSpinelInterface->Init(mUrl) == OT_ERROR_NONE,
                 status = errorStatus(ERROR_FAILED, "Failed to initialize the interface"));
                 status = errorStatus(ERROR_FAILED, "Failed to initialize the interface"));


    mCallback = in_callback;
    mCallback = in_callback;
@@ -94,7 +113,7 @@ exit:
ndk::ScopedAStatus ThreadChip::close() {
ndk::ScopedAStatus ThreadChip::close() {
    VerifyOrExit(mCallback != nullptr);
    VerifyOrExit(mCallback != nullptr);
    mCallback = nullptr;
    mCallback = nullptr;
    mInterface.Deinit();
    mSpinelInterface->Deinit();


    ot::Posix::Mainloop::Manager::Get().Remove(*this);
    ot::Posix::Mainloop::Manager::Get().Remove(*this);


@@ -113,7 +132,7 @@ ndk::ScopedAStatus ThreadChip::sendSpinelFrame(const std::vector<uint8_t>& in_fr
    VerifyOrExit(mCallback != nullptr,
    VerifyOrExit(mCallback != nullptr,
                 status = errorStatus(ERROR_FAILED, "The interface is not open"));
                 status = errorStatus(ERROR_FAILED, "The interface is not open"));


    error = mInterface.SendFrame(reinterpret_cast<const uint8_t*>(in_frame.data()),
    error = mSpinelInterface->SendFrame(reinterpret_cast<const uint8_t*>(in_frame.data()),
                                        in_frame.size());
                                        in_frame.size());
    if (error == OT_ERROR_NONE) {
    if (error == OT_ERROR_NONE) {
        status = ndk::ScopedAStatus::ok();
        status = ndk::ScopedAStatus::ok();
@@ -134,20 +153,20 @@ exit:
}
}


ndk::ScopedAStatus ThreadChip::reset() {
ndk::ScopedAStatus ThreadChip::reset() {
    mInterface.HardwareReset();
    mSpinelInterface->HardwareReset();
    ALOGI("reset()");
    ALOGI("reset()");
    return ndk::ScopedAStatus::ok();
    return ndk::ScopedAStatus::ok();
}
}


void ThreadChip::Update(otSysMainloopContext& context) {
void ThreadChip::Update(otSysMainloopContext& context) {
    if (mCallback != nullptr) {
    if (mCallback != nullptr) {
        mInterface.UpdateFdSet(&context);
        mSpinelInterface->UpdateFdSet(&context);
    }
    }
}
}


void ThreadChip::Process(const otSysMainloopContext& context) {
void ThreadChip::Process(const otSysMainloopContext& context) {
    if (mCallback != nullptr) {
    if (mCallback != nullptr) {
        mInterface.Process(&context);
        mSpinelInterface->Process(&context);
    }
    }
}
}


+2 −3
Original line number Original line Diff line number Diff line
@@ -19,7 +19,6 @@
#include <aidl/android/hardware/threadnetwork/BnThreadChip.h>
#include <aidl/android/hardware/threadnetwork/BnThreadChip.h>
#include <aidl/android/hardware/threadnetwork/IThreadChipCallback.h>
#include <aidl/android/hardware/threadnetwork/IThreadChipCallback.h>


#include "hdlc_interface.hpp"
#include "lib/spinel/spinel_interface.hpp"
#include "lib/spinel/spinel_interface.hpp"
#include "mainloop.hpp"
#include "mainloop.hpp"


@@ -45,12 +44,12 @@ class ThreadChip : public BnThreadChip, ot::Posix::Mainloop::Source {
  private:
  private:
    static void clientDeathCallback(void* context);
    static void clientDeathCallback(void* context);
    void clientDeathCallback(void);
    void clientDeathCallback(void);
    static void handleReceivedFrame(void* context);
    static void handleReceivedFrameJump(void* context);
    void handleReceivedFrame(void);
    void handleReceivedFrame(void);
    ndk::ScopedAStatus errorStatus(int32_t error, const char* message);
    ndk::ScopedAStatus errorStatus(int32_t error, const char* message);


    ot::Url::Url mUrl;
    ot::Url::Url mUrl;
    ot::Posix::HdlcInterface mInterface;
    std::shared_ptr<ot::Spinel::SpinelInterface> mSpinelInterface;
    ot::Spinel::SpinelInterface::RxFrameBuffer mRxFrameBuffer;
    ot::Spinel::SpinelInterface::RxFrameBuffer mRxFrameBuffer;
    std::shared_ptr<IThreadChipCallback> mCallback;
    std::shared_ptr<IThreadChipCallback> mCallback;
    AIBinder_DeathRecipient* mBinderDeathRecipient;
    AIBinder_DeathRecipient* mBinderDeathRecipient;
+39 −0
Original line number Original line Diff line number Diff line
@@ -36,6 +36,45 @@ void otLogWarnPlat(const char* format, ...) {
    va_end(args);
    va_end(args);
}
}


void otLogNotePlat(const char* format, ...) {
    va_list args;

    va_start(args, format);
    __android_log_vprint(ANDROID_LOG_INFO, LOG_TAG, format, args);
    va_end(args);
}

void otLogInfoPlat(const char* format, ...) {
    va_list args;

    va_start(args, format);
    __android_log_vprint(ANDROID_LOG_INFO, LOG_TAG, format, args);
    va_end(args);
}

void otLogDebgPlat(const char* format, ...) {
    va_list args;

    va_start(args, format);
    __android_log_vprint(ANDROID_LOG_DEBUG, LOG_TAG, format, args);
    va_end(args);
}

void otDumpDebgPlat(const char* aText, const void* aData, uint16_t aDataLength) {
    constexpr uint16_t kBufSize = 512;
    char buf[kBufSize];

    if ((aText != nullptr) && (aData != nullptr)) {
        const uint8_t* data = reinterpret_cast<const uint8_t*>(aData);

        for (uint16_t i = 0; (i < aDataLength) && (i < (kBufSize - 1) / 3); i++) {
            snprintf(buf + (i * 3), (kBufSize - 1) - (i * 3), "%02x ", data[i]);
        }

        __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, "%s: %s", aText, buf);
    }
}

OT_TOOL_WEAK void otPlatAlarmMilliFired(otInstance* aInstance) {
OT_TOOL_WEAK void otPlatAlarmMilliFired(otInstance* aInstance) {
    OT_UNUSED_VARIABLE(aInstance);
    OT_UNUSED_VARIABLE(aInstance);
}
}