/* * 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 };