// SPDX-License-Identifier: GPL-2.0-only
/*
 * lsgpio - example on how to list the GPIO lines on a system
 *
 * Copyright (C) 2015 Linus Walleij
 *
 * Usage:
 *	lsgpio <-n device-name>
 */

#include <unistd.h>
#include <stdlib.h>
#include <stdbool.h>
#include <stdio.h>
#include <dirent.h>
#include <errno.h>
#include <string.h>
#include <poll.h>
#include <fcntl.h>
#include <getopt.h>
#include <sys/ioctl.h>
#include <linux/gpio.h>

#include "gpio-utils.h"

struct gpio_flag {
	char *name;
	unsigned long long mask;
};

struct gpio_flag flagnames[] = {
	{
		.name = "used",
		.mask = GPIO_V2_LINE_FLAG_USED,
	},
	{
		.name = "input",
		.mask = GPIO_V2_LINE_FLAG_INPUT,
	},
	{
		.name = "output",
		.mask = GPIO_V2_LINE_FLAG_OUTPUT,
	},
	{
		.name = "active-low",
		.mask = GPIO_V2_LINE_FLAG_ACTIVE_LOW,
	},
	{
		.name = "open-drain",
		.mask = GPIO_V2_LINE_FLAG_OPEN_DRAIN,
	},
	{
		.name = "open-source",
		.mask = GPIO_V2_LINE_FLAG_OPEN_SOURCE,
	},
	{
		.name = "pull-up",
		.mask = GPIO_V2_LINE_FLAG_BIAS_PULL_UP,
	},
	{
		.name = "pull-down",
		.mask = GPIO_V2_LINE_FLAG_BIAS_PULL_DOWN,
	},
	{
		.name = "bias-disabled",
		.mask = GPIO_V2_LINE_FLAG_BIAS_DISABLED,
	},
	{
		.name = "clock-realtime",
		.mask = GPIO_V2_LINE_FLAG_EVENT_CLOCK_REALTIME,
	},
};

static void print_attributes(struct gpio_v2_line_info *info)
{
	int i;
	const char *field_format = "%s";

	for (i = 0; i < ARRAY_SIZE(flagnames); i++) {
		if (info->flags & flagnames[i].mask) {
			fprintf(stdout, field_format, flagnames[i].name);
			field_format = ", %s";
		}
	}

	if ((info->flags & GPIO_V2_LINE_FLAG_EDGE_RISING) &&
	    (info->flags & GPIO_V2_LINE_FLAG_EDGE_FALLING))
		fprintf(stdout, field_format, "both-edges");
	else if (info->flags & GPIO_V2_LINE_FLAG_EDGE_RISING)
		fprintf(stdout, field_format, "rising-edge");
	else if (info->flags & GPIO_V2_LINE_FLAG_EDGE_FALLING)
		fprintf(stdout, field_format, "falling-edge");

	for (i = 0; i < info->num_attrs; i++) {
		if (info->attrs[i].id == GPIO_V2_LINE_ATTR_ID_DEBOUNCE)
			fprintf(stdout, ", debounce_period=%dusec",
				info->attrs[0].debounce_period_us);
	}
}

int list_device(const char *device_name)
{
	struct gpiochip_info cinfo;
	char *chrdev_name;
	int fd;
	int ret;
	int i;

	ret = asprintf(&chrdev_name, "/dev/%s", device_name);
	if (ret < 0)
		return -ENOMEM;

	fd = open(chrdev_name, 0);
	if (fd == -1) {
		ret = -errno;
		fprintf(stderr, "Failed to open %s\n", chrdev_name);
		goto exit_free_name;
	}

	/* Inspect this GPIO chip */
	ret = ioctl(fd, GPIO_GET_CHIPINFO_IOCTL, &cinfo);
	if (ret == -1) {
		ret = -errno;
		perror("Failed to issue CHIPINFO IOCTL\n");
		goto exit_close_error;
	}
	fprintf(stdout, "GPIO chip: %s, \"%s\", %u GPIO lines\n",
		cinfo.name, cinfo.label, cinfo.lines);

	/* Loop over the lines and print info */
	for (i = 0; i < cinfo.lines; i++) {
		struct gpio_v2_line_info linfo;

		memset(&linfo, 0, sizeof(linfo));
		linfo.offset = i;

		ret = ioctl(fd, GPIO_V2_GET_LINEINFO_IOCTL, &linfo);
		if (ret == -1) {
			ret = -errno;
			perror("Failed to issue LINEINFO IOCTL\n");
			goto exit_close_error;
		}
		fprintf(stdout, "\tline %2d:", linfo.offset);
		if (linfo.name[0])
			fprintf(stdout, " \"%s\"", linfo.name);
		else
			fprintf(stdout, " unnamed");
		if (linfo.consumer[0])
			fprintf(stdout, " \"%s\"", linfo.consumer);
		else
			fprintf(stdout, " unused");
		if (linfo.flags) {
			fprintf(stdout, " [");
			print_attributes(&linfo);
			fprintf(stdout, "]");
		}
		fprintf(stdout, "\n");

	}

exit_close_error:
	if (close(fd) == -1)
		perror("Failed to close GPIO character device file");
exit_free_name:
	free(chrdev_name);
	return ret;
}

void print_usage(void)
{
	fprintf(stderr, "Usage: lsgpio [options]...\n"
		"List GPIO chips, lines and states\n"
		"  -n <name>  List GPIOs on a named device\n"
		"  -?         This helptext\n"
	);
}

int main(int argc, char **argv)
{
	const char *device_name = NULL;
	int ret;
	int c;

	while ((c = getopt(argc, argv, "n:")) != -1) {
		switch (c) {
		case 'n':
			device_name = optarg;
			break;
		case '?':
			print_usage();
			return -1;
		}
	}

	if (device_name)
		ret = list_device(device_name);
	else {
		const struct dirent *ent;
		DIR *dp;

		/* List all GPIO devices one at a time */
		dp = opendir("/dev");
		if (!dp) {
			ret = -errno;
			goto error_out;
		}

		ret = -ENOENT;
		while (ent = readdir(dp), ent) {
			if (check_prefix(ent->d_name, "gpiochip")) {
				ret = list_device(ent->d_name);
				if (ret)
					break;
			}
		}

		ret = 0;
		if (closedir(dp) == -1) {
			perror("scanning devices: Failed to close directory");
			ret = -errno;
		}
	}
error_out:
	return ret;
}
