From patchwork Thu Oct 22 08:32:28 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Linus Walleij X-Patchwork-Id: 534305 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id CA51B141315 for ; Thu, 22 Oct 2015 19:33:05 +1100 (AEDT) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1756766AbbJVIdE (ORCPT ); Thu, 22 Oct 2015 04:33:04 -0400 Received: from mail-lf0-f49.google.com ([209.85.215.49]:33526 "EHLO mail-lf0-f49.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1756737AbbJVIdC (ORCPT ); Thu, 22 Oct 2015 04:33:02 -0400 Received: by lffv3 with SMTP id v3so39293211lff.0 for ; Thu, 22 Oct 2015 01:33:00 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=bxVoh96VK4AnaiNgaywk/IlYabpS8V4kAj4DKoA1W54=; b=N6KuV+ZvPjpSLAR10lTfwvHIX9XHx7ije5PjnoHhfexUcmTbvPXE3VTEDlspaunTbF 1f5VJtRugVA0RAse56lQbYFve2df7qeHnXWouAsY449jiQeFFws6yALRr12XJCqV5C0z ySQNf3SH+JsJqyxThF4fQvH6aymhYJaOUkO8pJ/Cbk5z4AeokqxNscLhe44oabLMU3MP a6NSL2UaF2ZHiawsA7gJSvrB8Fa4ybzR3i3B+GwrQi/8ih89/4H+Tnp+/h+7BfSyTpHO fwZ85+7MQUTQrTapTRdpjz1DZ0R9+oucnTOKp+ZE38hhX3An0mGB7x8tgPj9eEfg1xHw oATQ== X-Gm-Message-State: ALoCoQk46qsP5W0QeX6Vt8dyxm8bmI3xH/UW1YxZaR8j6RzkgSLxtdKWh60wWkGsqW2flXwdeWB1 X-Received: by 10.25.143.72 with SMTP id r69mr4987629lfd.65.1445502780756; Thu, 22 Oct 2015 01:33:00 -0700 (PDT) Received: from localhost.localdomain ([85.235.10.227]) by smtp.gmail.com with ESMTPSA id um10sm2148562lbc.15.2015.10.22.01.32.59 (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Thu, 22 Oct 2015 01:33:00 -0700 (PDT) From: Linus Walleij To: linux-gpio@vger.kernel.org, Johan Hovold , Alexandre Courbot , Arnd Bergmann , Michael Welling , Markus Pargmann Cc: Mark Brown , Amit Kucheria , Linus Walleij Subject: [PATCH 4/6] tools/gpio: create GPIO tools Date: Thu, 22 Oct 2015 10:32:28 +0200 Message-Id: <1445502750-22672-5-git-send-email-linus.walleij@linaro.org> X-Mailer: git-send-email 2.4.3 In-Reply-To: <1445502750-22672-1-git-send-email-linus.walleij@linaro.org> References: <1445502750-22672-1-git-send-email-linus.walleij@linaro.org> Sender: linux-gpio-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-gpio@vger.kernel.org This creates GPIO tools under tools/gpio/* and adds a single example program to list the GPIOs on a system. When proper devices are created it provides this minimal output: Cc: Johan Hovold Cc: Michael Welling Cc: Markus Pargmann Signed-off-by: Linus Walleij --- MAINTAINERS | 1 + tools/Makefile | 7 +-- tools/gpio/Makefile | 12 +++++ tools/gpio/gpio-utils.c | 11 +++++ tools/gpio/gpio-utils.h | 25 ++++++++++ tools/gpio/lsgpio.c | 128 ++++++++++++++++++++++++++++++++++++++++++++++++ 6 files changed, 181 insertions(+), 3 deletions(-) create mode 100644 tools/gpio/Makefile create mode 100644 tools/gpio/gpio-utils.c create mode 100644 tools/gpio/gpio-utils.h create mode 100644 tools/gpio/lsgpio.c diff --git a/MAINTAINERS b/MAINTAINERS index 4a12cd019511..3bb1f52d54e0 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -4647,6 +4647,7 @@ F: include/linux/gpio/ F: include/linux/gpio.h F: include/asm-generic/gpio.h F: include/uapi/linux/gpio.h +F: tools/gpio/ GRE DEMULTIPLEXER DRIVER M: Dmitry Kozlov diff --git a/tools/Makefile b/tools/Makefile index d6f307dfb1a3..8912759247b5 100644 --- a/tools/Makefile +++ b/tools/Makefile @@ -12,6 +12,7 @@ help: @echo ' cgroup - cgroup tools' @echo ' cpupower - a tool for all things x86 CPU power' @echo ' firewire - the userspace part of nosy, an IEEE-1394 traffic sniffer' + @echo ' gpio - GPIO tools' @echo ' hv - tools used when in Hyper-V clients' @echo ' iio - IIO tools' @echo ' lguest - a minimal 32-bit x86 hypervisor' @@ -48,7 +49,7 @@ acpi: FORCE cpupower: FORCE $(call descend,power/$@) -cgroup firewire hv guest usb virtio vm net iio: FORCE +cgroup firewire hv guest usb virtio vm net iio gpio: FORCE $(call descend,$@) liblockdep: FORCE @@ -109,7 +110,7 @@ acpi_clean: cpupower_clean: $(call descend,power/cpupower,clean) -cgroup_clean hv_clean firewire_clean lguest_clean usb_clean virtio_clean vm_clean net_clean iio_clean: +cgroup_clean hv_clean firewire_clean lguest_clean usb_clean virtio_clean vm_clean net_clean iio_clean gpio_clean: $(call descend,$(@:_clean=),clean) liblockdep_clean: @@ -136,6 +137,6 @@ freefall_clean: clean: acpi_clean cgroup_clean cpupower_clean hv_clean firewire_clean lguest_clean \ perf_clean selftests_clean turbostat_clean usb_clean virtio_clean \ vm_clean net_clean iio_clean x86_energy_perf_policy_clean tmon_clean \ - freefall_clean + freefall_clean gpio_clean .PHONY: FORCE diff --git a/tools/gpio/Makefile b/tools/gpio/Makefile new file mode 100644 index 000000000000..4d198d5c4203 --- /dev/null +++ b/tools/gpio/Makefile @@ -0,0 +1,12 @@ +CC = $(CROSS_COMPILE)gcc +CFLAGS += -Wall -g -D_GNU_SOURCE + +all: lsgpio + +lsgpio: lsgpio.o gpio-utils.o + +%.o: %.c gpio-utils.h + +.PHONY: clean +clean: + rm -f *.o lsgpio diff --git a/tools/gpio/gpio-utils.c b/tools/gpio/gpio-utils.c new file mode 100644 index 000000000000..8208718f2c99 --- /dev/null +++ b/tools/gpio/gpio-utils.c @@ -0,0 +1,11 @@ +/* + * GPIO tools - helpers library for the GPIO tools + * + * Copyright (C) 2015 Linus Walleij + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 as published by + * the Free Software Foundation. + */ + +#include "gpio-utils.h" diff --git a/tools/gpio/gpio-utils.h b/tools/gpio/gpio-utils.h new file mode 100644 index 000000000000..b18209a45ad3 --- /dev/null +++ b/tools/gpio/gpio-utils.h @@ -0,0 +1,25 @@ +/* + * GPIO tools - utility helpers library for the GPIO tools + * + * Copyright (C) 2015 Linus Walleij + * + * Portions copied from iio_utils and lssio: + * Copyright (c) 2010 Manuel Stahl + * Copyright (c) 2008 Jonathan Cameron + * * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 as published by + * the Free Software Foundation. + */ +#ifndef _GPIO_UTILS_H_ +#define _GPIO_UTILS_H_ + +#include + +static inline int check_prefix(const char *str, const char *prefix) +{ + return strlen(str) > strlen(prefix) && + strncmp(str, prefix, strlen(prefix)) == 0; +} + +#endif /* _GPIO_UTILS_H_ */ diff --git a/tools/gpio/lsgpio.c b/tools/gpio/lsgpio.c new file mode 100644 index 000000000000..4cfe29da279b --- /dev/null +++ b/tools/gpio/lsgpio.c @@ -0,0 +1,128 @@ +/* + * lsgpio - example on how to list the GPIO lines on a system + * + * Copyright (C) 2015 Linus Walleij + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 as published by + * the Free Software Foundation. + * + * Usage: + * lsgpio <-n device-name> + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "gpio-utils.h" + +int list_device(const char *device_name) +{ + struct gpiochip_info cinfo; + char *chrdev_name; + int fd; + int ret; + + ret = asprintf(&chrdev_name, "/dev/%s", device_name); + if (ret < 0) + return -ENOMEM; + + fd = open(chrdev_name, 0); + if (fd == -1) { + ret = -errno; + fprintf(stderr, "Failed to open %s\n", chrdev_name); + goto free_chrdev_name; + } + + /* Inspect this GPIO chip */ + ret = ioctl(fd, GPIO_GET_CHIPINFO_IOCTL, &cinfo); + if (ret == -1) { + ret = -errno; + fprintf(stderr, "Failed to retrieve GPIO fd\n"); + if (close(fd) == -1) + perror("Failed to close GPIO character device file"); + + goto free_chrdev_name; + } + fprintf(stdout, "GPIO chip: %s, %u GPIO lines\n", + cinfo.name, cinfo.lines); + + if (close(fd) == -1) { + ret = -errno; + goto free_chrdev_name; + } + +free_chrdev_name: + free(chrdev_name); + + return ret; + +} + +void print_usage(void) +{ + fprintf(stderr, "Usage: lsgpio [options]...\n" + "List GPIO chips, lines and states\n" + " -n List GPIOs on a named device\n" + " -? This helptext\n" + ); +} + +int main(int argc, char **argv) +{ + const char *device_name; + int ret; + int c; + + while ((c = getopt(argc, argv, "n:")) != -1) { + switch (c) { + case 'n': + device_name = optarg; + break; + case '?': + print_usage(); + return -1; + } + } + + if (device_name) + ret = list_device(device_name); + else { + const struct dirent *ent; + DIR *dp; + + /* List all GPIO devices one at a time */ + dp = opendir("/dev"); + if (!dp) { + ret = -errno; + goto error_out; + } + + ret = -ENOENT; + while (ent = readdir(dp), ent) { + if (check_prefix(ent->d_name, "gpiochip")) { + ret = list_device(ent->d_name); + if (ret) + break; + } + } + + ret = 0; + if (closedir(dp) == -1) { + perror("scanning devices: Failed to close directory"); + ret = -errno; + } + } +error_out: + return ret; +}