xref: /openbmc/linux/tools/gpio/lsgpio.c (revision 6d591c46)
16d591c46SLinus Walleij /*
26d591c46SLinus Walleij  * lsgpio - example on how to list the GPIO lines on a system
36d591c46SLinus Walleij  *
46d591c46SLinus Walleij  * Copyright (C) 2015 Linus Walleij
56d591c46SLinus Walleij  *
66d591c46SLinus Walleij  * This program is free software; you can redistribute it and/or modify it
76d591c46SLinus Walleij  * under the terms of the GNU General Public License version 2 as published by
86d591c46SLinus Walleij  * the Free Software Foundation.
96d591c46SLinus Walleij  *
106d591c46SLinus Walleij  * Usage:
116d591c46SLinus Walleij  *	lsgpio <-n device-name>
126d591c46SLinus Walleij  */
136d591c46SLinus Walleij 
146d591c46SLinus Walleij #include <unistd.h>
156d591c46SLinus Walleij #include <stdlib.h>
166d591c46SLinus Walleij #include <stdbool.h>
176d591c46SLinus Walleij #include <stdio.h>
186d591c46SLinus Walleij #include <dirent.h>
196d591c46SLinus Walleij #include <errno.h>
206d591c46SLinus Walleij #include <string.h>
216d591c46SLinus Walleij #include <poll.h>
226d591c46SLinus Walleij #include <fcntl.h>
236d591c46SLinus Walleij #include <getopt.h>
246d591c46SLinus Walleij #include <sys/ioctl.h>
256d591c46SLinus Walleij #include <linux/gpio.h>
266d591c46SLinus Walleij 
276d591c46SLinus Walleij #include "gpio-utils.h"
286d591c46SLinus Walleij 
296d591c46SLinus Walleij int list_device(const char *device_name)
306d591c46SLinus Walleij {
316d591c46SLinus Walleij 	struct gpiochip_info cinfo;
326d591c46SLinus Walleij 	char *chrdev_name;
336d591c46SLinus Walleij 	int fd;
346d591c46SLinus Walleij 	int ret;
356d591c46SLinus Walleij 
366d591c46SLinus Walleij 	ret = asprintf(&chrdev_name, "/dev/%s", device_name);
376d591c46SLinus Walleij 	if (ret < 0)
386d591c46SLinus Walleij 		return -ENOMEM;
396d591c46SLinus Walleij 
406d591c46SLinus Walleij 	fd = open(chrdev_name, 0);
416d591c46SLinus Walleij 	if (fd == -1) {
426d591c46SLinus Walleij 		ret = -errno;
436d591c46SLinus Walleij 		fprintf(stderr, "Failed to open %s\n", chrdev_name);
446d591c46SLinus Walleij 		goto free_chrdev_name;
456d591c46SLinus Walleij 	}
466d591c46SLinus Walleij 
476d591c46SLinus Walleij 	/* Inspect this GPIO chip */
486d591c46SLinus Walleij 	ret = ioctl(fd, GPIO_GET_CHIPINFO_IOCTL, &cinfo);
496d591c46SLinus Walleij 	if (ret == -1) {
506d591c46SLinus Walleij 		ret = -errno;
516d591c46SLinus Walleij 		fprintf(stderr, "Failed to retrieve GPIO fd\n");
526d591c46SLinus Walleij 		if (close(fd) == -1)
536d591c46SLinus Walleij 			perror("Failed to close GPIO character device file");
546d591c46SLinus Walleij 
556d591c46SLinus Walleij 		goto free_chrdev_name;
566d591c46SLinus Walleij 	}
576d591c46SLinus Walleij 	fprintf(stdout, "GPIO chip: %s, %u GPIO lines\n",
586d591c46SLinus Walleij 		cinfo.name, cinfo.lines);
596d591c46SLinus Walleij 
606d591c46SLinus Walleij 	if (close(fd) == -1)  {
616d591c46SLinus Walleij 		ret = -errno;
626d591c46SLinus Walleij 		goto free_chrdev_name;
636d591c46SLinus Walleij 	}
646d591c46SLinus Walleij 
656d591c46SLinus Walleij free_chrdev_name:
666d591c46SLinus Walleij 	free(chrdev_name);
676d591c46SLinus Walleij 
686d591c46SLinus Walleij 	return ret;
696d591c46SLinus Walleij 
706d591c46SLinus Walleij }
716d591c46SLinus Walleij 
726d591c46SLinus Walleij void print_usage(void)
736d591c46SLinus Walleij {
746d591c46SLinus Walleij 	fprintf(stderr, "Usage: lsgpio [options]...\n"
756d591c46SLinus Walleij 		"List GPIO chips, lines and states\n"
766d591c46SLinus Walleij 		"  -n <name>  List GPIOs on a named device\n"
776d591c46SLinus Walleij 		"  -?         This helptext\n"
786d591c46SLinus Walleij 	);
796d591c46SLinus Walleij }
806d591c46SLinus Walleij 
816d591c46SLinus Walleij int main(int argc, char **argv)
826d591c46SLinus Walleij {
836d591c46SLinus Walleij 	const char *device_name;
846d591c46SLinus Walleij 	int ret;
856d591c46SLinus Walleij 	int c;
866d591c46SLinus Walleij 
876d591c46SLinus Walleij 	while ((c = getopt(argc, argv, "n:")) != -1) {
886d591c46SLinus Walleij 		switch (c) {
896d591c46SLinus Walleij 		case 'n':
906d591c46SLinus Walleij 			device_name = optarg;
916d591c46SLinus Walleij 			break;
926d591c46SLinus Walleij 		case '?':
936d591c46SLinus Walleij 			print_usage();
946d591c46SLinus Walleij 			return -1;
956d591c46SLinus Walleij 		}
966d591c46SLinus Walleij 	}
976d591c46SLinus Walleij 
986d591c46SLinus Walleij 	if (device_name)
996d591c46SLinus Walleij 		ret = list_device(device_name);
1006d591c46SLinus Walleij 	else {
1016d591c46SLinus Walleij 		const struct dirent *ent;
1026d591c46SLinus Walleij 		DIR *dp;
1036d591c46SLinus Walleij 
1046d591c46SLinus Walleij 		/* List all GPIO devices one at a time */
1056d591c46SLinus Walleij 		dp = opendir("/dev");
1066d591c46SLinus Walleij 		if (!dp) {
1076d591c46SLinus Walleij 			ret = -errno;
1086d591c46SLinus Walleij 			goto error_out;
1096d591c46SLinus Walleij 		}
1106d591c46SLinus Walleij 
1116d591c46SLinus Walleij 		ret = -ENOENT;
1126d591c46SLinus Walleij 		while (ent = readdir(dp), ent) {
1136d591c46SLinus Walleij 			if (check_prefix(ent->d_name, "gpiochip")) {
1146d591c46SLinus Walleij 				ret = list_device(ent->d_name);
1156d591c46SLinus Walleij 				if (ret)
1166d591c46SLinus Walleij 					break;
1176d591c46SLinus Walleij 			}
1186d591c46SLinus Walleij 		}
1196d591c46SLinus Walleij 
1206d591c46SLinus Walleij 		ret = 0;
1216d591c46SLinus Walleij 		if (closedir(dp) == -1) {
1226d591c46SLinus Walleij 			perror("scanning devices: Failed to close directory");
1236d591c46SLinus Walleij 			ret = -errno;
1246d591c46SLinus Walleij 		}
1256d591c46SLinus Walleij 	}
1266d591c46SLinus Walleij error_out:
1276d591c46SLinus Walleij 	return ret;
1286d591c46SLinus Walleij }
129