Linux Audio

Check our new training course

Loading...
Note: File does not exist in v3.1.
  1// SPDX-License-Identifier: GPL-2.0-only
  2/*
  3 * lsgpio - example on how to list the GPIO lines on a system
  4 *
  5 * Copyright (C) 2015 Linus Walleij
  6 *
  7 * Usage:
  8 *	lsgpio <-n device-name>
  9 */
 10
 11#include <unistd.h>
 12#include <stdlib.h>
 13#include <stdbool.h>
 14#include <stdio.h>
 15#include <dirent.h>
 16#include <errno.h>
 17#include <string.h>
 18#include <poll.h>
 19#include <fcntl.h>
 20#include <getopt.h>
 21#include <sys/ioctl.h>
 22#include <linux/gpio.h>
 23
 24#include "gpio-utils.h"
 25
 26struct gpio_flag {
 27	char *name;
 28	unsigned long mask;
 29};
 30
 31struct gpio_flag flagnames[] = {
 32	{
 33		.name = "kernel",
 34		.mask = GPIOLINE_FLAG_KERNEL,
 35	},
 36	{
 37		.name = "output",
 38		.mask = GPIOLINE_FLAG_IS_OUT,
 39	},
 40	{
 41		.name = "active-low",
 42		.mask = GPIOLINE_FLAG_ACTIVE_LOW,
 43	},
 44	{
 45		.name = "open-drain",
 46		.mask = GPIOLINE_FLAG_OPEN_DRAIN,
 47	},
 48	{
 49		.name = "open-source",
 50		.mask = GPIOLINE_FLAG_OPEN_SOURCE,
 51	},
 52	{
 53		.name = "pull-up",
 54		.mask = GPIOLINE_FLAG_BIAS_PULL_UP,
 55	},
 56	{
 57		.name = "pull-down",
 58		.mask = GPIOLINE_FLAG_BIAS_PULL_DOWN,
 59	},
 60	{
 61		.name = "bias-disabled",
 62		.mask = GPIOLINE_FLAG_BIAS_DISABLE,
 63	},
 64};
 65
 66void print_flags(unsigned long flags)
 67{
 68	int i;
 69	int printed = 0;
 70
 71	for (i = 0; i < ARRAY_SIZE(flagnames); i++) {
 72		if (flags & flagnames[i].mask) {
 73			if (printed)
 74				fprintf(stdout, " ");
 75			fprintf(stdout, "%s", flagnames[i].name);
 76			printed++;
 77		}
 78	}
 79}
 80
 81int list_device(const char *device_name)
 82{
 83	struct gpiochip_info cinfo;
 84	char *chrdev_name;
 85	int fd;
 86	int ret;
 87	int i;
 88
 89	ret = asprintf(&chrdev_name, "/dev/%s", device_name);
 90	if (ret < 0)
 91		return -ENOMEM;
 92
 93	fd = open(chrdev_name, 0);
 94	if (fd == -1) {
 95		ret = -errno;
 96		fprintf(stderr, "Failed to open %s\n", chrdev_name);
 97		goto exit_free_name;
 98	}
 99
100	/* Inspect this GPIO chip */
101	ret = ioctl(fd, GPIO_GET_CHIPINFO_IOCTL, &cinfo);
102	if (ret == -1) {
103		ret = -errno;
104		perror("Failed to issue CHIPINFO IOCTL\n");
105		goto exit_close_error;
106	}
107	fprintf(stdout, "GPIO chip: %s, \"%s\", %u GPIO lines\n",
108		cinfo.name, cinfo.label, cinfo.lines);
109
110	/* Loop over the lines and print info */
111	for (i = 0; i < cinfo.lines; i++) {
112		struct gpioline_info linfo;
113
114		memset(&linfo, 0, sizeof(linfo));
115		linfo.line_offset = i;
116
117		ret = ioctl(fd, GPIO_GET_LINEINFO_IOCTL, &linfo);
118		if (ret == -1) {
119			ret = -errno;
120			perror("Failed to issue LINEINFO IOCTL\n");
121			goto exit_close_error;
122		}
123		fprintf(stdout, "\tline %2d:", linfo.line_offset);
124		if (linfo.name[0])
125			fprintf(stdout, " \"%s\"", linfo.name);
126		else
127			fprintf(stdout, " unnamed");
128		if (linfo.consumer[0])
129			fprintf(stdout, " \"%s\"", linfo.consumer);
130		else
131			fprintf(stdout, " unused");
132		if (linfo.flags) {
133			fprintf(stdout, " [");
134			print_flags(linfo.flags);
135			fprintf(stdout, "]");
136		}
137		fprintf(stdout, "\n");
138
139	}
140
141exit_close_error:
142	if (close(fd) == -1)
143		perror("Failed to close GPIO character device file");
144exit_free_name:
145	free(chrdev_name);
146	return ret;
147}
148
149void print_usage(void)
150{
151	fprintf(stderr, "Usage: lsgpio [options]...\n"
152		"List GPIO chips, lines and states\n"
153		"  -n <name>  List GPIOs on a named device\n"
154		"  -?         This helptext\n"
155	);
156}
157
158int main(int argc, char **argv)
159{
160	const char *device_name = NULL;
161	int ret;
162	int c;
163
164	while ((c = getopt(argc, argv, "n:")) != -1) {
165		switch (c) {
166		case 'n':
167			device_name = optarg;
168			break;
169		case '?':
170			print_usage();
171			return -1;
172		}
173	}
174
175	if (device_name)
176		ret = list_device(device_name);
177	else {
178		const struct dirent *ent;
179		DIR *dp;
180
181		/* List all GPIO devices one at a time */
182		dp = opendir("/dev");
183		if (!dp) {
184			ret = -errno;
185			goto error_out;
186		}
187
188		ret = -ENOENT;
189		while (ent = readdir(dp), ent) {
190			if (check_prefix(ent->d_name, "gpiochip")) {
191				ret = list_device(ent->d_name);
192				if (ret)
193					break;
194			}
195		}
196
197		ret = 0;
198		if (closedir(dp) == -1) {
199			perror("scanning devices: Failed to close directory");
200			ret = -errno;
201		}
202	}
203error_out:
204	return ret;
205}