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