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_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_multi_instance/Kconfig"
|
||||
source "subsys/ipc/ipc_service/Kconfig"
|
||||
|
||||
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