/*
 * Copyright (c) 2020-2021, Nordic Semiconductor ASA
 *
 * SPDX-License-Identifier: Apache-2.0
 */

#include <zephyr/ipc/rpmsg_service.h>

#include "rpmsg_backend.h"

#include <zephyr/kernel.h>
#include <zephyr/init.h>
#include <zephyr/logging/log.h>

#include <openamp/open_amp.h>


#define LOG_MODULE_NAME rpmsg_service
LOG_MODULE_REGISTER(LOG_MODULE_NAME, CONFIG_RPMSG_SERVICE_LOG_LEVEL);

#define MASTER IS_ENABLED(CONFIG_RPMSG_SERVICE_MODE_MASTER)

static struct virtio_device vdev;
static struct rpmsg_virtio_device rvdev;
static struct metal_io_region *io;
static bool ep_crt_started;

#if MASTER
static struct rpmsg_virtio_shm_pool shpool;
#endif

static struct {
	const char *name;
	rpmsg_ept_cb cb;
	struct rpmsg_endpoint ep;
	volatile bool bound;
} endpoints[CONFIG_RPMSG_SERVICE_NUM_ENDPOINTS];

static void rpmsg_service_unbind(struct rpmsg_endpoint *ep)
{
	rpmsg_destroy_ept(ep);
}

#if MASTER

static void ns_bind_cb(struct rpmsg_device *rdev,
					const char *name,
					uint32_t dest)
{
	int err;

	for (int i = 0; i < CONFIG_RPMSG_SERVICE_NUM_ENDPOINTS; ++i) {
		if (strcmp(name, endpoints[i].name) == 0) {
			err = rpmsg_create_ept(&endpoints[i].ep,
						   rdev,
						   name,
						   RPMSG_ADDR_ANY,
						   dest,
						   endpoints[i].cb,
						   rpmsg_service_unbind);

			if (err != 0) {
				LOG_ERR("Creating remote endpoint %s"
					" failed wirh error %d", name, err);
			} else {
				endpoints[i].bound = true;
			}

			return;
		}
	}

	LOG_ERR("Remote endpoint %s not registered locally", name);
}

#endif

static int rpmsg_service_init(void)
{
	int32_t err;

	LOG_DBG("RPMsg service initialization start");

	err = rpmsg_backend_init(&io, &vdev);
	if (err) {
		LOG_ERR("RPMsg backend init failed with error %d", err);
		return err;
	}

#if MASTER
	rpmsg_virtio_init_shm_pool(&shpool, (void *)SHM_START_ADDR, SHM_SIZE);
	err = rpmsg_init_vdev(&rvdev, &vdev, ns_bind_cb, io, &shpool);
#else
	err = rpmsg_init_vdev(&rvdev, &vdev, NULL, io, NULL);
#endif

	if (err) {
		LOG_ERR("rpmsg_init_vdev failed %d", err);
		return err;
	}

	ep_crt_started = true;

#if !MASTER
	struct rpmsg_device *rdev;

	rdev = rpmsg_virtio_get_rpmsg_device(&rvdev);

	for (int i = 0; i < CONFIG_RPMSG_SERVICE_NUM_ENDPOINTS; ++i) {
		if (endpoints[i].name) {
			err = rpmsg_create_ept(&endpoints[i].ep,
						rdev,
						endpoints[i].name,
						RPMSG_ADDR_ANY,
						RPMSG_ADDR_ANY,
						endpoints[i].cb,
						rpmsg_service_unbind);

			if (err) {
				LOG_ERR("rpmsg_create_ept failed %d", err);
				return err;
			}
		}
	}
#endif

	LOG_DBG("RPMsg service initialized");

	return 0;
}

int rpmsg_service_register_endpoint(const char *name, rpmsg_ept_cb cb)
{
	if (ep_crt_started) {
		return -EINPROGRESS;
	}

	for (int i = 0; i < CONFIG_RPMSG_SERVICE_NUM_ENDPOINTS; ++i) {
		if (!endpoints[i].name) {
			endpoints[i].name = name;
			endpoints[i].cb = cb;

			return i;
		}
	}

	LOG_ERR("No free slots to register endpoint %s", name);

	return -ENOMEM;
}

bool rpmsg_service_endpoint_is_bound(int endpoint_id)
{
	return endpoints[endpoint_id].bound;
}

int rpmsg_service_send(int endpoint_id, const void *data, size_t len)
{
	return rpmsg_send(&endpoints[endpoint_id].ep, data, len);
}

SYS_INIT(rpmsg_service_init, POST_KERNEL, CONFIG_RPMSG_SERVICE_INIT_PRIORITY);
