#include <sys/syscall.h>
#include <sys/types.h>
#include <dirent.h>
#include <errno.h>
#include <fcntl.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <string.h>
#include <unistd.h>

#include "rmtfs.h"

#define RPROC_BASE_PATH		"/sys/bus/platform/drivers/qcom-q6v5-mss/"
#define RPROC_CLASS_PATH	"/sys/class/remoteproc/"

static pthread_t start_thread;
static pthread_t stop_thread;
static int rproc_state_fd;
static int rproc_pipe[2];

static int rproc_init_by_modalias(void)
{
	struct dirent *rproc_de;
	char modalias[256];
	DIR *base_dir;
	int modalias_fd;
	int rproc_fd;
	int state_fd = -1;
	int base_fd;
	int ret;

	base_fd = open(RPROC_CLASS_PATH, O_RDONLY | O_DIRECTORY);
	if (base_fd < 0)
		return -1;

	base_dir = fdopendir(base_fd);
	if (!base_dir) {
		fprintf(stderr, "failed to open remoteproc class path\n");
		close(base_fd);
		return -1;
	}

	while (state_fd < 0 && (rproc_de = readdir(base_dir)) != NULL) {
		if (!strcmp(rproc_de->d_name, ".") ||
		    !strcmp(rproc_de->d_name, ".."))
			continue;

		rproc_fd = openat(base_fd, rproc_de->d_name, O_RDONLY | O_DIRECTORY);
		if (rproc_fd < 0)
			continue;

		modalias_fd = openat(rproc_fd, "device/modalias", O_RDONLY);
		if (modalias_fd < 0)
			goto close_rproc_fd;

		ret = read(modalias_fd, modalias, sizeof(modalias) - 1);
		if (ret < 0)
			goto close_modalias_fd;
		modalias[ret] = '\0';

		if (!strstr(modalias, "-mpss-pas") && !strstr(modalias, "-mss-pil"))
			goto close_modalias_fd;

		state_fd = openat(rproc_fd, "state", O_WRONLY);
		if (state_fd < 0) {
			fprintf(stderr,
				"unable to open remoteproc \"state\" control file of %s\n",
				rproc_de->d_name);
		}

close_modalias_fd:
		close(modalias_fd);
close_rproc_fd:
		close(rproc_fd);
	}
	closedir(base_dir);
	close(base_fd);

	return state_fd;
}

static int rproc_init_by_mss_driver(void)
{
	struct dirent *device_de;
	struct dirent *rproc_de;
	int rproc_base_fd;
	DIR *rproc_dir;
	DIR *base_dir;
	int device_fd;
	int rproc_fd;
	int state_fd = -1;
	int base_fd;

	base_fd = open(RPROC_BASE_PATH, O_RDONLY | O_DIRECTORY);
	if (base_fd < 0)
		return -1;

	base_dir = fdopendir(base_fd);
	if (!base_dir) {
		fprintf(stderr, "failed to open mss driver path\n");
		close(base_fd);
		return -1;
	}

	while (state_fd < 0 && (device_de = readdir(base_dir)) != NULL) {
		if (!strcmp(device_de->d_name, ".") ||
		    !strcmp(device_de->d_name, ".."))
			continue;

		device_fd = openat(base_fd, device_de->d_name, O_RDONLY | O_DIRECTORY);
		if (device_fd < 0)
			continue;

		rproc_base_fd = openat(device_fd, "remoteproc", O_RDONLY | O_DIRECTORY);
		if (rproc_base_fd < 0) {
			close(device_fd);
			continue;
		}

		rproc_dir = fdopendir(rproc_base_fd);
		while (state_fd < 0 && (rproc_de = readdir(rproc_dir)) != NULL) {
			if (!strcmp(rproc_de->d_name, ".") ||
			    !strcmp(rproc_de->d_name, ".."))
				continue;

			rproc_fd = openat(rproc_base_fd, rproc_de->d_name, O_RDONLY | O_DIRECTORY);
			if (rproc_fd < 0)
				continue;

			state_fd = openat(rproc_fd, "state", O_WRONLY);
			if (state_fd < 0) {
				fprintf(stderr,
					"unable to open remoteproc \"state\" control file of %s\n",
					device_de->d_name);
			}

			close(rproc_fd);

		}
		closedir(rproc_dir);
		close(rproc_base_fd);
		close(device_fd);
	}
	closedir(base_dir);
	close(base_fd);

	return state_fd;
}

int rproc_init(void)
{
	int state_fd;
	int ret;

	state_fd = rproc_init_by_modalias();
	if (state_fd < 0) {
		state_fd = rproc_init_by_mss_driver();
		if (state_fd < 0)
			return -1;
	}

	ret = pipe(rproc_pipe);
	if (ret < 0) {
		close(state_fd);
		return -1;
	}

	rproc_state_fd = state_fd;

	return rproc_pipe[0];
}

static void *do_rproc_start(void *unused __unused)
{
	ssize_t ret;

	ret = pwrite(rproc_state_fd, "start", 5, 0);
	if (ret < 4) {
		fprintf(stderr, "failed to update start state: %s\n",
			strerror(errno));
	}

	return NULL;
}

int rproc_start()
{
	pthread_attr_t attr;

	pthread_attr_init(&attr);
	pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);

	return pthread_create(&start_thread, &attr, do_rproc_start, NULL);
}

static void *do_rproc_stop(void *unused __unused)
{
	ssize_t ret;

	ret = pwrite(rproc_state_fd, "stop", 4, 0);
	if (ret < 4) {
		fprintf(stderr, "failed to update stop state: %s\n",
			strerror(errno));
	}

	ret = write(rproc_pipe[1], "Y", 1);
	if (ret != 1) {
		fprintf(stderr, "failed to signal event loop about exit\n");
		exit(0);
	}

	return NULL;
}

int rproc_stop(void)
{
	pthread_attr_t attr;

	pthread_attr_init(&attr);
	pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);

	return pthread_create(&stop_thread, &attr, do_rproc_stop, NULL);
}
