diff --git a/include/zephyr/logging/log_multidomain_helper.h b/include/zephyr/logging/log_multidomain_helper.h new file mode 100644 index 00000000000..e67b3c75810 --- /dev/null +++ b/include/zephyr/logging/log_multidomain_helper.h @@ -0,0 +1,237 @@ +/* + * Copyright (c) 2022 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef ZEPHYR_INCLUDE_LOGGING_LOG_MULTIDOMAIN_HELPER_H_ +#define ZEPHYR_INCLUDE_LOGGING_LOG_MULTIDOMAIN_HELPER_H_ + +/* This module aims to provide baseline for links and backends and simplify + * the implementation. It is not core part of logging in similar way as + * log_output module is just a helper for log message formatting. Links and + * backends can be implemented without this helper. + */ + +/**@defgroup LOG_MULTIDOMAIN_HALPER_MESSAGE_IDS IDs of message. + * @{ + */ + +/** @brief Logging message ID. */ +#define Z_LOG_MULTIDOMAIN_ID_MSG 0 + +/** @brief Domain count request ID. */ +#define Z_LOG_MULTIDOMAIN_ID_GET_DOMAIN_CNT 1 + +/** @brief Source count request ID. */ +#define Z_LOG_MULTIDOMAIN_ID_GET_SOURCE_CNT 2 + +/** @brief Domain name request ID. */ +#define Z_LOG_MULTIDOMAIN_ID_GET_DOMAIN_NAME 3 + +/** @brief Source name request ID. */ +#define Z_LOG_MULTIDOMAIN_ID_GET_SOURCE_NAME 4 + +/** @brief Compile time and run-time levels request ID. */ +#define Z_LOG_MULTIDOMAIN_ID_GET_LEVELS 5 + +/** @brief Setting run-time level ID. */ +#define Z_LOG_MULTIDOMAIN_ID_SET_RUNTIME_LEVEL 6 + +/** @brief Get number of dropped message ID. */ +#define Z_LOG_MULTIDOMAIN_ID_DROPPED 7 + +/** @brief Link-backend readiness indication ID/ */ +#define Z_LOG_MULTIDOMAIN_ID_READY 8 + +/**@} */ + +/**@defgroup LOG_MULTIDOMAIN_STATUS. + * @{ + */ + +/** @brief OK. */ +#define Z_LOG_MULTIDOMAIN_STATUS_OK 0 +/** @brief Error. */ +#define Z_LOG_MULTIDOMAIN_STATUS_ERR 1 + +/**@} */ + +/** @brief Content of the logging message. */ +struct log_multidomain_log_msg { + uint8_t data[0]; +} __packed; + +/** @brief Content of the domain count message. */ +struct log_multidomain_domain_cnt { + uint16_t count; +} __packed; + +/** @brief Content of the source count message. */ +struct log_multidomain_source_cnt { + uint8_t domain_id; + uint16_t count; +} __packed; + +/** @brief Content of the domain name message. */ +struct log_multidomain_domain_name { + uint8_t domain_id; + char name[0]; +} __packed; + +/** @brief Content of the source name message. */ +struct log_multidomain_source_name { + uint8_t domain_id; + uint16_t source_id; + char name[0]; +} __packed; + +/** @brief Content of the message for getting logging levels. */ +struct log_multidomain_levels { + uint8_t domain_id; + uint16_t source_id; + uint8_t level; + uint8_t runtime_level; +} __packed; + +/** @brief Content of the message for setting logging level. */ +struct log_multidomain_set_runtime_level { + uint8_t domain_id; + uint16_t source_id; + uint8_t runtime_level; +} __packed; + +/** @brief Content of the message for getting amount of dropped messages. */ +struct log_multidomain_dropped { + uint32_t dropped; +} __packed; + +/** @brief Union with all message types. */ +union log_multidomain_msg_data { + struct log_multidomain_log_msg log_msg; + struct log_multidomain_domain_cnt domain_cnt; + struct log_multidomain_source_cnt source_cnt; + struct log_multidomain_domain_name domain_name; + struct log_multidomain_source_name source_name; + struct log_multidomain_levels levels; + struct log_multidomain_set_runtime_level set_rt_level; + struct log_multidomain_dropped dropped; +}; + +/** @brief Message. */ +struct log_multidomain_msg { + uint8_t id; + uint8_t status; + union log_multidomain_msg_data data; +} __packed; + +/** @brief Forward declaration. */ +struct log_multidomain_link; + +/** @brief Structure with link transport API. */ +struct log_multidomain_link_transport_api { + int (*init)(struct log_multidomain_link *link); + int (*send)(struct log_multidomain_link *link, void *data, size_t len); +}; + +/** @brief Union for holding data returned by associated remote backend. */ +union log_multidomain_link_dst { + uint16_t count; + + struct { + char *dst; + size_t *len; + } name; + + struct { + uint8_t level; + uint8_t runtime_level; + } levels; + + struct { + uint8_t level; + } set_runtime_level; +}; + +/** @brief Remote link API. */ +extern struct log_link_api log_multidomain_link_api; + +/** @brief Remote link structure. */ +struct log_multidomain_link { + const struct log_multidomain_link_transport_api *transport_api; + struct k_sem rdy_sem; + const struct log_link *link; + union log_multidomain_link_dst dst; + int status; + bool ready; +}; + +/** @brief Forward declaration. */ +struct log_multidomain_backend; + +/** @brief Backend transport API. */ +struct log_multidomain_backend_transport_api { + int (*init)(struct log_multidomain_backend *backend); + int (*send)(struct log_multidomain_backend *backend, void *data, size_t len); +}; + +/** @brief Remote backend API. */ +extern const struct log_backend_api log_multidomain_backend_api; + +/** @brief Remote backend structure. */ +struct log_multidomain_backend { + const struct log_multidomain_backend_transport_api *transport_api; + const struct log_backend *log_backend; + struct k_sem rdy_sem; + bool panic; + int status; + bool ready; +}; + +/** @brief Function to be called when data is received from remote. + * + * @param link Link instance. + * @param data Data. + * @param len Data length. + */ +void log_multidomain_link_on_recv_cb(struct log_multidomain_link *link, + const void *data, size_t len); + +/** @brief Function called on error reported by transport layer. + * + * @param link Link instance. + * @param err Error code. + */ +void log_multidomain_link_on_error(struct log_multidomain_link *link, int err); + +/** @brief Function called when connection with remote is established. + * + * @param link Link instance. + * @param err Error code. + */ +void log_multidomain_link_on_started(struct log_multidomain_link *link, int err); + +/** @brief Function to be called when data is received from remote. + * + * @param backend Backend instance. + * @param data Data. + * @param len Data length. + */ +void log_multidomain_backend_on_recv_cb(struct log_multidomain_backend *backend, + const void *data, size_t len); + +/** @brief Function called on error reported by transport layer. + * + * @param backend Backend instance. + * @param err Error code. + */ +void log_multidomain_backend_on_error(struct log_multidomain_backend *backend, int err); + +/** @brief Function called when connection with remote is established. + * + * @param backend Backend instance. + * @param err Error code. + */ +void log_multidomain_backend_on_started(struct log_multidomain_backend *backend, int err); + +#endif /* ZEPHYR_INCLUDE_LOGGING_LOG_MULTIDOMAIN_HELPER_H_ */ diff --git a/subsys/logging/CMakeLists.txt b/subsys/logging/CMakeLists.txt index cfcce45b079..3591f345281 100644 --- a/subsys/logging/CMakeLists.txt +++ b/subsys/logging/CMakeLists.txt @@ -65,6 +65,13 @@ if(NOT CONFIG_LOG_MODE_MINIMAL) zephyr_sources(log_output_custom.c) endif() + zephyr_sources_ifdef( + CONFIG_LOG_MULTIDOMAIN_LINK + log_multidomain_link.c + ) + + endif() + else() zephyr_sources(log_minimal.c) endif() diff --git a/subsys/logging/Kconfig b/subsys/logging/Kconfig index 269357bd7fc..83020b388f6 100644 --- a/subsys/logging/Kconfig +++ b/subsys/logging/Kconfig @@ -36,6 +36,12 @@ rsource "Kconfig.frontends" endif #LOG_FRONTEND +if LOG_MULTIDOMAIN + +rsource "Kconfig.links" + +endif + rsource "Kconfig.misc" endif # LOG diff --git a/subsys/logging/Kconfig.links b/subsys/logging/Kconfig.links new file mode 100644 index 00000000000..0aa6828d0a1 --- /dev/null +++ b/subsys/logging/Kconfig.links @@ -0,0 +1,6 @@ +# Copyright (c) 2022 Nordic Semiconductor ASA +# SPDX-License-Identifier: Apache-2.0 + +config LOG_MULTIDOMAIN_LINK + bool + select LOG_TIMESTAMP_64BIT diff --git a/subsys/logging/backends/CMakeLists.txt b/subsys/logging/backends/CMakeLists.txt index cdadfa16dc5..149e3f53c2f 100644 --- a/subsys/logging/backends/CMakeLists.txt +++ b/subsys/logging/backends/CMakeLists.txt @@ -64,3 +64,8 @@ zephyr_sources_ifdef( CONFIG_LOG_BACKEND_XTENSA_SIM log_backend_xtensa_sim.c ) + +zephyr_sources_ifdef( + CONFIG_LOG_MULTIDOMAIN_BACKEND + log_multidomain_backend.c +) diff --git a/subsys/logging/backends/Kconfig b/subsys/logging/backends/Kconfig index 7d60b19e936..a329a10aeaf 100644 --- a/subsys/logging/backends/Kconfig +++ b/subsys/logging/backends/Kconfig @@ -15,5 +15,6 @@ rsource "Kconfig.spinel" rsource "Kconfig.swo" rsource "Kconfig.uart" rsource "Kconfig.xtensa_sim" +rsource "Kconfig.multidomain" endmenu diff --git a/subsys/logging/backends/Kconfig.multidomain b/subsys/logging/backends/Kconfig.multidomain new file mode 100644 index 00000000000..8f6dc2565aa --- /dev/null +++ b/subsys/logging/backends/Kconfig.multidomain @@ -0,0 +1,7 @@ +# Copyright (c) 2022 Nordic Semiconductor ASA +# SPDX-License-Identifier: Apache-2.0 + +config LOG_MULTIDOMAIN_BACKEND + bool + select LOG_TIMESTAMP_64BIT + select LOG_MSG_APPEND_RO_STRING_LOC diff --git a/subsys/logging/backends/log_multidomain_backend.c b/subsys/logging/backends/log_multidomain_backend.c new file mode 100644 index 00000000000..652dd0b06fe --- /dev/null +++ b/subsys/logging/backends/log_multidomain_backend.c @@ -0,0 +1,246 @@ +/* + * Copyright (c) 2021 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include +#include +#include +#include + +static void process(const struct log_backend *const backend, + union log_msg_generic *msg) +{ + int err; + struct log_multidomain_backend *backend_remote = backend->cb->ctx; + uint32_t dlen = msg->log.hdr.desc.data_len; + int fsc_plen; + + if (backend_remote->panic) { + return; + } + + fsc_plen = cbprintf_fsc_package(msg->log.data, + msg->log.hdr.desc.package_len, + NULL, + 0); + if (fsc_plen < 0) { + __ASSERT_NO_MSG(false); + return; + } + + /* Need to ensure that package is aligned to a pointer size. */ + uint32_t msg_len = Z_LOG_MSG2_LEN(fsc_plen, dlen); + uint8_t buf[msg_len + sizeof(void *)] __aligned(sizeof(void *)); + size_t msg_offset = offsetof(struct log_multidomain_msg, data); + struct log_multidomain_msg *out_msg = + (struct log_multidomain_msg *)&buf[sizeof(void *) - msg_offset]; + struct log_msg *out_log_msg = (struct log_msg *)out_msg->data.log_msg.data; + + /* Set ipc message id. */ + out_msg->id = Z_LOG_MULTIDOMAIN_ID_MSG; + out_msg->status = Z_LOG_MULTIDOMAIN_STATUS_OK; + /* Copy log message header. */ + memcpy(&out_log_msg->hdr, &msg->log.hdr, sizeof(struct log_msg_hdr)); + /* Update package len field in the message descriptor. */ + out_log_msg->hdr.desc.package_len = fsc_plen; + + out_log_msg->hdr.source = out_log_msg->hdr.source ? + (const void *)(IS_ENABLED(CONFIG_LOG_RUNTIME_FILTERING) ? + log_dynamic_source_id((void *)out_log_msg->hdr.source) : + log_const_source_id((void *)out_log_msg->hdr.source)) : + (const void *)-1; + + /* Fill new package. */ + fsc_plen = cbprintf_fsc_package(msg->log.data, msg->log.hdr.desc.package_len, + out_log_msg->data, fsc_plen); + if (fsc_plen < 0) { + __ASSERT_NO_MSG(false); + return; + } + + /* Copy data */ + if (dlen) { + memcpy(&out_log_msg->data[fsc_plen], + &msg->log.data[msg->log.hdr.desc.package_len], + dlen); + } + + err = backend_remote->transport_api->send(backend_remote, out_msg, msg_len + msg_offset); + if (err < 0) { + __ASSERT(false, "Unexpected error: %d\n", err); + return; + } +} + +void log_multidomain_backend_on_started(struct log_multidomain_backend *backend_remote, int err) +{ + backend_remote->status = err; + + k_sem_give(&backend_remote->rdy_sem); +} + +void log_multidomain_backend_on_error(struct log_multidomain_backend *backend_remote, int err) +{ + backend_remote->status = err; +} + +static void get_name_response(struct log_multidomain_backend *backend_remote, + uint8_t domain_id, uint16_t source_id, + bool domain_name) +{ + const char *name = domain_name ? + log_domain_name_get(domain_id) : + log_source_name_get(domain_id, source_id); + size_t slen = strlen(name); + size_t msg_offset = offsetof(struct log_multidomain_msg, data); + size_t msg_size = slen + 1 + msg_offset + + (domain_name ? sizeof(struct log_multidomain_domain_name) : + sizeof(struct log_multidomain_source_name)); + uint8_t msg_buf[msg_size]; + struct log_multidomain_msg *outmsg = (struct log_multidomain_msg *)msg_buf; + char *dst = domain_name ? + outmsg->data.domain_name.name : + outmsg->data.source_name.name; + int err; + + outmsg->id = domain_name ? Z_LOG_MULTIDOMAIN_ID_GET_DOMAIN_NAME : + Z_LOG_MULTIDOMAIN_ID_GET_SOURCE_NAME; + outmsg->status = Z_LOG_MULTIDOMAIN_STATUS_OK; + memcpy(dst, name, slen); + dst[slen] = '\0'; + + if (domain_name) { + outmsg->data.domain_name.domain_id = domain_id; + } else { + outmsg->data.source_name.domain_id = domain_id; + outmsg->data.source_name.source_id = source_id; + } + + err = backend_remote->transport_api->send(backend_remote, outmsg, msg_size); + __ASSERT_NO_MSG(err >= 0); +} + +void log_multidomain_backend_on_recv_cb(struct log_multidomain_backend *backend_remote, + const void *data, size_t len) +{ + struct log_multidomain_msg *msg = (struct log_multidomain_msg *)data; + struct log_multidomain_msg outmsg = { + .id = msg->id, + .status = Z_LOG_MULTIDOMAIN_STATUS_OK + }; + int err; + + memcpy(&outmsg, msg, sizeof(struct log_multidomain_msg)); + + switch (msg->id) { + case Z_LOG_MULTIDOMAIN_ID_GET_DOMAIN_CNT: + outmsg.data.domain_cnt.count = log_domains_count(); + break; + + case Z_LOG_MULTIDOMAIN_ID_GET_SOURCE_CNT: + outmsg.data.source_cnt.count = + log_src_cnt_get(msg->data.source_cnt.domain_id); + break; + + case Z_LOG_MULTIDOMAIN_ID_GET_DOMAIN_NAME: + get_name_response(backend_remote, + msg->data.domain_name.domain_id, + 0, true); + return; + + case Z_LOG_MULTIDOMAIN_ID_GET_SOURCE_NAME: + get_name_response(backend_remote, + msg->data.source_name.domain_id, + msg->data.source_name.source_id, + false); + return; + + case Z_LOG_MULTIDOMAIN_ID_GET_LEVELS: + outmsg.data.levels.level = + log_filter_get(backend_remote->log_backend, + outmsg.data.levels.domain_id, + outmsg.data.levels.source_id, + false); + outmsg.data.levels.runtime_level = + log_filter_get(backend_remote->log_backend, + outmsg.data.levels.domain_id, + outmsg.data.levels.source_id, + true); + break; + case Z_LOG_MULTIDOMAIN_ID_SET_RUNTIME_LEVEL: + outmsg.data.set_rt_level.runtime_level = + log_filter_set(backend_remote->log_backend, + outmsg.data.set_rt_level.domain_id, + outmsg.data.set_rt_level.source_id, + outmsg.data.set_rt_level.runtime_level); + break; + case Z_LOG_MULTIDOMAIN_ID_READY: + backend_remote->ready = true; + break; + default: + __ASSERT(0, "Unexpected message"); + break; + } + + err = backend_remote->transport_api->send(backend_remote, &outmsg, sizeof(outmsg)); + __ASSERT_NO_MSG(err >= 0); +} + +static void init(struct log_backend const *const backend) +{ + struct log_multidomain_backend *backend_remote = backend->cb->ctx; + int err; + + backend_remote->log_backend = backend; + k_sem_init(&backend_remote->rdy_sem, 0, 1); + + err = backend_remote->transport_api->init(backend_remote); + __ASSERT_NO_MSG(err >= 0); + + err = k_sem_take(&backend_remote->rdy_sem, K_MSEC(4000)); + __ASSERT_NO_MSG(err >= 0); +} + +static int is_ready(struct log_backend const *const backend) +{ + struct log_multidomain_backend *backend_remote = backend->cb->ctx; + + return backend_remote->ready ? 0 : -EINPROGRESS; +} + +static void panic(struct log_backend const *const backend) +{ + struct log_multidomain_backend *backend_remote = backend->cb->ctx; + + backend_remote->panic = true; +} + +static void dropped(const struct log_backend *const backend, uint32_t cnt) +{ + struct log_multidomain_backend *backend_remote = backend->cb->ctx; + int err; + struct log_multidomain_msg msg = { + .id = Z_LOG_MULTIDOMAIN_ID_DROPPED, + .status = Z_LOG_MULTIDOMAIN_STATUS_OK, + .data = { + .dropped = { + .dropped = cnt + } + } + }; + + err = backend_remote->transport_api->send(backend_remote, &msg, sizeof(msg)); + __ASSERT_NO_MSG(err >= 0); +} + +const struct log_backend_api log_multidomain_backend_api = { + .process = process, + .panic = panic, + .dropped = dropped, + .init = init, + .is_ready = is_ready +}; diff --git a/subsys/logging/log_multidomain_link.c b/subsys/logging/log_multidomain_link.c new file mode 100644 index 00000000000..c730f405455 --- /dev/null +++ b/subsys/logging/log_multidomain_link.c @@ -0,0 +1,325 @@ +/* + * Copyright (c) 2021 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include +#include +#include +#include + +LOG_MODULE_DECLARE(link_ipc); + +void log_multidomain_link_on_error(struct log_multidomain_link *link_remote, int err) +{ + link_remote->status = err; +} + +void log_multidomain_link_on_started(struct log_multidomain_link *link_remote, int err) +{ + link_remote->status = err; + + if (err == 0) { + link_remote->ready = true; + } +} + +void log_multidomain_link_on_recv_cb(struct log_multidomain_link *link_remote, + const void *data, size_t len) +{ + struct log_multidomain_msg *msg = (struct log_multidomain_msg *)data; + + if (msg->status != Z_LOG_MULTIDOMAIN_STATUS_OK) { + link_remote->status = -EIO; + goto exit; + } else { + link_remote->status = 0; + } + + switch (msg->id) { + case Z_LOG_MULTIDOMAIN_ID_MSG: + z_log_msg_enqueue(link_remote->link, + msg->data.log_msg.data, + len - offsetof(struct log_multidomain_msg, data)); + return; + case Z_LOG_MULTIDOMAIN_ID_GET_DOMAIN_CNT: + link_remote->dst.count = msg->data.domain_cnt.count; + break; + case Z_LOG_MULTIDOMAIN_ID_GET_SOURCE_CNT: + link_remote->dst.count = msg->data.source_cnt.count; + break; + case Z_LOG_MULTIDOMAIN_ID_GET_DOMAIN_NAME: + { + size_t slen = MIN(len - 1, *link_remote->dst.name.len - 1); + + *link_remote->dst.name.len = len - 1; + memcpy(link_remote->dst.name.dst, msg->data.domain_name.name, slen); + link_remote->dst.name.dst[slen] = '\0'; + break; + } + case Z_LOG_MULTIDOMAIN_ID_GET_SOURCE_NAME: + { + size_t slen = MIN(len - 1, *link_remote->dst.name.len - 1); + + *link_remote->dst.name.len = len - 1; + memcpy(link_remote->dst.name.dst, msg->data.source_name.name, slen); + link_remote->dst.name.dst[slen] = '\0'; + break; + } + case Z_LOG_MULTIDOMAIN_ID_GET_LEVELS: + link_remote->dst.levels.level = msg->data.levels.level; + link_remote->dst.levels.runtime_level = msg->data.levels.runtime_level; + break; + case Z_LOG_MULTIDOMAIN_ID_SET_RUNTIME_LEVEL: + link_remote->dst.set_runtime_level.level = msg->data.set_rt_level.runtime_level; + break; + case Z_LOG_MULTIDOMAIN_ID_READY: + break; + default: + __ASSERT(0, "Unexpected message"); + break; + } + +exit: + k_sem_give(&link_remote->rdy_sem); +} + +static int getter_msg_process(struct log_multidomain_link *link_remote, + struct log_multidomain_msg *msg, size_t msg_size) +{ + int err; + + err = link_remote->transport_api->send(link_remote, msg, msg_size); + if (err < 0) { + return err; + } + + err = k_sem_take(&link_remote->rdy_sem, K_MSEC(1000)); + if (err < 0) { + return err; + } + + return (link_remote->status == Z_LOG_MULTIDOMAIN_STATUS_OK) ? 0 : -EIO; +} + +static int link_remote_get_domain_count(struct log_multidomain_link *link_remote, + uint16_t *cnt) +{ + int err; + struct log_multidomain_msg msg = { + .id = Z_LOG_MULTIDOMAIN_ID_GET_DOMAIN_CNT, + }; + + err = getter_msg_process(link_remote, &msg, sizeof(msg)); + if (err < 0) { + return err; + } + + *cnt = link_remote->dst.count; + + return 0; +} + +static int link_remote_get_source_count(struct log_multidomain_link *link_remote, + uint32_t domain_id, + uint16_t *cnt) +{ + int err; + struct log_multidomain_msg msg = { + .id = Z_LOG_MULTIDOMAIN_ID_GET_SOURCE_CNT, + .data = { .source_cnt = { .domain_id = domain_id } } + }; + + err = getter_msg_process(link_remote, &msg, sizeof(msg)); + if (err < 0) { + return err; + } + + *cnt = link_remote->dst.count; + + return 0; +} + +static int link_remote_ready(struct log_multidomain_link *link_remote) +{ + int err; + struct log_multidomain_msg msg = { + .id = Z_LOG_MULTIDOMAIN_ID_READY + }; + + err = getter_msg_process(link_remote, &msg, sizeof(msg)); + if (err < 0) { + return err; + } + + return 0; +} + +static int link_remote_initiate(const struct log_link *link, + struct log_link_config *config) +{ + struct log_multidomain_link *link_remote = link->ctx; + + link_remote->link = link; + k_sem_init(&link_remote->rdy_sem, 0, 1); + + return link_remote->transport_api->init(link_remote); +} + +static int link_remote_activate(const struct log_link *link) +{ + struct log_multidomain_link *link_remote = link->ctx; + int err; + + if (!link_remote->ready) { + return -EINPROGRESS; + } + + if (link_remote->status != 0) { + return link_remote->status; + } + + uint16_t cnt; + + err = link_remote_get_domain_count(link_remote, &cnt); + if (err < 0) { + return err; + } + + if (cnt > ARRAY_SIZE(link->ctrl_blk->source_cnt)) { + __ASSERT(0, "Number of domains not supported."); + return -ENOMEM; + } + + link->ctrl_blk->domain_cnt = cnt; + for (int i = 0; i < link->ctrl_blk->domain_cnt; i++) { + err = link_remote_get_source_count(link_remote, i, &cnt); + if (err < 0) { + return err; + } + + link->ctrl_blk->source_cnt[i] = cnt; + } + + err = link_remote_ready(link_remote); + + return err; +} + +static int link_remote_get_domain_name(const struct log_link *link, + uint32_t domain_id, + char *name, uint32_t *length) +{ + struct log_multidomain_link *link_remote = link->ctx; + struct log_multidomain_msg msg = { + .id = Z_LOG_MULTIDOMAIN_ID_GET_DOMAIN_NAME, + .data = { .domain_name = { .domain_id = domain_id } } + }; + int err; + + + link_remote->dst.name.dst = name; + link_remote->dst.name.len = length; + + err = getter_msg_process(link_remote, &msg, sizeof(msg)); + if (err < 0) { + return err; + } + + return 0; +} + +static int link_remote_get_source_name(const struct log_link *link, + uint32_t domain_id, uint16_t source_id, + char *name, size_t *length) +{ + struct log_multidomain_link *link_remote = link->ctx; + struct log_multidomain_msg msg = { + .id = Z_LOG_MULTIDOMAIN_ID_GET_SOURCE_NAME, + .data = { + .source_name = { + .domain_id = domain_id, + .source_id = source_id + } + } + }; + int err; + + link_remote->dst.name.dst = name; + link_remote->dst.name.len = length; + + err = getter_msg_process(link_remote, &msg, sizeof(msg)); + if (err < 0) { + return err; + } + + return 0; +} + +static int link_remote_get_levels(const struct log_link *link, + uint32_t domain_id, uint16_t source_id, + uint8_t *level, uint8_t *runtime_level) +{ + struct log_multidomain_link *link_remote = link->ctx; + struct log_multidomain_msg msg = { + .id = Z_LOG_MULTIDOMAIN_ID_GET_LEVELS, + .data = { + .levels = { + .domain_id = domain_id, + .source_id = source_id + } + } + }; + int err; + + err = getter_msg_process(link_remote, &msg, sizeof(msg)); + if (err < 0) { + return err; + } + + if (level) { + *level = link_remote->dst.levels.level; + } + if (runtime_level) { + *runtime_level = link_remote->dst.levels.runtime_level; + } + + return 0; +} + +static int link_remote_set_runtime_level(const struct log_link *link, + uint32_t domain_id, uint16_t source_id, + uint8_t level) +{ + struct log_multidomain_link *link_remote = link->ctx; + struct log_multidomain_msg msg = { + .id = Z_LOG_MULTIDOMAIN_ID_SET_RUNTIME_LEVEL, + .data = { + .set_rt_level = { + .domain_id = domain_id, + .source_id = source_id, + .runtime_level = level + } + } + }; + int err; + + err = getter_msg_process(link_remote, &msg, sizeof(msg)); + if (err < 0) { + return err; + } + + return 0; +} + +struct log_link_api log_multidomain_link_api = { + .initiate = link_remote_initiate, + .activate = link_remote_activate, + .get_domain_name = link_remote_get_domain_name, + .get_source_name = link_remote_get_source_name, + .get_levels = link_remote_get_levels, + .set_runtime_level = link_remote_set_runtime_level +};