summaryrefslogtreecommitdiff
path: root/tools
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2016-07-24 16:55:23 -0700
committerLinus Torvalds <torvalds@linux-foundation.org>2016-07-24 16:55:23 -0700
commit25a0dc4be86fc0d8c7e81bb5f8be8427022bf15f (patch)
treec8d66d65eb0910a2dc8e00a96c1a4da1fc9e33d4 /tools
parent9d0be76f52faff97fd9581eba70870f27061ae93 (diff)
parent6c71ee3b6157fdbde5c839405b593876d3687eb9 (diff)
Merge tag 'staging-4.8-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/staging
Pull staging and IIO driver updates from Greg KH: "Here is the big Staging and IIO driver update for 4.8-rc1. We ended up adding more code than removing, again, but it's not all that bad. Lots of cleanups all over the staging tree, and new IIO drivers, full details in the shortlog. All of these have been in linux-next for a while with no reported issues" * tag 'staging-4.8-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/staging: (417 commits) drivers:iio:accel:mma8452: removed unwanted return statements drivers:iio:accel:mma8452: added cleanup provision in case of failure. iio: Add iio.git tree to MAINTAINERS iio:st_pressure: clean useless static channel initializers iio:st_pressure:lps22hb: temperature support iio:st_pressure:lps22hb: open drain support iio:st_pressure: temperature triggered buffering iio:st_pressure: document sampling gains iio:st_pressure: align storagebits on power of 2 iio:st_sensors: align on storagebits boundaries staging:iio:lis3l02dq drop separate driver iio: accel: st_accel: Add lis3l02dq support iio: adc: add missing of_node references to iio_dev iio: adc: ti-ads1015: add indio_dev->dev.of_node reference iio: potentiometer: Fix typo in Kconfig iio: potentiometer: mcp4531: Add device tree binding iio: potentiometer: mcp4531: Add device tree binding documentation iio: potentiometer: mcp4531: Add support for MCP454x, MCP456x, MCP464x and MCP466x iio:imu:mpu6050: icm20608 initial support iio: adc: max1363: Add device tree binding ...
Diffstat (limited to 'tools')
-rw-r--r--tools/iio/Makefile21
-rw-r--r--tools/iio/iio_generic_buffer.c (renamed from tools/iio/generic_buffer.c)261
2 files changed, 199 insertions, 83 deletions
diff --git a/tools/iio/Makefile b/tools/iio/Makefile
index 3a7a54f59713..5446d625e17d 100644
--- a/tools/iio/Makefile
+++ b/tools/iio/Makefile
@@ -1,16 +1,31 @@
CC = $(CROSS_COMPILE)gcc
CFLAGS += -Wall -g -D_GNU_SOURCE
-all: iio_event_monitor lsiio generic_buffer
+BINDIR=usr/bin
+INSTALL_PROGRAM=install -m 755 -p
+DEL_FILE=rm -f
+
+all: iio_event_monitor lsiio iio_generic_buffer
iio_event_monitor: iio_event_monitor.o iio_utils.o
lsiio: lsiio.o iio_utils.o
-generic_buffer: generic_buffer.o iio_utils.o
+iio_generic_buffer: iio_generic_buffer.o iio_utils.o
%.o: %.c iio_utils.h
+install:
+ - mkdir -p $(INSTALL_ROOT)/$(BINDIR)
+ - $(INSTALL_PROGRAM) "iio_event_monitor" "$(INSTALL_ROOT)/$(BINDIR)/iio_event_monitor"
+ - $(INSTALL_PROGRAM) "lsiio" "$(INSTALL_ROOT)/$(BINDIR)/lsiio"
+ - $(INSTALL_PROGRAM) "iio_generic_buffer" "$(INSTALL_ROOT)/$(BINDIR)/iio_generic_buffer"
+
+uninstall:
+ $(DEL_FILE) "$(INSTALL_ROOT)/$(BINDIR)/iio_event_monitor"
+ $(DEL_FILE) "$(INSTALL_ROOT)/$(BINDIR)/lsiio"
+ $(DEL_FILE) "$(INSTALL_ROOT)/$(BINDIR)/iio_generic_buffer"
+
.PHONY: clean
clean:
- rm -f *.o iio_event_monitor lsiio generic_buffer
+ rm -f *.o iio_event_monitor lsiio iio_generic_buffer
diff --git a/tools/iio/generic_buffer.c b/tools/iio/iio_generic_buffer.c
index 2429c78de940..0e8a1f7a292d 100644
--- a/tools/iio/generic_buffer.c
+++ b/tools/iio/iio_generic_buffer.c
@@ -32,6 +32,8 @@
#include <endian.h>
#include <getopt.h>
#include <inttypes.h>
+#include <stdbool.h>
+#include <signal.h>
#include "iio_utils.h"
/**
@@ -249,11 +251,82 @@ void print_usage(void)
" -e Disable wait for event (new data)\n"
" -g Use trigger-less mode\n"
" -l <n> Set buffer length to n samples\n"
- " -n <name> Set device name (mandatory)\n"
- " -t <name> Set trigger name\n"
+ " --device-name -n <name>\n"
+ " --device-num -N <num>\n"
+ " Set device by name or number (mandatory)\n"
+ " --trigger-name -t <name>\n"
+ " --trigger-num -T <num>\n"
+ " Set trigger by name or number\n"
" -w <n> Set delay between reads in us (event-less mode)\n");
}
+enum autochan autochannels = AUTOCHANNELS_DISABLED;
+char *dev_dir_name = NULL;
+char *buf_dir_name = NULL;
+bool current_trigger_set = false;
+
+void cleanup(void)
+{
+ int ret;
+
+ /* Disable trigger */
+ if (dev_dir_name && current_trigger_set) {
+ /* Disconnect the trigger - just write a dummy name. */
+ ret = write_sysfs_string("trigger/current_trigger",
+ dev_dir_name, "NULL");
+ if (ret < 0)
+ fprintf(stderr, "Failed to disable trigger: %s\n",
+ strerror(-ret));
+ current_trigger_set = false;
+ }
+
+ /* Disable buffer */
+ if (buf_dir_name) {
+ ret = write_sysfs_int("enable", buf_dir_name, 0);
+ if (ret < 0)
+ fprintf(stderr, "Failed to disable buffer: %s\n",
+ strerror(-ret));
+ }
+
+ /* Disable channels if auto-enabled */
+ if (dev_dir_name && autochannels == AUTOCHANNELS_ACTIVE) {
+ ret = enable_disable_all_channels(dev_dir_name, 0);
+ if (ret)
+ fprintf(stderr, "Failed to disable all channels\n");
+ autochannels = AUTOCHANNELS_DISABLED;
+ }
+}
+
+void sig_handler(int signum)
+{
+ fprintf(stderr, "Caught signal %d\n", signum);
+ cleanup();
+ exit(-signum);
+}
+
+void register_cleanup(void)
+{
+ struct sigaction sa = { .sa_handler = sig_handler };
+ const int signums[] = { SIGINT, SIGTERM, SIGABRT };
+ int ret, i;
+
+ for (i = 0; i < ARRAY_SIZE(signums); ++i) {
+ ret = sigaction(signums[i], &sa, NULL);
+ if (ret) {
+ perror("Failed to register signal handler");
+ exit(-1);
+ }
+ }
+}
+
+static const struct option longopts[] = {
+ { "device-name", 1, 0, 'n' },
+ { "device-num", 1, 0, 'N' },
+ { "trigger-name", 1, 0, 't' },
+ { "trigger-num", 1, 0, 'T' },
+ { },
+};
+
int main(int argc, char **argv)
{
unsigned long num_loops = 2;
@@ -261,26 +334,25 @@ int main(int argc, char **argv)
unsigned long buf_len = 128;
int ret, c, i, j, toread;
- int fp;
+ int fp = -1;
- int num_channels;
+ int num_channels = 0;
char *trigger_name = NULL, *device_name = NULL;
- char *dev_dir_name, *buf_dir_name;
- int datardytrigger = 1;
- char *data;
+ char *data = NULL;
ssize_t read_size;
- int dev_num, trig_num;
- char *buffer_access;
+ int dev_num = -1, trig_num = -1;
+ char *buffer_access = NULL;
int scan_size;
int noevents = 0;
int notrigger = 0;
- enum autochan autochannels = AUTOCHANNELS_DISABLED;
char *dummy;
struct iio_channel_info *channels;
- while ((c = getopt(argc, argv, "ac:egl:n:t:w:")) != -1) {
+ register_cleanup();
+
+ while ((c = getopt_long(argc, argv, "ac:egl:n:N:t:T:w:", longopts, NULL)) != -1) {
switch (c) {
case 'a':
autochannels = AUTOCHANNELS_ENABLED;
@@ -288,8 +360,10 @@ int main(int argc, char **argv)
case 'c':
errno = 0;
num_loops = strtoul(optarg, &dummy, 10);
- if (errno)
- return -errno;
+ if (errno) {
+ ret = -errno;
+ goto error;
+ }
break;
case 'e':
@@ -301,49 +375,102 @@ int main(int argc, char **argv)
case 'l':
errno = 0;
buf_len = strtoul(optarg, &dummy, 10);
- if (errno)
- return -errno;
+ if (errno) {
+ ret = -errno;
+ goto error;
+ }
break;
case 'n':
- device_name = optarg;
+ device_name = strdup(optarg);
+ break;
+ case 'N':
+ errno = 0;
+ dev_num = strtoul(optarg, &dummy, 10);
+ if (errno) {
+ ret = -errno;
+ goto error;
+ }
break;
case 't':
- trigger_name = optarg;
- datardytrigger = 0;
+ trigger_name = strdup(optarg);
break;
- case 'w':
+ case 'T':
errno = 0;
- timedelay = strtoul(optarg, &dummy, 10);
+ trig_num = strtoul(optarg, &dummy, 10);
if (errno)
return -errno;
break;
+ case 'w':
+ errno = 0;
+ timedelay = strtoul(optarg, &dummy, 10);
+ if (errno) {
+ ret = -errno;
+ goto error;
+ }
+ break;
case '?':
print_usage();
- return -1;
+ ret = -1;
+ goto error;
}
}
- if (!device_name) {
- fprintf(stderr, "Device name not set\n");
- print_usage();
- return -1;
- }
-
/* Find the device requested */
- dev_num = find_type_by_name(device_name, "iio:device");
- if (dev_num < 0) {
- fprintf(stderr, "Failed to find the %s\n", device_name);
- return dev_num;
+ if (dev_num < 0 && !device_name) {
+ fprintf(stderr, "Device not set\n");
+ print_usage();
+ ret = -1;
+ goto error;
+ } else if (dev_num >= 0 && device_name) {
+ fprintf(stderr, "Only one of --device-num or --device-name needs to be set\n");
+ print_usage();
+ ret = -1;
+ goto error;
+ } else if (dev_num < 0) {
+ dev_num = find_type_by_name(device_name, "iio:device");
+ if (dev_num < 0) {
+ fprintf(stderr, "Failed to find the %s\n", device_name);
+ ret = dev_num;
+ goto error;
+ }
}
-
printf("iio device number being used is %d\n", dev_num);
ret = asprintf(&dev_dir_name, "%siio:device%d", iio_dir, dev_num);
if (ret < 0)
return -ENOMEM;
+ /* Fetch device_name if specified by number */
+ if (!device_name) {
+ device_name = malloc(IIO_MAX_NAME_LENGTH);
+ if (!device_name) {
+ ret = -ENOMEM;
+ goto error;
+ }
+ ret = read_sysfs_string("name", dev_dir_name, device_name);
+ if (ret < 0) {
+ fprintf(stderr, "Failed to read name of device %d\n", dev_num);
+ goto error;
+ }
+ }
- if (!notrigger) {
+ if (notrigger) {
+ printf("trigger-less mode selected\n");
+ } if (trig_num >= 0) {
+ char *trig_dev_name;
+ ret = asprintf(&trig_dev_name, "%strigger%d", iio_dir, trig_num);
+ if (ret < 0) {
+ return -ENOMEM;
+ }
+ trigger_name = malloc(IIO_MAX_NAME_LENGTH);
+ ret = read_sysfs_string("name", trig_dev_name, trigger_name);
+ free(trig_dev_name);
+ if (ret < 0) {
+ fprintf(stderr, "Failed to read trigger%d name from\n", trig_num);
+ return ret;
+ }
+ printf("iio trigger number being used is %d\n", trig_num);
+ } else {
if (!trigger_name) {
/*
* Build the trigger name. If it is device associated
@@ -354,7 +481,7 @@ int main(int argc, char **argv)
"%s-dev%d", device_name, dev_num);
if (ret < 0) {
ret = -ENOMEM;
- goto error_free_dev_dir_name;
+ goto error;
}
}
@@ -367,7 +494,7 @@ int main(int argc, char **argv)
"%s-trigger", device_name);
if (ret < 0) {
ret = -ENOMEM;
- goto error_free_dev_dir_name;
+ goto error;
}
}
@@ -376,12 +503,10 @@ int main(int argc, char **argv)
fprintf(stderr, "Failed to find the trigger %s\n",
trigger_name);
ret = trig_num;
- goto error_free_triggername;
+ goto error;
}
printf("iio trigger number being used is %d\n", trig_num);
- } else {
- printf("trigger-less mode selected\n");
}
/*
@@ -392,7 +517,7 @@ int main(int argc, char **argv)
if (ret) {
fprintf(stderr, "Problem reading scan element information\n"
"diag %s\n", dev_dir_name);
- goto error_free_triggername;
+ goto error;
}
if (num_channels && autochannels == AUTOCHANNELS_ENABLED) {
fprintf(stderr, "Auto-channels selected but some channels "
@@ -407,7 +532,7 @@ int main(int argc, char **argv)
ret = enable_disable_all_channels(dev_dir_name, 1);
if (ret) {
fprintf(stderr, "Failed to enable all channels\n");
- goto error_free_triggername;
+ goto error;
}
/* This flags that we need to disable the channels again */
@@ -419,12 +544,12 @@ int main(int argc, char **argv)
fprintf(stderr, "Problem reading scan element "
"information\n"
"diag %s\n", dev_dir_name);
- goto error_disable_channels;
+ goto error;
}
if (!num_channels) {
fprintf(stderr, "Still no channels after "
"auto-enabling, giving up\n");
- goto error_disable_channels;
+ goto error;
}
}
@@ -436,7 +561,7 @@ int main(int argc, char **argv)
"/*_en or pass -a to autoenable channels and "
"try again.\n", dev_dir_name);
ret = -ENOENT;
- goto error_free_triggername;
+ goto error;
}
/*
@@ -448,7 +573,7 @@ int main(int argc, char **argv)
"%siio:device%d/buffer", iio_dir, dev_num);
if (ret < 0) {
ret = -ENOMEM;
- goto error_free_channels;
+ goto error;
}
if (!notrigger) {
@@ -463,34 +588,34 @@ int main(int argc, char **argv)
if (ret < 0) {
fprintf(stderr,
"Failed to write current_trigger file\n");
- goto error_free_buf_dir_name;
+ goto error;
}
}
/* Setup ring buffer parameters */
ret = write_sysfs_int("length", buf_dir_name, buf_len);
if (ret < 0)
- goto error_free_buf_dir_name;
+ goto error;
/* Enable the buffer */
ret = write_sysfs_int("enable", buf_dir_name, 1);
if (ret < 0) {
fprintf(stderr,
"Failed to enable buffer: %s\n", strerror(-ret));
- goto error_free_buf_dir_name;
+ goto error;
}
scan_size = size_from_channelarray(channels, num_channels);
data = malloc(scan_size * buf_len);
if (!data) {
ret = -ENOMEM;
- goto error_free_buf_dir_name;
+ goto error;
}
ret = asprintf(&buffer_access, "/dev/iio:device%d", dev_num);
if (ret < 0) {
ret = -ENOMEM;
- goto error_free_data;
+ goto error;
}
/* Attempt to open non blocking the access dev */
@@ -498,7 +623,7 @@ int main(int argc, char **argv)
if (fp == -1) { /* TODO: If it isn't there make the node */
ret = -errno;
fprintf(stderr, "Failed to open %s\n", buffer_access);
- goto error_free_buffer_access;
+ goto error;
}
for (j = 0; j < num_loops; j++) {
@@ -511,7 +636,7 @@ int main(int argc, char **argv)
ret = poll(&pfd, 1, -1);
if (ret < 0) {
ret = -errno;
- goto error_close_buffer_access;
+ goto error;
} else if (ret == 0) {
continue;
}
@@ -536,45 +661,21 @@ int main(int argc, char **argv)
num_channels);
}
- /* Stop the buffer */
- ret = write_sysfs_int("enable", buf_dir_name, 0);
- if (ret < 0)
- goto error_close_buffer_access;
+error:
+ cleanup();
- if (!notrigger)
- /* Disconnect the trigger - just write a dummy name. */
- ret = write_sysfs_string("trigger/current_trigger",
- dev_dir_name, "NULL");
- if (ret < 0)
- fprintf(stderr, "Failed to write to %s\n",
- dev_dir_name);
-
-error_close_buffer_access:
- if (close(fp) == -1)
+ if (fp >= 0 && close(fp) == -1)
perror("Failed to close buffer");
-
-error_free_buffer_access:
free(buffer_access);
-error_free_data:
free(data);
-error_free_buf_dir_name:
free(buf_dir_name);
-error_free_channels:
for (i = num_channels - 1; i >= 0; i--) {
free(channels[i].name);
free(channels[i].generic_name);
}
free(channels);
-error_free_triggername:
- if (datardytrigger)
- free(trigger_name);
-error_disable_channels:
- if (autochannels == AUTOCHANNELS_ACTIVE) {
- ret = enable_disable_all_channels(dev_dir_name, 0);
- if (ret)
- fprintf(stderr, "Failed to disable all channels\n");
- }
-error_free_dev_dir_name:
+ free(trigger_name);
+ free(device_name);
free(dev_dir_name);
return ret;