2 * GPIO chardev test helper
4 * Copyright (C) 2016 Bamvor Jian Zhang
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.
20 #include <sys/ioctl.h>
24 #include <linux/gpio.h>
25 #include "../../../gpio/gpio-utils.h"
27 #define CONSUMER "gpio-selftest"
34 static int get_debugfs(char **path
)
36 struct libmnt_context
*cxt
;
37 struct libmnt_table
*tb
;
38 struct libmnt_iter
*itr
= NULL
;
42 cxt
= mnt_new_context();
44 err(EXIT_FAILURE
, "libmount context allocation failed");
46 itr
= mnt_new_iter(MNT_ITER_FORWARD
);
48 err(EXIT_FAILURE
, "failed to initialize libmount iterator");
50 if (mnt_context_get_mtab(cxt
, &tb
))
51 err(EXIT_FAILURE
, "failed to read mtab");
53 while (mnt_table_next_fs(tb
, itr
, &fs
) == 0) {
54 const char *type
= mnt_fs_get_fstype(fs
);
56 if (!strcmp(type
, "debugfs")) {
62 asprintf(path
, "%s/gpio", mnt_fs_get_target(fs
));
65 mnt_free_context(cxt
);
73 static int gpio_debugfs_get(const char *consumer
, int *dir
, int *value
)
82 if (get_debugfs(&debugfs
) != 0)
83 err(EXIT_FAILURE
, "debugfs is not mounted");
85 f
= fopen(debugfs
, "r");
87 err(EXIT_FAILURE
, "read from gpio debugfs failed");
90 * gpio-2 ( |gpio-selftest ) in lo
92 while (getline(&line
, &len
, f
) != -1) {
93 cur
= strstr(line
, consumer
);
97 cur
= strchr(line
, ')');
102 if (!strncmp(cur
, "out", 3)) {
105 } else if (!strncmp(cur
, "in", 2)) {
110 if (!strncmp(cur
, "hi", 2))
112 else if (!strncmp(cur
, "lo", 2))
128 static struct gpiochip_info
*list_gpiochip(const char *gpiochip_name
, int *ret
)
130 struct gpiochip_info
*cinfo
;
131 struct gpiochip_info
*current
;
132 const struct dirent
*ent
;
138 cinfo
= calloc(sizeof(struct gpiochip_info
) * 4, GC_NUM
+ 1);
140 err(EXIT_FAILURE
, "gpiochip_info allocation failed");
143 dp
= opendir("/dev");
151 while (ent
= readdir(dp
), ent
) {
152 if (check_prefix(ent
->d_name
, "gpiochip")) {
153 *ret
= asprintf(&chrdev_name
, "/dev/%s", ent
->d_name
);
157 fd
= open(chrdev_name
, 0);
160 fprintf(stderr
, "Failed to open %s\n",
162 goto error_close_dir
;
164 *ret
= ioctl(fd
, GPIO_GET_CHIPINFO_IOCTL
, current
);
166 perror("Failed to issue CHIPINFO IOCTL\n");
167 goto error_close_dir
;
170 if (strcmp(current
->label
, gpiochip_name
) == 0
171 || check_prefix(current
->label
, gpiochip_name
)) {
179 if ((!*ret
&& i
== 0) || *ret
< 0) {
183 if (!*ret
&& i
> 0) {
184 cinfo
= realloc(cinfo
, sizeof(struct gpiochip_info
) * 4 * i
);
192 err(EXIT_FAILURE
, "list gpiochip failed: %s", strerror(*ret
));
197 int gpio_pin_test(struct gpiochip_info
*cinfo
, int line
, int flag
, int value
)
199 struct gpiohandle_data data
;
200 unsigned int lines
[] = {line
};
202 int debugfs_dir
= IN
;
203 int debugfs_value
= 0;
206 data
.values
[0] = value
;
207 ret
= gpiotools_request_linehandle(cinfo
->name
, lines
, 1, flag
, &data
,
214 ret
= gpio_debugfs_get(CONSUMER
, &debugfs_dir
, &debugfs_value
);
219 if (flag
& GPIOHANDLE_REQUEST_INPUT
) {
220 if (debugfs_dir
!= IN
) {
224 } else if (flag
& GPIOHANDLE_REQUEST_OUTPUT
) {
225 if (flag
& GPIOHANDLE_REQUEST_ACTIVE_LOW
)
226 debugfs_value
= !debugfs_value
;
228 if (!(debugfs_dir
== OUT
&& value
== debugfs_value
))
233 gpiotools_release_linehandle(fd
);
237 err(EXIT_FAILURE
, "gpio<%s> line<%d> test flag<0x%x> value<%d>",
238 cinfo
->name
, line
, flag
, value
);
243 void gpio_pin_tests(struct gpiochip_info
*cinfo
, unsigned int line
)
245 printf("line<%d>", line
);
246 gpio_pin_test(cinfo
, line
, GPIOHANDLE_REQUEST_OUTPUT
, 0);
248 gpio_pin_test(cinfo
, line
, GPIOHANDLE_REQUEST_OUTPUT
, 1);
250 gpio_pin_test(cinfo
, line
,
251 GPIOHANDLE_REQUEST_OUTPUT
| GPIOHANDLE_REQUEST_ACTIVE_LOW
,
254 gpio_pin_test(cinfo
, line
,
255 GPIOHANDLE_REQUEST_OUTPUT
| GPIOHANDLE_REQUEST_ACTIVE_LOW
,
258 gpio_pin_test(cinfo
, line
, GPIOHANDLE_REQUEST_INPUT
, 0);
263 * ./gpio-mockup-chardev gpio_chip_name_prefix is_valid_gpio_chip
264 * Return 0 if successful or exit with EXIT_FAILURE if test failed.
265 * gpio_chip_name_prefix: The prefix of gpiochip you want to test. E.g.
267 * is_valid_gpio_chip: Whether the gpio_chip is valid. 1 means valid,
268 * 0 means invalid which could not be found by
271 int main(int argc
, char *argv
[])
275 struct gpiochip_info
*cinfo
;
276 struct gpiochip_info
*current
;
281 printf("Usage: %s prefix is_valid", argv
[0]);
286 valid
= strcmp(argv
[2], "true") == 0 ? 1 : 0;
288 printf("Test gpiochip %s: ", prefix
);
289 cinfo
= list_gpiochip(prefix
, &ret
);
291 if (!valid
&& ret
== 0) {
292 printf("Invalid test successful\n");
299 } else if (cinfo
&& !valid
) {
304 for (i
= 0; i
< ret
; i
++) {
305 gpio_pin_tests(current
, 0);
306 gpio_pin_tests(current
, current
->lines
- 1);
307 gpio_pin_tests(current
, random() % current
->lines
);
311 printf("successful\n");
315 fprintf(stderr
, "gpio<%s> test failed\n", prefix
);