hc
2024-01-05 071106ecf68c401173c58808b1cf5f68cc50d390
kernel/tools/gpio/gpio-event-mon.c
....@@ -1,11 +1,8 @@
1
+// SPDX-License-Identifier: GPL-2.0-only
12 /*
23 * gpio-event-mon - monitor GPIO line events from userspace
34 *
45 * Copyright (C) 2016 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.
96 *
107 * Usage:
118 * gpio-event-mon -n <device-name> -o <offset>
....@@ -26,17 +23,17 @@
2623 #include <sys/ioctl.h>
2724 #include <sys/types.h>
2825 #include <linux/gpio.h>
26
+#include "gpio-utils.h"
2927
3028 int monitor_device(const char *device_name,
31
- unsigned int line,
32
- uint32_t handleflags,
33
- uint32_t eventflags,
29
+ unsigned int *lines,
30
+ unsigned int num_lines,
31
+ struct gpio_v2_line_config *config,
3432 unsigned int loops)
3533 {
36
- struct gpioevent_request req;
37
- struct gpiohandle_data data;
34
+ struct gpio_v2_line_values values;
3835 char *chrdev_name;
39
- int fd;
36
+ int cfd, lfd;
4037 int ret;
4138 int i = 0;
4239
....@@ -44,44 +41,56 @@
4441 if (ret < 0)
4542 return -ENOMEM;
4643
47
- fd = open(chrdev_name, 0);
48
- if (fd == -1) {
44
+ cfd = open(chrdev_name, 0);
45
+ if (cfd == -1) {
4946 ret = -errno;
5047 fprintf(stderr, "Failed to open %s\n", chrdev_name);
51
- goto exit_close_error;
48
+ goto exit_free_name;
5249 }
5350
54
- req.lineoffset = line;
55
- req.handleflags = handleflags;
56
- req.eventflags = eventflags;
57
- strcpy(req.consumer_label, "gpio-event-mon");
58
-
59
- ret = ioctl(fd, GPIO_GET_LINEEVENT_IOCTL, &req);
60
- if (ret == -1) {
61
- ret = -errno;
62
- fprintf(stderr, "Failed to issue GET EVENT "
63
- "IOCTL (%d)\n",
64
- ret);
65
- goto exit_close_error;
66
- }
51
+ ret = gpiotools_request_line(device_name, lines, num_lines, config,
52
+ "gpio-event-mon");
53
+ if (ret < 0)
54
+ goto exit_device_close;
55
+ else
56
+ lfd = ret;
6757
6858 /* Read initial states */
69
- ret = ioctl(req.fd, GPIOHANDLE_GET_LINE_VALUES_IOCTL, &data);
70
- if (ret == -1) {
71
- ret = -errno;
72
- fprintf(stderr, "Failed to issue GPIOHANDLE GET LINE "
73
- "VALUES IOCTL (%d)\n",
59
+ values.mask = 0;
60
+ values.bits = 0;
61
+ for (i = 0; i < num_lines; i++)
62
+ gpiotools_set_bit(&values.mask, i);
63
+ ret = gpiotools_get_values(lfd, &values);
64
+ if (ret < 0) {
65
+ fprintf(stderr,
66
+ "Failed to issue GPIO LINE GET VALUES IOCTL (%d)\n",
7467 ret);
75
- goto exit_close_error;
68
+ goto exit_line_close;
7669 }
7770
78
- fprintf(stdout, "Monitoring line %d on %s\n", line, device_name);
79
- fprintf(stdout, "Initial line value: %d\n", data.values[0]);
71
+ if (num_lines == 1) {
72
+ fprintf(stdout, "Monitoring line %d on %s\n", lines[0], device_name);
73
+ fprintf(stdout, "Initial line value: %d\n",
74
+ gpiotools_test_bit(values.bits, 0));
75
+ } else {
76
+ fprintf(stdout, "Monitoring lines %d", lines[0]);
77
+ for (i = 1; i < num_lines - 1; i++)
78
+ fprintf(stdout, ", %d", lines[i]);
79
+ fprintf(stdout, " and %d on %s\n", lines[i], device_name);
80
+ fprintf(stdout, "Initial line values: %d",
81
+ gpiotools_test_bit(values.bits, 0));
82
+ for (i = 1; i < num_lines - 1; i++)
83
+ fprintf(stdout, ", %d",
84
+ gpiotools_test_bit(values.bits, i));
85
+ fprintf(stdout, " and %d\n",
86
+ gpiotools_test_bit(values.bits, i));
87
+ }
8088
89
+ i = 0;
8190 while (1) {
82
- struct gpioevent_data event;
91
+ struct gpio_v2_line_event event;
8392
84
- ret = read(req.fd, &event, sizeof(event));
93
+ ret = read(lfd, &event, sizeof(event));
8594 if (ret == -1) {
8695 if (errno == -EAGAIN) {
8796 fprintf(stderr, "nothing available\n");
....@@ -99,12 +108,14 @@
99108 ret = -EIO;
100109 break;
101110 }
102
- fprintf(stdout, "GPIO EVENT %llu: ", event.timestamp);
111
+ fprintf(stdout, "GPIO EVENT at %" PRIu64 " on line %d (%d|%d) ",
112
+ (uint64_t)event.timestamp_ns, event.offset, event.line_seqno,
113
+ event.seqno);
103114 switch (event.id) {
104
- case GPIOEVENT_EVENT_RISING_EDGE:
115
+ case GPIO_V2_LINE_EVENT_RISING_EDGE:
105116 fprintf(stdout, "rising edge");
106117 break;
107
- case GPIOEVENT_EVENT_FALLING_EDGE:
118
+ case GPIO_V2_LINE_EVENT_FALLING_EDGE:
108119 fprintf(stdout, "falling edge");
109120 break;
110121 default:
....@@ -117,9 +128,13 @@
117128 break;
118129 }
119130
120
-exit_close_error:
121
- if (close(fd) == -1)
131
+exit_line_close:
132
+ if (close(lfd) == -1)
133
+ perror("Failed to close line file");
134
+exit_device_close:
135
+ if (close(cfd) == -1)
122136 perror("Failed to close GPIO character device file");
137
+exit_free_name:
123138 free(chrdev_name);
124139 return ret;
125140 }
....@@ -129,29 +144,37 @@
129144 fprintf(stderr, "Usage: gpio-event-mon [options]...\n"
130145 "Listen to events on GPIO lines, 0->1 1->0\n"
131146 " -n <name> Listen on GPIOs on a named device (must be stated)\n"
132
- " -o <n> Offset to monitor\n"
147
+ " -o <n> Offset of line to monitor (may be repeated)\n"
133148 " -d Set line as open drain\n"
134149 " -s Set line as open source\n"
135150 " -r Listen for rising edges\n"
136151 " -f Listen for falling edges\n"
152
+ " -b <n> Debounce the line with period n microseconds\n"
137153 " [-c <n>] Do <n> loops (optional, infinite loop if not stated)\n"
138154 " -? This helptext\n"
139155 "\n"
140156 "Example:\n"
141
- "gpio-event-mon -n gpiochip0 -o 4 -r -f\n"
157
+ "gpio-event-mon -n gpiochip0 -o 4 -r -f -b 10000\n"
142158 );
143159 }
160
+
161
+#define EDGE_FLAGS \
162
+ (GPIO_V2_LINE_FLAG_EDGE_RISING | \
163
+ GPIO_V2_LINE_FLAG_EDGE_FALLING)
144164
145165 int main(int argc, char **argv)
146166 {
147167 const char *device_name = NULL;
148
- unsigned int line = -1;
168
+ unsigned int lines[GPIO_V2_LINES_MAX];
169
+ unsigned int num_lines = 0;
149170 unsigned int loops = 0;
150
- uint32_t handleflags = GPIOHANDLE_REQUEST_INPUT;
151
- uint32_t eventflags = 0;
152
- int c;
171
+ struct gpio_v2_line_config config;
172
+ int c, attr, i;
173
+ unsigned long debounce_period_us = 0;
153174
154
- while ((c = getopt(argc, argv, "c:n:o:dsrf?")) != -1) {
175
+ memset(&config, 0, sizeof(config));
176
+ config.flags = GPIO_V2_LINE_FLAG_INPUT;
177
+ while ((c = getopt(argc, argv, "c:n:o:b:dsrf?")) != -1) {
155178 switch (c) {
156179 case 'c':
157180 loops = strtoul(optarg, NULL, 10);
....@@ -160,19 +183,27 @@
160183 device_name = optarg;
161184 break;
162185 case 'o':
163
- line = strtoul(optarg, NULL, 10);
186
+ if (num_lines >= GPIO_V2_LINES_MAX) {
187
+ print_usage();
188
+ return -1;
189
+ }
190
+ lines[num_lines] = strtoul(optarg, NULL, 10);
191
+ num_lines++;
192
+ break;
193
+ case 'b':
194
+ debounce_period_us = strtoul(optarg, NULL, 10);
164195 break;
165196 case 'd':
166
- handleflags |= GPIOHANDLE_REQUEST_OPEN_DRAIN;
197
+ config.flags |= GPIO_V2_LINE_FLAG_OPEN_DRAIN;
167198 break;
168199 case 's':
169
- handleflags |= GPIOHANDLE_REQUEST_OPEN_SOURCE;
200
+ config.flags |= GPIO_V2_LINE_FLAG_OPEN_SOURCE;
170201 break;
171202 case 'r':
172
- eventflags |= GPIOEVENT_REQUEST_RISING_EDGE;
203
+ config.flags |= GPIO_V2_LINE_FLAG_EDGE_RISING;
173204 break;
174205 case 'f':
175
- eventflags |= GPIOEVENT_REQUEST_FALLING_EDGE;
206
+ config.flags |= GPIO_V2_LINE_FLAG_EDGE_FALLING;
176207 break;
177208 case '?':
178209 print_usage();
....@@ -180,15 +211,23 @@
180211 }
181212 }
182213
183
- if (!device_name || line == -1) {
214
+ if (debounce_period_us) {
215
+ attr = config.num_attrs;
216
+ config.num_attrs++;
217
+ for (i = 0; i < num_lines; i++)
218
+ gpiotools_set_bit(&config.attrs[attr].mask, i);
219
+ config.attrs[attr].attr.id = GPIO_V2_LINE_ATTR_ID_DEBOUNCE;
220
+ config.attrs[attr].attr.debounce_period_us = debounce_period_us;
221
+ }
222
+
223
+ if (!device_name || num_lines == 0) {
184224 print_usage();
185225 return -1;
186226 }
187
- if (!eventflags) {
227
+ if (!(config.flags & EDGE_FLAGS)) {
188228 printf("No flags specified, listening on both rising and "
189229 "falling edges\n");
190
- eventflags = GPIOEVENT_REQUEST_BOTH_EDGES;
230
+ config.flags |= EDGE_FLAGS;
191231 }
192
- return monitor_device(device_name, line, handleflags,
193
- eventflags, loops);
232
+ return monitor_device(device_name, lines, num_lines, &config, loops);
194233 }