LCOV - code coverage report
Current view: top level - zephyr/ipc - ipc_service.h Hit Total Coverage
Test: new.info Lines: 23 24 95.8 %
Date: 2024-12-22 00:14:23

          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_ */

Generated by: LCOV version 1.14