From 3fcd8d10034bf170d23037c7dfd436bff4e48657 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marcin=20Jeli=C5=84ski?= Date: Wed, 9 Jun 2021 15:22:38 +0200 Subject: [PATCH] ipc: Added IPC Service to support different transport backends MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit IPC Service allow plugging in different transport backends. Specifies a generic API that is implemented by the backend. Signed-off-by: Marcin JeliƄski --- include/ipc/ipc_service.h | 107 ++++++++++++++++++++++++++ include/ipc/ipc_service_backend.h | 72 +++++++++++++++++ subsys/ipc/CMakeLists.txt | 1 + subsys/ipc/Kconfig | 1 + subsys/ipc/ipc_service/CMakeLists.txt | 3 + subsys/ipc/ipc_service/Kconfig | 32 ++++++++ subsys/ipc/ipc_service/ipc_service.c | 59 ++++++++++++++ 7 files changed, 275 insertions(+) create mode 100644 include/ipc/ipc_service.h create mode 100644 include/ipc/ipc_service_backend.h create mode 100644 subsys/ipc/ipc_service/CMakeLists.txt create mode 100644 subsys/ipc/ipc_service/Kconfig create mode 100644 subsys/ipc/ipc_service/ipc_service.c diff --git a/include/ipc/ipc_service.h b/include/ipc/ipc_service.h new file mode 100644 index 0000000000..0a6954f7dd --- /dev/null +++ b/include/ipc/ipc_service.h @@ -0,0 +1,107 @@ +/* + * Copyright (c) 2021 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef ZEPHYR_INCLUDE_IPC_SERVICE_IPC_SERVICE_H_ +#define ZEPHYR_INCLUDE_IPC_SERVICE_IPC_SERVICE_H_ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief IPC Service API + * @defgroup ipc_service_api IPC service APIs + * @{ + */ + +/** @brief Event callback structure. + * + * It is registered during endpoint registration. + * This structure is part of the endpoint configuration. + */ +struct ipc_service_cb { + /** @brief Bind was successful. + * + * @param priv Private user data. + */ + void (*bound)(void *priv); + + /** @brief New packet arrived. + * + * @param data Pointer to data buffer. + * @param len Length of @a data. + * @param priv Private user data. + */ + void (*received)(const void *data, size_t len, void *priv); + + /** @brief An error occurred. + * + * @param message Error message. + * @param priv Private user data. + */ + void (*error)(const char *message, void *priv); +}; + +/** @brief Endpoint instance. + * + * Content is not important for user of the API. + * It is implemented in a specific backend. + */ +struct ipc_ept; + +/** @brief Endpoint configuration structure. */ +struct ipc_ept_cfg { + + /** Name of the endpoint. */ + const char *name; + + /** Endpoint priority. If the backend supports priorities. */ + int prio; + + /** Event callback structure. */ + struct ipc_service_cb cb; + + /** Private user data. */ + void *priv; +}; + +/** @brief Register IPC endpoint. + * + * Registers IPC endpoint to enable communication with a remote device. + * + * The same function registers endpoints for both master and slave devices. + * + * @param ept Endpoint object. + * @param cfg Endpoint configuration. + * + * @retval -EIO when no backend is registered. + * @retval -EINVAL when pointer to an endpoint or endpoint configuration is invalid. + * @retval Other errno codes depending on the implementation of the backend. + */ +int ipc_service_register_endpoint(struct ipc_ept **ept, const struct ipc_ept_cfg *cfg); + +/** @brief Send data using given IPC endpoint. + * + * @param ept Registered endpoint by @ref ipc_service_register_endpoint. + * @param data Pointer to the buffer to send. + * @param len Number of bytes to send. + * + * @retval -EIO when no backend is registered. + * @retval Other errno codes depending on the implementation of the backend. + */ +int ipc_service_send(struct ipc_ept *ept, const void *data, size_t len); + +/** + * @} + */ + +#ifdef __cplusplus +} +#endif + +#endif /* ZEPHYR_INCLUDE_IPC_SERVICE_IPC_SERVICE_H_ */ diff --git a/include/ipc/ipc_service_backend.h b/include/ipc/ipc_service_backend.h new file mode 100644 index 0000000000..d4f97cbc00 --- /dev/null +++ b/include/ipc/ipc_service_backend.h @@ -0,0 +1,72 @@ +/* + * Copyright (c) 2021 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef ZEPHYR_INCLUDE_IPC_SERVICE_IPC_SERVICE_BACKEND_H_ +#define ZEPHYR_INCLUDE_IPC_SERVICE_IPC_SERVICE_BACKEND_H_ + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief IPC Service backend + * @ingroup ipc_service_api + * @{ + */ + +/** @brief IPC backend configuration structure. + * + * This structure is used for configuration backend during registration. + */ +struct ipc_service_backend { + /** @brief Name of the IPC backend. */ + const char *name; + + /** @brief Pointer to the function that will be used to send data to the endpoint. + * + * @param ept Registered endpoint. + * @param data Pointer to the buffer to send. + * @param len Number of bytes to send. + * + * @retval Status code. + */ + int (*send)(struct ipc_ept *ept, const void *data, size_t len); + + /** @brief Pointer to the function that will be used to register endpoints. + * + * @param ept Endpoint object. + * @param cfg Endpoint configuration. + * + * @retval Status code. + */ + int (*register_endpoint)(struct ipc_ept **ept, const struct ipc_ept_cfg *cfg); +}; + +/** @brief IPC backend registration. + * + * Registration must be done before using IPC Service. + * + * @param backend Configuration of the backend. + * + * @retval -EALREADY The backend is already registered. + * @retval -EINVAL The backend configuration is incorrect. + * @retval Zero on success. + * + */ +int ipc_service_register_backend(const struct ipc_service_backend *backend); + +/** + * @} + */ + +#ifdef __cplusplus +} +#endif + +#endif /* ZEPHYR_INCLUDE_IPC_SERVICE_IPC_SERVICE_BACKEND_H_ */ diff --git a/subsys/ipc/CMakeLists.txt b/subsys/ipc/CMakeLists.txt index baf897bd5f..76bf54bcc6 100644 --- a/subsys/ipc/CMakeLists.txt +++ b/subsys/ipc/CMakeLists.txt @@ -2,3 +2,4 @@ add_subdirectory_ifdef(CONFIG_RPMSG_SERVICE rpmsg_service) add_subdirectory_ifdef(CONFIG_RPMSG_MULTI_INSTANCE rpmsg_multi_instance) +add_subdirectory_ifdef(CONFIG_IPC_SERVICE ipc_service) diff --git a/subsys/ipc/Kconfig b/subsys/ipc/Kconfig index 67b393e229..38cbf7a1ef 100644 --- a/subsys/ipc/Kconfig +++ b/subsys/ipc/Kconfig @@ -7,5 +7,6 @@ menu "Inter Processor Communication" source "subsys/ipc/rpmsg_service/Kconfig" source "subsys/ipc/rpmsg_multi_instance/Kconfig" +source "subsys/ipc/ipc_service/Kconfig" endmenu diff --git a/subsys/ipc/ipc_service/CMakeLists.txt b/subsys/ipc/ipc_service/CMakeLists.txt new file mode 100644 index 0000000000..1677a3772d --- /dev/null +++ b/subsys/ipc/ipc_service/CMakeLists.txt @@ -0,0 +1,3 @@ +# SPDX-License-Identifier: Apache-2.0 + +zephyr_sources(ipc_service.c) diff --git a/subsys/ipc/ipc_service/Kconfig b/subsys/ipc/ipc_service/Kconfig new file mode 100644 index 0000000000..62f8b9322a --- /dev/null +++ b/subsys/ipc/ipc_service/Kconfig @@ -0,0 +1,32 @@ +# Copyright (c) -2021 Nordic Semiconductor (ASA) +# SPDX-License-Identifier: Apache-2.0 + +menuconfig IPC_SERVICE + bool "IPC service support multiple backends" + help + Enables support for a service that can be shared by multiple + users. Ability to work in different backends. The backend + should be registered before application starts using + the IPC Service. + +if IPC_SERVICE + +choice IPC_SERVICE_BACKEND + prompt "IPC Service backend" + +config IPC_SERVICE_BACKEND_XYZ + bool "Example backend" + +endchoice + +config IPC_SERVICE_BACKEND_REG_PRIORITY + int "Initialization priority of modules registering IPC backend" + default 46 + help + The backend must be registered before the endpoint register. + +module = IPC_SERVICE +module-str = IPC service and backend +source "${ZEPHYR_BASE}/subsys/logging/Kconfig.template.log_config" + +endif # IPC_SERVICE \ No newline at end of file diff --git a/subsys/ipc/ipc_service/ipc_service.c b/subsys/ipc/ipc_service/ipc_service.c new file mode 100644 index 0000000000..7c2ae6957b --- /dev/null +++ b/subsys/ipc/ipc_service/ipc_service.c @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2021 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include + +#include +#include +#include + +#define LOG_MODULE_NAME ipc_service +LOG_MODULE_REGISTER(LOG_MODULE_NAME, CONFIG_IPC_SERVICE_LOG_LEVEL); + +const static struct ipc_service_backend *backend; + +int ipc_service_register_backend(const struct ipc_service_backend *bkd) +{ + if (backend) { + return -EALREADY; + } + + if (!bkd || !bkd->register_endpoint || !bkd->send) { + return -EINVAL; + } + + backend = bkd; + LOG_DBG("Registered: %s", backend->name ? backend->name : ""); + + return 0; +} + +int ipc_service_register_endpoint(struct ipc_ept **ept, const struct ipc_ept_cfg *cfg) +{ + LOG_DBG("Register endpoint %s", cfg->name ? cfg->name : ""); + if (!backend || !backend->register_endpoint) { + LOG_ERR("Backend not registered"); + return -EIO; + } + + if (!ept || !cfg) { + LOG_ERR("Invalid endpoint or configuration"); + return -EINVAL; + } + + return backend->register_endpoint(ept, cfg); +} + +int ipc_service_send(struct ipc_ept *ept, const void *data, size_t len) +{ + if (!backend || !backend->send) { + LOG_ERR("Backend not registered"); + return -EIO; + } + + return backend->send(ept, data, len); +}