blob: 554f5785ba837d47c51398bb6c56fc2a1ef70b57 [file] [log] [blame]
/*
* Copyright (c) 2023 Nordic Semiconductor ASA
*
* SPDX-License-Identifier: Apache-2.0
*/
#ifndef ZEPHYR_INCLUDE_IPC_ICMSG_ME_H_
#define ZEPHYR_INCLUDE_IPC_ICMSG_ME_H_
#include <stdint.h>
#include <zephyr/kernel.h>
#include <zephyr/ipc/icmsg.h>
#include <zephyr/ipc/ipc_service.h>
#ifdef __cplusplus
extern "C" {
#endif
/**
* @brief Multi-endpoint extension of icmsg IPC library
* @defgroup ipc_icmsg_me_api Icmsg multi-endpoint IPC library API
* @ingroup ipc
* @{
*/
/* If more bytes than 1 was used for endpoint id, endianness should be
* considered.
*/
typedef uint8_t icmsg_me_ept_id_t;
struct icmsg_me_data_t {
struct icmsg_data_t icmsg_data;
struct ipc_ept_cfg ept_cfg;
struct k_event event;
struct k_mutex send_mutex;
const struct ipc_ept_cfg *epts[CONFIG_IPC_SERVICE_BACKEND_ICMSG_ME_NUM_EP];
uint8_t send_buffer[CONFIG_IPC_SERVICE_BACKEND_ICMSG_ME_SEND_BUF_SIZE] __aligned(4);
};
/** @brief Initialize an icmsg_me instance
*
* This function is intended to be called during system initialization.
* It initializes the underlying icmsg instace as one of the initialization
* steps.
*
* @param[in] conf Structure containing configuration parameters for the
* underlying icmsg instance being created.
* @param[inout] data Structure containing run-time data used by the icmsg_me
* instance. The structure shall be filled with zeros
* when calling this function. The content of this
* structure must be preserved while the icmsg_me instance
* is active.
*
* @retval 0 on success.
* @retval other errno codes from dependent modules.
*/
int icmsg_me_init(const struct icmsg_config_t *conf,
struct icmsg_me_data_t *data);
/** @brief Open an icmsg_me instance
*
* Open an icmsg_me instance to be able to send and receive messages to a
* remote instance.
* This function is blocking until the handshake with the remote instance is
* completed.
* This function is intended to be called late in the initialization process,
* possibly from a thread which can be safely blocked while handshake with the
* remote instance is being pefromed.
*
* @param[in] conf Structure containing configuration parameters for the
* underlying icmsg instance.
* @param[inout] data Structure containing run-time data used by the icmsg_me
* instance. The structure is initialized with
* @ref icmsg_me_init and its content must be preserved
* while the icmsg_me instance is active.
* @param[in] cb Structure containing callback functions to be called on
* events generated by this icmsg_me instance. The pointed memory
* must be preserved while the icmsg_me instance is active.
* @param[in] ctx Pointer to context passed as an argument to callbacks.
*
*
* @retval 0 on success.
* @retval other errno codes from dependent modules.
*/
int icmsg_me_open(const struct icmsg_config_t *conf,
struct icmsg_me_data_t *data,
const struct ipc_service_cb *cb,
void *ctx);
/** @brief Wait until the underlying icmsg instance calls bound callback
*
* This function blocks calling thread until the underlying icmsg connection
* is bound. If the connection was bound before this function is called, the
* function ends immediately without any delay.
*
* This function is intended to be used in the endpoints handshake procedure
* to make sure that handshake is not performed until the icmsg channel is
* ready to pass handshake messages.
*
* @param[inout] data Structure containing run-time data used by the icmsg_me
* instance. The structure is initialized with
* @ref icmsg_me_init and its content must be preserved
* while the icmsg_me instance is active.
*/
void icmsg_me_wait_for_icmsg_bind(struct icmsg_me_data_t *data);
/** @brief Notify the icmsg_me instance that the underlying icmsg was bound
*
* The icmsg_me API users are responsible to implement the callback functions
* called by the underlying icmsg instance. One of the actions of the bound
* callback must be calling this function.
*
* @param[inout] data Structure containing run-time data used by the icmsg_me
* instance. The structure is initialized with
* @ref icmsg_me_init and its content must be preserved
* while the icmsg_me instance is active.
*/
void icmsg_me_icmsg_bound(struct icmsg_me_data_t *data);
/** @brief Notify the icmsg_me instance that data for an endpoint was received
*
* The icmsg_me API users are responsible to implement the callback functions
* called by the underlying icmsg instance. If the data received by the icmsg
* instance contains data frame destined to one of the endpoints, this
* function must be called.
*
* @param[inout] data Structure containing run-time data used by the icmsg_me
* instance. The structure is initialized with
* @ref icmsg_me_init and its content must be preserved
* while the icmsg_me instance is active.
* @param[in] id The value identifyig the endpoint.
* @param[in] msg Data frame received from the peer, stripped of the
* multi-endpoint header.
* @param[in] len Size of the data pointed by @p msg.
*/
void icmsg_me_received_data(struct icmsg_me_data_t *data, icmsg_me_ept_id_t id,
const void *msg, size_t len);
/** @brief Set endpoint configuration in an empty endpoint slot
*
* During endpoint handshake the handshake initiator must select an id number
* and store endpoint metadata required to finalize handshake and maintain
* the connection. This function is a helper which stores the configuration
* in an empty configuration slot and provides the unique id value associated
* with the selected slot.
*
* @note This function is not reentrant for a single icmsg_me instance.
* It must be protected by the caller using mutex, critical section,
* spinlock, or similar solution.
* This function is reentrant for different icmsg_me instances. The
* protection scope might be limited to a single instance.
*
* @param[inout] data Structure containing run-time data used by the icmsg_me
* instance. The structure is initialized with
* @ref icmsg_me_init and its content must be preserved
* while the icmsg_me instance is active.
* @param[in] ept_cfg Configuration data of the endpoint for which the
* handshake procedure is being initiated.
* @param[out] id The value uniquely identifyig this endpoint.
*
* @retval 0 on success.
* @retval -ENOMEM when there are no more empty endpoint configuration slots.
*/
int icmsg_me_set_empty_ept_cfg_slot(struct icmsg_me_data_t *data,
const struct ipc_ept_cfg *ept_cfg,
icmsg_me_ept_id_t *id);
/** @brief Set endpoint configuration in a selected endpoint slot
*
* During endpoint handshake the handshake follower must store endpoint id and
* metadata required to finalize handshake and maintain the connection. This
* function is a helper which stores the configuration in a configuration slot
* associated with the id of the endpoint.
*
* @param[inout] data Structure containing run-time data used by the icmsg_me
* instance. The structure is initialized with
* @ref icmsg_me_init and its content must be preserved
* while the icmsg_me instance is active.
* @param[in] id The value uniquely identifyig this endpoint.
* @param[in] ept_cfg Configuration data of the endpoint for which the
* handshake procedure is ongoing.
*
* @retval 0 on success.
* @retval -ENOENT when @p id is out of range of available slots.
*/
int icmsg_me_set_ept_cfg(struct icmsg_me_data_t *data, icmsg_me_ept_id_t id,
const struct ipc_ept_cfg *ept_cfg);
/** @brief Get endpoint configuration from a selected endpoint slot
*
* When the icmsg_me instance receives data from a remote endpoint, it must
* get the endpoint configuration based on the id of the endpoint. This
* function is designed for this purpose.
*
* If retrieved endpoint configuration is not set, @p ept_cfg points to NULL.
*
* @param[inout] data Structure containing run-time data used by the icmsg_me
* instance. The structure is initialized with
* @ref icmsg_me_init and its content must be preserved
* while the icmsg_me instance is active.
* @param[in] id The value uniquely identifyig endpoint.
* @param[in] ept_cfg Configuration data of the endpoint with given id.
*
* @retval 0 on success.
* @retval -ENOENT when @p id is out of range of available slots.
*/
int icmsg_me_get_ept_cfg(struct icmsg_me_data_t *data, icmsg_me_ept_id_t id,
const struct ipc_ept_cfg **ept_cfg);
/** @brief Reset endpoint configuration in a selected endpoint slot.
*
* If handshake fails or an endpoint is disconnected, then configuration
* slot for given endpoint should be vacated. This function is intended to
* be used for this purpose.
*
* @param[inout] data Structure containing run-time data used by the icmsg_me
* instance. The structure is initialized with
* @ref icmsg_me_init and its content must be preserved
* while the icmsg_me instance is active.
* @param[in] id The value uniquely identifyig endpoint.
*/
void icmsg_me_reset_ept_cfg(struct icmsg_me_data_t *data, icmsg_me_ept_id_t id);
/** @brief Send a message to the remote icmsg_me endpoint.
*
* @param[in] conf Structure containing configuration parameters for the
* underlying icmsg instance.
* @param[inout] data Structure containing run-time data used by the icmsg_me
* instance. The structure is initialized with
* @ref icmsg_me_init and its content must be preserved
* while the icmsg_me instance is active.
* @param[in] id Id of the endpoint to use.
* @param[in] msg Pointer to a buffer containing data to send.
* @param[in] len Size of data in the @p msg buffer.
*
*
* @retval 0 on success.
* @retval -EBADMSG when the requested data to send is too big.
* @retval other errno codes from dependent modules.
*/
int icmsg_me_send(const struct icmsg_config_t *conf,
struct icmsg_me_data_t *data, icmsg_me_ept_id_t id,
const void *msg, size_t len);
/** @brief Get an empty TX buffer to be sent using @ref icmsg_me_send_nocopy
*
* This function is a wrapper around @ref icmsg_get_tx_buffer aligning buffer
* size and pointers to fit header required by the multi-endpoint feature.
* It shares all properites and usage scenarios with @ref icmsg_get_tx_buffer.
*
* @param[in] conf Structure containing configuration parameters for the
& underlying icmsg instance.
* @param[inout] data Structure containing run-time data used by the icmsg_me
* instance. The structure is initialized with
* @ref icmsg_me_init and its content must be preserved
* while the icmsg_me instance is active.
* @param[out] buffer Pointer to the empty TX buffer.
* @param[inout] size Pointer to store the requested TX buffer size. If the
* function returns -ENOMEM, this parameter returns the
* maximum allowed size.
* @param[in] wait Timeout value to wait for a free buffer acceptable by
* the function caller. Only K_NO_WAIT is supported by icmsg.
*
* @retval 0 on success.
* @retval -ENOTSUP when requested unsupported @p wait timeout.
* @retval -ENOBUFS when there are no TX buffers available.
* @retval -ENOMEM when the requested size is too big (and the size parameter
* contains the maximum allowed size).
* @retval other errno codes from dependent modules.
*/
int icmsg_me_get_tx_buffer(const struct icmsg_config_t *conf,
struct icmsg_me_data_t *data,
void **buffer, uint32_t *size, k_timeout_t wait);
/** @brief Drop and release a TX buffer
*
* This function is a wrapper around @ref icmsg_drop_tx_buffer aligning buffer
* pointer to fit header required by the multi-endpoint feature. This function
* shares all properties and usage scenarios with @ref icmsg_drop_tx_buffer.
*
* @param[in] conf Structure containing configuration parameters for the
* underlying icmsg instance.
* @param[inout] data Structure containing run-time data used by the icmsg_me
* instance. The structure is initialized with
* @ref icmsg_me_init and its content must be preserved
* while the icmsg_me instance is active.
* @param[in] buffer Pointer to the TX buffer obtained with
* @ref icmsg_me_get_tx_buffer.
*
* @retval 0 on success.
* @retval other errno codes from dependent modules.
*/
int icmsg_me_drop_tx_buffer(const struct icmsg_config_t *conf,
struct icmsg_me_data_t *data,
const void *buffer);
/** @brief Send a message from a buffer obtained by @ref icmsg_me_get_tx_buffer
* to the remote icmsg_me instance.
*
* This function is a wrapper around @ref icmsg_send_nocopy aligning buffer
* size and pointer to fit header required by the multi-endpoint feature. This
* function shares all properties and usage scenarios with
* @ref icmsg_send_nocopy.
*
* @param[in] conf Structure containing configuration parameters for the
* underlying icmsg instance.
* @param[inout] data Structure containing run-time data used by the icmsg_me
* instance. The structure is initialized with
* @ref icmsg_me_init and its content must be preserved
* while the icmsg_me instance is active.
* @param[in] id Id of the endpoint to use.
* @param[in] msg Pointer to a buffer containing data to send.
* @param[in] len Size of data in the @p msg buffer.
*
*
* @return Size of sent data on success.
* @retval other errno codes from dependent modules.
*/
int icmsg_me_send_nocopy(const struct icmsg_config_t *conf,
struct icmsg_me_data_t *data, icmsg_me_ept_id_t id,
const void *msg, size_t len);
#ifdef CONFIG_IPC_SERVICE_ICMSG_ME_NOCOPY_RX
/** @brief Hold RX buffer to be used outside of the received callback.
*
* @param[in] conf Structure containing configuration parameters for the
* underlying icmsg instance.
* @param[inout] data Structure containing run-time data used by the icmsg_me
* instance. The structure is initialized with
* @ref icmsg_me_init and its content must be preserved
* while the icmsg_me instance is active.
* @param[in] buffer Pointer to the buffer to be held.
*
* @retval 0 on success.
* @retval other errno codes from dependent modules.
*/
int icmsg_me_hold_rx_buffer(const struct icmsg_config_t *conf,
struct icmsg_me_data_t *data, void *buffer);
/** @brief Release RX buffer for future use.
*
* @param[in] conf Structure containing configuration parameters for the
* underlying icmsg instance.
* @param[inout] data Structure containing run-time data used by the icmsg_me
* instance. The structure is initialized with
* @ref icmsg_me_init and its content must be preserved
* while the icmsg_me instance is active.
* @param[in] buffer Pointer to the buffer to be released.
*
* @retval 0 on success.
* @retval other errno codes from dependent modules.
*/
int icmsg_me_release_rx_buffer(const struct icmsg_config_t *conf,
struct icmsg_me_data_t *data, void *buffer);
#endif /* CONFIG_IPC_SERVICE_ICMSG_ME_NOCOPY_RX */
/**
* @}
*/
#ifdef __cplusplus
}
#endif
#endif /* ZEPHYR_INCLUDE_IPC_ICMSG_ME_H_ */