/* * 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_DROPPED: return; case Z_LOG_MULTIDOMAIN_ID_READY: break; default: __ASSERT(0, "Unexpected message"); return; } 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 };