diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2016-07-24 16:55:23 -0700 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2016-07-24 16:55:23 -0700 |
commit | 25a0dc4be86fc0d8c7e81bb5f8be8427022bf15f (patch) | |
tree | c8d66d65eb0910a2dc8e00a96c1a4da1fc9e33d4 /tools | |
parent | 9d0be76f52faff97fd9581eba70870f27061ae93 (diff) | |
parent | 6c71ee3b6157fdbde5c839405b593876d3687eb9 (diff) | |
download | linux-25a0dc4be86fc0d8c7e81bb5f8be8427022bf15f.tar.bz2 |
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/Makefile | 21 | ||||
-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; |