esp-idf/components/openthread/private_include/esp_spi_spinel_interface.hpp

188 wiersze
5.5 KiB
C++

/*
* SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#pragma once
#include "esp_err.h"
#include "esp_openthread_types.h"
#include "driver/spi_master.h"
#include "lib/spinel/spinel_interface.hpp"
namespace esp {
namespace openthread {
class SpiSpinelInterface : public ot::Spinel::SpinelInterface {
public:
/**
* @brief This constructor of object.
*/
SpiSpinelInterface();
/**
* @brief This destructor of the object.
*
*/
~SpiSpinelInterface(void);
/**
* 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] aCallback Callback on frame received
* @param[in] aCallbackContext Callback context
* @param[in] aFrameBuffer A reference to a `RxFrameBuffer` object.
*
* @retval OT_ERROR_NONE The interface is initialized successfully
* @retval OT_ERROR_ALREADY The interface is already initialized.
* @retval OT_ERROR_FAILED Failed to initialize the interface.
*
*/
otError Init(ReceiveFrameCallback aCallback, void *aCallbackContext, RxFrameBuffer &aFrameBuffer);
/**
* Deinitializes the interface to the RCP.
*
*/
void Deinit(void);
/**
* @brief This method encodes and sends a spinel frame to Radio Co-processor (RCP) over the socket.
*
* @param[in] frame A pointer to buffer containing the spinel frame to send.
* @param[in] length The length (number of bytes) in the frame.
*
* @return
* -OT_ERROR_NONE Successfully encoded and sent the spinel frame.
* -OT_ERROR_NO_BUFS Insufficient buffer space available to encode the frame.
* -OT_ERROR_FAILED Failed to send due to socket not becoming writable within `kMaxWaitTime`.
*
*/
otError SendFrame(const uint8_t *frame, uint16_t length);
/**
* This method waits for receiving part or all of spinel frame within specified timeout.
*
* @param[in] timeout_us The timeout value in microseconds.
*
* @return
* -OT_ERROR_NONE Part or all of spinel frame is received.
* -OT_ERROR_RESPONSE_TIMEOUT No spinel frame is received within @p timeout_us.
*
*/
otError WaitForFrame(uint64_t timeout_us);
/**
* Updates the file descriptor sets with file descriptors used by the radio driver.
*
* @param[in,out] aMainloopContext A pointer to the mainloop context.
*
*/
void UpdateFdSet(void *aMainloopContext);
/**
* Performs radio driver processing.
*
* @param[in] aMainloopContext A pointer to the mainloop context.
*
*/
void Process(const void *aMainloopContext);
/**
* 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.
*
*/
otError HardwareReset(void);
/**
* Returns the RCP interface metrics.
*
* @returns The RCP interface metrics.
*
*/
const otRcpInterfaceMetrics *GetRcpInterfaceMetrics(void) const { return &mInterfaceMetrics; }
/**
* This methods registers the callback for RCP failure.
*
* @param[in] handler The RCP failure handler.
*
*/
void RegisterRcpFailureHandler(esp_openthread_rcp_failure_handler handler) { mRcpFailureHandler = handler; }
/**
* This method is called when RCP is reset to recreate the connection with it.
* Intentionally empty.
*
*/
otError ResetConnection(void) { return OT_ERROR_NONE; }
/**
* @brief This method enable the spinel interface.
*
* @return
* - ESP_OK on success
* - ESP_ERR_INVALID_STATE if already initialized
* - ESP_ERR_NO_MEM if allocation has failed
* - ESP_FAIL on failure
*/
esp_err_t Enable(const esp_openthread_spi_host_config_t &spi_config);
/**
* @brief This method disable the spinel interface.
*
* @return
* - ESP_OK on success
* - ESP_FAIL on failure
*/
esp_err_t Disable(void);
/**
* @brief This method should be called after radio is initialized.
*
* @return
* - ESP_OK on success
* - ESP_FAIL on failure
*/
esp_err_t AfterRadioInit(void);
private:
static constexpr uint8_t kSPIFrameHeaderSize = 5;
static constexpr uint16_t kSPIFrameSize = ot::Spinel::SpinelInterface::kMaxFrameSize + kSPIFrameHeaderSize;
static constexpr uint8_t kSmallPacketSize = 32;
static constexpr uint16_t kSPIDataEvent = 1;
static void GpioIntrHandler(void *arg);
esp_err_t ConductSPITransaction(bool reset, uint16_t tx_data_size, uint16_t rx_data_size);
esp_openthread_spi_host_config_t m_spi_config;
uint8_t m_tx_buffer[kSPIFrameSize];
int m_event_fd;
volatile uint16_t m_pending_data_len;
ReceiveFrameCallback m_receiver_frame_callback;
void *m_receiver_frame_context;
RxFrameBuffer *m_receive_frame_buffer;
bool m_has_pending_device_frame;
spi_device_handle_t m_device;
esp_openthread_rcp_failure_handler mRcpFailureHandler;
otRcpInterfaceMetrics mInterfaceMetrics;
};
} // namespace openthread
} // namespace esp