Skip to content

Commit

Permalink
tools/gpio: create GPIO tools
Browse files Browse the repository at this point in the history
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 <[email protected]>
Cc: Michael Welling <[email protected]>
Cc: Markus Pargmann <[email protected]>
Signed-off-by: Linus Walleij <[email protected]>
  • Loading branch information
linusw committed Feb 9, 2016
1 parent 3c702e9 commit 6d591c4
Show file tree
Hide file tree
Showing 6 changed files with 182 additions and 3 deletions.
1 change: 1 addition & 0 deletions MAINTAINERS
Original file line number Diff line number Diff line change
Expand Up @@ -4820,6 +4820,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 <[email protected]>
Expand Down
8 changes: 5 additions & 3 deletions tools/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ help:
@echo ' cpupower - a tool for all things x86 CPU power'
@echo ' firewire - the userspace part of nosy, an IEEE-1394 traffic sniffer'
@echo ' freefall - laptop accelerometer program for disk protection'
@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'
Expand Down Expand Up @@ -53,7 +54,7 @@ acpi: FORCE
cpupower: FORCE
$(call descend,power/$@)

cgroup firewire hv guest spi usb virtio vm net iio: FORCE
cgroup firewire hv guest spi usb virtio vm net iio gpio: FORCE
$(call descend,$@)

liblockdep: FORCE
Expand Down Expand Up @@ -119,7 +120,7 @@ acpi_clean:
cpupower_clean:
$(call descend,power/cpupower,clean)

cgroup_clean hv_clean firewire_clean lguest_clean spi_clean usb_clean virtio_clean vm_clean net_clean iio_clean:
cgroup_clean hv_clean firewire_clean lguest_clean spi_clean usb_clean virtio_clean vm_clean net_clean iio_clean gpio_clean:
$(call descend,$(@:_clean=),clean)

liblockdep_clean:
Expand Down Expand Up @@ -155,6 +156,7 @@ build_clean:
clean: acpi_clean cgroup_clean cpupower_clean hv_clean firewire_clean lguest_clean \
perf_clean selftests_clean turbostat_clean spi_clean usb_clean virtio_clean \
vm_clean net_clean iio_clean x86_energy_perf_policy_clean tmon_clean \
freefall_clean build_clean libbpf_clean libsubcmd_clean liblockdep_clean
freefall_clean build_clean libbpf_clean libsubcmd_clean liblockdep_clean \
gpio_clean

.PHONY: FORCE
12 changes: 12 additions & 0 deletions tools/gpio/Makefile
Original file line number Diff line number Diff line change
@@ -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
11 changes: 11 additions & 0 deletions tools/gpio/gpio-utils.c
Original file line number Diff line number Diff line change
@@ -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"
25 changes: 25 additions & 0 deletions tools/gpio/gpio-utils.h
Original file line number Diff line number Diff line change
@@ -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 <[email protected]>
* 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 <string.h>

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_ */
128 changes: 128 additions & 0 deletions tools/gpio/lsgpio.c
Original file line number Diff line number Diff line change
@@ -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 <unistd.h>
#include <stdlib.h>
#include <stdbool.h>
#include <stdio.h>
#include <dirent.h>
#include <errno.h>
#include <string.h>
#include <poll.h>
#include <fcntl.h>
#include <getopt.h>
#include <sys/ioctl.h>
#include <linux/gpio.h>

#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 <name> 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;
}

0 comments on commit 6d591c4

Please sign in to comment.