Line data Source code
1 0 : /* 2 : * Copyright (c) 2021 Nordic Semiconductor ASA 3 : * 4 : * SPDX-License-Identifier: Apache-2.0 5 : */ 6 : 7 : #ifndef ZEPHYR_INCLUDE_IPC_IPC_SERVICE_H_ 8 : #define ZEPHYR_INCLUDE_IPC_IPC_SERVICE_H_ 9 : 10 : #include <stdio.h> 11 : #include <zephyr/device.h> 12 : #include <zephyr/kernel.h> 13 : 14 : #ifdef __cplusplus 15 : extern "C" { 16 : #endif 17 : 18 : /** 19 : * @brief IPC 20 : * @defgroup ipc IPC 21 : * @ingroup os_services 22 : * @{ 23 : * @} 24 : */ 25 : 26 : /** 27 : * @brief IPC Service API 28 : * @defgroup ipc_service_api IPC service APIs 29 : * @ingroup ipc 30 : * @{ 31 : */ 32 : 33 : /** 34 : * @cond INTERNAL_HIDDEN 35 : * 36 : * These are for internal use only, so skip these in 37 : * public documentation. 38 : */ 39 : 40 : /** 41 : * Some terminology: 42 : * 43 : * - INSTANCE: an instance is the external representation of a physical 44 : * communication channel between two domains / CPUs. 45 : * 46 : * The actual implementation and internal representation of the 47 : * instance is peculiar to each backend. For example for 48 : * OpenAMP-based backends, an instance is usually represented by a 49 : * shared memory region and a couple of IPM devices for RX/TX 50 : * signalling. 51 : * 52 : * It's important to note that an instance per se is not used to 53 : * send data between domains / CPUs. To send and receive data the 54 : * user have to create (register) an endpoint in the instance 55 : * connecting the two domains of interest. 56 : * 57 : * It's possible to have zero or multiple endpoints in one single 58 : * instance, each one used to exchange data, possibly with different 59 : * priorities. 60 : * 61 : * The creation of the instances is left to the backend (usually at 62 : * init time), while the registration of the endpoints is left to 63 : * the user (usually at run time). 64 : * 65 : * - ENDPOINT: an endpoint is the entity the user must use to send / receive 66 : * data between two domains (connected by the instance). An 67 : * endpoint is always associated to an instance. 68 : * 69 : * - BACKEND: the backend must take care of at least two different things: 70 : * 71 : * 1) creating the instances at init time 72 : * 2) creating / registering the endpoints onto an instance at run 73 : * time when requested by the user 74 : * 75 : * The API doesn't mandate a way for the backend to create the 76 : * instances but itis strongly recommended to use the DT to retrieve 77 : * the configuration parameters for the instance. 78 : * 79 : * Common API usage from the application prospective: 80 : * 81 : * HOST REMOTE 82 : * ----------------------------------------------------------------------------- 83 : * # Open the (same) instance on host and remote 84 : * ipc_service_open() ipc_service_open() 85 : * 86 : * # Register the endpoints 87 : * ipc_service_register_endpoint() ipc_service_register_endpoint() 88 : * .bound() .bound() 89 : * 90 : * # After the .bound() callbacks are received the communication channel 91 : * # is ready to be used 92 : * 93 : * # Start sending and receiving data 94 : * ipc_service_send() 95 : * .receive() 96 : * ipc_service_send() 97 : * .receive() 98 : * 99 : * 100 : * Common API usage from the application prospective when using NOCOPY feature: 101 : * 102 : * HOST REMOTE 103 : * ----------------------------------------------------------------------------- 104 : * ipc_service_open() ipc_service_open() 105 : * 106 : * ipc_service_register_endpoint() ipc_service_register_endpoint() 107 : * .bound() .bound() 108 : * 109 : * # Get a pointer to an available TX buffer 110 : * ipc_service_get_tx_buffer() 111 : * 112 : * # Fill the buffer with data 113 : * 114 : * # Send out the buffer 115 : * ipc_service_send_nocopy() 116 : * .receive() 117 : * 118 : * # Get hold of the received RX buffer 119 : * # in the .receive callback 120 : * ipc_service_hold_rx_buffer() 121 : * 122 : * # Copy the data out of the buffer at 123 : * # user convenience 124 : * 125 : * # Release the buffer when done 126 : * ipc_service_release_rx_buffer() 127 : * 128 : * # Get another TX buffer 129 : * ipc_service_get_tx_buffer() 130 : * 131 : * # We can also drop it if needed 132 : * ipc_service_drop_tx_buffer() 133 : * 134 : */ 135 : 136 : /** 137 : * @endcond 138 : */ 139 : 140 : /** @brief Event callback structure. 141 : * 142 : * It is registered during endpoint registration. 143 : * This structure is part of the endpoint configuration. 144 : */ 145 1 : struct ipc_service_cb { 146 : /** @brief Bind was successful. 147 : * 148 : * This callback is called when the endpoint binding is successful. 149 : * 150 : * @param[in] priv Private user data. 151 : */ 152 1 : void (*bound)(void *priv); 153 : 154 : /** @brief New packet arrived. 155 : * 156 : * This callback is called when new data is received. 157 : * 158 : * @note When @ref ipc_service_hold_rx_buffer is not used, the data 159 : * buffer is to be considered released and available again only 160 : * when this callback returns. 161 : * 162 : * @param[in] data Pointer to data buffer. 163 : * @param[in] len Length of @a data. 164 : * @param[in] priv Private user data. 165 : */ 166 1 : void (*received)(const void *data, size_t len, void *priv); 167 : 168 : /** @brief An error occurred. 169 : * 170 : * @param[in] message Error message. 171 : * @param[in] priv Private user data. 172 : */ 173 1 : void (*error)(const char *message, void *priv); 174 : }; 175 : 176 : /** @brief Endpoint instance. 177 : * 178 : * Token is not important for user of the API. It is implemented in a 179 : * specific backend. 180 : */ 181 1 : struct ipc_ept { 182 : 183 : /** Instance this endpoint belongs to. */ 184 1 : const struct device *instance; 185 : 186 : /** Backend-specific token used to identify an endpoint in an instance. */ 187 1 : void *token; 188 : }; 189 : 190 : /** @brief Endpoint configuration structure. */ 191 1 : struct ipc_ept_cfg { 192 : 193 : /** Name of the endpoint. */ 194 1 : const char *name; 195 : 196 : /** Endpoint priority. If the backend supports priorities. */ 197 1 : int prio; 198 : 199 : /** Event callback structure. */ 200 1 : struct ipc_service_cb cb; 201 : 202 : /** Private user data. */ 203 1 : void *priv; 204 : }; 205 : 206 : /** @brief Open an instance 207 : * 208 : * Function to be used to open an instance before being able to register a new 209 : * endpoint on it. 210 : * 211 : * @param[in] instance Instance to open. 212 : * 213 : * @retval -EINVAL when instance configuration is invalid. 214 : * @retval -EIO when no backend is registered. 215 : * @retval -EALREADY when the instance is already opened (or being opened). 216 : * 217 : * @retval 0 on success or when not implemented on the backend (not needed). 218 : * @retval other errno codes depending on the implementation of the backend. 219 : */ 220 1 : int ipc_service_open_instance(const struct device *instance); 221 : 222 : /** @brief Close an instance 223 : * 224 : * Function to be used to close an instance. All bounded endpoints must be 225 : * deregistered using ipc_service_deregister_endpoint before this 226 : * is called. 227 : * 228 : * @param[in] instance Instance to close. 229 : * 230 : * @retval -EINVAL when instance configuration is invalid. 231 : * @retval -EIO when no backend is registered. 232 : * @retval -EALREADY when the instance is not already opened. 233 : * @retval -EBUSY when an endpoint exists that hasn't been 234 : * deregistered 235 : * 236 : * @retval 0 on success or when not implemented on the backend (not needed). 237 : * @retval other errno codes depending on the implementation of the backend. 238 : */ 239 1 : int ipc_service_close_instance(const struct device *instance); 240 : 241 : /** @brief Register IPC endpoint onto an instance. 242 : * 243 : * Registers IPC endpoint onto an instance to enable communication with a 244 : * remote device. 245 : * 246 : * The same function registers endpoints for both host and remote devices. 247 : * 248 : * @param[in] instance Instance to register the endpoint onto. 249 : * @param[in] ept Endpoint object. 250 : * @param[in] cfg Endpoint configuration. 251 : * 252 : * @note Keep the variable pointed by @p cfg alive when endpoint is in use. 253 : * 254 : * @retval -EIO when no backend is registered. 255 : * @retval -EINVAL when instance, endpoint or configuration is invalid. 256 : * @retval -EBUSY when the instance is busy. 257 : * 258 : * @retval 0 on success. 259 : * @retval other errno codes depending on the implementation of the backend. 260 : */ 261 1 : int ipc_service_register_endpoint(const struct device *instance, 262 : struct ipc_ept *ept, 263 : const struct ipc_ept_cfg *cfg); 264 : 265 : /** @brief Deregister an IPC endpoint from its instance. 266 : * 267 : * Deregisters an IPC endpoint from its instance. 268 : * 269 : * The same function deregisters endpoints for both host and remote devices. 270 : * 271 : * @param[in] ept Endpoint object. 272 : * 273 : * @retval -EIO when no backend is registered. 274 : * @retval -EINVAL when instance, endpoint or configuration is invalid. 275 : * @retval -ENOENT when the endpoint is not registered with the instance. 276 : * @retval -EBUSY when the instance is busy. 277 : * 278 : * @retval 0 on success. 279 : * @retval other errno codes depending on the implementation of the backend. 280 : */ 281 1 : int ipc_service_deregister_endpoint(struct ipc_ept *ept); 282 : 283 : /** @brief Send data using given IPC endpoint. 284 : * 285 : * @param[in] ept Registered endpoint by @ref ipc_service_register_endpoint. 286 : * @param[in] data Pointer to the buffer to send. 287 : * @param[in] len Number of bytes to send. 288 : * 289 : * @retval -EIO when no backend is registered or send hook is missing from 290 : * backend. 291 : * @retval -EINVAL when instance or endpoint is invalid. 292 : * @retval -ENOENT when the endpoint is not registered with the instance. 293 : * @retval -EBADMSG when the data is invalid (i.e. invalid data format, 294 : * invalid length, ...) 295 : * @retval -EBUSY when the instance is busy. 296 : * @retval -ENOMEM when no memory / buffers are available. 297 : * 298 : * @retval bytes number of bytes sent. 299 : * @retval other errno codes depending on the implementation of the backend. 300 : */ 301 1 : int ipc_service_send(struct ipc_ept *ept, const void *data, size_t len); 302 : 303 : /** @brief Get the TX buffer size 304 : * 305 : * Get the maximal size of a buffer which can be obtained by @ref 306 : * ipc_service_get_tx_buffer 307 : * 308 : * @param[in] ept Registered endpoint by @ref ipc_service_register_endpoint. 309 : * 310 : * @retval -EIO when no backend is registered or send hook is missing from 311 : * backend. 312 : * @retval -EINVAL when instance or endpoint is invalid. 313 : * @retval -ENOENT when the endpoint is not registered with the instance. 314 : * @retval -ENOTSUP when the operation is not supported by backend. 315 : * 316 : * @retval size TX buffer size on success. 317 : * @retval other errno codes depending on the implementation of the backend. 318 : */ 319 1 : int ipc_service_get_tx_buffer_size(struct ipc_ept *ept); 320 : 321 : /** @brief Get an empty TX buffer to be sent using @ref ipc_service_send_nocopy 322 : * 323 : * This function can be called to get an empty TX buffer so that the 324 : * application can directly put its data into the sending buffer without copy 325 : * from an application buffer. 326 : * 327 : * It is the application responsibility to correctly fill the allocated TX 328 : * buffer with data and passing correct parameters to @ref 329 : * ipc_service_send_nocopy function to perform data no-copy-send mechanism. 330 : * 331 : * The size parameter can be used to request a buffer with a certain size: 332 : * - if the size can be accommodated the function returns no errors and the 333 : * buffer is allocated 334 : * - if the requested size is too big, the function returns -ENOMEM and the 335 : * the buffer is not allocated. 336 : * - if the requested size is '0' the buffer is allocated with the maximum 337 : * allowed size. 338 : * 339 : * In all the cases on return the size parameter contains the maximum size for 340 : * the returned buffer. 341 : * 342 : * When the function returns no errors, the buffer is intended as allocated 343 : * and it is released under two conditions: (1) when sending the buffer using 344 : * @ref ipc_service_send_nocopy (and in this case the buffer is automatically 345 : * released by the backend), (2) when using @ref ipc_service_drop_tx_buffer on 346 : * a buffer not sent. 347 : * 348 : * @param[in] ept Registered endpoint by @ref ipc_service_register_endpoint. 349 : * @param[out] data Pointer to the empty TX buffer. 350 : * @param[in,out] size Pointer to store the requested TX buffer size. If the 351 : * function returns -ENOMEM, this parameter returns the 352 : * maximum allowed size. 353 : * @param[in] wait Timeout waiting for an available TX buffer. 354 : * 355 : * @retval -EIO when no backend is registered or send hook is missing from 356 : * backend. 357 : * @retval -EINVAL when instance or endpoint is invalid. 358 : * @retval -ENOENT when the endpoint is not registered with the instance. 359 : * @retval -ENOTSUP when the operation or the timeout is not supported by backend. 360 : * @retval -ENOBUFS when there are no TX buffers available. 361 : * @retval -EALREADY when a buffer was already claimed and not yet released. 362 : * @retval -ENOMEM when the requested size is too big (and the size parameter 363 : * contains the maximum allowed size). 364 : * 365 : * @retval 0 on success. 366 : * @retval other errno codes depending on the implementation of the backend. 367 : */ 368 1 : int ipc_service_get_tx_buffer(struct ipc_ept *ept, void **data, uint32_t *size, k_timeout_t wait); 369 : 370 : /** @brief Drop and release a TX buffer 371 : * 372 : * Drop and release a TX buffer. It is possible to drop only TX buffers 373 : * obtained by using @ref ipc_service_get_tx_buffer. 374 : * 375 : * @param[in] ept Registered endpoint by @ref ipc_service_register_endpoint. 376 : * @param[in] data Pointer to the TX buffer. 377 : * 378 : * @retval -EIO when no backend is registered or send hook is missing from 379 : * backend. 380 : * @retval -EINVAL when instance or endpoint is invalid. 381 : * @retval -ENOENT when the endpoint is not registered with the instance. 382 : * @retval -ENOTSUP when this is not supported by backend. 383 : * @retval -EALREADY when the buffer was already dropped. 384 : * @retval -ENXIO when the buffer was not obtained using @ref 385 : * ipc_service_get_tx_buffer 386 : * 387 : * @retval 0 on success. 388 : * @retval other errno codes depending on the implementation of the backend. 389 : */ 390 1 : int ipc_service_drop_tx_buffer(struct ipc_ept *ept, const void *data); 391 : 392 : /** @brief Send data in a TX buffer reserved by @ref ipc_service_get_tx_buffer 393 : * using the given IPC endpoint. 394 : * 395 : * This is equivalent to @ref ipc_service_send but in this case the TX buffer 396 : * has been obtained by using @ref ipc_service_get_tx_buffer. 397 : * 398 : * The application has to take the responsibility for getting the TX buffer 399 : * using @ref ipc_service_get_tx_buffer and filling the TX buffer with the data. 400 : * 401 : * After the @ref ipc_service_send_nocopy function is issued the TX buffer is 402 : * no more owned by the sending task and must not be touched anymore unless 403 : * the function fails and returns an error. 404 : * 405 : * If this function returns an error, @ref ipc_service_drop_tx_buffer can be 406 : * used to drop the TX buffer. 407 : * 408 : * @param[in] ept Registered endpoint by @ref ipc_service_register_endpoint. 409 : * @param[in] data Pointer to the buffer to send obtained by @ref 410 : * ipc_service_get_tx_buffer. 411 : * @param[in] len Number of bytes to send. 412 : * 413 : * @retval -EIO when no backend is registered or send hook is missing from 414 : * backend. 415 : * @retval -EINVAL when instance or endpoint is invalid. 416 : * @retval -ENOENT when the endpoint is not registered with the instance. 417 : * @retval -EBADMSG when the data is invalid (i.e. invalid data format, 418 : * invalid length, ...) 419 : * @retval -EBUSY when the instance is busy. 420 : * 421 : * @retval bytes number of bytes sent. 422 : * @retval other errno codes depending on the implementation of the backend. 423 : */ 424 1 : int ipc_service_send_nocopy(struct ipc_ept *ept, const void *data, size_t len); 425 : 426 : /** @brief Holds the RX buffer for usage outside the receive callback. 427 : * 428 : * Calling this function prevents the receive buffer from being released 429 : * back to the pool of shmem buffers. This function can be called in the 430 : * receive callback when the user does not want to copy the message out in 431 : * the callback itself. 432 : * 433 : * After the message is processed, the application must release the buffer 434 : * using the @ref ipc_service_release_rx_buffer function. 435 : * 436 : * @param[in] ept Registered endpoint by @ref ipc_service_register_endpoint. 437 : * @param[in] data Pointer to the RX buffer to hold. 438 : * 439 : * @retval -EIO when no backend is registered or release hook is missing from 440 : * backend. 441 : * @retval -EINVAL when instance or endpoint is invalid. 442 : * @retval -ENOENT when the endpoint is not registered with the instance. 443 : * @retval -EALREADY when the buffer data has been hold already. 444 : * @retval -ENOTSUP when this is not supported by backend. 445 : * 446 : * @retval 0 on success. 447 : * @retval other errno codes depending on the implementation of the backend. 448 : */ 449 1 : int ipc_service_hold_rx_buffer(struct ipc_ept *ept, void *data); 450 : 451 : /** @brief Release the RX buffer for future reuse. 452 : * 453 : * When supported by the backend, this function can be called after the 454 : * received message has been processed and the buffer can be marked as 455 : * reusable again. 456 : * 457 : * It is possible to release only RX buffers on which @ref 458 : * ipc_service_hold_rx_buffer was previously used. 459 : * 460 : * @param[in] ept Registered endpoint by @ref ipc_service_register_endpoint. 461 : * @param[in] data Pointer to the RX buffer to release. 462 : * 463 : * @retval -EIO when no backend is registered or release hook is missing from 464 : * backend. 465 : * @retval -EINVAL when instance or endpoint is invalid. 466 : * @retval -ENOENT when the endpoint is not registered with the instance. 467 : * @retval -EALREADY when the buffer data has been already released. 468 : * @retval -ENOTSUP when this is not supported by backend. 469 : * @retval -ENXIO when the buffer was not hold before using @ref 470 : * ipc_service_hold_rx_buffer 471 : * 472 : * @retval 0 on success. 473 : * @retval other errno codes depending on the implementation of the backend. 474 : */ 475 1 : int ipc_service_release_rx_buffer(struct ipc_ept *ept, void *data); 476 : 477 : /** 478 : * @} 479 : */ 480 : 481 : #ifdef __cplusplus 482 : } 483 : #endif 484 : 485 : #endif /* ZEPHYR_INCLUDE_IPC_IPC_SERVICE_H_ */