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
This commit is contained in:
parent
59b018679b
commit
7ae6d6f4ff
4 changed files with 75 additions and 16 deletions
|
@ -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",
|
||||||
],
|
],
|
||||||
|
|
||||||
|
|
|
@ -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,8 +132,8 @@ 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();
|
||||||
} else if (error == OT_ERROR_NO_BUFS) {
|
} else if (error == OT_ERROR_NO_BUFS) {
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue