1 /* 2 * Copyright (c) 2023 Nordic Semiconductor ASA 3 * 4 * SPDX-License-Identifier: Apache-2.0 5 */ 6 7 #ifndef ZEPHYR_INCLUDE_IPC_ICMSG_ME_H_ 8 #define ZEPHYR_INCLUDE_IPC_ICMSG_ME_H_ 9 10 #include <stdint.h> 11 #include <zephyr/kernel.h> 12 #include <zephyr/ipc/icmsg.h> 13 #include <zephyr/ipc/ipc_service.h> 14 15 #ifdef __cplusplus 16 extern "C" { 17 #endif 18 19 /** 20 * @brief Multi-endpoint extension of icmsg IPC library 21 * @defgroup ipc_icmsg_me_api Icmsg multi-endpoint IPC library API 22 * @ingroup ipc 23 * @{ 24 */ 25 26 27 /* If more bytes than 1 was used for endpoint id, endianness should be 28 * considered. 29 */ 30 typedef uint8_t icmsg_me_ept_id_t; 31 32 struct icmsg_me_data_t { 33 struct icmsg_data_t icmsg_data; 34 struct ipc_ept_cfg ept_cfg; 35 36 struct k_event event; 37 38 struct k_mutex send_mutex; 39 const struct ipc_ept_cfg *epts[CONFIG_IPC_SERVICE_BACKEND_ICMSG_ME_NUM_EP]; 40 41 uint8_t send_buffer[CONFIG_IPC_SERVICE_BACKEND_ICMSG_ME_SEND_BUF_SIZE] __aligned(4); 42 }; 43 44 45 /** @brief Initialize an icmsg_me instance 46 * 47 * This function is intended to be called during system initialization. 48 * It initializes the underlying icmsg instace as one of the initialization 49 * steps. 50 * 51 * @param[in] conf Structure containing configuration parameters for the 52 * underlying icmsg instance being created. 53 * @param[inout] data Structure containing run-time data used by the icmsg_me 54 * instance. The structure shall be filled with zeros 55 * when calling this function. The content of this 56 * structure must be preserved while the icmsg_me instance 57 * is active. 58 * 59 * @retval 0 on success. 60 * @retval other errno codes from dependent modules. 61 */ 62 int icmsg_me_init(const struct icmsg_config_t *conf, 63 struct icmsg_me_data_t *data); 64 65 /** @brief Open an icmsg_me instance 66 * 67 * Open an icmsg_me instance to be able to send and receive messages to a 68 * remote instance. 69 * This function is blocking until the handshake with the remote instance is 70 * completed. 71 * This function is intended to be called late in the initialization process, 72 * possibly from a thread which can be safely blocked while handshake with the 73 * remote instance is being pefromed. 74 * 75 * @param[in] conf Structure containing configuration parameters for the 76 * underlying icmsg instance. 77 * @param[inout] data Structure containing run-time data used by the icmsg_me 78 * instance. The structure is initialized with 79 * @ref icmsg_me_init and its content must be preserved 80 * while the icmsg_me instance is active. 81 * @param[in] cb Structure containing callback functions to be called on 82 * events generated by this icmsg_me instance. The pointed memory 83 * must be preserved while the icmsg_me instance is active. 84 * @param[in] ctx Pointer to context passed as an argument to callbacks. 85 * 86 * 87 * @retval 0 on success. 88 * @retval other errno codes from dependent modules. 89 */ 90 int icmsg_me_open(const struct icmsg_config_t *conf, 91 struct icmsg_me_data_t *data, 92 const struct ipc_service_cb *cb, 93 void *ctx); 94 95 /** @brief Wait until the underlying icmsg instance calls bound callback 96 * 97 * This function blocks calling thread until the underlying icmsg connection 98 * is bound. If the connection was bound before this function is called, the 99 * function ends immediately without any delay. 100 * 101 * This function is intended to be used in the endpoints handshake procedure 102 * to make sure that handshake is not performed until the icmsg channel is 103 * ready to pass handshake messages. 104 * 105 * @param[inout] data Structure containing run-time data used by the icmsg_me 106 * instance. The structure is initialized with 107 * @ref icmsg_me_init and its content must be preserved 108 * while the icmsg_me instance is active. 109 */ 110 void icmsg_me_wait_for_icmsg_bind(struct icmsg_me_data_t *data); 111 112 /** @brief Notify the icmsg_me instance that the underlying icmsg was bound 113 * 114 * The icmsg_me API users are responsible to implement the callback functions 115 * called by the underlying icmsg instance. One of the actions of the bound 116 * callback must be calling this function. 117 * 118 * @param[inout] data Structure containing run-time data used by the icmsg_me 119 * instance. The structure is initialized with 120 * @ref icmsg_me_init and its content must be preserved 121 * while the icmsg_me instance is active. 122 */ 123 void icmsg_me_icmsg_bound(struct icmsg_me_data_t *data); 124 125 /** @brief Notify the icmsg_me instance that data for an endpoint was received 126 * 127 * The icmsg_me API users are responsible to implement the callback functions 128 * called by the underlying icmsg instance. If the data received by the icmsg 129 * instance contains data frame destined to one of the endpoints, this 130 * function must be called. 131 * 132 * @param[inout] data Structure containing run-time data used by the icmsg_me 133 * instance. The structure is initialized with 134 * @ref icmsg_me_init and its content must be preserved 135 * while the icmsg_me instance is active. 136 * @param[in] id The value identifyig the endpoint. 137 * @param[in] msg Data frame received from the peer, stripped of the 138 * multi-endpoint header. 139 * @param[in] len Size of the data pointed by @p msg. 140 */ 141 void icmsg_me_received_data(struct icmsg_me_data_t *data, icmsg_me_ept_id_t id, 142 const void *msg, size_t len); 143 144 /** @brief Set endpoint configuration in an empty endpoint slot 145 * 146 * During endpoint handshake the handshake initiator must select an id number 147 * and store endpoint metadata required to finalize handshake and maintain 148 * the connection. This function is a helper which stores the configuration 149 * in an empty configuration slot and provides the unique id value associated 150 * with the selected slot. 151 * 152 * @note This function is not reentrant for a single icmsg_me instance. 153 * It must be protected by the caller using mutex, critical section, 154 * spinlock, or similar solution. 155 * This function is reentrant for different icmsg_me instances. The 156 * protection scope might be limited to a single instance. 157 * 158 * @param[inout] data Structure containing run-time data used by the icmsg_me 159 * instance. The structure is initialized with 160 * @ref icmsg_me_init and its content must be preserved 161 * while the icmsg_me instance is active. 162 * @param[in] ept_cfg Configuration data of the endpoint for which the 163 * handshake procedure is being initiated. 164 * @param[out] id The value uniquely identifyig this endpoint. 165 * 166 * @retval 0 on success. 167 * @retval -ENOMEM when there are no more empty endpoint configuration slots. 168 */ 169 int icmsg_me_set_empty_ept_cfg_slot(struct icmsg_me_data_t *data, 170 const struct ipc_ept_cfg *ept_cfg, 171 icmsg_me_ept_id_t *id); 172 173 /** @brief Set endpoint configuration in a selected endpoint slot 174 * 175 * During endpoint handshake the handshake follower must store endpoint id and 176 * metadata required to finalize handshake and maintain the connection. This 177 * function is a helper which stores the configuration in a configuration slot 178 * associated with the id of the endpoint. 179 * 180 * @param[inout] data Structure containing run-time data used by the icmsg_me 181 * instance. The structure is initialized with 182 * @ref icmsg_me_init and its content must be preserved 183 * while the icmsg_me instance is active. 184 * @param[in] id The value uniquely identifyig this endpoint. 185 * @param[in] ept_cfg Configuration data of the endpoint for which the 186 * handshake procedure is ongoing. 187 * 188 * @retval 0 on success. 189 * @retval -ENOENT when @p id is out of range of available slots. 190 */ 191 int icmsg_me_set_ept_cfg(struct icmsg_me_data_t *data, icmsg_me_ept_id_t id, 192 const struct ipc_ept_cfg *ept_cfg); 193 194 /** @brief Get endpoint configuration from a selected endpoint slot 195 * 196 * When the icmsg_me instance receives data from a remote endpoint, it must 197 * get the endpoint configuration based on the id of the endpoint. This 198 * function is designed for this purpose. 199 * 200 * If retrieved endpoint configuration is not set, @p ept_cfg points to NULL. 201 * 202 * @param[inout] data Structure containing run-time data used by the icmsg_me 203 * instance. The structure is initialized with 204 * @ref icmsg_me_init and its content must be preserved 205 * while the icmsg_me instance is active. 206 * @param[in] id The value uniquely identifyig endpoint. 207 * @param[in] ept_cfg Configuration data of the endpoint with given id. 208 * 209 * @retval 0 on success. 210 * @retval -ENOENT when @p id is out of range of available slots. 211 */ 212 int icmsg_me_get_ept_cfg(struct icmsg_me_data_t *data, icmsg_me_ept_id_t id, 213 const struct ipc_ept_cfg **ept_cfg); 214 215 /** @brief Reset endpoint configuration in a selected endpoint slot. 216 * 217 * If handshake fails or an endpoint is disconnected, then configuration 218 * slot for given endpoint should be vacated. This function is intended to 219 * be used for this purpose. 220 * 221 * @param[inout] data Structure containing run-time data used by the icmsg_me 222 * instance. The structure is initialized with 223 * @ref icmsg_me_init and its content must be preserved 224 * while the icmsg_me instance is active. 225 * @param[in] id The value uniquely identifyig endpoint. 226 */ 227 void icmsg_me_reset_ept_cfg(struct icmsg_me_data_t *data, icmsg_me_ept_id_t id); 228 229 /** @brief Send a message to the remote icmsg_me endpoint. 230 * 231 * @param[in] conf Structure containing configuration parameters for the 232 * underlying icmsg instance. 233 * @param[inout] data Structure containing run-time data used by the icmsg_me 234 * instance. The structure is initialized with 235 * @ref icmsg_me_init and its content must be preserved 236 * while the icmsg_me instance is active. 237 * @param[in] id Id of the endpoint to use. 238 * @param[in] msg Pointer to a buffer containing data to send. 239 * @param[in] len Size of data in the @p msg buffer. 240 * 241 * 242 * @retval 0 on success. 243 * @retval -EBADMSG when the requested data to send is too big. 244 * @retval other errno codes from dependent modules. 245 */ 246 int icmsg_me_send(const struct icmsg_config_t *conf, 247 struct icmsg_me_data_t *data, icmsg_me_ept_id_t id, 248 const void *msg, size_t len); 249 250 /** @brief Get an empty TX buffer to be sent using @ref icmsg_me_send_nocopy 251 * 252 * This function is a wrapper around @ref icmsg_get_tx_buffer aligning buffer 253 * size and pointers to fit header required by the multi-endpoint feature. 254 * It shares all properites and usage scenarios with @ref icmsg_get_tx_buffer. 255 * 256 * @param[in] conf Structure containing configuration parameters for the 257 & underlying icmsg instance. 258 * @param[inout] data Structure containing run-time data used by the icmsg_me 259 * instance. The structure is initialized with 260 * @ref icmsg_me_init and its content must be preserved 261 * while the icmsg_me instance is active. 262 * @param[out] buffer Pointer to the empty TX buffer. 263 * @param[inout] size Pointer to store the requested TX buffer size. If the 264 * function returns -ENOMEM, this parameter returns the 265 * maximum allowed size. 266 * @param[in] wait Timeout value to wait for a free buffer acceptable by 267 * the function caller. Only K_NO_WAIT is supported by icmsg. 268 * 269 * @retval 0 on success. 270 * @retval -ENOTSUP when requested unsupported @p wait timeout. 271 * @retval -ENOBUFS when there are no TX buffers available. 272 * @retval -ENOMEM when the requested size is too big (and the size parameter 273 * contains the maximum allowed size). 274 * @retval other errno codes from dependent modules. 275 */ 276 int icmsg_me_get_tx_buffer(const struct icmsg_config_t *conf, 277 struct icmsg_me_data_t *data, 278 void **buffer, uint32_t *size, k_timeout_t wait); 279 280 /** @brief Drop and release a TX buffer 281 * 282 * This function is a wrapper around @ref icmsg_drop_tx_buffer aligning buffer 283 * pointer to fit header required by the multi-endpoint feature. This function 284 * shares all properties and usage scenarios with @ref icmsg_drop_tx_buffer. 285 * 286 * @param[in] conf Structure containing configuration parameters for the 287 * underlying icmsg instance. 288 * @param[inout] data Structure containing run-time data used by the icmsg_me 289 * instance. The structure is initialized with 290 * @ref icmsg_me_init and its content must be preserved 291 * while the icmsg_me instance is active. 292 * @param[in] buffer Pointer to the TX buffer obtained with 293 * @ref icmsg_me_get_tx_buffer. 294 * 295 * @retval 0 on success. 296 * @retval other errno codes from dependent modules. 297 */ 298 int icmsg_me_drop_tx_buffer(const struct icmsg_config_t *conf, 299 struct icmsg_me_data_t *data, 300 const void *buffer); 301 302 /** @brief Send a message from a buffer obtained by @ref icmsg_me_get_tx_buffer 303 * to the remote icmsg_me instance. 304 * 305 * This function is a wrapper around @ref icmsg_send_nocopy aligning buffer 306 * size and pointer to fit header required by the multi-endpoint feature. This 307 * function shares all properties and usage scenarios with 308 * @ref icmsg_send_nocopy. 309 * 310 * @param[in] conf Structure containing configuration parameters for the 311 * underlying icmsg instance. 312 * @param[inout] data Structure containing run-time data used by the icmsg_me 313 * instance. The structure is initialized with 314 * @ref icmsg_me_init and its content must be preserved 315 * while the icmsg_me instance is active. 316 * @param[in] id Id of the endpoint to use. 317 * @param[in] msg Pointer to a buffer containing data to send. 318 * @param[in] len Size of data in the @p msg buffer. 319 * 320 * 321 * @return Size of sent data on success. 322 * @retval other errno codes from dependent modules. 323 */ 324 int icmsg_me_send_nocopy(const struct icmsg_config_t *conf, 325 struct icmsg_me_data_t *data, icmsg_me_ept_id_t id, 326 const void *msg, size_t len); 327 328 #ifdef CONFIG_IPC_SERVICE_ICMSG_ME_NOCOPY_RX 329 /** @brief Hold RX buffer to be used outside of the received callback. 330 * 331 * @param[in] conf Structure containing configuration parameters for the 332 * underlying icmsg instance. 333 * @param[inout] data Structure containing run-time data used by the icmsg_me 334 * instance. The structure is initialized with 335 * @ref icmsg_me_init and its content must be preserved 336 * while the icmsg_me instance is active. 337 * @param[in] buffer Pointer to the buffer to be held. 338 * 339 * @retval 0 on success. 340 * @retval other errno codes from dependent modules. 341 */ 342 int icmsg_me_hold_rx_buffer(const struct icmsg_config_t *conf, 343 struct icmsg_me_data_t *data, void *buffer); 344 345 /** @brief Release RX buffer for future use. 346 * 347 * @param[in] conf Structure containing configuration parameters for the 348 * underlying icmsg instance. 349 * @param[inout] data Structure containing run-time data used by the icmsg_me 350 * instance. The structure is initialized with 351 * @ref icmsg_me_init and its content must be preserved 352 * while the icmsg_me instance is active. 353 * @param[in] buffer Pointer to the buffer to be released. 354 * 355 * @retval 0 on success. 356 * @retval other errno codes from dependent modules. 357 */ 358 int icmsg_me_release_rx_buffer(const struct icmsg_config_t *conf, 359 struct icmsg_me_data_t *data, void *buffer); 360 #endif /* CONFIG_IPC_SERVICE_ICMSG_ME_NOCOPY_RX */ 361 362 /** 363 * @} 364 */ 365 366 #ifdef __cplusplus 367 } 368 #endif 369 370 #endif /* ZEPHYR_INCLUDE_IPC_ICMSG_ME_H_ */ 371