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