LCOV - code coverage report
Current view: top level - zephyr/ipc - ipc_service.h Coverage Total Hit
Test: new.info Lines: 96.0 % 25 24
Test Date: 2025-09-05 16:43:28

            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 The endpoint unbound by the remote.
     155              :          *
     156              :          *  This callback is called when the endpoint binding is removed. It may happen on
     157              :          *  different reasons, e.g. when the remote deregistered the endpoint, connection was
     158              :          *  lost, or remote CPU got reset.
     159              :          *
     160              :          *  You may want to do some cleanup, resetting, e.t.c. and after that if you want to bound
     161              :          *  again, you can register the endpoint. When the remote becomes available again and it
     162              :          *  also registers the endpoint, the binding will be reestablished and the `bound()`
     163              :          *  callback will be called.
     164              :          *
     165              :          *  @param[in] priv Private user data.
     166              :          */
     167            1 :         void (*unbound)(void *priv);
     168              : 
     169              :         /** @brief New packet arrived.
     170              :          *
     171              :          *  This callback is called when new data is received.
     172              :          *
     173              :          *  @note When @ref ipc_service_hold_rx_buffer is not used, the data
     174              :          *        buffer is to be considered released and available again only
     175              :          *        when this callback returns.
     176              :          *
     177              :          *  @param[in] data Pointer to data buffer.
     178              :          *  @param[in] len Length of @a data.
     179              :          *  @param[in] priv Private user data.
     180              :          */
     181            1 :         void (*received)(const void *data, size_t len, void *priv);
     182              : 
     183              :         /** @brief An error occurred.
     184              :          *
     185              :          *  @param[in] message Error message.
     186              :          *  @param[in] priv Private user data.
     187              :          */
     188            1 :         void (*error)(const char *message, void *priv);
     189              : };
     190              : 
     191              : /** @brief Endpoint instance.
     192              :  *
     193              :  *  Token is not important for user of the API. It is implemented in a
     194              :  *  specific backend.
     195              :  */
     196            1 : struct ipc_ept {
     197              : 
     198              :         /** Instance this endpoint belongs to. */
     199            1 :         const struct device *instance;
     200              : 
     201              :         /** Backend-specific token used to identify an endpoint in an instance. */
     202            1 :         void *token;
     203              : };
     204              : 
     205              : /** @brief Endpoint configuration structure. */
     206            1 : struct ipc_ept_cfg {
     207              : 
     208              :         /** Name of the endpoint. */
     209            1 :         const char *name;
     210              : 
     211              :         /** Endpoint priority. If the backend supports priorities. */
     212            1 :         int prio;
     213              : 
     214              :         /** Event callback structure. */
     215            1 :         struct ipc_service_cb cb;
     216              : 
     217              :         /** Private user data. */
     218            1 :         void *priv;
     219              : };
     220              : 
     221              : /** @brief Open an instance
     222              :  *
     223              :  *  Function to be used to open an instance before being able to register a new
     224              :  *  endpoint on it.
     225              :  *
     226              :  *  @param[in] instance Instance to open.
     227              :  *
     228              :  *  @retval -EINVAL when instance configuration is invalid.
     229              :  *  @retval -EIO when no backend is registered.
     230              :  *  @retval -EALREADY when the instance is already opened (or being opened).
     231              :  *
     232              :  *  @retval 0 on success or when not implemented on the backend (not needed).
     233              :  *  @retval other errno codes depending on the implementation of the backend.
     234              :  */
     235            1 : int ipc_service_open_instance(const struct device *instance);
     236              : 
     237              : /** @brief Close an instance
     238              :  *
     239              :  *  Function to be used to close an instance. All bounded endpoints must be
     240              :  *  deregistered using ipc_service_deregister_endpoint before this
     241              :  *  is called.
     242              :  *
     243              :  *  @param[in] instance Instance to close.
     244              :  *
     245              :  *  @retval -EINVAL when instance configuration is invalid.
     246              :  *  @retval -EIO when no backend is registered.
     247              :  *  @retval -EALREADY when the instance is not already opened.
     248              :  *  @retval -EBUSY when an endpoint exists that hasn't been
     249              :  *           deregistered
     250              :  *
     251              :  *  @retval 0 on success or when not implemented on the backend (not needed).
     252              :  *  @retval other errno codes depending on the implementation of the backend.
     253              :  */
     254            1 : int ipc_service_close_instance(const struct device *instance);
     255              : 
     256              : /** @brief Register IPC endpoint onto an instance.
     257              :  *
     258              :  *  Registers IPC endpoint onto an instance to enable communication with a
     259              :  *  remote device.
     260              :  *
     261              :  *  The same function registers endpoints for both host and remote devices.
     262              :  *
     263              :  *  @param[in] instance Instance to register the endpoint onto.
     264              :  *  @param[in] ept Endpoint object.
     265              :  *  @param[in] cfg Endpoint configuration.
     266              :  *
     267              :  *  @note Keep the variable pointed by @p cfg alive when endpoint is in use.
     268              :  *
     269              :  *  @retval -EIO when no backend is registered.
     270              :  *  @retval -EINVAL when instance, endpoint or configuration is invalid.
     271              :  *  @retval -EBUSY when the instance is busy.
     272              :  *
     273              :  *  @retval 0 on success.
     274              :  *  @retval other errno codes depending on the implementation of the backend.
     275              :  */
     276            1 : int ipc_service_register_endpoint(const struct device *instance,
     277              :                                   struct ipc_ept *ept,
     278              :                                   const struct ipc_ept_cfg *cfg);
     279              : 
     280              : /** @brief Deregister an IPC endpoint from its instance.
     281              :  *
     282              :  *  Deregisters an IPC endpoint from its instance.
     283              :  *
     284              :  *  The same function deregisters endpoints for both host and remote devices.
     285              :  *
     286              :  *  @param[in] ept Endpoint object.
     287              :  *
     288              :  *  @retval -EIO when no backend is registered.
     289              :  *  @retval -EINVAL when instance, endpoint or configuration is invalid.
     290              :  *  @retval -ENOENT when the endpoint is not registered with the instance.
     291              :  *  @retval -EBUSY when the instance is busy.
     292              :  *
     293              :  *  @retval 0 on success.
     294              :  *  @retval other errno codes depending on the implementation of the backend.
     295              :  */
     296            1 : int ipc_service_deregister_endpoint(struct ipc_ept *ept);
     297              : 
     298              : /** @brief Send data using given IPC endpoint.
     299              :  *
     300              :  *  @param[in] ept Registered endpoint by @ref ipc_service_register_endpoint.
     301              :  *  @param[in] data Pointer to the buffer to send.
     302              :  *  @param[in] len Number of bytes to send.
     303              :  *
     304              :  *  @retval -EIO when no backend is registered or send hook is missing from
     305              :  *               backend.
     306              :  *  @retval -EINVAL when instance or endpoint is invalid.
     307              :  *  @retval -ENOENT when the endpoint is not registered with the instance.
     308              :  *  @retval -EBADMSG when the data is invalid (i.e. invalid data format,
     309              :  *                   invalid length, ...)
     310              :  *  @retval -EBUSY when the instance is busy.
     311              :  *  @retval -ENOMEM when no memory / buffers are available.
     312              :  *
     313              :  *  @retval bytes number of bytes sent.
     314              :  *  @retval other errno codes depending on the implementation of the backend.
     315              :  */
     316            1 : int ipc_service_send(struct ipc_ept *ept, const void *data, size_t len);
     317              : 
     318              : /** @brief Get the TX buffer size
     319              :  *
     320              :  *  Get the maximal size of a buffer which can be obtained by @ref
     321              :  *  ipc_service_get_tx_buffer
     322              :  *
     323              :  *  @param[in] ept Registered endpoint by @ref ipc_service_register_endpoint.
     324              :  *
     325              :  *  @retval -EIO when no backend is registered or send hook is missing from
     326              :  *               backend.
     327              :  *  @retval -EINVAL when instance or endpoint is invalid.
     328              :  *  @retval -ENOENT when the endpoint is not registered with the instance.
     329              :  *  @retval -ENOTSUP when the operation is not supported by backend.
     330              :  *
     331              :  *  @retval size TX buffer size on success.
     332              :  *  @retval other errno codes depending on the implementation of the backend.
     333              :  */
     334            1 : int ipc_service_get_tx_buffer_size(struct ipc_ept *ept);
     335              : 
     336              : /** @brief Get an empty TX buffer to be sent using @ref ipc_service_send_nocopy
     337              :  *
     338              :  *  This function can be called to get an empty TX buffer so that the
     339              :  *  application can directly put its data into the sending buffer without copy
     340              :  *  from an application buffer.
     341              :  *
     342              :  *  It is the application responsibility to correctly fill the allocated TX
     343              :  *  buffer with data and passing correct parameters to @ref
     344              :  *  ipc_service_send_nocopy function to perform data no-copy-send mechanism.
     345              :  *
     346              :  *  The size parameter can be used to request a buffer with a certain size:
     347              :  *  - if the size can be accommodated the function returns no errors and the
     348              :  *    buffer is allocated
     349              :  *  - if the requested size is too big, the function returns -ENOMEM and the
     350              :  *    the buffer is not allocated.
     351              :  *  - if the requested size is '0' the buffer is allocated with the maximum
     352              :  *    allowed size.
     353              :  *
     354              :  *  In all the cases on return the size parameter contains the maximum size for
     355              :  *  the returned buffer.
     356              :  *
     357              :  *  When the function returns no errors, the buffer is intended as allocated
     358              :  *  and it is released under two conditions: (1) when sending the buffer using
     359              :  *  @ref ipc_service_send_nocopy (and in this case the buffer is automatically
     360              :  *  released by the backend), (2) when using @ref ipc_service_drop_tx_buffer on
     361              :  *  a buffer not sent.
     362              :  *
     363              :  *  @param[in] ept Registered endpoint by @ref ipc_service_register_endpoint.
     364              :  *  @param[out] data Pointer to the empty TX buffer.
     365              :  *  @param[in,out] size Pointer to store the requested TX buffer size. If the
     366              :  *                      function returns -ENOMEM, this parameter returns the
     367              :  *                      maximum allowed size.
     368              :  *  @param[in] wait Timeout waiting for an available TX buffer.
     369              :  *
     370              :  *  @retval -EIO when no backend is registered or send hook is missing from
     371              :  *               backend.
     372              :  *  @retval -EINVAL when instance or endpoint is invalid.
     373              :  *  @retval -ENOENT when the endpoint is not registered with the instance.
     374              :  *  @retval -ENOTSUP when the operation or the timeout is not supported by backend.
     375              :  *  @retval -ENOBUFS when there are no TX buffers available.
     376              :  *  @retval -EALREADY when a buffer was already claimed and not yet released.
     377              :  *  @retval -ENOMEM when the requested size is too big (and the size parameter
     378              :  *                  contains the maximum allowed size).
     379              :  *
     380              :  *  @retval 0 on success.
     381              :  *  @retval other errno codes depending on the implementation of the backend.
     382              :  */
     383            1 : int ipc_service_get_tx_buffer(struct ipc_ept *ept, void **data, uint32_t *size, k_timeout_t wait);
     384              : 
     385              : /** @brief Drop and release a TX buffer
     386              :  *
     387              :  *  Drop and release a TX buffer. It is possible to drop only TX buffers
     388              :  *  obtained by using @ref ipc_service_get_tx_buffer.
     389              :  *
     390              :  *  @param[in] ept Registered endpoint by @ref ipc_service_register_endpoint.
     391              :  *  @param[in] data Pointer to the TX buffer.
     392              :  *
     393              :  *  @retval -EIO when no backend is registered or send hook is missing from
     394              :  *               backend.
     395              :  *  @retval -EINVAL when instance or endpoint is invalid.
     396              :  *  @retval -ENOENT when the endpoint is not registered with the instance.
     397              :  *  @retval -ENOTSUP when this is not supported by backend.
     398              :  *  @retval -EALREADY when the buffer was already dropped.
     399              :  *  @retval -ENXIO when the buffer was not obtained using @ref
     400              :  *                 ipc_service_get_tx_buffer
     401              :  *
     402              :  *  @retval 0 on success.
     403              :  *  @retval other errno codes depending on the implementation of the backend.
     404              :  */
     405            1 : int ipc_service_drop_tx_buffer(struct ipc_ept *ept, const void *data);
     406              : 
     407              : /** @brief Send data in a TX buffer reserved by @ref ipc_service_get_tx_buffer
     408              :  *         using the given IPC endpoint.
     409              :  *
     410              :  *  This is equivalent to @ref ipc_service_send but in this case the TX buffer
     411              :  *  has been obtained by using @ref ipc_service_get_tx_buffer.
     412              :  *
     413              :  *  The application has to take the responsibility for getting the TX buffer
     414              :  *  using @ref ipc_service_get_tx_buffer and filling the TX buffer with the data.
     415              :  *
     416              :  *  After the @ref ipc_service_send_nocopy function is issued the TX buffer is
     417              :  *  no more owned by the sending task and must not be touched anymore unless
     418              :  *  the function fails and returns an error.
     419              :  *
     420              :  *  If this function returns an error, @ref ipc_service_drop_tx_buffer can be
     421              :  *  used to drop the TX buffer.
     422              :  *
     423              :  *  @param[in] ept Registered endpoint by @ref ipc_service_register_endpoint.
     424              :  *  @param[in] data Pointer to the buffer to send obtained by @ref
     425              :  *                  ipc_service_get_tx_buffer.
     426              :  *  @param[in] len Number of bytes to send.
     427              :  *
     428              :  *  @retval -EIO when no backend is registered or send hook is missing from
     429              :  *               backend.
     430              :  *  @retval -EINVAL when instance or endpoint is invalid.
     431              :  *  @retval -ENOENT when the endpoint is not registered with the instance.
     432              :  *  @retval -EBADMSG when the data is invalid (i.e. invalid data format,
     433              :  *                   invalid length, ...)
     434              :  *  @retval -EBUSY when the instance is busy.
     435              :  *
     436              :  *  @retval bytes number of bytes sent.
     437              :  *  @retval other errno codes depending on the implementation of the backend.
     438              :  */
     439            1 : int ipc_service_send_nocopy(struct ipc_ept *ept, const void *data, size_t len);
     440              : 
     441              : /** @brief Holds the RX buffer for usage outside the receive callback.
     442              :  *
     443              :  *  Calling this function prevents the receive buffer from being released
     444              :  *  back to the pool of shmem buffers. This function can be called in the
     445              :  *  receive callback when the user does not want to copy the message out in
     446              :  *  the callback itself.
     447              :  *
     448              :  *  After the message is processed, the application must release the buffer
     449              :  *  using the @ref ipc_service_release_rx_buffer function.
     450              :  *
     451              :  *  @param[in] ept Registered endpoint by @ref ipc_service_register_endpoint.
     452              :  *  @param[in] data Pointer to the RX buffer to hold.
     453              :  *
     454              :  *  @retval -EIO when no backend is registered or release hook is missing from
     455              :  *               backend.
     456              :  *  @retval -EINVAL when instance or endpoint is invalid.
     457              :  *  @retval -ENOENT when the endpoint is not registered with the instance.
     458              :  *  @retval -EALREADY when the buffer data has been hold already.
     459              :  *  @retval -ENOTSUP when this is not supported by backend.
     460              :  *
     461              :  *  @retval 0 on success.
     462              :  *  @retval other errno codes depending on the implementation of the backend.
     463              :  */
     464            1 : int ipc_service_hold_rx_buffer(struct ipc_ept *ept, void *data);
     465              : 
     466              : /** @brief Release the RX buffer for future reuse.
     467              :  *
     468              :  *  When supported by the backend, this function can be called after the
     469              :  *  received message has been processed and the buffer can be marked as
     470              :  *  reusable again.
     471              :  *
     472              :  *  It is possible to release only RX buffers on which @ref
     473              :  *  ipc_service_hold_rx_buffer was previously used.
     474              :  *
     475              :  *  @param[in] ept Registered endpoint by @ref ipc_service_register_endpoint.
     476              :  *  @param[in] data Pointer to the RX buffer to release.
     477              :  *
     478              :  *  @retval -EIO when no backend is registered or release hook is missing from
     479              :  *               backend.
     480              :  *  @retval -EINVAL when instance or endpoint is invalid.
     481              :  *  @retval -ENOENT when the endpoint is not registered with the instance.
     482              :  *  @retval -EALREADY when the buffer data has been already released.
     483              :  *  @retval -ENOTSUP when this is not supported by backend.
     484              :  *  @retval -ENXIO when the buffer was not hold before using @ref
     485              :  *                 ipc_service_hold_rx_buffer
     486              :  *
     487              :  *  @retval 0 on success.
     488              :  *  @retval other errno codes depending on the implementation of the backend.
     489              :  */
     490            1 : int ipc_service_release_rx_buffer(struct ipc_ept *ept, void *data);
     491              : 
     492              : /**
     493              :  * @}
     494              :  */
     495              : 
     496              : #ifdef __cplusplus
     497              : }
     498              : #endif
     499              : 
     500              : #endif /* ZEPHYR_INCLUDE_IPC_IPC_SERVICE_H_ */
        

Generated by: LCOV version 2.0-1