diff options
author | Android Build Coastguard Worker <android-build-coastguard-worker@google.com> | 2023-02-15 05:11:29 +0000 |
---|---|---|
committer | Android Build Coastguard Worker <android-build-coastguard-worker@google.com> | 2023-02-15 05:11:29 +0000 |
commit | f781f63f9d734cfdfb6281ec14713786c05faa53 (patch) | |
tree | 7a87da4507a0b1e30e90fda5243f615e2a2dfde7 | |
parent | 6c19e7427d11c48889f4a82c77d1961ac599a871 (diff) | |
parent | 9d31b5ced11684e6b89a70461e2cd67cb12c1a36 (diff) | |
download | openthread-android-14.0.0_r6.tar.gz |
Snap for 9608188 from 9d31b5ced11684e6b89a70461e2cd67cb12c1a36 to udc-d1-releaseandroid-14.0.0_r9android-14.0.0_r8android-14.0.0_r7android-14.0.0_r6android-14.0.0_r5android-14.0.0_r4android-14.0.0_r3android-14.0.0_r12android-14.0.0_r11android-14.0.0_r10android14-d1-s7-releaseandroid14-d1-s6-releaseandroid14-d1-s5-releaseandroid14-d1-s4-releaseandroid14-d1-s3-releaseandroid14-d1-s2-releaseandroid14-d1-s1-releaseandroid14-d1-release
Change-Id: I73673e1b3a0a15062e06b3a437997e52b6227259
-rw-r--r-- | Android.bp | 123 | ||||
-rw-r--r-- | src/android/thread_network_hal/hal_interface.cpp | 290 | ||||
-rw-r--r-- | src/android/thread_network_hal/hal_interface.hpp | 210 | ||||
-rw-r--r-- | src/android/thread_network_hal/vendor_interface.cpp | 116 | ||||
-rw-r--r-- | src/posix/platform/mainloop.hpp | 6 |
5 files changed, 737 insertions, 8 deletions
diff --git a/Android.bp b/Android.bp index 8bc8aade0..93f283d8c 100644 --- a/Android.bp +++ b/Android.bp @@ -109,7 +109,7 @@ soong_config_module_type { soong_config_string_variable { name: "rcp_bus", - values: ["spi", "uart"], + values: ["spi", "uart", "hal"], } ot_config_cc_defaults { @@ -122,10 +122,9 @@ ot_config_cc_defaults { spi: { cflags: ["-DOPENTHREAD_POSIX_CONFIG_RCP_BUS=OT_POSIX_RCP_BUS_SPI"] }, - uart: { + hal: { cflags: [ - "-DOPENTHREAD_POSIX_CONFIG_RCP_BUS=OT_POSIX_RCP_BUS_UART", - "-DOPENTHREAD_POSIX_CONFIG_RCP_PTY_ENABLE=1", + "-DOPENTHREAD_POSIX_CONFIG_RCP_BUS=OT_POSIX_RCP_BUS_VENDOR", ] }, conditions_default: { @@ -146,6 +145,7 @@ cc_library_static { local_include_dirs: [ "include", "src", + "src/android/thread_network_hal", "src/cli", "src/core", "src/ncp", @@ -173,6 +173,8 @@ cc_library_static { ], srcs: [ + "src/android/thread_network_hal/hal_interface.cpp", + "src/android/thread_network_hal/vendor_interface.cpp", "src/core/api/backbone_router_api.cpp", "src/core/api/backbone_router_ftd_api.cpp", "src/core/api/border_agent_api.cpp", @@ -556,6 +558,7 @@ cc_defaults { "src/cli", "src/core", "src/ncp", + "src/lib/hdlc", "third_party", "third_party/mbedtls", "third_party/mbedtls/repo/include", @@ -586,6 +589,7 @@ cc_defaults { cc_library_static { name: "openthread-simulation", + vendor: true, defaults: [ "ot_rcp_cflags_defaults", @@ -606,13 +610,10 @@ cc_library_static { "examples/platforms/simulation/system.c", "examples/platforms/simulation/trel.c", "examples/platforms/simulation/uart.c", - "examples/platforms/utils/link_metrics.cpp", "examples/platforms/utils/mac_frame.cpp", "examples/platforms/utils/soft_source_match_table.c", - "src/lib/platform/exit_code.c", - "third_party/mbedtls/repo/library/aes.c", "third_party/mbedtls/repo/library/asn1parse.c", "third_party/mbedtls/repo/library/asn1write.c", @@ -643,6 +644,7 @@ cc_library_static { cc_library_static { name: "openthread-radio", + vendor: true, defaults: [ "ot_rcp_cflags_defaults", @@ -650,6 +652,9 @@ cc_library_static { ], generated_headers: ["ot_version_header"], + shared_libs: [ + "libcutils", + ], srcs: [ "src/core/api/diags_api.cpp", @@ -688,23 +693,71 @@ cc_library_static { cc_library_static { name: "openthread-hdlc", + vendor: true, defaults: [ "ot_rcp_cflags_defaults", "ot_simulation_cflags_defaults", ], + export_include_dirs: [ + "include", + "src", + ], srcs: [ "src/lib/hdlc/hdlc.cpp", ], } cc_library_static { + name: "openthread-url", + vendor: true, + local_include_dirs: [ + "include", + "src", + "src/core", + "src/lib/url", + ], + export_include_dirs: [ + "include", + "src", + ], + srcs: [ + "src/lib/url/url.cpp", + ], +} + +cc_library_static { + name: "openthread-platform", + vendor: true, + local_include_dirs: [ + "include", + "src", + "src/core", + "src/lib/platform", + ], + export_include_dirs: [ + "include", + "src", + ], + srcs: [ + "src/lib/platform/exit_code.c", + ], +} + + +cc_library_static { name: "openthread-spinel-rcp", + vendor: true, defaults: [ "ot_rcp_cflags_defaults", "ot_simulation_cflags_defaults", ], + export_include_dirs: [ + "include", + "src", + ], + srcs: [ "src/lib/spinel/spinel.c", "src/lib/spinel/spinel_buffer.cpp", @@ -715,6 +768,7 @@ cc_library_static { cc_library_static { name: "openthread-rcp", + vendor: true, defaults: [ "ot_rcp_cflags_defaults", @@ -733,7 +787,7 @@ cc_library_static { cc_binary { name: "ot-rcp", - + vendor: true, defaults: [ "ot_rcp_cflags_defaults", "ot_simulation_cflags_defaults", @@ -760,3 +814,56 @@ cc_binary { ], } +cc_library_static { + name: "openthread-posix", + vendor: true, + local_include_dirs: [ + "include", + "src", + "src/core", + "src/lib/platform", + "src/posix/platform", + "src/posix/platform/include", + ], + export_include_dirs: [ + "include", + "src/core", + "src/posix/platform", + "src/posix/platform/include", + ], + + cflags: [ + "-DOPENTHREAD_POSIX_CONFIG_RCP_BUS=OT_POSIX_RCP_BUS_UART", + "-DOPENTHREAD_OSIX_CONFIG_RCP_PTY_ENABLE=1", + ], + + cppflags: [ + "-Wno-non-virtual-dtor", + ], + + srcs: [ + "src/posix/platform/alarm.cpp", + "src/posix/platform/mainloop.cpp", + "src/posix/platform/hdlc_interface.cpp", + ], +} + +cc_library_static { + name: "openthread-common", + vendor: true, + local_include_dirs: [ + "include", + "src", + "src/core", + ], + + export_include_dirs: [ + "include", + "src/core", + ], + + srcs: [ + "src/core/common/error.cpp", + "src/core/api/error_api.cpp", + ], +} diff --git a/src/android/thread_network_hal/hal_interface.cpp b/src/android/thread_network_hal/hal_interface.cpp new file mode 100644 index 000000000..25d629206 --- /dev/null +++ b/src/android/thread_network_hal/hal_interface.cpp @@ -0,0 +1,290 @@ +/* + * Copyright (c) 2022, The OpenThread Authors. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/** + * @file + * This file includes the implementation for the IPC Binder interface to radio Co-Processor (RCP). + */ + +#include "hal_interface.hpp" + +#if OPENTHREAD_POSIX_CONFIG_RCP_BUS == OT_POSIX_RCP_BUS_VENDOR + +#include <linux/gpio.h> +#include <linux/ioctl.h> +#include <linux/spi/spidev.h> +#include <sys/select.h> + +#include <android/binder_manager.h> +#include <android/binder_process.h> + +namespace ot { +namespace Posix { +using ::aidl::android::hardware::threadnetwork::IThreadChip; +using ::aidl::android::hardware::threadnetwork::IThreadChipCallback; +using ::ndk::ScopedAStatus; + +using ot::Spinel::SpinelInterface; + +HalInterface::HalInterface(SpinelInterface::ReceiveFrameCallback aCallback, + void * aCallbackContext, + SpinelInterface::RxFrameBuffer & aFrameBuffer) + : mRxFrameCallback(aCallback) + , mRxFrameContext(aCallbackContext) + , mRxFrameBuffer(aFrameBuffer) + , mThreadChip(nullptr) + , mThreadChipCallback(nullptr) + , mDeathRecipient(AIBinder_DeathRecipient_new(BinderDeathCallback)) + , mBinderFd(-1) +{ + OT_ASSERT(mRxFrameCallback != nullptr); +} + +otError HalInterface::Init(const Url::Url &aRadioUrl) +{ + static const std::string kServicePrefix = std::string() + IThreadChip::descriptor + "/chip"; + uint32_t id = 0; + const char * value; + binder_status_t binderStatus; + ScopedAStatus ndkStatus; + std::shared_ptr<ThreadChipCallback> callback; + std::string serviceName; + + binderStatus = ABinderProcess_setupPolling(&mBinderFd); + VerifyOrDie(binderStatus == ::STATUS_OK, OT_EXIT_FAILURE); + VerifyOrDie(mBinderFd >= 0, OT_EXIT_FAILURE); + + if ((value = aRadioUrl.GetValue("id")) != nullptr) + { + id = static_cast<uint32_t>(atoi(value)); + } + + serviceName = kServicePrefix + std::to_string(id); + otLogInfoPlat("[HAL] Wait for getting the service %s ...", serviceName.c_str()); + mThreadChip = IThreadChip::fromBinder(::ndk::SpAIBinder(AServiceManager_waitForService(serviceName.c_str()))); + VerifyOrDie(mThreadChip != nullptr, OT_EXIT_FAILURE); + + callback = ndk::SharedRefBase::make<ThreadChipCallback>(this); + VerifyOrDie(callback->asBinder().get() != nullptr, OT_EXIT_FAILURE); + + mThreadChipCallback = IThreadChipCallback::fromBinder(callback->asBinder()); + VerifyOrDie(mThreadChipCallback != nullptr, OT_EXIT_FAILURE); + + VerifyOrDie(AIBinder_linkToDeath(mThreadChip->asBinder().get(), mDeathRecipient.get(), this) == STATUS_OK, + OT_EXIT_FAILURE); + + ndkStatus = mThreadChip->open(mThreadChipCallback); + if (!ndkStatus.isOk()) + { + otLogCritPlat("[HAL] Open the HAL interface failed: %s", ndkStatus.getMessage()); + DieNow(OT_EXIT_FAILURE); + } + + otLogInfoPlat("[HAL] Successfully got the service %s", serviceName.c_str()); + + return OT_ERROR_NONE; +} + +void HalInterface::BinderDeathCallback(void *aContext) +{ + OT_UNUSED_VARIABLE(aContext); + + otLogInfoPlat("[HAL] Thread network HAL is dead, exit!"); + DieNow(OT_EXIT_FAILURE); +} + +HalInterface::~HalInterface(void) +{ + Deinit(); +} + +void HalInterface::Deinit(void) +{ + if (mThreadChip != nullptr) + { + mThreadChip->close(); + AIBinder_unlinkToDeath(mThreadChip->asBinder().get(), mDeathRecipient.get(), this); + mThreadChip = nullptr; + mThreadChipCallback = nullptr; + } + + if (mBinderFd >= 0) + { + close(mBinderFd); + } +} + +uint32_t HalInterface::GetBusSpeed(void) const +{ + static const uint32_t kBusSpeed = 1000000; + return kBusSpeed; +} + +void HalInterface::OnRcpReset(void) +{ + mThreadChip->reset(); +} + +void HalInterface::UpdateFdSet(fd_set &aReadFdSet, fd_set &aWriteFdSet, int &aMaxFd, struct timeval &aTimeout) +{ + OT_UNUSED_VARIABLE(aWriteFdSet); + OT_UNUSED_VARIABLE(aTimeout); + + if (mBinderFd >= 0) + { + FD_SET(mBinderFd, &aReadFdSet); + aMaxFd = std::max(aMaxFd, mBinderFd); + } +} + +void HalInterface::Process(const RadioProcessContext &aContext) +{ + if ((mBinderFd >= 0) && FD_ISSET(mBinderFd, aContext.mReadFdSet)) + { + ABinderProcess_handlePolledCommands(); + } +} + +otError HalInterface::WaitForFrame(uint64_t aTimeoutUs) +{ + otError error = OT_ERROR_NONE; + struct timeval timeout; + fd_set readFdSet; + int ret; + + VerifyOrExit(mBinderFd >= 0, error = OT_ERROR_FAILED); + + timeout.tv_sec = static_cast<time_t>(aTimeoutUs / US_PER_S); + timeout.tv_usec = static_cast<suseconds_t>(aTimeoutUs % US_PER_S); + + FD_ZERO(&readFdSet); + FD_SET(mBinderFd, &readFdSet); + + ret = select(mBinderFd + 1, &readFdSet, nullptr, nullptr, &timeout); + + if ((ret > 0) && FD_ISSET(mBinderFd, &readFdSet)) + { + ABinderProcess_handlePolledCommands(); + } + else if (ret == 0) + { + ExitNow(error = OT_ERROR_RESPONSE_TIMEOUT); + } + else if (errno != EINTR) + { + DieNow(OT_EXIT_ERROR_ERRNO); + } + +exit: + + if (error != OT_ERROR_NONE) + { + otLogWarnPlat("[HAL] Wait for frame failed: %s", otThreadErrorToString(error)); + } + + return error; +} + +otError HalInterface::SendFrame(const uint8_t *aFrame, uint16_t aLength) +{ + otError error = OT_ERROR_NONE; + ScopedAStatus status; + + VerifyOrExit((aFrame != nullptr) && (aLength <= kMaxFrameSize), error = OT_ERROR_INVALID_ARGS); + status = mThreadChip->sendSpinelFrame(std::vector<uint8_t>(aFrame, aFrame + aLength)); + VerifyOrExit(!status.isOk(), error = OT_ERROR_NONE); + error = StatusToError(status); + otLogWarnPlat("[HAL] Send frame to HAL interface failed: %s", otThreadErrorToString(error)); + +exit: + return error; +} + +void HalInterface::ReceiveFrameCallback(const std::vector<uint8_t> &aFrame) +{ + otError error = OT_ERROR_NONE; + + VerifyOrExit(aFrame.size() > 0, error = OT_ERROR_FAILED); + + for (uint32_t i = 0; i < aFrame.size(); i++) + { + if ((error = mRxFrameBuffer.WriteByte(aFrame[i])) != OT_ERROR_NONE) + { + otLogNotePlat("[HAL] Drop the received spinel frame: %s", otThreadErrorToString(error)); + mRxFrameBuffer.DiscardFrame(); + ExitNow(); + } + } + + mRxFrameCallback(mRxFrameContext); + +exit: + return; +} + +otError HalInterface::StatusToError(ScopedAStatus &aStatus) +{ + otError error = OT_ERROR_FAILED; + + VerifyOrExit(!aStatus.isOk(), error = OT_ERROR_NONE); + + if (aStatus.getExceptionCode() == EX_ILLEGAL_STATE) + { + error = OT_ERROR_INVALID_STATE; + } + else if (aStatus.getExceptionCode() == EX_ILLEGAL_ARGUMENT) + { + error = OT_ERROR_INVALID_ARGS; + } + else if (aStatus.getExceptionCode() == EX_SERVICE_SPECIFIC) + { + switch (aStatus.getServiceSpecificError()) + { + case IThreadChip::ERROR_FAILED: + error = OT_ERROR_FAILED; + break; + case IThreadChip::ERROR_BUSY: + error = OT_ERROR_BUSY; + break; + case IThreadChip::ERROR_NO_BUFS: + error = OT_ERROR_NO_BUFS; + break; + default: + error = OT_ERROR_FAILED; + break; + } + } + +exit: + return error; +} + +} // namespace Posix +} // namespace ot + +#endif // OPENTHREAD_POSIX_CONFIG_RCP_BUS == OT_POSIX_RCP_BUS_VENDOR diff --git a/src/android/thread_network_hal/hal_interface.hpp b/src/android/thread_network_hal/hal_interface.hpp new file mode 100644 index 000000000..da1939017 --- /dev/null +++ b/src/android/thread_network_hal/hal_interface.hpp @@ -0,0 +1,210 @@ +/* + * Copyright (c) 2022, The OpenThread Authors. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/** + * @file + * This file includes definitions for the IPC binder interface to radio (RCP). + */ + +#ifndef ANDROID_THREAD_NETWORK_HAL_INTERFACE_HPP_ +#define ANDROID_THREAD_NETWORK_HAL_INTERFACE_HPP_ + +#include "openthread-posix-config.h" + +#include "platform-posix.h" +#include "lib/spinel/spinel_interface.hpp" + +#include <openthread/openthread-system.h> + +#if OPENTHREAD_POSIX_CONFIG_RCP_BUS == OT_POSIX_RCP_BUS_VENDOR + +#include <aidl/android/hardware/threadnetwork/BnThreadChipCallback.h> +#include <aidl/android/hardware/threadnetwork/IThreadChip.h> +#include <aidl/android/hardware/threadnetwork/IThreadChipCallback.h> + +namespace ot { +namespace Posix { + +/** + * This class defines an IPC Binder interface to the Radio Co-processor (RCP). + * + */ +class HalInterface +{ +public: + /** + * This constructor initializes the object. + * + * @param[in] aCallback A reference to a `Callback` object. + * @param[in] aCallbackContext The context pointer passed to the callback. + * @param[in] aFrameBuffer A reference to a `RxFrameBuffer` object. + * + */ + HalInterface(Spinel::SpinelInterface::ReceiveFrameCallback aCallback, + void *aCallbackContext, + Spinel::SpinelInterface::RxFrameBuffer &aFrameBuffer); + + /** + * This destructor deinitializes the object. + * + */ + ~HalInterface(void); + + /** + * This method initializes the interface to the Radio Co-processor (RCP). + * + * @note This method should be called before reading and sending spinel frames to the interface. + * + * @param[in] aRadioUrl Arguments parsed from radio url. + * + * @retval OT_ERROR_NONE The interface is initialized successfully. + * @retval OT_ERROR_ALREADY The interface is already initialized. + * @retval OT_ERROR_INVALID_ARGS The UART device or executable cannot be found or failed to open/run. + * + */ + otError Init(const Url::Url &aRadioUrl); + + /** + * This method deinitializes the interface to the RCP. + * + */ + void Deinit(void); + + /** + * This method encodes and sends a spinel frame to Radio Co-processor (RCP) over the socket. + * + * @param[in] aFrame A pointer to buffer containing the spinel frame to send. + * @param[in] aLength The length (number of bytes) in the frame. + * + * @retval OT_ERROR_NONE Successfully encoded and sent the spinel frame. + * @retval OT_ERROR_BUSY Failed due to another operation is on going. + * @retval OT_ERROR_NO_BUFS Insufficient buffer space available to encode the frame. + * @retval OT_ERROR_FAILED Failed to call the HAL to send the frame. + * + */ + otError SendFrame(const uint8_t *aFrame, uint16_t aLength); + + /** + * This method waits for receiving part or all of spinel frame within specified interval. + * + * @param[in] aTimeout The timeout value in microseconds. + * + * @retval OT_ERROR_NONE Part or all of spinel frame is received. + * @retval OT_ERROR_RESPONSE_TIMEOUT No spinel frame is received within @p aTimeout. + * + */ + otError WaitForFrame(uint64_t aTimeoutUs); + + /** + * This method updates the file descriptor sets with file descriptors used by the radio driver. + * + * @param[inout] aReadFdSet A reference to the read file descriptors. + * @param[inout] aWriteFdSet A reference to the write file descriptors. + * @param[inout] aMaxFd A reference to the max file descriptor. + * @param[inout] aTimeout A reference to the timeout. + * + */ + void UpdateFdSet(fd_set &aReadFdSet, fd_set &aWriteFdSet, int &aMaxFd, struct timeval &aTimeout); + + /** + * This method performs radio driver processing. + * + * @param[in] aContext The context containing fd_sets. + * + */ + void Process(const RadioProcessContext &aContext); + + /** + * This method returns the bus speed between the host and the radio. + * + * @returns Bus speed in bits/second. + * + */ + uint32_t GetBusSpeed(void) const; + + /** + * This method is called when RCP failure detected and resets internal states of the interface. + * + */ + void OnRcpReset(void); + + /** + * This method is called when RCP is reset to recreate the connection with it. + * Intentionally empty. + * + */ + otError ResetConnection(void) { return OT_ERROR_NONE; } + +private: + void ReceiveFrameCallback(const std::vector<uint8_t> &aFrame); + static void BinderDeathCallback(void *aContext); + otError StatusToError(::ndk::ScopedAStatus &aStatus); + + class ThreadChipCallback : public ::aidl::android::hardware::threadnetwork::BnThreadChipCallback + { + public: + ThreadChipCallback(HalInterface *aInterface) + : mInterface(aInterface) + { + } + + ::ndk::ScopedAStatus onReceiveSpinelFrame(const std::vector<uint8_t> &in_aFrame) + { + mInterface->ReceiveFrameCallback(in_aFrame); + return ndk::ScopedAStatus::ok(); + } + + private: + HalInterface *mInterface; + }; + + enum + { + kMaxFrameSize = Spinel::SpinelInterface::kMaxFrameSize, + }; + + Spinel::SpinelInterface::ReceiveFrameCallback mRxFrameCallback; + void *mRxFrameContext; + Spinel::SpinelInterface::RxFrameBuffer &mRxFrameBuffer; + + std::shared_ptr<::aidl::android::hardware::threadnetwork::IThreadChip> mThreadChip; + std::shared_ptr<::aidl::android::hardware::threadnetwork::IThreadChipCallback> mThreadChipCallback; + + ::ndk::ScopedAIBinder_DeathRecipient mDeathRecipient; + int mBinderFd; + + // Non-copyable, intentionally not implemented. + HalInterface(const HalInterface &); + HalInterface &operator=(const HalInterface &); +}; + +} // namespace Posix +} // namespace ot + +#endif // OPENTHREAD_POSIX_CONFIG_RCP_BUS == OT_POSIX_RCP_BUS_VENDOR +#endif // ANDROID_THREAD_NETWORK_HAL_INTERFACE_HPP_ diff --git a/src/android/thread_network_hal/vendor_interface.cpp b/src/android/thread_network_hal/vendor_interface.cpp new file mode 100644 index 000000000..fb8c66fc2 --- /dev/null +++ b/src/android/thread_network_hal/vendor_interface.cpp @@ -0,0 +1,116 @@ +/* + * Copyright (c) 2022, The OpenThread Authors. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/** + * @file + * This file includes the implementation for the vendor defined radio spinel interface + * to radio Co-Processor (RCP). + */ + +#include "vendor_interface.hpp" + +#if OPENTHREAD_POSIX_CONFIG_RCP_BUS == OT_POSIX_RCP_BUS_VENDOR + +#include <linux/gpio.h> +#include <linux/ioctl.h> +#include <linux/spi/spidev.h> +#include <sys/select.h> + +#include <memory> + +#include "hal_interface.hpp" + +namespace ot { +namespace Posix { +using ot::Spinel::SpinelInterface; + +HalInterface *sHalInterface = nullptr; + +VendorInterface::VendorInterface(SpinelInterface::ReceiveFrameCallback aCallback, + void *aCallbackContext, + SpinelInterface::RxFrameBuffer &aFrameBuffer) +{ + sHalInterface = new HalInterface(aCallback, aCallbackContext, aFrameBuffer); + assert(sHalInterface != nullptr); +} + +otError VendorInterface::Init(const Url::Url &aRadioUrl) +{ + return sHalInterface->Init(aRadioUrl); +} + +VendorInterface::~VendorInterface(void) +{ + sHalInterface->Deinit(); + delete sHalInterface; + sHalInterface = nullptr; +} + +void VendorInterface::Deinit(void) +{ + sHalInterface->Deinit(); +} + +uint32_t VendorInterface::GetBusSpeed(void) const +{ + return sHalInterface->GetBusSpeed(); +} + +void VendorInterface::OnRcpReset(void) +{ + sHalInterface->OnRcpReset(); +} + +void VendorInterface::UpdateFdSet(fd_set &aReadFdSet, fd_set &aWriteFdSet, int &aMaxFd, struct timeval &aTimeout) +{ + sHalInterface->UpdateFdSet(aReadFdSet, aWriteFdSet, aMaxFd, aTimeout); +} + +void VendorInterface::Process(const RadioProcessContext &aContext) +{ + sHalInterface->Process(aContext); +} + +otError VendorInterface::WaitForFrame(uint64_t aTimeoutUs) +{ + return sHalInterface->WaitForFrame(aTimeoutUs); +} + +otError VendorInterface::SendFrame(const uint8_t *aFrame, uint16_t aLength) +{ + return sHalInterface->SendFrame(aFrame, aLength); +} + +otError VendorInterface::ResetConnection(void) +{ + return sHalInterface->ResetConnection(); +} +} // namespace Posix +} // namespace ot + +#endif // OPENTHREAD_POSIX_CONFIG_RCP_BUS == OT_POSIX_RCP_BUS_SPI diff --git a/src/posix/platform/mainloop.hpp b/src/posix/platform/mainloop.hpp index d4f6ac8ff..4f0fa7cc9 100644 --- a/src/posix/platform/mainloop.hpp +++ b/src/posix/platform/mainloop.hpp @@ -65,6 +65,12 @@ public: */ virtual void Process(const otSysMainloopContext &aContext) = 0; + /** + * This method marks desturctor virtual method. + * + */ + virtual ~Source() = default; + private: Source *mNext = nullptr; }; |