1 /* 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 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 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 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 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 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 struct ipc_ept { 197 198 /** Instance this endpoint belongs to. */ 199 const struct device *instance; 200 201 /** Backend-specific token used to identify an endpoint in an instance. */ 202 void *token; 203 }; 204 205 /** @brief Endpoint configuration structure. */ 206 struct ipc_ept_cfg { 207 208 /** Name of the endpoint. */ 209 const char *name; 210 211 /** Endpoint priority. If the backend supports priorities. */ 212 int prio; 213 214 /** Event callback structure. */ 215 struct ipc_service_cb cb; 216 217 /** Private user data. */ 218 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 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 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 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 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 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 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 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 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 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 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 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_ */ 501