1 /* 2 * Copyright (c) 2022, The OpenThread Authors. 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions are met: 7 * 1. Redistributions of source code must retain the above copyright 8 * notice, this list of conditions and the following disclaimer. 9 * 2. Redistributions in binary form must reproduce the above copyright 10 * notice, this list of conditions and the following disclaimer in the 11 * documentation and/or other materials provided with the distribution. 12 * 3. Neither the name of the copyright holder nor the 13 * names of its contributors may be used to endorse or promote products 14 * derived from this software without specific prior written permission. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 17 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 20 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 23 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 24 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 25 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 26 * POSSIBILITY OF SUCH DAMAGE. 27 */ 28 29 /** 30 * @file 31 * This file includes definitions for the IPC binder interface to radio (RCP). 32 */ 33 34 #ifndef ANDROID_THREAD_NETWORK_HAL_INTERFACE_HPP_ 35 #define ANDROID_THREAD_NETWORK_HAL_INTERFACE_HPP_ 36 37 #include "openthread-posix-config.h" 38 39 #include "platform-posix.h" 40 #include "lib/spinel/spinel_interface.hpp" 41 42 #include <openthread/openthread-system.h> 43 44 #if OPENTHREAD_POSIX_CONFIG_RCP_BUS == OT_POSIX_RCP_BUS_VENDOR 45 46 #include <aidl/android/hardware/threadnetwork/BnThreadChipCallback.h> 47 #include <aidl/android/hardware/threadnetwork/IThreadChip.h> 48 #include <aidl/android/hardware/threadnetwork/IThreadChipCallback.h> 49 50 namespace ot { 51 namespace Posix { 52 53 /** 54 * This class defines an IPC Binder interface to the Radio Co-processor (RCP). 55 * 56 */ 57 class HalInterface : public ot::Spinel::SpinelInterface 58 { 59 public: 60 /** 61 * This constructor initializes the object. 62 * 63 * @param[in] aRadioUrl Arguments parsed from radio url. 64 * 65 */ 66 HalInterface(const Url::Url &aRadioUrl); 67 68 /** 69 * This destructor deinitializes the object. 70 * 71 */ 72 ~HalInterface(void); 73 74 /** 75 * This method initializes the interface to the Radio Co-processor (RCP). 76 * 77 * @note This method should be called before reading and sending spinel frames to the interface. 78 * 79 * @param[in] aCallback A reference to a `Callback` object. 80 * @param[in] aCallbackContext The context pointer passed to the callback. 81 * @param[in] aFrameBuffer A reference to a `RxFrameBuffer` object. 82 * 83 * @retval OT_ERROR_NONE The interface is initialized successfully. 84 * @retval OT_ERROR_ALREADY The interface is already initialized. 85 * @retval OT_ERROR_INVALID_ARGS The UART device or executable cannot be found or failed to open/run. 86 * 87 */ 88 otError Init(Spinel::SpinelInterface::ReceiveFrameCallback aCallback, 89 void *aCallbackContext, 90 Spinel::SpinelInterface::RxFrameBuffer &aFrameBuffer) override; 91 92 /** 93 * This method deinitializes the interface to the RCP. 94 * 95 */ 96 void Deinit(void) override; 97 98 /** 99 * This method encodes and sends a spinel frame to Radio Co-processor (RCP) over the socket. 100 * 101 * @param[in] aFrame A pointer to buffer containing the spinel frame to send. 102 * @param[in] aLength The length (number of bytes) in the frame. 103 * 104 * @retval OT_ERROR_NONE Successfully encoded and sent the spinel frame. 105 * @retval OT_ERROR_BUSY Failed due to another operation is on going. 106 * @retval OT_ERROR_NO_BUFS Insufficient buffer space available to encode the frame. 107 * @retval OT_ERROR_FAILED Failed to call the HAL to send the frame. 108 * 109 */ 110 otError SendFrame(const uint8_t *aFrame, uint16_t aLength) override; 111 112 /** 113 * This method waits for receiving part or all of spinel frame within specified interval. 114 * 115 * @param[in] aTimeout The timeout value in microseconds. 116 * 117 * @retval OT_ERROR_NONE Part or all of spinel frame is received. 118 * @retval OT_ERROR_RESPONSE_TIMEOUT No spinel frame is received within @p aTimeout. 119 * 120 */ 121 otError WaitForFrame(uint64_t aTimeoutUs) override; 122 123 /** 124 * This method updates the file descriptor sets with file descriptors used by the radio driver. 125 * 126 * @param[in] aMainloopContext The context containing fd_sets. 127 * 128 */ 129 void UpdateFdSet(void *aMainloopContext) override; 130 131 /** 132 * This method performs radio driver processing. 133 * 134 * @param[in] aMainloopContext The context containing fd_sets. 135 * 136 */ 137 void Process(const void *aMainloopContext) override; 138 139 /** 140 * This method returns the bus speed between the host and the radio. 141 * 142 * @returns Bus speed in bits/second. 143 * 144 */ 145 uint32_t GetBusSpeed(void) const override; 146 147 /** 148 * This method hardware resets the RCP. It will be called after a software reset fails. 149 * 150 * @retval OT_ERROR_NONE Successfully reset the RCP. 151 * @retval OT_ERROR_NOT_IMPLEMENT The hardware reset is not implemented. 152 * 153 */ 154 otError HardwareReset(void) override; 155 156 /** 157 * Returns the RCP interface metrics. 158 * 159 * @returns The RCP interface metrics. 160 * 161 */ GetRcpInterfaceMetrics(void) const162 const otRcpInterfaceMetrics *GetRcpInterfaceMetrics(void) const override { return &mInterfaceMetrics; } 163 164 private: 165 void ReceiveFrameCallback(const std::vector<uint8_t> &aFrame); 166 static void BinderDeathCallback(void *aContext); 167 otError StatusToError(const ::ndk::ScopedAStatus &aStatus) const; 168 169 class ThreadChipCallback : public ::aidl::android::hardware::threadnetwork::BnThreadChipCallback 170 { 171 public: ThreadChipCallback(HalInterface * aInterface)172 ThreadChipCallback(HalInterface *aInterface) 173 : mInterface(aInterface) 174 { 175 } 176 onReceiveSpinelFrame(const std::vector<uint8_t> & in_aFrame)177 ::ndk::ScopedAStatus onReceiveSpinelFrame(const std::vector<uint8_t> &in_aFrame) 178 { 179 mInterface->ReceiveFrameCallback(in_aFrame); 180 return ndk::ScopedAStatus::ok(); 181 } 182 183 private: 184 HalInterface *mInterface; 185 }; 186 187 enum 188 { 189 kMaxFrameSize = Spinel::SpinelInterface::kMaxFrameSize, 190 }; 191 192 Spinel::SpinelInterface::ReceiveFrameCallback mRxFrameCallback; 193 void *mRxFrameContext; 194 Spinel::SpinelInterface::RxFrameBuffer *mRxFrameBuffer; 195 196 otRcpInterfaceMetrics mInterfaceMetrics; 197 198 std::shared_ptr<::aidl::android::hardware::threadnetwork::IThreadChip> mThreadChip; 199 std::shared_ptr<::aidl::android::hardware::threadnetwork::IThreadChipCallback> mThreadChipCallback; 200 201 ::ndk::ScopedAIBinder_DeathRecipient mDeathRecipient; 202 int mBinderFd; 203 uint8_t mHalInterfaceId; 204 205 // Non-copyable, intentionally not implemented. 206 HalInterface(const HalInterface &); 207 HalInterface &operator=(const HalInterface &); 208 }; 209 210 } // namespace Posix 211 } // namespace ot 212 213 #endif // OPENTHREAD_POSIX_CONFIG_RCP_BUS == OT_POSIX_RCP_BUS_VENDOR 214 #endif // ANDROID_THREAD_NETWORK_HAL_INTERFACE_HPP_ 215