From 5d48d6b0203de854587e8338376661e2315b2571 Mon Sep 17 00:00:00 2001 From: Daniel Baluta Date: Tue, 24 May 2016 18:03:55 +0300 Subject: tools: iio: Rename generic_buffer to iio_generic_buffer This makes it clear that generic_buffer is an IIO tool and also complies with filename conventions in tools/iio. Signed-off-by: Daniel Baluta Signed-off-by: Jonathan Cameron --- tools/iio/Makefile | 10 +- tools/iio/generic_buffer.c | 581 ----------------------------------------- tools/iio/iio_generic_buffer.c | 581 +++++++++++++++++++++++++++++++++++++++++ 3 files changed, 586 insertions(+), 586 deletions(-) delete mode 100644 tools/iio/generic_buffer.c create mode 100644 tools/iio/iio_generic_buffer.c diff --git a/tools/iio/Makefile b/tools/iio/Makefile index 5c32e908f576..5446d625e17d 100644 --- a/tools/iio/Makefile +++ b/tools/iio/Makefile @@ -5,13 +5,13 @@ BINDIR=usr/bin INSTALL_PROGRAM=install -m 755 -p DEL_FILE=rm -f -all: iio_event_monitor lsiio generic_buffer +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 @@ -19,13 +19,13 @@ 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) "generic_buffer" "$(INSTALL_ROOT)/$(BINDIR)/generic_buffer" + - $(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)/generic_buffer" + $(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/generic_buffer.c deleted file mode 100644 index 2429c78de940..000000000000 --- a/tools/iio/generic_buffer.c +++ /dev/null @@ -1,581 +0,0 @@ -/* Industrialio buffer test code. - * - * 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. - * - * This program is primarily intended as an example application. - * Reads the current buffer setup from sysfs and starts a short capture - * from the specified device, pretty printing the result after appropriate - * conversion. - * - * Command line parameters - * generic_buffer -n -t - * If trigger name is not specified the program assumes you want a dataready - * trigger associated with the device and goes looking for it. - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "iio_utils.h" - -/** - * enum autochan - state for the automatic channel enabling mechanism - */ -enum autochan { - AUTOCHANNELS_DISABLED, - AUTOCHANNELS_ENABLED, - AUTOCHANNELS_ACTIVE, -}; - -/** - * size_from_channelarray() - calculate the storage size of a scan - * @channels: the channel info array - * @num_channels: number of channels - * - * Has the side effect of filling the channels[i].location values used - * in processing the buffer output. - **/ -int size_from_channelarray(struct iio_channel_info *channels, int num_channels) -{ - int bytes = 0; - int i = 0; - - while (i < num_channels) { - if (bytes % channels[i].bytes == 0) - channels[i].location = bytes; - else - channels[i].location = bytes - bytes % channels[i].bytes - + channels[i].bytes; - - bytes = channels[i].location + channels[i].bytes; - i++; - } - - return bytes; -} - -void print1byte(uint8_t input, struct iio_channel_info *info) -{ - /* - * Shift before conversion to avoid sign extension - * of left aligned data - */ - input >>= info->shift; - input &= info->mask; - if (info->is_signed) { - int8_t val = (int8_t)(input << (8 - info->bits_used)) >> - (8 - info->bits_used); - printf("%05f ", ((float)val + info->offset) * info->scale); - } else { - printf("%05f ", ((float)input + info->offset) * info->scale); - } -} - -void print2byte(uint16_t input, struct iio_channel_info *info) -{ - /* First swap if incorrect endian */ - if (info->be) - input = be16toh(input); - else - input = le16toh(input); - - /* - * Shift before conversion to avoid sign extension - * of left aligned data - */ - input >>= info->shift; - input &= info->mask; - if (info->is_signed) { - int16_t val = (int16_t)(input << (16 - info->bits_used)) >> - (16 - info->bits_used); - printf("%05f ", ((float)val + info->offset) * info->scale); - } else { - printf("%05f ", ((float)input + info->offset) * info->scale); - } -} - -void print4byte(uint32_t input, struct iio_channel_info *info) -{ - /* First swap if incorrect endian */ - if (info->be) - input = be32toh(input); - else - input = le32toh(input); - - /* - * Shift before conversion to avoid sign extension - * of left aligned data - */ - input >>= info->shift; - input &= info->mask; - if (info->is_signed) { - int32_t val = (int32_t)(input << (32 - info->bits_used)) >> - (32 - info->bits_used); - printf("%05f ", ((float)val + info->offset) * info->scale); - } else { - printf("%05f ", ((float)input + info->offset) * info->scale); - } -} - -void print8byte(uint64_t input, struct iio_channel_info *info) -{ - /* First swap if incorrect endian */ - if (info->be) - input = be64toh(input); - else - input = le64toh(input); - - /* - * Shift before conversion to avoid sign extension - * of left aligned data - */ - input >>= info->shift; - input &= info->mask; - if (info->is_signed) { - int64_t val = (int64_t)(input << (64 - info->bits_used)) >> - (64 - info->bits_used); - /* special case for timestamp */ - if (info->scale == 1.0f && info->offset == 0.0f) - printf("%" PRId64 " ", val); - else - printf("%05f ", - ((float)val + info->offset) * info->scale); - } else { - printf("%05f ", ((float)input + info->offset) * info->scale); - } -} - -/** - * process_scan() - print out the values in SI units - * @data: pointer to the start of the scan - * @channels: information about the channels. - * Note: size_from_channelarray must have been called first - * to fill the location offsets. - * @num_channels: number of channels - **/ -void process_scan(char *data, - struct iio_channel_info *channels, - int num_channels) -{ - int k; - - for (k = 0; k < num_channels; k++) - switch (channels[k].bytes) { - /* only a few cases implemented so far */ - case 1: - print1byte(*(uint8_t *)(data + channels[k].location), - &channels[k]); - break; - case 2: - print2byte(*(uint16_t *)(data + channels[k].location), - &channels[k]); - break; - case 4: - print4byte(*(uint32_t *)(data + channels[k].location), - &channels[k]); - break; - case 8: - print8byte(*(uint64_t *)(data + channels[k].location), - &channels[k]); - break; - default: - break; - } - printf("\n"); -} - -static int enable_disable_all_channels(char *dev_dir_name, int enable) -{ - const struct dirent *ent; - char scanelemdir[256]; - DIR *dp; - int ret; - - snprintf(scanelemdir, sizeof(scanelemdir), - FORMAT_SCAN_ELEMENTS_DIR, dev_dir_name); - scanelemdir[sizeof(scanelemdir)-1] = '\0'; - - dp = opendir(scanelemdir); - if (!dp) { - fprintf(stderr, "Enabling/disabling channels: can't open %s\n", - scanelemdir); - return -EIO; - } - - ret = -ENOENT; - while (ent = readdir(dp), ent) { - if (iioutils_check_suffix(ent->d_name, "_en")) { - printf("%sabling: %s\n", - enable ? "En" : "Dis", - ent->d_name); - ret = write_sysfs_int(ent->d_name, scanelemdir, - enable); - if (ret < 0) - fprintf(stderr, "Failed to enable/disable %s\n", - ent->d_name); - } - } - - if (closedir(dp) == -1) { - perror("Enabling/disabling channels: " - "Failed to close directory"); - return -errno; - } - return 0; -} - -void print_usage(void) -{ - fprintf(stderr, "Usage: generic_buffer [options]...\n" - "Capture, convert and output data from IIO device buffer\n" - " -a Auto-activate all available channels\n" - " -c Do n conversions\n" - " -e Disable wait for event (new data)\n" - " -g Use trigger-less mode\n" - " -l Set buffer length to n samples\n" - " -n Set device name (mandatory)\n" - " -t Set trigger name\n" - " -w Set delay between reads in us (event-less mode)\n"); -} - -int main(int argc, char **argv) -{ - unsigned long num_loops = 2; - unsigned long timedelay = 1000000; - unsigned long buf_len = 128; - - int ret, c, i, j, toread; - int fp; - - int num_channels; - char *trigger_name = NULL, *device_name = NULL; - char *dev_dir_name, *buf_dir_name; - - int datardytrigger = 1; - char *data; - ssize_t read_size; - int dev_num, trig_num; - char *buffer_access; - 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) { - switch (c) { - case 'a': - autochannels = AUTOCHANNELS_ENABLED; - break; - case 'c': - errno = 0; - num_loops = strtoul(optarg, &dummy, 10); - if (errno) - return -errno; - - break; - case 'e': - noevents = 1; - break; - case 'g': - notrigger = 1; - break; - case 'l': - errno = 0; - buf_len = strtoul(optarg, &dummy, 10); - if (errno) - return -errno; - - break; - case 'n': - device_name = optarg; - break; - case 't': - trigger_name = optarg; - datardytrigger = 0; - break; - case 'w': - errno = 0; - timedelay = strtoul(optarg, &dummy, 10); - if (errno) - return -errno; - break; - case '?': - print_usage(); - return -1; - } - } - - 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; - } - - 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; - - if (!notrigger) { - if (!trigger_name) { - /* - * Build the trigger name. If it is device associated - * its name is _dev[n] where n matches - * the device number found above. - */ - ret = asprintf(&trigger_name, - "%s-dev%d", device_name, dev_num); - if (ret < 0) { - ret = -ENOMEM; - goto error_free_dev_dir_name; - } - } - - /* Look for this "-devN" trigger */ - trig_num = find_type_by_name(trigger_name, "trigger"); - if (trig_num < 0) { - /* OK try the simpler "-trigger" suffix instead */ - free(trigger_name); - ret = asprintf(&trigger_name, - "%s-trigger", device_name); - if (ret < 0) { - ret = -ENOMEM; - goto error_free_dev_dir_name; - } - } - - trig_num = find_type_by_name(trigger_name, "trigger"); - if (trig_num < 0) { - fprintf(stderr, "Failed to find the trigger %s\n", - trigger_name); - ret = trig_num; - goto error_free_triggername; - } - - printf("iio trigger number being used is %d\n", trig_num); - } else { - printf("trigger-less mode selected\n"); - } - - /* - * Parse the files in scan_elements to identify what channels are - * present - */ - ret = build_channel_array(dev_dir_name, &channels, &num_channels); - if (ret) { - fprintf(stderr, "Problem reading scan element information\n" - "diag %s\n", dev_dir_name); - goto error_free_triggername; - } - if (num_channels && autochannels == AUTOCHANNELS_ENABLED) { - fprintf(stderr, "Auto-channels selected but some channels " - "are already activated in sysfs\n"); - fprintf(stderr, "Proceeding without activating any channels\n"); - } - - if (!num_channels && autochannels == AUTOCHANNELS_ENABLED) { - fprintf(stderr, - "No channels are enabled, enabling all channels\n"); - - ret = enable_disable_all_channels(dev_dir_name, 1); - if (ret) { - fprintf(stderr, "Failed to enable all channels\n"); - goto error_free_triggername; - } - - /* This flags that we need to disable the channels again */ - autochannels = AUTOCHANNELS_ACTIVE; - - ret = build_channel_array(dev_dir_name, &channels, - &num_channels); - if (ret) { - fprintf(stderr, "Problem reading scan element " - "information\n" - "diag %s\n", dev_dir_name); - goto error_disable_channels; - } - if (!num_channels) { - fprintf(stderr, "Still no channels after " - "auto-enabling, giving up\n"); - goto error_disable_channels; - } - } - - if (!num_channels && autochannels == AUTOCHANNELS_DISABLED) { - fprintf(stderr, - "No channels are enabled, we have nothing to scan.\n"); - fprintf(stderr, "Enable channels manually in " - FORMAT_SCAN_ELEMENTS_DIR - "/*_en or pass -a to autoenable channels and " - "try again.\n", dev_dir_name); - ret = -ENOENT; - goto error_free_triggername; - } - - /* - * Construct the directory name for the associated buffer. - * As we know that the lis3l02dq has only one buffer this may - * be built rather than found. - */ - ret = asprintf(&buf_dir_name, - "%siio:device%d/buffer", iio_dir, dev_num); - if (ret < 0) { - ret = -ENOMEM; - goto error_free_channels; - } - - if (!notrigger) { - printf("%s %s\n", dev_dir_name, trigger_name); - /* - * Set the device trigger to be the data ready trigger found - * above - */ - ret = write_sysfs_string_and_verify("trigger/current_trigger", - dev_dir_name, - trigger_name); - if (ret < 0) { - fprintf(stderr, - "Failed to write current_trigger file\n"); - goto error_free_buf_dir_name; - } - } - - /* Setup ring buffer parameters */ - ret = write_sysfs_int("length", buf_dir_name, buf_len); - if (ret < 0) - goto error_free_buf_dir_name; - - /* 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; - } - - scan_size = size_from_channelarray(channels, num_channels); - data = malloc(scan_size * buf_len); - if (!data) { - ret = -ENOMEM; - goto error_free_buf_dir_name; - } - - ret = asprintf(&buffer_access, "/dev/iio:device%d", dev_num); - if (ret < 0) { - ret = -ENOMEM; - goto error_free_data; - } - - /* Attempt to open non blocking the access dev */ - fp = open(buffer_access, O_RDONLY | O_NONBLOCK); - 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; - } - - for (j = 0; j < num_loops; j++) { - if (!noevents) { - struct pollfd pfd = { - .fd = fp, - .events = POLLIN, - }; - - ret = poll(&pfd, 1, -1); - if (ret < 0) { - ret = -errno; - goto error_close_buffer_access; - } else if (ret == 0) { - continue; - } - - toread = buf_len; - } else { - usleep(timedelay); - toread = 64; - } - - read_size = read(fp, data, toread * scan_size); - if (read_size < 0) { - if (errno == EAGAIN) { - fprintf(stderr, "nothing available\n"); - continue; - } else { - break; - } - } - for (i = 0; i < read_size / scan_size; i++) - process_scan(data + scan_size * i, channels, - num_channels); - } - - /* Stop the buffer */ - ret = write_sysfs_int("enable", buf_dir_name, 0); - if (ret < 0) - goto error_close_buffer_access; - - 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) - 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(dev_dir_name); - - return ret; -} diff --git a/tools/iio/iio_generic_buffer.c b/tools/iio/iio_generic_buffer.c new file mode 100644 index 000000000000..2429c78de940 --- /dev/null +++ b/tools/iio/iio_generic_buffer.c @@ -0,0 +1,581 @@ +/* Industrialio buffer test code. + * + * 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. + * + * This program is primarily intended as an example application. + * Reads the current buffer setup from sysfs and starts a short capture + * from the specified device, pretty printing the result after appropriate + * conversion. + * + * Command line parameters + * generic_buffer -n -t + * If trigger name is not specified the program assumes you want a dataready + * trigger associated with the device and goes looking for it. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "iio_utils.h" + +/** + * enum autochan - state for the automatic channel enabling mechanism + */ +enum autochan { + AUTOCHANNELS_DISABLED, + AUTOCHANNELS_ENABLED, + AUTOCHANNELS_ACTIVE, +}; + +/** + * size_from_channelarray() - calculate the storage size of a scan + * @channels: the channel info array + * @num_channels: number of channels + * + * Has the side effect of filling the channels[i].location values used + * in processing the buffer output. + **/ +int size_from_channelarray(struct iio_channel_info *channels, int num_channels) +{ + int bytes = 0; + int i = 0; + + while (i < num_channels) { + if (bytes % channels[i].bytes == 0) + channels[i].location = bytes; + else + channels[i].location = bytes - bytes % channels[i].bytes + + channels[i].bytes; + + bytes = channels[i].location + channels[i].bytes; + i++; + } + + return bytes; +} + +void print1byte(uint8_t input, struct iio_channel_info *info) +{ + /* + * Shift before conversion to avoid sign extension + * of left aligned data + */ + input >>= info->shift; + input &= info->mask; + if (info->is_signed) { + int8_t val = (int8_t)(input << (8 - info->bits_used)) >> + (8 - info->bits_used); + printf("%05f ", ((float)val + info->offset) * info->scale); + } else { + printf("%05f ", ((float)input + info->offset) * info->scale); + } +} + +void print2byte(uint16_t input, struct iio_channel_info *info) +{ + /* First swap if incorrect endian */ + if (info->be) + input = be16toh(input); + else + input = le16toh(input); + + /* + * Shift before conversion to avoid sign extension + * of left aligned data + */ + input >>= info->shift; + input &= info->mask; + if (info->is_signed) { + int16_t val = (int16_t)(input << (16 - info->bits_used)) >> + (16 - info->bits_used); + printf("%05f ", ((float)val + info->offset) * info->scale); + } else { + printf("%05f ", ((float)input + info->offset) * info->scale); + } +} + +void print4byte(uint32_t input, struct iio_channel_info *info) +{ + /* First swap if incorrect endian */ + if (info->be) + input = be32toh(input); + else + input = le32toh(input); + + /* + * Shift before conversion to avoid sign extension + * of left aligned data + */ + input >>= info->shift; + input &= info->mask; + if (info->is_signed) { + int32_t val = (int32_t)(input << (32 - info->bits_used)) >> + (32 - info->bits_used); + printf("%05f ", ((float)val + info->offset) * info->scale); + } else { + printf("%05f ", ((float)input + info->offset) * info->scale); + } +} + +void print8byte(uint64_t input, struct iio_channel_info *info) +{ + /* First swap if incorrect endian */ + if (info->be) + input = be64toh(input); + else + input = le64toh(input); + + /* + * Shift before conversion to avoid sign extension + * of left aligned data + */ + input >>= info->shift; + input &= info->mask; + if (info->is_signed) { + int64_t val = (int64_t)(input << (64 - info->bits_used)) >> + (64 - info->bits_used); + /* special case for timestamp */ + if (info->scale == 1.0f && info->offset == 0.0f) + printf("%" PRId64 " ", val); + else + printf("%05f ", + ((float)val + info->offset) * info->scale); + } else { + printf("%05f ", ((float)input + info->offset) * info->scale); + } +} + +/** + * process_scan() - print out the values in SI units + * @data: pointer to the start of the scan + * @channels: information about the channels. + * Note: size_from_channelarray must have been called first + * to fill the location offsets. + * @num_channels: number of channels + **/ +void process_scan(char *data, + struct iio_channel_info *channels, + int num_channels) +{ + int k; + + for (k = 0; k < num_channels; k++) + switch (channels[k].bytes) { + /* only a few cases implemented so far */ + case 1: + print1byte(*(uint8_t *)(data + channels[k].location), + &channels[k]); + break; + case 2: + print2byte(*(uint16_t *)(data + channels[k].location), + &channels[k]); + break; + case 4: + print4byte(*(uint32_t *)(data + channels[k].location), + &channels[k]); + break; + case 8: + print8byte(*(uint64_t *)(data + channels[k].location), + &channels[k]); + break; + default: + break; + } + printf("\n"); +} + +static int enable_disable_all_channels(char *dev_dir_name, int enable) +{ + const struct dirent *ent; + char scanelemdir[256]; + DIR *dp; + int ret; + + snprintf(scanelemdir, sizeof(scanelemdir), + FORMAT_SCAN_ELEMENTS_DIR, dev_dir_name); + scanelemdir[sizeof(scanelemdir)-1] = '\0'; + + dp = opendir(scanelemdir); + if (!dp) { + fprintf(stderr, "Enabling/disabling channels: can't open %s\n", + scanelemdir); + return -EIO; + } + + ret = -ENOENT; + while (ent = readdir(dp), ent) { + if (iioutils_check_suffix(ent->d_name, "_en")) { + printf("%sabling: %s\n", + enable ? "En" : "Dis", + ent->d_name); + ret = write_sysfs_int(ent->d_name, scanelemdir, + enable); + if (ret < 0) + fprintf(stderr, "Failed to enable/disable %s\n", + ent->d_name); + } + } + + if (closedir(dp) == -1) { + perror("Enabling/disabling channels: " + "Failed to close directory"); + return -errno; + } + return 0; +} + +void print_usage(void) +{ + fprintf(stderr, "Usage: generic_buffer [options]...\n" + "Capture, convert and output data from IIO device buffer\n" + " -a Auto-activate all available channels\n" + " -c Do n conversions\n" + " -e Disable wait for event (new data)\n" + " -g Use trigger-less mode\n" + " -l Set buffer length to n samples\n" + " -n Set device name (mandatory)\n" + " -t Set trigger name\n" + " -w Set delay between reads in us (event-less mode)\n"); +} + +int main(int argc, char **argv) +{ + unsigned long num_loops = 2; + unsigned long timedelay = 1000000; + unsigned long buf_len = 128; + + int ret, c, i, j, toread; + int fp; + + int num_channels; + char *trigger_name = NULL, *device_name = NULL; + char *dev_dir_name, *buf_dir_name; + + int datardytrigger = 1; + char *data; + ssize_t read_size; + int dev_num, trig_num; + char *buffer_access; + 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) { + switch (c) { + case 'a': + autochannels = AUTOCHANNELS_ENABLED; + break; + case 'c': + errno = 0; + num_loops = strtoul(optarg, &dummy, 10); + if (errno) + return -errno; + + break; + case 'e': + noevents = 1; + break; + case 'g': + notrigger = 1; + break; + case 'l': + errno = 0; + buf_len = strtoul(optarg, &dummy, 10); + if (errno) + return -errno; + + break; + case 'n': + device_name = optarg; + break; + case 't': + trigger_name = optarg; + datardytrigger = 0; + break; + case 'w': + errno = 0; + timedelay = strtoul(optarg, &dummy, 10); + if (errno) + return -errno; + break; + case '?': + print_usage(); + return -1; + } + } + + 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; + } + + 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; + + if (!notrigger) { + if (!trigger_name) { + /* + * Build the trigger name. If it is device associated + * its name is _dev[n] where n matches + * the device number found above. + */ + ret = asprintf(&trigger_name, + "%s-dev%d", device_name, dev_num); + if (ret < 0) { + ret = -ENOMEM; + goto error_free_dev_dir_name; + } + } + + /* Look for this "-devN" trigger */ + trig_num = find_type_by_name(trigger_name, "trigger"); + if (trig_num < 0) { + /* OK try the simpler "-trigger" suffix instead */ + free(trigger_name); + ret = asprintf(&trigger_name, + "%s-trigger", device_name); + if (ret < 0) { + ret = -ENOMEM; + goto error_free_dev_dir_name; + } + } + + trig_num = find_type_by_name(trigger_name, "trigger"); + if (trig_num < 0) { + fprintf(stderr, "Failed to find the trigger %s\n", + trigger_name); + ret = trig_num; + goto error_free_triggername; + } + + printf("iio trigger number being used is %d\n", trig_num); + } else { + printf("trigger-less mode selected\n"); + } + + /* + * Parse the files in scan_elements to identify what channels are + * present + */ + ret = build_channel_array(dev_dir_name, &channels, &num_channels); + if (ret) { + fprintf(stderr, "Problem reading scan element information\n" + "diag %s\n", dev_dir_name); + goto error_free_triggername; + } + if (num_channels && autochannels == AUTOCHANNELS_ENABLED) { + fprintf(stderr, "Auto-channels selected but some channels " + "are already activated in sysfs\n"); + fprintf(stderr, "Proceeding without activating any channels\n"); + } + + if (!num_channels && autochannels == AUTOCHANNELS_ENABLED) { + fprintf(stderr, + "No channels are enabled, enabling all channels\n"); + + ret = enable_disable_all_channels(dev_dir_name, 1); + if (ret) { + fprintf(stderr, "Failed to enable all channels\n"); + goto error_free_triggername; + } + + /* This flags that we need to disable the channels again */ + autochannels = AUTOCHANNELS_ACTIVE; + + ret = build_channel_array(dev_dir_name, &channels, + &num_channels); + if (ret) { + fprintf(stderr, "Problem reading scan element " + "information\n" + "diag %s\n", dev_dir_name); + goto error_disable_channels; + } + if (!num_channels) { + fprintf(stderr, "Still no channels after " + "auto-enabling, giving up\n"); + goto error_disable_channels; + } + } + + if (!num_channels && autochannels == AUTOCHANNELS_DISABLED) { + fprintf(stderr, + "No channels are enabled, we have nothing to scan.\n"); + fprintf(stderr, "Enable channels manually in " + FORMAT_SCAN_ELEMENTS_DIR + "/*_en or pass -a to autoenable channels and " + "try again.\n", dev_dir_name); + ret = -ENOENT; + goto error_free_triggername; + } + + /* + * Construct the directory name for the associated buffer. + * As we know that the lis3l02dq has only one buffer this may + * be built rather than found. + */ + ret = asprintf(&buf_dir_name, + "%siio:device%d/buffer", iio_dir, dev_num); + if (ret < 0) { + ret = -ENOMEM; + goto error_free_channels; + } + + if (!notrigger) { + printf("%s %s\n", dev_dir_name, trigger_name); + /* + * Set the device trigger to be the data ready trigger found + * above + */ + ret = write_sysfs_string_and_verify("trigger/current_trigger", + dev_dir_name, + trigger_name); + if (ret < 0) { + fprintf(stderr, + "Failed to write current_trigger file\n"); + goto error_free_buf_dir_name; + } + } + + /* Setup ring buffer parameters */ + ret = write_sysfs_int("length", buf_dir_name, buf_len); + if (ret < 0) + goto error_free_buf_dir_name; + + /* 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; + } + + scan_size = size_from_channelarray(channels, num_channels); + data = malloc(scan_size * buf_len); + if (!data) { + ret = -ENOMEM; + goto error_free_buf_dir_name; + } + + ret = asprintf(&buffer_access, "/dev/iio:device%d", dev_num); + if (ret < 0) { + ret = -ENOMEM; + goto error_free_data; + } + + /* Attempt to open non blocking the access dev */ + fp = open(buffer_access, O_RDONLY | O_NONBLOCK); + 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; + } + + for (j = 0; j < num_loops; j++) { + if (!noevents) { + struct pollfd pfd = { + .fd = fp, + .events = POLLIN, + }; + + ret = poll(&pfd, 1, -1); + if (ret < 0) { + ret = -errno; + goto error_close_buffer_access; + } else if (ret == 0) { + continue; + } + + toread = buf_len; + } else { + usleep(timedelay); + toread = 64; + } + + read_size = read(fp, data, toread * scan_size); + if (read_size < 0) { + if (errno == EAGAIN) { + fprintf(stderr, "nothing available\n"); + continue; + } else { + break; + } + } + for (i = 0; i < read_size / scan_size; i++) + process_scan(data + scan_size * i, channels, + num_channels); + } + + /* Stop the buffer */ + ret = write_sysfs_int("enable", buf_dir_name, 0); + if (ret < 0) + goto error_close_buffer_access; + + 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) + 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(dev_dir_name); + + return ret; +} -- cgit v1.2.3