PCI: dwc: Centralize link gen setting
[linux-2.6-microblaze.git] / tools / gpio / lsgpio.c
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
26 struct gpio_flag {
27         char *name;
28         unsigned long mask;
29 };
30
31 struct 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
66 void 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
81 int 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
141 exit_close_error:
142         if (close(fd) == -1)
143                 perror("Failed to close GPIO character device file");
144 exit_free_name:
145         free(chrdev_name);
146         return ret;
147 }
148
149 void 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
158 int 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         }
203 error_out:
204         return ret;
205 }