ipc: Added IPC Service to support different transport backends
IPC Service allow plugging in different transport backends. Specifies a generic API that is implemented by the backend. Signed-off-by: Marcin Jeliński <marcin.jelinski@nordicsemi.no>
This commit is contained in:
parent
14272c2726
commit
3fcd8d1003
107
include/ipc/ipc_service.h
Normal file
107
include/ipc/ipc_service.h
Normal file
|
@ -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 <stdio.h>
|
||||||
|
|
||||||
|
#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_ */
|
72
include/ipc/ipc_service_backend.h
Normal file
72
include/ipc/ipc_service_backend.h
Normal file
|
@ -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 <ipc/ipc_service.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
#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_ */
|
|
@ -2,3 +2,4 @@
|
||||||
|
|
||||||
add_subdirectory_ifdef(CONFIG_RPMSG_SERVICE rpmsg_service)
|
add_subdirectory_ifdef(CONFIG_RPMSG_SERVICE rpmsg_service)
|
||||||
add_subdirectory_ifdef(CONFIG_RPMSG_MULTI_INSTANCE rpmsg_multi_instance)
|
add_subdirectory_ifdef(CONFIG_RPMSG_MULTI_INSTANCE rpmsg_multi_instance)
|
||||||
|
add_subdirectory_ifdef(CONFIG_IPC_SERVICE ipc_service)
|
||||||
|
|
|
@ -7,5 +7,6 @@ menu "Inter Processor Communication"
|
||||||
|
|
||||||
source "subsys/ipc/rpmsg_service/Kconfig"
|
source "subsys/ipc/rpmsg_service/Kconfig"
|
||||||
source "subsys/ipc/rpmsg_multi_instance/Kconfig"
|
source "subsys/ipc/rpmsg_multi_instance/Kconfig"
|
||||||
|
source "subsys/ipc/ipc_service/Kconfig"
|
||||||
|
|
||||||
endmenu
|
endmenu
|
||||||
|
|
3
subsys/ipc/ipc_service/CMakeLists.txt
Normal file
3
subsys/ipc/ipc_service/CMakeLists.txt
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
# SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
|
zephyr_sources(ipc_service.c)
|
32
subsys/ipc/ipc_service/Kconfig
Normal file
32
subsys/ipc/ipc_service/Kconfig
Normal file
|
@ -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
|
59
subsys/ipc/ipc_service/ipc_service.c
Normal file
59
subsys/ipc/ipc_service/ipc_service.c
Normal file
|
@ -0,0 +1,59 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2021 Nordic Semiconductor ASA
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <ipc/ipc_service.h>
|
||||||
|
#include <ipc/ipc_service_backend.h>
|
||||||
|
|
||||||
|
#include <logging/log.h>
|
||||||
|
#include <zephyr.h>
|
||||||
|
#include <device.h>
|
||||||
|
|
||||||
|
#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);
|
||||||
|
}
|
Loading…
Reference in a new issue