.. | .. |
---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-only |
---|
1 | 2 | /* |
---|
2 | 3 | * lsgpio - example on how to list the GPIO lines on a system |
---|
3 | 4 | * |
---|
4 | 5 | * 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 | 6 | * |
---|
10 | 7 | * Usage: |
---|
11 | 8 | * lsgpio <-n device-name> |
---|
.. | .. |
---|
28 | 25 | |
---|
29 | 26 | struct gpio_flag { |
---|
30 | 27 | char *name; |
---|
31 | | - unsigned long mask; |
---|
| 28 | + unsigned long long mask; |
---|
32 | 29 | }; |
---|
33 | 30 | |
---|
34 | 31 | struct gpio_flag flagnames[] = { |
---|
35 | 32 | { |
---|
36 | | - .name = "kernel", |
---|
37 | | - .mask = GPIOLINE_FLAG_KERNEL, |
---|
| 33 | + .name = "used", |
---|
| 34 | + .mask = GPIO_V2_LINE_FLAG_USED, |
---|
| 35 | + }, |
---|
| 36 | + { |
---|
| 37 | + .name = "input", |
---|
| 38 | + .mask = GPIO_V2_LINE_FLAG_INPUT, |
---|
38 | 39 | }, |
---|
39 | 40 | { |
---|
40 | 41 | .name = "output", |
---|
41 | | - .mask = GPIOLINE_FLAG_IS_OUT, |
---|
| 42 | + .mask = GPIO_V2_LINE_FLAG_OUTPUT, |
---|
42 | 43 | }, |
---|
43 | 44 | { |
---|
44 | 45 | .name = "active-low", |
---|
45 | | - .mask = GPIOLINE_FLAG_ACTIVE_LOW, |
---|
| 46 | + .mask = GPIO_V2_LINE_FLAG_ACTIVE_LOW, |
---|
46 | 47 | }, |
---|
47 | 48 | { |
---|
48 | 49 | .name = "open-drain", |
---|
49 | | - .mask = GPIOLINE_FLAG_OPEN_DRAIN, |
---|
| 50 | + .mask = GPIO_V2_LINE_FLAG_OPEN_DRAIN, |
---|
50 | 51 | }, |
---|
51 | 52 | { |
---|
52 | 53 | .name = "open-source", |
---|
53 | | - .mask = GPIOLINE_FLAG_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, |
---|
54 | 67 | }, |
---|
55 | 68 | }; |
---|
56 | 69 | |
---|
57 | | -void print_flags(unsigned long flags) |
---|
| 70 | +static void print_attributes(struct gpio_v2_line_info *info) |
---|
58 | 71 | { |
---|
59 | 72 | int i; |
---|
60 | | - int printed = 0; |
---|
| 73 | + const char *field_format = "%s"; |
---|
61 | 74 | |
---|
62 | 75 | 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++; |
---|
| 76 | + if (info->flags & flagnames[i].mask) { |
---|
| 77 | + fprintf(stdout, field_format, flagnames[i].name); |
---|
| 78 | + field_format = ", %s"; |
---|
68 | 79 | } |
---|
| 80 | + } |
---|
| 81 | + |
---|
| 82 | + if ((info->flags & GPIO_V2_LINE_FLAG_EDGE_RISING) && |
---|
| 83 | + (info->flags & GPIO_V2_LINE_FLAG_EDGE_FALLING)) |
---|
| 84 | + fprintf(stdout, field_format, "both-edges"); |
---|
| 85 | + else if (info->flags & GPIO_V2_LINE_FLAG_EDGE_RISING) |
---|
| 86 | + fprintf(stdout, field_format, "rising-edge"); |
---|
| 87 | + else if (info->flags & GPIO_V2_LINE_FLAG_EDGE_FALLING) |
---|
| 88 | + fprintf(stdout, field_format, "falling-edge"); |
---|
| 89 | + |
---|
| 90 | + for (i = 0; i < info->num_attrs; i++) { |
---|
| 91 | + if (info->attrs[i].id == GPIO_V2_LINE_ATTR_ID_DEBOUNCE) |
---|
| 92 | + fprintf(stdout, ", debounce_period=%dusec", |
---|
| 93 | + info->attrs[i].debounce_period_us); |
---|
69 | 94 | } |
---|
70 | 95 | } |
---|
71 | 96 | |
---|
.. | .. |
---|
85 | 110 | if (fd == -1) { |
---|
86 | 111 | ret = -errno; |
---|
87 | 112 | fprintf(stderr, "Failed to open %s\n", chrdev_name); |
---|
88 | | - goto exit_close_error; |
---|
| 113 | + goto exit_free_name; |
---|
89 | 114 | } |
---|
90 | 115 | |
---|
91 | 116 | /* Inspect this GPIO chip */ |
---|
.. | .. |
---|
100 | 125 | |
---|
101 | 126 | /* Loop over the lines and print info */ |
---|
102 | 127 | for (i = 0; i < cinfo.lines; i++) { |
---|
103 | | - struct gpioline_info linfo; |
---|
| 128 | + struct gpio_v2_line_info linfo; |
---|
104 | 129 | |
---|
105 | 130 | memset(&linfo, 0, sizeof(linfo)); |
---|
106 | | - linfo.line_offset = i; |
---|
| 131 | + linfo.offset = i; |
---|
107 | 132 | |
---|
108 | | - ret = ioctl(fd, GPIO_GET_LINEINFO_IOCTL, &linfo); |
---|
| 133 | + ret = ioctl(fd, GPIO_V2_GET_LINEINFO_IOCTL, &linfo); |
---|
109 | 134 | if (ret == -1) { |
---|
110 | 135 | ret = -errno; |
---|
111 | 136 | perror("Failed to issue LINEINFO IOCTL\n"); |
---|
112 | 137 | goto exit_close_error; |
---|
113 | 138 | } |
---|
114 | | - fprintf(stdout, "\tline %2d:", linfo.line_offset); |
---|
| 139 | + fprintf(stdout, "\tline %2d:", linfo.offset); |
---|
115 | 140 | if (linfo.name[0]) |
---|
116 | 141 | fprintf(stdout, " \"%s\"", linfo.name); |
---|
117 | 142 | else |
---|
.. | .. |
---|
122 | 147 | fprintf(stdout, " unused"); |
---|
123 | 148 | if (linfo.flags) { |
---|
124 | 149 | fprintf(stdout, " ["); |
---|
125 | | - print_flags(linfo.flags); |
---|
| 150 | + print_attributes(&linfo); |
---|
126 | 151 | fprintf(stdout, "]"); |
---|
127 | 152 | } |
---|
128 | 153 | fprintf(stdout, "\n"); |
---|
.. | .. |
---|
132 | 157 | exit_close_error: |
---|
133 | 158 | if (close(fd) == -1) |
---|
134 | 159 | perror("Failed to close GPIO character device file"); |
---|
| 160 | +exit_free_name: |
---|
135 | 161 | free(chrdev_name); |
---|
136 | 162 | return ret; |
---|
137 | 163 | } |
---|