1*cfb92d14SAndroid Build Coastguard Worker /* 2*cfb92d14SAndroid Build Coastguard Worker * Copyright (c) 2019, The OpenThread Authors. 3*cfb92d14SAndroid Build Coastguard Worker * All rights reserved. 4*cfb92d14SAndroid Build Coastguard Worker * 5*cfb92d14SAndroid Build Coastguard Worker * Redistribution and use in source and binary forms, with or without 6*cfb92d14SAndroid Build Coastguard Worker * modification, are permitted provided that the following conditions are met: 7*cfb92d14SAndroid Build Coastguard Worker * 1. Redistributions of source code must retain the above copyright 8*cfb92d14SAndroid Build Coastguard Worker * notice, this list of conditions and the following disclaimer. 9*cfb92d14SAndroid Build Coastguard Worker * 2. Redistributions in binary form must reproduce the above copyright 10*cfb92d14SAndroid Build Coastguard Worker * notice, this list of conditions and the following disclaimer in the 11*cfb92d14SAndroid Build Coastguard Worker * documentation and/or other materials provided with the distribution. 12*cfb92d14SAndroid Build Coastguard Worker * 3. Neither the name of the copyright holder nor the 13*cfb92d14SAndroid Build Coastguard Worker * names of its contributors may be used to endorse or promote products 14*cfb92d14SAndroid Build Coastguard Worker * derived from this software without specific prior written permission. 15*cfb92d14SAndroid Build Coastguard Worker * 16*cfb92d14SAndroid Build Coastguard Worker * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 17*cfb92d14SAndroid Build Coastguard Worker * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18*cfb92d14SAndroid Build Coastguard Worker * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19*cfb92d14SAndroid Build Coastguard Worker * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 20*cfb92d14SAndroid Build Coastguard Worker * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 21*cfb92d14SAndroid Build Coastguard Worker * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 22*cfb92d14SAndroid Build Coastguard Worker * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 23*cfb92d14SAndroid Build Coastguard Worker * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 24*cfb92d14SAndroid Build Coastguard Worker * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 25*cfb92d14SAndroid Build Coastguard Worker * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 26*cfb92d14SAndroid Build Coastguard Worker * POSSIBILITY OF SUCH DAMAGE. 27*cfb92d14SAndroid Build Coastguard Worker */ 28*cfb92d14SAndroid Build Coastguard Worker 29*cfb92d14SAndroid Build Coastguard Worker /** 30*cfb92d14SAndroid Build Coastguard Worker * @file 31*cfb92d14SAndroid Build Coastguard Worker * This file includes definitions for the spinel interface to Radio Co-processor (RCP) 32*cfb92d14SAndroid Build Coastguard Worker * 33*cfb92d14SAndroid Build Coastguard Worker */ 34*cfb92d14SAndroid Build Coastguard Worker 35*cfb92d14SAndroid Build Coastguard Worker #ifndef SPINEL_SPINEL_INTERFACE_HPP_ 36*cfb92d14SAndroid Build Coastguard Worker #define SPINEL_SPINEL_INTERFACE_HPP_ 37*cfb92d14SAndroid Build Coastguard Worker 38*cfb92d14SAndroid Build Coastguard Worker #include "openthread-spinel-config.h" 39*cfb92d14SAndroid Build Coastguard Worker 40*cfb92d14SAndroid Build Coastguard Worker #include "lib/spinel/multi_frame_buffer.hpp" 41*cfb92d14SAndroid Build Coastguard Worker #include "lib/spinel/radio_spinel_metrics.h" 42*cfb92d14SAndroid Build Coastguard Worker #include "lib/spinel/spinel.h" 43*cfb92d14SAndroid Build Coastguard Worker 44*cfb92d14SAndroid Build Coastguard Worker namespace ot { 45*cfb92d14SAndroid Build Coastguard Worker namespace Spinel { 46*cfb92d14SAndroid Build Coastguard Worker 47*cfb92d14SAndroid Build Coastguard Worker class SpinelInterface 48*cfb92d14SAndroid Build Coastguard Worker { 49*cfb92d14SAndroid Build Coastguard Worker public: 50*cfb92d14SAndroid Build Coastguard Worker enum 51*cfb92d14SAndroid Build Coastguard Worker { 52*cfb92d14SAndroid Build Coastguard Worker kMaxFrameSize = OPENTHREAD_LIB_SPINEL_RX_FRAME_BUFFER_SIZE, ///< Maximum buffer size. 53*cfb92d14SAndroid Build Coastguard Worker }; 54*cfb92d14SAndroid Build Coastguard Worker 55*cfb92d14SAndroid Build Coastguard Worker /** 56*cfb92d14SAndroid Build Coastguard Worker * Defines a receive frame buffer to store received spinel frame(s). 57*cfb92d14SAndroid Build Coastguard Worker * 58*cfb92d14SAndroid Build Coastguard Worker * @note The receive frame buffer is an `Spinel::MultiFrameBuffer` and therefore it is capable of storing multiple 59*cfb92d14SAndroid Build Coastguard Worker * frames in a FIFO queue manner. 60*cfb92d14SAndroid Build Coastguard Worker * 61*cfb92d14SAndroid Build Coastguard Worker */ 62*cfb92d14SAndroid Build Coastguard Worker typedef MultiFrameBuffer<kMaxFrameSize> RxFrameBuffer; 63*cfb92d14SAndroid Build Coastguard Worker 64*cfb92d14SAndroid Build Coastguard Worker typedef void (*ReceiveFrameCallback)(void *aContext); 65*cfb92d14SAndroid Build Coastguard Worker 66*cfb92d14SAndroid Build Coastguard Worker /** 67*cfb92d14SAndroid Build Coastguard Worker * Initializes the interface to the Radio Co-processor (RCP) 68*cfb92d14SAndroid Build Coastguard Worker * 69*cfb92d14SAndroid Build Coastguard Worker * @note This method should be called before reading and sending spinel frames to the interface. 70*cfb92d14SAndroid Build Coastguard Worker * 71*cfb92d14SAndroid Build Coastguard Worker * @param[in] aCallback Callback on frame received 72*cfb92d14SAndroid Build Coastguard Worker * @param[in] aCallbackContext Callback context 73*cfb92d14SAndroid Build Coastguard Worker * @param[in] aFrameBuffer A reference to a `RxFrameBuffer` object. 74*cfb92d14SAndroid Build Coastguard Worker * 75*cfb92d14SAndroid Build Coastguard Worker * @retval OT_ERROR_NONE The interface is initialized successfully 76*cfb92d14SAndroid Build Coastguard Worker * @retval OT_ERROR_ALREADY The interface is already initialized. 77*cfb92d14SAndroid Build Coastguard Worker * @retval OT_ERROR_FAILED Failed to initialize the interface. 78*cfb92d14SAndroid Build Coastguard Worker * 79*cfb92d14SAndroid Build Coastguard Worker */ 80*cfb92d14SAndroid Build Coastguard Worker virtual otError Init(ReceiveFrameCallback aCallback, void *aCallbackContext, RxFrameBuffer &aFrameBuffer) = 0; 81*cfb92d14SAndroid Build Coastguard Worker 82*cfb92d14SAndroid Build Coastguard Worker /** 83*cfb92d14SAndroid Build Coastguard Worker * Deinitializes the interface to the RCP. 84*cfb92d14SAndroid Build Coastguard Worker * 85*cfb92d14SAndroid Build Coastguard Worker */ 86*cfb92d14SAndroid Build Coastguard Worker virtual void Deinit(void) = 0; 87*cfb92d14SAndroid Build Coastguard Worker 88*cfb92d14SAndroid Build Coastguard Worker /** 89*cfb92d14SAndroid Build Coastguard Worker * Encodes and sends a spinel frame to Radio Co-processor (RCP) over the socket. 90*cfb92d14SAndroid Build Coastguard Worker * 91*cfb92d14SAndroid Build Coastguard Worker * @param[in] aFrame A pointer to buffer containing the spinel frame to send. 92*cfb92d14SAndroid Build Coastguard Worker * @param[in] aLength The length (number of bytes) in the frame. 93*cfb92d14SAndroid Build Coastguard Worker * 94*cfb92d14SAndroid Build Coastguard Worker * @retval OT_ERROR_NONE Successfully encoded and sent the spinel frame. 95*cfb92d14SAndroid Build Coastguard Worker * @retval OT_ERROR_BUSY Failed due to another operation is on going. 96*cfb92d14SAndroid Build Coastguard Worker * @retval OT_ERROR_NO_BUFS Insufficient buffer space available to encode the frame. 97*cfb92d14SAndroid Build Coastguard Worker * @retval OT_ERROR_FAILED Failed to call the SPI driver to send the frame. 98*cfb92d14SAndroid Build Coastguard Worker * 99*cfb92d14SAndroid Build Coastguard Worker */ 100*cfb92d14SAndroid Build Coastguard Worker virtual otError SendFrame(const uint8_t *aFrame, uint16_t aLength) = 0; 101*cfb92d14SAndroid Build Coastguard Worker 102*cfb92d14SAndroid Build Coastguard Worker /** 103*cfb92d14SAndroid Build Coastguard Worker * Waits for receiving part or all of spinel frame within specified interval. 104*cfb92d14SAndroid Build Coastguard Worker * 105*cfb92d14SAndroid Build Coastguard Worker * @param[in] aTimeout The timeout value in microseconds. 106*cfb92d14SAndroid Build Coastguard Worker * 107*cfb92d14SAndroid Build Coastguard Worker * @retval OT_ERROR_NONE Part or all of spinel frame is received. 108*cfb92d14SAndroid Build Coastguard Worker * @retval OT_ERROR_RESPONSE_TIMEOUT No spinel frame is received within @p aTimeout. 109*cfb92d14SAndroid Build Coastguard Worker * 110*cfb92d14SAndroid Build Coastguard Worker */ 111*cfb92d14SAndroid Build Coastguard Worker virtual otError WaitForFrame(uint64_t aTimeoutUs) = 0; 112*cfb92d14SAndroid Build Coastguard Worker 113*cfb92d14SAndroid Build Coastguard Worker /** 114*cfb92d14SAndroid Build Coastguard Worker * Updates the file descriptor sets with file descriptors used by the radio driver. 115*cfb92d14SAndroid Build Coastguard Worker * 116*cfb92d14SAndroid Build Coastguard Worker * @param[in,out] aMainloopContext A pointer to the mainloop context. 117*cfb92d14SAndroid Build Coastguard Worker * 118*cfb92d14SAndroid Build Coastguard Worker */ 119*cfb92d14SAndroid Build Coastguard Worker virtual void UpdateFdSet(void *aMainloopContext) = 0; 120*cfb92d14SAndroid Build Coastguard Worker 121*cfb92d14SAndroid Build Coastguard Worker /** 122*cfb92d14SAndroid Build Coastguard Worker * Performs radio driver processing. 123*cfb92d14SAndroid Build Coastguard Worker * 124*cfb92d14SAndroid Build Coastguard Worker * @param[in] aMainloopContext A pointer to the mainloop context. 125*cfb92d14SAndroid Build Coastguard Worker * 126*cfb92d14SAndroid Build Coastguard Worker */ 127*cfb92d14SAndroid Build Coastguard Worker virtual void Process(const void *aMainloopContext) = 0; 128*cfb92d14SAndroid Build Coastguard Worker 129*cfb92d14SAndroid Build Coastguard Worker /** 130*cfb92d14SAndroid Build Coastguard Worker * Returns the bus speed between the host and the radio. 131*cfb92d14SAndroid Build Coastguard Worker * 132*cfb92d14SAndroid Build Coastguard Worker * @returns Bus speed in bits/second. 133*cfb92d14SAndroid Build Coastguard Worker * 134*cfb92d14SAndroid Build Coastguard Worker */ 135*cfb92d14SAndroid Build Coastguard Worker virtual uint32_t GetBusSpeed(void) const = 0; 136*cfb92d14SAndroid Build Coastguard Worker 137*cfb92d14SAndroid Build Coastguard Worker /** 138*cfb92d14SAndroid Build Coastguard Worker * Hardware resets the RCP. 139*cfb92d14SAndroid Build Coastguard Worker * 140*cfb92d14SAndroid Build Coastguard Worker * @retval OT_ERROR_NONE Successfully reset the RCP. 141*cfb92d14SAndroid Build Coastguard Worker * @retval OT_ERROR_NOT_IMPLEMENT The hardware reset is not implemented. 142*cfb92d14SAndroid Build Coastguard Worker * 143*cfb92d14SAndroid Build Coastguard Worker */ 144*cfb92d14SAndroid Build Coastguard Worker virtual otError HardwareReset(void) = 0; 145*cfb92d14SAndroid Build Coastguard Worker 146*cfb92d14SAndroid Build Coastguard Worker /** 147*cfb92d14SAndroid Build Coastguard Worker * Returns the RCP interface metrics. 148*cfb92d14SAndroid Build Coastguard Worker * 149*cfb92d14SAndroid Build Coastguard Worker * @returns The RCP interface metrics. 150*cfb92d14SAndroid Build Coastguard Worker * 151*cfb92d14SAndroid Build Coastguard Worker */ 152*cfb92d14SAndroid Build Coastguard Worker virtual const otRcpInterfaceMetrics *GetRcpInterfaceMetrics(void) const = 0; 153*cfb92d14SAndroid Build Coastguard Worker 154*cfb92d14SAndroid Build Coastguard Worker /** 155*cfb92d14SAndroid Build Coastguard Worker * Marks destructor virtual method. 156*cfb92d14SAndroid Build Coastguard Worker * 157*cfb92d14SAndroid Build Coastguard Worker */ 158*cfb92d14SAndroid Build Coastguard Worker virtual ~SpinelInterface() = default; 159*cfb92d14SAndroid Build Coastguard Worker 160*cfb92d14SAndroid Build Coastguard Worker protected: 161*cfb92d14SAndroid Build Coastguard Worker enum : uint8_t 162*cfb92d14SAndroid Build Coastguard Worker { 163*cfb92d14SAndroid Build Coastguard Worker kSpinelInterfaceTypeHdlc = 1, ///< The type of Spinel HDLC interface. 164*cfb92d14SAndroid Build Coastguard Worker kSpinelInterfaceTypeSpi = 2, ///< The type of Spinel SPI interface. 165*cfb92d14SAndroid Build Coastguard Worker kSpinelInterfaceTypeVendor = 3, ///< The type of Spinel Vendor interface. 166*cfb92d14SAndroid Build Coastguard Worker }; 167*cfb92d14SAndroid Build Coastguard Worker 168*cfb92d14SAndroid Build Coastguard Worker /** 169*cfb92d14SAndroid Build Coastguard Worker * Indicates whether or not the frame is the Spinel SPINEL_CMD_RESET frame. 170*cfb92d14SAndroid Build Coastguard Worker * 171*cfb92d14SAndroid Build Coastguard Worker * @param[in] aFrame A pointer to buffer containing the spinel frame. 172*cfb92d14SAndroid Build Coastguard Worker * @param[in] aLength The length (number of bytes) in the frame. 173*cfb92d14SAndroid Build Coastguard Worker * 174*cfb92d14SAndroid Build Coastguard Worker * @retval true If the frame is a Spinel SPINEL_CMD_RESET frame. 175*cfb92d14SAndroid Build Coastguard Worker * @retval false If the frame is not a Spinel SPINEL_CMD_RESET frame. 176*cfb92d14SAndroid Build Coastguard Worker * 177*cfb92d14SAndroid Build Coastguard Worker */ IsSpinelResetCommand(const uint8_t * aFrame,uint16_t aLength)178*cfb92d14SAndroid Build Coastguard Worker bool IsSpinelResetCommand(const uint8_t *aFrame, uint16_t aLength) 179*cfb92d14SAndroid Build Coastguard Worker { 180*cfb92d14SAndroid Build Coastguard Worker const uint8_t kSpinelResetCommandLength = 2; 181*cfb92d14SAndroid Build Coastguard Worker bool resetCmd = false; 182*cfb92d14SAndroid Build Coastguard Worker 183*cfb92d14SAndroid Build Coastguard Worker if (aLength >= kSpinelResetCommandLength) 184*cfb92d14SAndroid Build Coastguard Worker { 185*cfb92d14SAndroid Build Coastguard Worker #ifndef OPENTHREAD_CONFIG_MULTIPAN_RCP_ENABLE 186*cfb92d14SAndroid Build Coastguard Worker // Validate the iid. 187*cfb92d14SAndroid Build Coastguard Worker if (!((aFrame[0] & SPINEL_HEADER_IID_MASK) == SPINEL_HEADER_IID_0)) 188*cfb92d14SAndroid Build Coastguard Worker { 189*cfb92d14SAndroid Build Coastguard Worker goto exit; 190*cfb92d14SAndroid Build Coastguard Worker } 191*cfb92d14SAndroid Build Coastguard Worker #endif 192*cfb92d14SAndroid Build Coastguard Worker 193*cfb92d14SAndroid Build Coastguard Worker // Validate the header flag by masking out the iid bits as it is validated above. 194*cfb92d14SAndroid Build Coastguard Worker if (!((aFrame[0] & ~SPINEL_HEADER_IID_MASK) == SPINEL_HEADER_FLAG)) 195*cfb92d14SAndroid Build Coastguard Worker { 196*cfb92d14SAndroid Build Coastguard Worker goto exit; 197*cfb92d14SAndroid Build Coastguard Worker } 198*cfb92d14SAndroid Build Coastguard Worker 199*cfb92d14SAndroid Build Coastguard Worker // Validate the reset command. 200*cfb92d14SAndroid Build Coastguard Worker if (!(aFrame[1] == SPINEL_CMD_RESET)) 201*cfb92d14SAndroid Build Coastguard Worker { 202*cfb92d14SAndroid Build Coastguard Worker goto exit; 203*cfb92d14SAndroid Build Coastguard Worker } 204*cfb92d14SAndroid Build Coastguard Worker 205*cfb92d14SAndroid Build Coastguard Worker resetCmd = true; 206*cfb92d14SAndroid Build Coastguard Worker } 207*cfb92d14SAndroid Build Coastguard Worker 208*cfb92d14SAndroid Build Coastguard Worker exit: 209*cfb92d14SAndroid Build Coastguard Worker return resetCmd; 210*cfb92d14SAndroid Build Coastguard Worker } 211*cfb92d14SAndroid Build Coastguard Worker }; 212*cfb92d14SAndroid Build Coastguard Worker 213*cfb92d14SAndroid Build Coastguard Worker } // namespace Spinel 214*cfb92d14SAndroid Build Coastguard Worker } // namespace ot 215*cfb92d14SAndroid Build Coastguard Worker 216*cfb92d14SAndroid Build Coastguard Worker #endif // SPINEL_SPINEL_INTERFACE_HPP_ 217