1 // SPDX-License-Identifier: GPL-2.0-only
3 * GPIO chardev test helper
5 * Copyright (C) 2016 Bamvor Jian Zhang
16 #include <sys/ioctl.h>
20 #include <linux/gpio.h>
21 #include "../../../gpio/gpio-utils.h"
23 #define CONSUMER "gpio-selftest"
30 static int get_debugfs(char **path
)
32 struct libmnt_context
*cxt
;
33 struct libmnt_table
*tb
;
34 struct libmnt_iter
*itr
= NULL
;
38 cxt
= mnt_new_context();
40 err(EXIT_FAILURE
, "libmount context allocation failed");
42 itr
= mnt_new_iter(MNT_ITER_FORWARD
);
44 err(EXIT_FAILURE
, "failed to initialize libmount iterator");
46 if (mnt_context_get_mtab(cxt
, &tb
))
47 err(EXIT_FAILURE
, "failed to read mtab");
49 while (mnt_table_next_fs(tb
, itr
, &fs
) == 0) {
50 const char *type
= mnt_fs_get_fstype(fs
);
52 if (!strcmp(type
, "debugfs")) {
58 ret
= asprintf(path
, "%s/gpio", mnt_fs_get_target(fs
));
60 err(EXIT_FAILURE
, "failed to format string");
64 mnt_free_context(cxt
);
72 static int gpio_debugfs_get(const char *consumer
, int *dir
, int *value
)
81 if (get_debugfs(&debugfs
) != 0)
82 err(EXIT_FAILURE
, "debugfs is not mounted");
84 f
= fopen(debugfs
, "r");
86 err(EXIT_FAILURE
, "read from gpio debugfs failed");
89 * gpio-2 ( |gpio-selftest ) in lo
91 while (getline(&line
, &len
, f
) != -1) {
92 cur
= strstr(line
, consumer
);
96 cur
= strchr(line
, ')');
101 if (!strncmp(cur
, "out", 3)) {
104 } else if (!strncmp(cur
, "in", 2)) {
109 if (!strncmp(cur
, "hi", 2))
111 else if (!strncmp(cur
, "lo", 2))
127 static struct gpiochip_info
*list_gpiochip(const char *gpiochip_name
, int *ret
)
129 struct gpiochip_info
*cinfo
;
130 struct gpiochip_info
*current
;
131 const struct dirent
*ent
;
137 cinfo
= calloc(sizeof(struct gpiochip_info
) * 4, GC_NUM
+ 1);
139 err(EXIT_FAILURE
, "gpiochip_info allocation failed");
142 dp
= opendir("/dev");
150 while (ent
= readdir(dp
), ent
) {
151 if (check_prefix(ent
->d_name
, "gpiochip")) {
152 *ret
= asprintf(&chrdev_name
, "/dev/%s", ent
->d_name
);
156 fd
= open(chrdev_name
, 0);
159 fprintf(stderr
, "Failed to open %s\n",
161 goto error_close_dir
;
163 *ret
= ioctl(fd
, GPIO_GET_CHIPINFO_IOCTL
, current
);
165 perror("Failed to issue CHIPINFO IOCTL\n");
166 goto error_close_dir
;
169 if (strcmp(current
->label
, gpiochip_name
) == 0
170 || check_prefix(current
->label
, gpiochip_name
)) {
178 if ((!*ret
&& i
== 0) || *ret
< 0) {
182 if (!*ret
&& i
> 0) {
183 cinfo
= realloc(cinfo
, sizeof(struct gpiochip_info
) * 4 * i
);
191 err(EXIT_FAILURE
, "list gpiochip failed: %s", strerror(*ret
));
196 int gpio_pin_test(struct gpiochip_info
*cinfo
, int line
, int flag
, int value
)
198 struct gpiohandle_data data
;
199 unsigned int lines
[] = {line
};
201 int debugfs_dir
= IN
;
202 int debugfs_value
= 0;
205 data
.values
[0] = value
;
206 ret
= gpiotools_request_linehandle(cinfo
->name
, lines
, 1, flag
, &data
,
213 ret
= gpio_debugfs_get(CONSUMER
, &debugfs_dir
, &debugfs_value
);
218 if (flag
& GPIOHANDLE_REQUEST_INPUT
) {
219 if (debugfs_dir
!= IN
) {
223 } else if (flag
& GPIOHANDLE_REQUEST_OUTPUT
) {
224 if (flag
& GPIOHANDLE_REQUEST_ACTIVE_LOW
)
225 debugfs_value
= !debugfs_value
;
227 if (!(debugfs_dir
== OUT
&& value
== debugfs_value
)) {
232 gpiotools_release_linehandle(fd
);
236 err(EXIT_FAILURE
, "gpio<%s> line<%d> test flag<0x%x> value<%d>",
237 cinfo
->name
, line
, flag
, value
);
242 void gpio_pin_tests(struct gpiochip_info
*cinfo
, unsigned int line
)
244 printf("line<%d>", line
);
245 gpio_pin_test(cinfo
, line
, GPIOHANDLE_REQUEST_OUTPUT
, 0);
247 gpio_pin_test(cinfo
, line
, GPIOHANDLE_REQUEST_OUTPUT
, 1);
249 gpio_pin_test(cinfo
, line
,
250 GPIOHANDLE_REQUEST_OUTPUT
| GPIOHANDLE_REQUEST_ACTIVE_LOW
,
253 gpio_pin_test(cinfo
, line
,
254 GPIOHANDLE_REQUEST_OUTPUT
| GPIOHANDLE_REQUEST_ACTIVE_LOW
,
257 gpio_pin_test(cinfo
, line
, GPIOHANDLE_REQUEST_INPUT
, 0);
262 * ./gpio-mockup-chardev gpio_chip_name_prefix is_valid_gpio_chip
263 * Return 0 if successful or exit with EXIT_FAILURE if test failed.
264 * gpio_chip_name_prefix: The prefix of gpiochip you want to test. E.g.
266 * is_valid_gpio_chip: Whether the gpio_chip is valid. 1 means valid,
267 * 0 means invalid which could not be found by
270 int main(int argc
, char *argv
[])
274 struct gpiochip_info
*cinfo
;
275 struct gpiochip_info
*current
;
280 printf("Usage: %s prefix is_valid", argv
[0]);
285 valid
= strcmp(argv
[2], "true") == 0 ? 1 : 0;
287 printf("Test gpiochip %s: ", prefix
);
288 cinfo
= list_gpiochip(prefix
, &ret
);
290 if (!valid
&& ret
== 0) {
291 printf("Invalid test successful\n");
298 } else if (cinfo
&& !valid
) {
303 for (i
= 0; i
< ret
; i
++) {
304 gpio_pin_tests(current
, 0);
305 gpio_pin_tests(current
, current
->lines
- 1);
306 gpio_pin_tests(current
, random() % current
->lines
);
310 printf("successful\n");
314 fprintf(stderr
, "gpio<%s> test failed\n", prefix
);