1 /*
2  * Copyright (c) 2022 Nordic Semiconductor ASA
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #ifndef ZEPHYR_INCLUDE_IPC_ICMSG_H_
8 #define ZEPHYR_INCLUDE_IPC_ICMSG_H_
9 
10 #include <stddef.h>
11 #include <stdint.h>
12 #include <zephyr/kernel.h>
13 #include <zephyr/drivers/mbox.h>
14 #include <zephyr/ipc/ipc_service.h>
15 #include <zephyr/ipc/pbuf.h>
16 #include <zephyr/sys/atomic.h>
17 
18 #ifdef __cplusplus
19 extern "C" {
20 #endif
21 
22 /**
23  * @brief Icmsg IPC library API
24  * @defgroup ipc_icmsg_api Icmsg IPC library API
25  * @ingroup ipc
26  * @{
27  */
28 
29 enum icmsg_state {
30 	/** Instance is not initialized yet. In this state: sending will fail, opening allowed.
31 	 */
32 	ICMSG_STATE_OFF,
33 
34 	/** Instance is initializing without session handshake. In this state: sending will fail,
35 	 * opening will fail.
36 	 */
37 	ICMSG_STATE_INITIALIZING_SID_DISABLED,
38 
39 	/** Instance is initializing with session handshake. It is waiting for remote to acknowledge
40 	 * local session id. In this state: sending will fail, opening is allowed (local session id
41 	 * will change, so the remote may get unbound() callback).
42 	 */
43 	ICMSG_STATE_INITIALIZING_SID_ENABLED,
44 
45 	/** Instance is initializing with detection of session handshake support on remote side.
46 	 * It is waiting for remote to acknowledge local session id or to send magic bytes.
47 	 * In this state: sending will fail, opening is allowed (local session id
48 	 * will change, so the remote may get unbound() callback if it supports it).
49 	 */
50 	ICMSG_STATE_INITIALIZING_SID_DETECT,
51 
52 	/** Instance was closed on remote side. The unbound() callback was send on local side.
53 	 * In this state: sending will be silently discarded (there may be outdated sends),
54 	 * opening is allowed.
55 	 */
56 	ICMSG_STATE_DISCONNECTED,
57 
58 	/* Connected states must be at the end. */
59 
60 	/** Instance is connected without session handshake support. In this state: sending will be
61 	 * successful, opening will fail.
62 	 */
63 	ICMSG_STATE_CONNECTED_SID_DISABLED,
64 
65 	/** Instance is connected with session handshake support. In this state: sending will be
66 	 * successful, opening is allowed (session will change and remote will get unbound()
67 	 * callback).
68 	 */
69 	ICMSG_STATE_CONNECTED_SID_ENABLED,
70 };
71 
72 enum icmsg_unbound_mode {
73 	ICMSG_UNBOUND_MODE_DISABLE = ICMSG_STATE_INITIALIZING_SID_DISABLED,
74 	ICMSG_UNBOUND_MODE_ENABLE = ICMSG_STATE_INITIALIZING_SID_ENABLED,
75 	ICMSG_UNBOUND_MODE_DETECT = ICMSG_STATE_INITIALIZING_SID_DETECT,
76 };
77 
78 struct icmsg_config_t {
79 	struct mbox_dt_spec mbox_tx;
80 	struct mbox_dt_spec mbox_rx;
81 	enum icmsg_unbound_mode unbound_mode;
82 };
83 
84 struct icmsg_data_t {
85 	/* Tx/Rx buffers. */
86 	struct pbuf *tx_pb;
87 	struct pbuf *rx_pb;
88 #ifdef CONFIG_IPC_SERVICE_ICMSG_SHMEM_ACCESS_SYNC
89 	struct k_mutex tx_lock;
90 #endif
91 
92 	/* Callbacks for an endpoint. */
93 	const struct ipc_service_cb *cb;
94 	void *ctx;
95 
96 	/* General */
97 	const struct icmsg_config_t *cfg;
98 #ifdef CONFIG_MULTITHREADING
99 	struct k_work mbox_work;
100 #endif
101 	uint16_t remote_sid;
102 	uint16_t local_sid;
103 	atomic_t state;
104 };
105 
106 /** @brief Open an icmsg instance
107  *
108  *  Open an icmsg instance to be able to send and receive messages to a remote
109  *  instance.
110  *  This function is blocking until the handshake with the remote instance is
111  *  completed.
112  *  This function is intended to be called late in the initialization process,
113  *  possibly from a thread which can be safely blocked while handshake with the
114  *  remote instance is being performed.
115  *
116  *  @param[in] conf Structure containing configuration parameters for the icmsg
117  *                  instance.
118  *  @param[inout] dev_data Structure containing run-time data used by the icmsg
119  *                         instance.
120  *  @param[in] cb Structure containing callback functions to be called on
121  *                events generated by this icmsg instance. The pointed memory
122  *                must be preserved while the icmsg instance is active.
123  *  @param[in] ctx Pointer to context passed as an argument to callbacks.
124  *
125  *
126  *  @retval 0 on success.
127  *  @retval -EALREADY when the instance is already opened.
128  *  @retval other errno codes from dependent modules.
129  */
130 int icmsg_open(const struct icmsg_config_t *conf,
131 	       struct icmsg_data_t *dev_data,
132 	       const struct ipc_service_cb *cb, void *ctx);
133 
134 /** @brief Close an icmsg instance
135  *
136  *  Closing an icmsg instance results in releasing all resources used by given
137  *  instance including the shared memory regions and mbox devices.
138  *
139  *  @param[in] conf Structure containing configuration parameters for the icmsg
140  *                  instance being closed. Its content must be the same as used
141  *                  for creating this instance with @ref icmsg_open.
142  *  @param[inout] dev_data Structure containing run-time data used by the icmsg
143  *                         instance.
144  *
145  *  @retval 0 on success.
146  *  @retval other errno codes from dependent modules.
147  */
148 int icmsg_close(const struct icmsg_config_t *conf,
149 		struct icmsg_data_t *dev_data);
150 
151 /** @brief Send a message to the remote icmsg instance.
152  *
153  *  @param[in] conf Structure containing configuration parameters for the icmsg
154  *                  instance.
155  *  @param[inout] dev_data Structure containing run-time data used by the icmsg
156  *                         instance.
157  *  @param[in] msg Pointer to a buffer containing data to send.
158  *  @param[in] len Size of data in the @p msg buffer.
159  *
160  *
161  *  @retval Number of sent bytes.
162  *  @retval -EBUSY when the instance has not finished handshake with the remote
163  *                 instance.
164  *  @retval -ENODATA when the requested data to send is empty.
165  *  @retval -EBADMSG when the requested data to send is too big.
166  *  @retval -ENOBUFS when there are no TX buffers available.
167  *  @retval other errno codes from dependent modules.
168  */
169 int icmsg_send(const struct icmsg_config_t *conf,
170 	       struct icmsg_data_t *dev_data,
171 	       const void *msg, size_t len);
172 
173 /**
174  * @}
175  */
176 
177 #ifdef __cplusplus
178 }
179 #endif
180 
181 #endif /* ZEPHYR_INCLUDE_IPC_ICMSG_H_ */
182