cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

lsgpio.c (4611B)


      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 long mask;
     29};
     30
     31struct gpio_flag flagnames[] = {
     32	{
     33		.name = "used",
     34		.mask = GPIO_V2_LINE_FLAG_USED,
     35	},
     36	{
     37		.name = "input",
     38		.mask = GPIO_V2_LINE_FLAG_INPUT,
     39	},
     40	{
     41		.name = "output",
     42		.mask = GPIO_V2_LINE_FLAG_OUTPUT,
     43	},
     44	{
     45		.name = "active-low",
     46		.mask = GPIO_V2_LINE_FLAG_ACTIVE_LOW,
     47	},
     48	{
     49		.name = "open-drain",
     50		.mask = GPIO_V2_LINE_FLAG_OPEN_DRAIN,
     51	},
     52	{
     53		.name = "open-source",
     54		.mask = GPIO_V2_LINE_FLAG_OPEN_SOURCE,
     55	},
     56	{
     57		.name = "pull-up",
     58		.mask = GPIO_V2_LINE_FLAG_BIAS_PULL_UP,
     59	},
     60	{
     61		.name = "pull-down",
     62		.mask = GPIO_V2_LINE_FLAG_BIAS_PULL_DOWN,
     63	},
     64	{
     65		.name = "bias-disabled",
     66		.mask = GPIO_V2_LINE_FLAG_BIAS_DISABLED,
     67	},
     68	{
     69		.name = "clock-realtime",
     70		.mask = GPIO_V2_LINE_FLAG_EVENT_CLOCK_REALTIME,
     71	},
     72};
     73
     74static void print_attributes(struct gpio_v2_line_info *info)
     75{
     76	int i;
     77	const char *field_format = "%s";
     78
     79	for (i = 0; i < ARRAY_SIZE(flagnames); i++) {
     80		if (info->flags & flagnames[i].mask) {
     81			fprintf(stdout, field_format, flagnames[i].name);
     82			field_format = ", %s";
     83		}
     84	}
     85
     86	if ((info->flags & GPIO_V2_LINE_FLAG_EDGE_RISING) &&
     87	    (info->flags & GPIO_V2_LINE_FLAG_EDGE_FALLING))
     88		fprintf(stdout, field_format, "both-edges");
     89	else if (info->flags & GPIO_V2_LINE_FLAG_EDGE_RISING)
     90		fprintf(stdout, field_format, "rising-edge");
     91	else if (info->flags & GPIO_V2_LINE_FLAG_EDGE_FALLING)
     92		fprintf(stdout, field_format, "falling-edge");
     93
     94	for (i = 0; i < info->num_attrs; i++) {
     95		if (info->attrs[i].id == GPIO_V2_LINE_ATTR_ID_DEBOUNCE)
     96			fprintf(stdout, ", debounce_period=%dusec",
     97				info->attrs[0].debounce_period_us);
     98	}
     99}
    100
    101int list_device(const char *device_name)
    102{
    103	struct gpiochip_info cinfo;
    104	char *chrdev_name;
    105	int fd;
    106	int ret;
    107	int i;
    108
    109	ret = asprintf(&chrdev_name, "/dev/%s", device_name);
    110	if (ret < 0)
    111		return -ENOMEM;
    112
    113	fd = open(chrdev_name, 0);
    114	if (fd == -1) {
    115		ret = -errno;
    116		fprintf(stderr, "Failed to open %s\n", chrdev_name);
    117		goto exit_free_name;
    118	}
    119
    120	/* Inspect this GPIO chip */
    121	ret = ioctl(fd, GPIO_GET_CHIPINFO_IOCTL, &cinfo);
    122	if (ret == -1) {
    123		ret = -errno;
    124		perror("Failed to issue CHIPINFO IOCTL\n");
    125		goto exit_close_error;
    126	}
    127	fprintf(stdout, "GPIO chip: %s, \"%s\", %u GPIO lines\n",
    128		cinfo.name, cinfo.label, cinfo.lines);
    129
    130	/* Loop over the lines and print info */
    131	for (i = 0; i < cinfo.lines; i++) {
    132		struct gpio_v2_line_info linfo;
    133
    134		memset(&linfo, 0, sizeof(linfo));
    135		linfo.offset = i;
    136
    137		ret = ioctl(fd, GPIO_V2_GET_LINEINFO_IOCTL, &linfo);
    138		if (ret == -1) {
    139			ret = -errno;
    140			perror("Failed to issue LINEINFO IOCTL\n");
    141			goto exit_close_error;
    142		}
    143		fprintf(stdout, "\tline %2d:", linfo.offset);
    144		if (linfo.name[0])
    145			fprintf(stdout, " \"%s\"", linfo.name);
    146		else
    147			fprintf(stdout, " unnamed");
    148		if (linfo.consumer[0])
    149			fprintf(stdout, " \"%s\"", linfo.consumer);
    150		else
    151			fprintf(stdout, " unused");
    152		if (linfo.flags) {
    153			fprintf(stdout, " [");
    154			print_attributes(&linfo);
    155			fprintf(stdout, "]");
    156		}
    157		fprintf(stdout, "\n");
    158
    159	}
    160
    161exit_close_error:
    162	if (close(fd) == -1)
    163		perror("Failed to close GPIO character device file");
    164exit_free_name:
    165	free(chrdev_name);
    166	return ret;
    167}
    168
    169void print_usage(void)
    170{
    171	fprintf(stderr, "Usage: lsgpio [options]...\n"
    172		"List GPIO chips, lines and states\n"
    173		"  -n <name>  List GPIOs on a named device\n"
    174		"  -?         This helptext\n"
    175	);
    176}
    177
    178int main(int argc, char **argv)
    179{
    180	const char *device_name = NULL;
    181	int ret;
    182	int c;
    183
    184	while ((c = getopt(argc, argv, "n:")) != -1) {
    185		switch (c) {
    186		case 'n':
    187			device_name = optarg;
    188			break;
    189		case '?':
    190			print_usage();
    191			return -1;
    192		}
    193	}
    194
    195	if (device_name)
    196		ret = list_device(device_name);
    197	else {
    198		const struct dirent *ent;
    199		DIR *dp;
    200
    201		/* List all GPIO devices one at a time */
    202		dp = opendir("/dev");
    203		if (!dp) {
    204			ret = -errno;
    205			goto error_out;
    206		}
    207
    208		ret = -ENOENT;
    209		while (ent = readdir(dp), ent) {
    210			if (check_prefix(ent->d_name, "gpiochip")) {
    211				ret = list_device(ent->d_name);
    212				if (ret)
    213					break;
    214			}
    215		}
    216
    217		ret = 0;
    218		if (closedir(dp) == -1) {
    219			perror("scanning devices: Failed to close directory");
    220			ret = -errno;
    221		}
    222	}
    223error_out:
    224	return ret;
    225}