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 ret
= asprintf(path
, "%s/gpio", mnt_fs_get_target(fs
));
64 err(EXIT_FAILURE
, "failed to format string");
68 mnt_free_context(cxt
);
76 static int gpio_debugfs_get(const char *consumer
, int *dir
, int *value
)
85 if (get_debugfs(&debugfs
) != 0)
86 err(EXIT_FAILURE
, "debugfs is not mounted");
88 f
= fopen(debugfs
, "r");
90 err(EXIT_FAILURE
, "read from gpio debugfs failed");
93 * gpio-2 ( |gpio-selftest ) in lo
95 while (getline(&line
, &len
, f
) != -1) {
96 cur
= strstr(line
, consumer
);
100 cur
= strchr(line
, ')');
105 if (!strncmp(cur
, "out", 3)) {
108 } else if (!strncmp(cur
, "in", 2)) {
113 if (!strncmp(cur
, "hi", 2))
115 else if (!strncmp(cur
, "lo", 2))
131 static struct gpiochip_info
*list_gpiochip(const char *gpiochip_name
, int *ret
)
133 struct gpiochip_info
*cinfo
;
134 struct gpiochip_info
*current
;
135 const struct dirent
*ent
;
141 cinfo
= calloc(sizeof(struct gpiochip_info
) * 4, GC_NUM
+ 1);
143 err(EXIT_FAILURE
, "gpiochip_info allocation failed");
146 dp
= opendir("/dev");
154 while (ent
= readdir(dp
), ent
) {
155 if (check_prefix(ent
->d_name
, "gpiochip")) {
156 *ret
= asprintf(&chrdev_name
, "/dev/%s", ent
->d_name
);
160 fd
= open(chrdev_name
, 0);
163 fprintf(stderr
, "Failed to open %s\n",
165 goto error_close_dir
;
167 *ret
= ioctl(fd
, GPIO_GET_CHIPINFO_IOCTL
, current
);
169 perror("Failed to issue CHIPINFO IOCTL\n");
170 goto error_close_dir
;
173 if (strcmp(current
->label
, gpiochip_name
) == 0
174 || check_prefix(current
->label
, gpiochip_name
)) {
182 if ((!*ret
&& i
== 0) || *ret
< 0) {
186 if (!*ret
&& i
> 0) {
187 cinfo
= realloc(cinfo
, sizeof(struct gpiochip_info
) * 4 * i
);
195 err(EXIT_FAILURE
, "list gpiochip failed: %s", strerror(*ret
));
200 int gpio_pin_test(struct gpiochip_info
*cinfo
, int line
, int flag
, int value
)
202 struct gpiohandle_data data
;
203 unsigned int lines
[] = {line
};
205 int debugfs_dir
= IN
;
206 int debugfs_value
= 0;
209 data
.values
[0] = value
;
210 ret
= gpiotools_request_linehandle(cinfo
->name
, lines
, 1, flag
, &data
,
217 ret
= gpio_debugfs_get(CONSUMER
, &debugfs_dir
, &debugfs_value
);
222 if (flag
& GPIOHANDLE_REQUEST_INPUT
) {
223 if (debugfs_dir
!= IN
) {
227 } else if (flag
& GPIOHANDLE_REQUEST_OUTPUT
) {
228 if (flag
& GPIOHANDLE_REQUEST_ACTIVE_LOW
)
229 debugfs_value
= !debugfs_value
;
231 if (!(debugfs_dir
== OUT
&& value
== debugfs_value
)) {
236 gpiotools_release_linehandle(fd
);
240 err(EXIT_FAILURE
, "gpio<%s> line<%d> test flag<0x%x> value<%d>",
241 cinfo
->name
, line
, flag
, value
);
246 void gpio_pin_tests(struct gpiochip_info
*cinfo
, unsigned int line
)
248 printf("line<%d>", line
);
249 gpio_pin_test(cinfo
, line
, GPIOHANDLE_REQUEST_OUTPUT
, 0);
251 gpio_pin_test(cinfo
, line
, GPIOHANDLE_REQUEST_OUTPUT
, 1);
253 gpio_pin_test(cinfo
, line
,
254 GPIOHANDLE_REQUEST_OUTPUT
| GPIOHANDLE_REQUEST_ACTIVE_LOW
,
257 gpio_pin_test(cinfo
, line
,
258 GPIOHANDLE_REQUEST_OUTPUT
| GPIOHANDLE_REQUEST_ACTIVE_LOW
,
261 gpio_pin_test(cinfo
, line
, GPIOHANDLE_REQUEST_INPUT
, 0);
266 * ./gpio-mockup-chardev gpio_chip_name_prefix is_valid_gpio_chip
267 * Return 0 if successful or exit with EXIT_FAILURE if test failed.
268 * gpio_chip_name_prefix: The prefix of gpiochip you want to test. E.g.
270 * is_valid_gpio_chip: Whether the gpio_chip is valid. 1 means valid,
271 * 0 means invalid which could not be found by
274 int main(int argc
, char *argv
[])
278 struct gpiochip_info
*cinfo
;
279 struct gpiochip_info
*current
;
284 printf("Usage: %s prefix is_valid", argv
[0]);
289 valid
= strcmp(argv
[2], "true") == 0 ? 1 : 0;
291 printf("Test gpiochip %s: ", prefix
);
292 cinfo
= list_gpiochip(prefix
, &ret
);
294 if (!valid
&& ret
== 0) {
295 printf("Invalid test successful\n");
302 } else if (cinfo
&& !valid
) {
307 for (i
= 0; i
< ret
; i
++) {
308 gpio_pin_tests(current
, 0);
309 gpio_pin_tests(current
, current
->lines
- 1);
310 gpio_pin_tests(current
, random() % current
->lines
);
314 printf("successful\n");
318 fprintf(stderr
, "gpio<%s> test failed\n", prefix
);