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);