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

Commit 83c4ef44 authored by Zhanglong Xia's avatar Zhanglong Xia Committed by Kangping Dong
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.
(cherry picked from https://android-review.googlesource.com/q/commit:7ae6d6f4ffe49c358978b9ea9c670ee2aefe4a27)
Merged-In: I6726eead5686f0afb33e5e2035ebc9021eca5afa
Change-Id: I6726eead5686f0afb33e5e2035ebc9021eca5afa
parent aa36cb13
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -29,6 +29,7 @@ cc_defaults {
        "openthread-hdlc",
        "openthread-platform",
        "openthread-posix",
        "openthread-spi",
        "openthread-url",
    ],

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

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

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

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

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

    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) {
@@ -43,7 +62,7 @@ void ThreadChip::clientDeathCallback(void) {
    close();
}

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

@@ -70,7 +89,7 @@ ndk::ScopedAStatus ThreadChip::open(const std::shared_ptr<IThreadChipCallback>&
    mBinderDeathRecipient = AIBinder_DeathRecipient_new(clientDeathCallback);
    VerifyOrExit(AIBinder_linkToDeath(binder, mBinderDeathRecipient, this) == STATUS_OK,
                 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"));

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

    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,
                 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());
    if (error == OT_ERROR_NONE) {
        status = ndk::ScopedAStatus::ok();
@@ -134,20 +153,20 @@ exit:
}

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

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

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

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

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

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

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