16d591c46SLinus Walleij /* 26d591c46SLinus Walleij * lsgpio - example on how to list the GPIO lines on a system 36d591c46SLinus Walleij * 46d591c46SLinus Walleij * Copyright (C) 2015 Linus Walleij 56d591c46SLinus Walleij * 66d591c46SLinus Walleij * This program is free software; you can redistribute it and/or modify it 76d591c46SLinus Walleij * under the terms of the GNU General Public License version 2 as published by 86d591c46SLinus Walleij * the Free Software Foundation. 96d591c46SLinus Walleij * 106d591c46SLinus Walleij * Usage: 116d591c46SLinus Walleij * lsgpio <-n device-name> 126d591c46SLinus Walleij */ 136d591c46SLinus Walleij 146d591c46SLinus Walleij #include <unistd.h> 156d591c46SLinus Walleij #include <stdlib.h> 166d591c46SLinus Walleij #include <stdbool.h> 176d591c46SLinus Walleij #include <stdio.h> 186d591c46SLinus Walleij #include <dirent.h> 196d591c46SLinus Walleij #include <errno.h> 206d591c46SLinus Walleij #include <string.h> 216d591c46SLinus Walleij #include <poll.h> 226d591c46SLinus Walleij #include <fcntl.h> 236d591c46SLinus Walleij #include <getopt.h> 246d591c46SLinus Walleij #include <sys/ioctl.h> 256d591c46SLinus Walleij #include <linux/gpio.h> 266d591c46SLinus Walleij 276d591c46SLinus Walleij #include "gpio-utils.h" 286d591c46SLinus Walleij 296d591c46SLinus Walleij int list_device(const char *device_name) 306d591c46SLinus Walleij { 316d591c46SLinus Walleij struct gpiochip_info cinfo; 326d591c46SLinus Walleij char *chrdev_name; 336d591c46SLinus Walleij int fd; 346d591c46SLinus Walleij int ret; 356d591c46SLinus Walleij 366d591c46SLinus Walleij ret = asprintf(&chrdev_name, "/dev/%s", device_name); 376d591c46SLinus Walleij if (ret < 0) 386d591c46SLinus Walleij return -ENOMEM; 396d591c46SLinus Walleij 406d591c46SLinus Walleij fd = open(chrdev_name, 0); 416d591c46SLinus Walleij if (fd == -1) { 426d591c46SLinus Walleij ret = -errno; 436d591c46SLinus Walleij fprintf(stderr, "Failed to open %s\n", chrdev_name); 446d591c46SLinus Walleij goto free_chrdev_name; 456d591c46SLinus Walleij } 466d591c46SLinus Walleij 476d591c46SLinus Walleij /* Inspect this GPIO chip */ 486d591c46SLinus Walleij ret = ioctl(fd, GPIO_GET_CHIPINFO_IOCTL, &cinfo); 496d591c46SLinus Walleij if (ret == -1) { 506d591c46SLinus Walleij ret = -errno; 516d591c46SLinus Walleij fprintf(stderr, "Failed to retrieve GPIO fd\n"); 526d591c46SLinus Walleij if (close(fd) == -1) 536d591c46SLinus Walleij perror("Failed to close GPIO character device file"); 546d591c46SLinus Walleij 556d591c46SLinus Walleij goto free_chrdev_name; 566d591c46SLinus Walleij } 576d591c46SLinus Walleij fprintf(stdout, "GPIO chip: %s, %u GPIO lines\n", 586d591c46SLinus Walleij cinfo.name, cinfo.lines); 596d591c46SLinus Walleij 606d591c46SLinus Walleij if (close(fd) == -1) { 616d591c46SLinus Walleij ret = -errno; 626d591c46SLinus Walleij goto free_chrdev_name; 636d591c46SLinus Walleij } 646d591c46SLinus Walleij 656d591c46SLinus Walleij free_chrdev_name: 666d591c46SLinus Walleij free(chrdev_name); 676d591c46SLinus Walleij 686d591c46SLinus Walleij return ret; 696d591c46SLinus Walleij 706d591c46SLinus Walleij } 716d591c46SLinus Walleij 726d591c46SLinus Walleij void print_usage(void) 736d591c46SLinus Walleij { 746d591c46SLinus Walleij fprintf(stderr, "Usage: lsgpio [options]...\n" 756d591c46SLinus Walleij "List GPIO chips, lines and states\n" 766d591c46SLinus Walleij " -n <name> List GPIOs on a named device\n" 776d591c46SLinus Walleij " -? This helptext\n" 786d591c46SLinus Walleij ); 796d591c46SLinus Walleij } 806d591c46SLinus Walleij 816d591c46SLinus Walleij int main(int argc, char **argv) 826d591c46SLinus Walleij { 836d591c46SLinus Walleij const char *device_name; 846d591c46SLinus Walleij int ret; 856d591c46SLinus Walleij int c; 866d591c46SLinus Walleij 876d591c46SLinus Walleij while ((c = getopt(argc, argv, "n:")) != -1) { 886d591c46SLinus Walleij switch (c) { 896d591c46SLinus Walleij case 'n': 906d591c46SLinus Walleij device_name = optarg; 916d591c46SLinus Walleij break; 926d591c46SLinus Walleij case '?': 936d591c46SLinus Walleij print_usage(); 946d591c46SLinus Walleij return -1; 956d591c46SLinus Walleij } 966d591c46SLinus Walleij } 976d591c46SLinus Walleij 986d591c46SLinus Walleij if (device_name) 996d591c46SLinus Walleij ret = list_device(device_name); 1006d591c46SLinus Walleij else { 1016d591c46SLinus Walleij const struct dirent *ent; 1026d591c46SLinus Walleij DIR *dp; 1036d591c46SLinus Walleij 1046d591c46SLinus Walleij /* List all GPIO devices one at a time */ 1056d591c46SLinus Walleij dp = opendir("/dev"); 1066d591c46SLinus Walleij if (!dp) { 1076d591c46SLinus Walleij ret = -errno; 1086d591c46SLinus Walleij goto error_out; 1096d591c46SLinus Walleij } 1106d591c46SLinus Walleij 1116d591c46SLinus Walleij ret = -ENOENT; 1126d591c46SLinus Walleij while (ent = readdir(dp), ent) { 1136d591c46SLinus Walleij if (check_prefix(ent->d_name, "gpiochip")) { 1146d591c46SLinus Walleij ret = list_device(ent->d_name); 1156d591c46SLinus Walleij if (ret) 1166d591c46SLinus Walleij break; 1176d591c46SLinus Walleij } 1186d591c46SLinus Walleij } 1196d591c46SLinus Walleij 1206d591c46SLinus Walleij ret = 0; 1216d591c46SLinus Walleij if (closedir(dp) == -1) { 1226d591c46SLinus Walleij perror("scanning devices: Failed to close directory"); 1236d591c46SLinus Walleij ret = -errno; 1246d591c46SLinus Walleij } 1256d591c46SLinus Walleij } 1266d591c46SLinus Walleij error_out: 1276d591c46SLinus Walleij return ret; 1286d591c46SLinus Walleij } 129