// SPDX-License-Identifier: GPL-2.0
/*
 * GPIO mockup cdev test helper
 *
 * Copyright (C) 2020 Kent Gibson
 */

#include <errno.h>
#include <fcntl.h>
#include <signal.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <linux/gpio.h>

#define CONSUMER	"gpio-mockup-cdev"

static int request_line_v2(int cfd, unsigned int offset,
			   uint64_t flags, unsigned int val)
{
	struct gpio_v2_line_request req;
	int ret;

	memset(&req, 0, sizeof(req));
	req.num_lines = 1;
	req.offsets[0] = offset;
	req.config.flags = flags;
	strcpy(req.consumer, CONSUMER);
	if (flags & GPIO_V2_LINE_FLAG_OUTPUT) {
		req.config.num_attrs = 1;
		req.config.attrs[0].mask = 1;
		req.config.attrs[0].attr.id = GPIO_V2_LINE_ATTR_ID_OUTPUT_VALUES;
		if (val)
			req.config.attrs[0].attr.values = 1;
	}
	ret = ioctl(cfd, GPIO_V2_GET_LINE_IOCTL, &req);
	if (ret == -1)
		return -errno;
	return req.fd;
}


static int get_value_v2(int lfd)
{
	struct gpio_v2_line_values vals;
	int ret;

	memset(&vals, 0, sizeof(vals));
	vals.mask = 1;
	ret = ioctl(lfd, GPIO_V2_LINE_GET_VALUES_IOCTL, &vals);
	if (ret == -1)
		return -errno;
	return vals.bits & 0x1;
}

static int request_line_v1(int cfd, unsigned int offset,
			   uint32_t flags, unsigned int val)
{
	struct gpiohandle_request req;
	int ret;

	memset(&req, 0, sizeof(req));
	req.lines = 1;
	req.lineoffsets[0] = offset;
	req.flags = flags;
	strcpy(req.consumer_label, CONSUMER);
	if (flags & GPIOHANDLE_REQUEST_OUTPUT)
		req.default_values[0] = val;

	ret = ioctl(cfd, GPIO_GET_LINEHANDLE_IOCTL, &req);
	if (ret == -1)
		return -errno;
	return req.fd;
}

static int get_value_v1(int lfd)
{
	struct gpiohandle_data vals;
	int ret;

	memset(&vals, 0, sizeof(vals));
	ret = ioctl(lfd, GPIOHANDLE_GET_LINE_VALUES_IOCTL, &vals);
	if (ret == -1)
		return -errno;
	return vals.values[0];
}

static void usage(char *prog)
{
	printf("Usage: %s [-l] [-b <bias>] [-s <value>] [-u <uAPI>] <gpiochip> <offset>\n", prog);
	printf("        -b: set line bias to one of pull-down, pull-up, disabled\n");
	printf("               (default is to leave bias unchanged):\n");
	printf("        -l: set line active low (default is active high)\n");
	printf("        -s: set line value (default is to get line value)\n");
	printf("        -u: uAPI version to use (default is 2)\n");
	exit(-1);
}

static int wait_signal(void)
{
	int sig;
	sigset_t wset;

	sigemptyset(&wset);
	sigaddset(&wset, SIGHUP);
	sigaddset(&wset, SIGINT);
	sigaddset(&wset, SIGTERM);
	sigwait(&wset, &sig);

	return sig;
}

int main(int argc, char *argv[])
{
	char *chip;
	int opt, ret, cfd, lfd;
	unsigned int offset, val, abiv;
	uint32_t flags_v1;
	uint64_t flags_v2;

	abiv = 2;
	ret = 0;
	flags_v1 = GPIOHANDLE_REQUEST_INPUT;
	flags_v2 = GPIO_V2_LINE_FLAG_INPUT;

	while ((opt = getopt(argc, argv, "lb:s:u:")) != -1) {
		switch (opt) {
		case 'l':
			flags_v1 |= GPIOHANDLE_REQUEST_ACTIVE_LOW;
			flags_v2 |= GPIO_V2_LINE_FLAG_ACTIVE_LOW;
			break;
		case 'b':
			if (strcmp("pull-up", optarg) == 0) {
				flags_v1 |= GPIOHANDLE_REQUEST_BIAS_PULL_UP;
				flags_v2 |= GPIO_V2_LINE_FLAG_BIAS_PULL_UP;
			} else if (strcmp("pull-down", optarg) == 0) {
				flags_v1 |= GPIOHANDLE_REQUEST_BIAS_PULL_DOWN;
				flags_v2 |= GPIO_V2_LINE_FLAG_BIAS_PULL_DOWN;
			} else if (strcmp("disabled", optarg) == 0) {
				flags_v1 |= GPIOHANDLE_REQUEST_BIAS_DISABLE;
				flags_v2 |= GPIO_V2_LINE_FLAG_BIAS_DISABLED;
			}
			break;
		case 's':
			val = atoi(optarg);
			flags_v1 &= ~GPIOHANDLE_REQUEST_INPUT;
			flags_v1 |= GPIOHANDLE_REQUEST_OUTPUT;
			flags_v2 &= ~GPIO_V2_LINE_FLAG_INPUT;
			flags_v2 |= GPIO_V2_LINE_FLAG_OUTPUT;
			break;
		case 'u':
			abiv = atoi(optarg);
			break;
		default:
			usage(argv[0]);
		}
	}

	if (argc < optind + 2)
		usage(argv[0]);

	chip = argv[optind];
	offset = atoi(argv[optind + 1]);

	cfd = open(chip, 0);
	if (cfd == -1) {
		fprintf(stderr, "Failed to open %s: %s\n", chip, strerror(errno));
		return -errno;
	}

	if (abiv == 1)
		lfd = request_line_v1(cfd, offset, flags_v1, val);
	else
		lfd = request_line_v2(cfd, offset, flags_v2, val);

	close(cfd);

	if (lfd < 0) {
		fprintf(stderr, "Failed to request %s:%d: %s\n", chip, offset, strerror(-lfd));
		return lfd;
	}

	if (flags_v2 & GPIO_V2_LINE_FLAG_OUTPUT) {
		wait_signal();
	} else {
		if (abiv == 1)
			ret = get_value_v1(lfd);
		else
			ret = get_value_v2(lfd);
	}

	close(lfd);

	return ret;
}
