libiio  0.24
Library for interfacing with IIO devices
iio_attr.c

Part of the libiio-utilites, iio_attr is a utility for displaying information about local or remote IIO devices. By providing an optional value, iio_attr will attempt to write the new value to the attribute.

// SPDX-License-Identifier: GPL-2.0-or-later
/*
* iio_attr - part of the Industrial I/O (IIO) utilities
*
* Copyright (C) 2014 - 2020 Analog Devices, Inc.
* Author: Paul Cercueil <paul.cercueil@analog.com>
* Robin Getz <robin.getz@analog.com>
* */
#include <errno.h>
#include <getopt.h>
#include <iio.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <sys/types.h>
#include "gen_code.h"
#include "iio_common.h"
#define MY_NAME "iio_attr"
#ifdef _WIN32
#define snprintf sprintf_s
#endif
enum verbosity {
ATTR_QUIET,
ATTR_NORMAL,
ATTR_VERBOSE,
};
static bool str_match(const char * haystack, char * needle, bool ignore)
{
bool ret = false;
int i;
char *ncpy, *hcpy, *idx, first, last;
if (!haystack || !needle)
return false;
if (!strlen(haystack) || !strlen(needle))
return false;
/* '.' means match any */
if (!strcmp(".", needle) || !strcmp("*", needle))
return true;
ncpy = cmn_strndup(needle, NAME_MAX);
hcpy = cmn_strndup(haystack, NAME_MAX);
if (!ncpy || !hcpy)
goto eek;
if (ignore) {
for (i = 0; hcpy[i]; i++)
hcpy[i] = (char) (tolower(hcpy[i]) & 0xFF);
for (i = 0; ncpy[i]; i++)
ncpy[i] = (char) (tolower(ncpy[i]) & 0xFF);
}
first = ncpy[0];
last = ncpy[strlen(ncpy) - 1];
if (first != '*' && last == '*') {
/* 'key*' */
ret = !strncmp(hcpy, ncpy, strlen(ncpy) - 1);
} else if ((first == '*') && (last == '*')) {
/* '*key*' */
ncpy[strlen(ncpy) - 1] = 0;
ret = strstr(hcpy, &ncpy[1]);
} else if ((first == '*') && (last != '*')) {
/* '*key' */
idx = strstr(hcpy, &ncpy[1]);
if ((idx + strlen(&ncpy[1])) == (hcpy + strlen(hcpy)))
ret = true;
} else {
/* 'key' */
ret = !strcmp(hcpy, ncpy);
}
eek:
free(ncpy);
free(hcpy);
return ret;
}
static inline const char *get_label_or_name_or_id(const struct iio_device *dev)
{
const char *label, *name;
label = iio_device_get_label(dev);
if (label)
return label;
name = iio_device_get_name(dev);
if (name)
return name;
return iio_device_get_id(dev);
}
static int dump_device_attributes(const struct iio_device *dev,
const char *attr, const char *wbuf, enum verbosity quiet)
{
ssize_t ret = 0;
char *buf = xmalloc(BUF_SIZE, MY_NAME);
if (!wbuf || quiet == ATTR_VERBOSE) {
if (quiet == ATTR_VERBOSE) {
printf("%s ", iio_device_is_trigger(dev) ? "trig" : "dev");
printf("'%s'", get_label_or_name_or_id(dev));
printf(", attr '%s', value :", attr);
}
gen_function("device", "dev", attr, NULL);
ret = iio_device_attr_read(dev, attr, buf, BUF_SIZE);
if (ret > 0) {
if (quiet == ATTR_NORMAL)
printf("%s\n", buf);
else if (quiet == ATTR_VERBOSE)
printf("'%s'\n", buf);
} else {
iio_strerror(-(int)ret, buf, BUF_SIZE);
printf("ERROR: %s\n", buf);
}
}
if (wbuf) {
gen_function("device", "dev", attr, wbuf);
ret = iio_device_attr_write(dev, attr, wbuf);
if (ret > 0) {
if (quiet == ATTR_VERBOSE)
printf("wrote %li bytes to %s\n", (long)ret, attr);
dump_device_attributes(dev, attr, NULL, quiet);
} else {
iio_strerror(-(int)ret, buf, BUF_SIZE);
printf("ERROR: %s while writing '%s' with '%s'\n",
buf, attr, wbuf);
}
}
free(buf);
return (int)ret;
}
static int dump_buffer_attributes(const struct iio_device *dev,
const char *attr, const char *wbuf, enum verbosity quiet)
{
ssize_t ret = 0;
char *buf = xmalloc(BUF_SIZE, MY_NAME);
if (!wbuf || quiet == ATTR_VERBOSE ) {
gen_function("device_buffer", "dev", attr, NULL);
ret = iio_device_buffer_attr_read(dev, attr, buf, BUF_SIZE);
if (quiet == ATTR_VERBOSE) {
printf("%s ", iio_device_is_trigger(dev) ? "trig" : "dev");
printf("'%s'", get_label_or_name_or_id(dev));
printf(", buffer attr '%s', value :", attr);
}
if (ret > 0) {
if (quiet == ATTR_NORMAL)
printf("%s\n", buf);
else if (quiet == ATTR_VERBOSE)
printf("'%s'\n", buf);
} else {
iio_strerror(-(int)ret, buf, BUF_SIZE);
printf("ERROR: %s\n", buf);
}
}
if (wbuf) {
gen_function("device_buffer", "dev", attr, wbuf);
ret = iio_device_buffer_attr_write(dev, attr, wbuf);
if (ret > 0) {
if (quiet == ATTR_VERBOSE)
printf("wrote %li bytes to %s\n", (long)ret, attr);
dump_buffer_attributes(dev, attr, NULL, quiet);
} else {
iio_strerror(-(int)ret, buf, BUF_SIZE);
printf("ERROR: %s while writing '%s' with '%s'\n",
buf, attr, wbuf);
}
}
free(buf);
return (int)ret;
}
static int dump_debug_attributes(const struct iio_device *dev,
const char *attr, const char *wbuf, enum verbosity quiet)
{
ssize_t ret = 0;
char *buf = xmalloc(BUF_SIZE, MY_NAME);
if (!wbuf || quiet == ATTR_VERBOSE) {
gen_function("device_debug", "dev", attr, NULL);
ret = iio_device_debug_attr_read(dev, attr, buf, BUF_SIZE);
if (quiet == ATTR_VERBOSE) {
printf("%s ", iio_device_is_trigger(dev) ? "trig" : "dev");
printf("'%s'", get_label_or_name_or_id(dev));
printf(", debug attr '%s', value :", attr);
}
if (ret > 0) {
if (quiet == ATTR_NORMAL)
printf("%s\n", buf);
else if (quiet == ATTR_VERBOSE)
printf("'%s'\n", buf);
} else {
iio_strerror(-(int)ret, buf, BUF_SIZE);
printf("ERROR: %s\n", buf);
}
}
if (wbuf) {
gen_function("device_debug", "dev", attr, wbuf);
ret = iio_device_debug_attr_write(dev, attr, wbuf);
if (ret > 0) {
if (quiet == ATTR_VERBOSE)
printf("wrote %li bytes to %s\n", (long)ret, attr);
dump_debug_attributes(dev, attr, NULL, quiet);
} else {
iio_strerror(-(int)ret, buf, BUF_SIZE);
printf("ERROR: %s while writing '%s' with '%s'\n",
buf, attr, wbuf);
}
}
free(buf);
return (int)ret;
}
static int dump_channel_attributes(const struct iio_device *dev,
struct iio_channel *ch, const char *attr, const char *wbuf, enum verbosity quiet)
{
ssize_t ret = 0;
char *buf = xmalloc(BUF_SIZE, MY_NAME);
const char *type_name;
if (!wbuf || quiet == ATTR_VERBOSE) {
type_name = "output";
else
type_name = "input";
gen_function("channel", "ch", attr, NULL);
ret = iio_channel_attr_read(ch, attr, buf, BUF_SIZE);
if (quiet == ATTR_VERBOSE) {
printf("%s ", iio_device_is_trigger(dev) ? "trig" : "dev");
printf("'%s'", get_label_or_name_or_id(dev));
printf(", channel '%s' (%s), ",
type_name);
}
if (iio_channel_get_name(ch) && quiet == ATTR_VERBOSE)
printf("id '%s', ", iio_channel_get_name(ch));
if (quiet == ATTR_VERBOSE)
printf("attr '%s', ", attr);
if (ret > 0) {
if (quiet == ATTR_NORMAL)
printf("%s\n", buf);
else if (quiet == ATTR_VERBOSE)
printf("value '%s'\n", buf);
} else {
iio_strerror(-(int)ret, buf, BUF_SIZE);
printf("ERROR: %s\n", buf);
}
}
if (wbuf) {
gen_function("channel", "ch", attr, wbuf);
ret = iio_channel_attr_write(ch, attr, wbuf);
if (ret > 0) {
if (quiet == ATTR_VERBOSE)
printf("wrote %li bytes to %s\n", (long)ret, attr);
dump_channel_attributes(dev, ch, attr, NULL, quiet);
} else {
iio_strerror(-(int)ret, buf, BUF_SIZE);
printf("error %s while writing '%s' with '%s'\n",
buf, attr, wbuf);
}
}
free(buf);
return (int)ret;
}
static const struct option options[] = {
{"ignore-case", no_argument, 0, 'I'},
{"quiet", no_argument, 0, 'q'},
{"verbose", no_argument, 0, 'v'},
{"generate-code", required_argument, 0, 'g'},
/* Channel qualifiers */
{"input-channel", no_argument, 0, 'i'},
{"output-channel", no_argument, 0, 'o'},
{"scan-channel", no_argument, 0, 's'},
/* Attribute type */
{"device-attr", no_argument, 0, 'd'},
{"channel-attr", no_argument, 0, 'c'},
{"context-attr", no_argument, 0, 'C'},
{"buffer-attr", no_argument, 0, 'B'},
{"debug-attr", no_argument, 0, 'D'},
{0, 0, 0, 0},
};
static const char *options_descriptions[] = {
("-d [device] [attr] [value]\n"
"\t\t\t\t-c [device] [channel] [attr] [value]\n"
"\t\t\t\t-B [device] [attr] [value]\n"
"\t\t\t\t-D [device] [attr] [value]\n"
"\t\t\t\t-C [attr]"),
/* help */
"Ignore case distinctions.",
"Return result only.",
"Verbose, say what is going on",
"Generate code.",
/* Channel qualifiers */
"Filter Input Channels only.",
"Filter Output Channels only.",
"Filter Scan Channels only.",
/* attribute type */
"Read/Write device attributes",
"Read/Write channel attributes.",
"Read IIO context attributes.",
"Read/Write buffer attributes.",
"Read/Write debug attributes.",
};
#define MY_OPTS "CdcBDiosIqvg:"
int main(int argc, char **argv)
{
char **argw;
struct iio_context *ctx;
int c, argd = argc;
int device_index = 0, channel_index = 0, attr_index = 0;
const char *gen_file = NULL;
bool search_device = false, ignore_case = false,
search_channel = false, search_buffer = false, search_debug = false,
search_context = false, input_only = false, output_only = false,
scan_only = false, gen_code = false;
enum verbosity quiet = ATTR_NORMAL;
bool found_err = false, read_err = false, write_err = false,
dev_found = false, attr_found = false, ctx_found = false,
debug_found = false, channel_found = false ;
bool context_scan = false;
unsigned int i;
char *wbuf = NULL;
struct option *opts;
argw = dup_argv(MY_NAME, argc, argv);
/*
* getopt_long() thinks negative numbers are options, -1 is option '1'
* The only time we should see a negative number is the last argument during a write,
* so if there is one, we skip that argument during getopt processing
* look for "-" followed by a number.
*/
if (strnlen(argv[argc - 1], 2) >= 2 && argv[argc - 1][0] == '-' &&
(argv[argc - 1][1] >= '0' && argv[argc - 1][1] <= '9')) {
argd--;
}
ctx = handle_common_opts(MY_NAME, argd, argw, MY_OPTS, options, options_descriptions);
opts = add_common_options(options);
if (!opts) {
fprintf(stderr, "Failed to add common options\n");
return EXIT_FAILURE;
}
while ((c = getopt_long(argd, argw, "+" COMMON_OPTIONS MY_OPTS, /* Flawfinder: ignore */
opts, NULL)) != -1) {
switch (c) {
/* All these are handled in the common */
case 'h':
case 'V':
case 'n':
case 'x':
case 'u':
case 'T':
break;
case 'S':
context_scan = true;
/* FALLTHRU */
case 'a':
if (!optarg && argc > optind && argv[optind] != NULL
&& argv[optind][0] != '-')
optind++;
break;
/* Attribute type
* 'd'evice, 'c'hannel, 'C'ontext, 'B'uffer or 'D'ebug
*/
case 'd':
search_device = true;
break;
case 'c':
search_channel = true;
break;
case 'B':
search_buffer = true;
break;
case 'D':
search_debug = true;
break;
case 'C':
search_context = true;
break;
/* Channel qualifiers */
case 'i':
input_only = true;
break;
case 'o':
output_only = true;
break;
case 's':
scan_only = true;
break;
/* options */
case 'I':
ignore_case = true;
break;
case 'q':
quiet = ATTR_QUIET;
break;
case 'v':
quiet = ATTR_VERBOSE;
break;
case 'g':
if (!optarg || optarg[0] == '-') {
fprintf(stderr, "Code generation requires an option\n");
return EXIT_FAILURE;
}
gen_code = true;
gen_file = optarg;
break;
case '?':
printf("Unknown argument '%c'\n", c);
return EXIT_FAILURE;
}
}
free(opts);
if (context_scan)
return EXIT_SUCCESS;
if (!ctx)
return EXIT_FAILURE;
if (gen_code) {
if (!gen_test_path(gen_file)) {
fprintf(stderr, "Can't write to %s to generate file\n", gen_file);
return EXIT_FAILURE;
}
}
if ((search_device + search_channel + search_context + search_debug + search_buffer) >= 2 ) {
fprintf(stderr, "The options -d, -c, -C, -B, and -D are exclusive"
" (can use only one).\n");
return EXIT_FAILURE;
}
if (!(search_device + search_channel + search_context + search_debug + search_buffer)) {
if (argc == 1) {
usage(MY_NAME, options, options_descriptions);
return EXIT_SUCCESS;
}
fprintf(stderr, "must specify one of -d, -c, -C, -B or -D.\n");
return EXIT_FAILURE;
}
if (search_context) {
/* -C [IIO_attribute] */
if (argc >= optind + 1)
attr_index = optind;
if (argc >= optind + 2) {
fprintf(stderr, "Too many options for searching for context attributes\n");
return EXIT_FAILURE;
}
if (gen_code && !attr_index) {
printf("When generating code for Context Attributes, must include specific attribute\n"
"-C [IIO_context_attribute]\n");
return EXIT_FAILURE;
}
} else if (search_device) {
/* -d [device] [attr] [value] */
if (argc >= optind + 1)
device_index = optind;
if (argc >= optind + 2)
attr_index = optind + 1;
if (argc >= optind + 3)
wbuf = argw[optind + 2];
if (argc >= optind + 4) {
fprintf(stderr, "Too many options for searching for device attributes\n");
return EXIT_FAILURE;
}
if (gen_code && !attr_index) {
printf("When generating code for device Attributes, must include specific attribute\n"
"-d [IIO_device] [IIO_device_attr] [value]\n");
return EXIT_FAILURE;
}
} else if (search_channel) {
/* -c [device] [channel] [attr] [value] */
if (argc >= optind + 1)
device_index = optind;
if (argc >= optind + 2)
channel_index = optind + 1;
if (argc >= optind + 3)
attr_index = optind + 2;
if (argc >= optind + 4)
wbuf = argw[optind + 3];
if (argc >= optind + 5) {
fprintf(stderr, "Too many options for searching for channel attributes\n");
return EXIT_FAILURE;
}
if (gen_code && !attr_index) {
printf("When generating code for Channel Attributes, must include specific attribute\n"
"-c [IIO_device] [IIO_device_channel] [IIO_channel_attr] [value]\n");
return EXIT_FAILURE;
}
} else if (search_buffer) {
/* -B [device] [attribute] [value] */
if (argc >= optind + 1)
device_index = optind;
if (argc >= optind + 2)
attr_index = optind + 1;
if (argc >= optind + 3)
wbuf = argw[optind + 2];
if (argc >= optind + 4) {
fprintf(stderr, "Too many options for searching for buffer attributes\n");
return EXIT_FAILURE;
}
if (gen_code && !attr_index) {
printf("When generating code for Buffer Attributes, must include specific attribute\n"
"-B [IIO_device] [IIO_buffer_attribute] [value]\n");
return EXIT_FAILURE;
}
} else if (search_debug) {
/* -D [device] [attribute] [value] */
if (argc >= optind + 1)
device_index = optind;
if (argc >= optind + 2)
attr_index = optind + 1;
if (argc >= optind + 3)
wbuf = argw[optind + 2];
if (argc >= optind + 4) {
fprintf(stderr, "Too many options for searching for device attributes\n");
return EXIT_FAILURE;
}
if (gen_code && !attr_index) {
printf("When generating code for Debug Attributes, must include specific attribute\n"
"-D [IIO_device] [IIO_debug_attribute] [value]\n");
return EXIT_FAILURE;
}
} else {
fprintf(stderr, "error in application\n");
return EXIT_FAILURE;
}
if (device_index && !argw[device_index])
return EXIT_FAILURE;
if (channel_index && !argw[channel_index])
return EXIT_FAILURE;
if (attr_index && !argw[attr_index])
return EXIT_FAILURE;
/* check for wildcards */
if (((device_index && (!strcmp(".", argw[device_index]) ||
strchr(argw[device_index], '*'))) ||
(channel_index && (!strcmp(".", argw[channel_index]) ||
strchr(argw[channel_index], '*'))) ||
(attr_index && (!strcmp(".", argw[attr_index]) ||
strchr(argw[attr_index], '*'))))) {
if (gen_code || wbuf) {
printf("can't %s with wildcard match\n",
gen_code ? "generate code" : "write value");
return EXIT_FAILURE;
}
/* Force verbose mode */
quiet = ATTR_VERBOSE;
}
if (gen_code) {
gen_start(gen_file);
gen_context(iio_context_get_attr_value(ctx, "uri"));
}
if (search_context) {
unsigned int nb_ctx_attrs = iio_context_get_attrs_count(ctx);
if (!attr_index && nb_ctx_attrs > 0)
printf("IIO context with %u attributes:\n", nb_ctx_attrs);
if (!attr_index && !nb_ctx_attrs) {
printf("%s: Found context, but it has %u context attributes\n",
MY_NAME, nb_ctx_attrs);
found_err = true;
}
ctx_found = true;
for (i = 0; i < nb_ctx_attrs; i++) {
const char *key, *value;
ssize_t ret;
ret = iio_context_get_attr(ctx, i, &key, &value);
if (!ret) {
if (!attr_index || str_match(key, argw[attr_index], ignore_case)) {
found_err = false;
attr_found = true;
printf("%s: %s\n", key, value);
gen_context_attr(key);
}
} else {
char *buf = xmalloc(BUF_SIZE, MY_NAME);
iio_strerror(errno, buf, BUF_SIZE);
fprintf(stderr, "Unable to get context attributes: %s\n",
buf);
free(buf);
}
}
}
if (search_device || search_channel || search_buffer || search_debug) {
unsigned int nb_devices = iio_context_get_devices_count(ctx);
if (!device_index)
printf("IIO context has %u devices:\n", nb_devices);
for (i = 0; i < nb_devices; i++) {
const struct iio_device *dev = iio_context_get_device(ctx, i);
const char *dev_id = iio_device_get_id(dev);
const char *label = iio_device_get_label(dev);
const char *name = iio_device_get_name(dev);
const char *label_or_name = label ? label : name;
const char *label_or_name_or_id = label_or_name ? label_or_name : dev_id;
const char *ch_name;
unsigned int nb_attrs, nb_channels, j;
if (device_index && !str_match(dev_id, argw[device_index], ignore_case)
&& !str_match(label, argw[device_index], ignore_case)
&& !str_match(name, argw[device_index], ignore_case)) {
continue;
}
dev_found = true;
if ((search_device && !device_index) || (search_channel && !device_index) ||
(search_buffer && !device_index) || (search_debug && !device_index)) {
printf("\t%s", dev_id);
if (label_or_name)
printf(", %s", label_or_name);
printf(": ");
}
nb_channels = iio_device_get_channels_count(dev);
if (search_channel && !device_index) {
if (scan_only || input_only || output_only) {
unsigned int scan = 0, in = 0, out = 0;
for (j = 0; j < nb_channels; j++) {
struct iio_channel *ch;
ch = iio_device_get_channel(dev, j);
out++;
else
in++;
scan++;
}
printf("found ");
if (scan_only)
printf("%u scan", scan);
if (output_only) {
if (scan_only)
printf(", ");
printf("%u output", out);
}
if (input_only) {
if (scan_only || output_only)
printf(", ");
printf("%u input", in);
}
printf(" channels\n");
} else {
printf("found %u channels\n", nb_channels);
}
}
if (search_channel && device_index && !channel_index && !nb_channels) {
printf("%s: Found %s device, but it has %u channels\n",
MY_NAME, argw[device_index], nb_channels);
found_err = true;
}
for (j = 0; j < nb_channels; j++) {
struct iio_channel *ch;
const char *type_name;
unsigned int k;
if (!search_channel || !device_index)
continue;
ch = iio_device_get_channel(dev, j);
if (input_only && iio_channel_is_output(ch))
continue;
if (output_only && !iio_channel_is_output(ch))
continue;
if (scan_only && !iio_channel_is_scan_element(ch))
continue;
type_name = "output";
else
type_name = "input";
ch_name = iio_channel_get_name(ch);
if (channel_index &&
!str_match(iio_channel_get_id(ch),
argw[channel_index], ignore_case) &&
(!ch_name || !str_match(ch_name,argw[channel_index], ignore_case)))
continue;
channel_found = true;
if ((!scan_only && !channel_index) ||
( scan_only && iio_channel_is_scan_element(ch))) {
printf("%s ", iio_device_is_trigger(dev) ? "trig" : "dev");
printf("'%s', ", label_or_name_or_id);
printf("channel '%s'",
if (ch_name)
printf(", id '%s'", ch_name);
printf(" (%s", type_name);
const struct iio_data_format *format =
char sign = format->is_signed ? 's' : 'u';
char repeat[12] = "";
if (format->is_fully_defined)
sign += 'A' - 'a';
if (format->repeat > 1)
snprintf(repeat, sizeof(repeat), "X%u",
format->repeat);
printf(", index: %lu, format: %ce:%c%u/%u%s>>%u)",
format->is_be ? 'b' : 'l',
sign, format->bits,
format->length, repeat,
format->shift);
if (scan_only)
printf("\n");
else
printf(", ");
} else {
printf("), ");
}
}
if (!channel_index)
printf("found %u channel-specific attributes\n",
nb_attrs);
/* search_channel & device_index are checked in L630 */
if(channel_index && !attr_index && !nb_attrs) {
printf("%s: Found %s device, but it has %u channel attributes\n",
MY_NAME, argw[device_index], nb_attrs);
found_err = true;
}
if (!nb_attrs || !channel_index)
continue;
for (k = 0; k < nb_attrs; k++) {
int ret;
const char *attr =
if (attr_index &&
!str_match(attr, argw[attr_index],
ignore_case))
continue;
gen_dev(dev);
found_err = false;
attr_found = true;
gen_ch(ch);
ret = dump_channel_attributes(dev, ch, attr, wbuf,
attr_index ? quiet : ATTR_VERBOSE);
if (wbuf && ret < 0)
write_err = true;
else if (ret < 0 && attr_index)
read_err = true;
}
}
nb_attrs = iio_device_get_attrs_count(dev);
if (search_device && !device_index)
printf("found %u device attributes\n", nb_attrs);
if (search_device && device_index && !attr_index && !nb_attrs) {
printf("%s: Found %s device, but it has %u device attributes\n",
MY_NAME, label_or_name_or_id, nb_attrs);
if (!attr_found)
found_err = true;
}
if (search_device && device_index && nb_attrs) {
int ret;
for (j = 0; j < nb_attrs; j++) {
const char *attr = iio_device_get_attr(dev, j);
if (attr_index &&
!str_match(attr, argw[attr_index], ignore_case))
continue;
gen_dev(dev);
found_err = false;
attr_found = true;
ret = dump_device_attributes(dev, attr, wbuf,
attr_index ? quiet : ATTR_VERBOSE);
if (wbuf && ret < 0)
write_err = true;
else if (ret < 0 && attr_index)
read_err = true;
}
}
if (search_buffer && !device_index)
printf("found %u buffer attributes\n", nb_attrs);
if (search_buffer && device_index && !attr_index && !nb_attrs) {
printf("%s: Found %s device, but it has %u buffer attributes\n",
MY_NAME, label_or_name_or_id, nb_attrs);
if (!attr_found)
found_err = true;
}
if (search_buffer && device_index && nb_attrs) {
for (j = 0; j < nb_attrs; j++) {
int ret;
const char *attr = iio_device_get_buffer_attr(dev, j);
if ((attr_index && str_match(attr, argw[attr_index],
ignore_case)) || !attr_index) {
gen_dev(dev);
found_err = false;
attr_found = true;
ret = dump_buffer_attributes(dev, attr, wbuf,
attr_index ? quiet : ATTR_VERBOSE);
if (wbuf && ret < 0)
write_err = true;
else if (ret < 0 && attr_index)
read_err = true;
}
}
}
if (search_debug && !device_index)
printf("found %u debug attributes\n", nb_attrs);
if (search_debug && device_index && nb_attrs) {
for (j = 0; j < nb_attrs; j++) {
int ret;
const char *attr = iio_device_get_debug_attr(dev, j);
if ((attr_index && str_match(attr, argw[attr_index],
ignore_case)) || !attr_index) {
gen_dev(dev);
found_err = false;
attr_found = true;
debug_found = true;
ret = dump_debug_attributes(dev, attr, wbuf,
attr_index ? quiet : ATTR_VERBOSE);
if (wbuf && ret < 0)
write_err = true;
else if (ret < 0 && attr_index)
read_err = true;
}
}
}
}
}
if (gen_code)
gen_context_destroy();
if (!dev_found && device_index)
fprintf(stderr, "%s: Error : could not find device (%s)\n", MY_NAME, argw[device_index]);
else if (!ctx_found && search_context)
fprintf(stderr, "%s: Error : could not find Context Attributes\n", MY_NAME);
else if (!channel_found && channel_index) {
if (input_only)
fprintf(stderr, "%s: Error : could not find Input channel (%s)\n", MY_NAME, argw[channel_index]);
if (output_only)
fprintf(stderr, "%s: Error : could not find Output channel (%s)\n", MY_NAME, argw[channel_index]);
if (scan_only)
fprintf(stderr, "%s: Error : could not find Scan channel (%s)\n", MY_NAME, argw[channel_index]);
if (!input_only && !output_only && !scan_only)
fprintf(stderr, "%s: Error : could not find channel (%s)\n", MY_NAME, argw[channel_index]);
} else if (!attr_found && attr_index)
fprintf(stderr, "%s: Error : could not find attribute (%s)\n", MY_NAME, argw[attr_index]);
else if (!debug_found && search_debug && device_index) {
fprintf(stderr, "%s: Error : device (%s) had 0 debug attributes\n", MY_NAME, argw[device_index]);
}
free_argw(argc, argw);
if ((!dev_found && device_index) || (!ctx_found && search_context) ||
(!channel_found && channel_index) || (!attr_found && attr_index) ||
(!debug_found && search_debug && device_index))
return EXIT_FAILURE;
if (write_err || read_err || found_err)
return EXIT_FAILURE;
return EXIT_SUCCESS;
}
bool iio_channel_is_scan_element(const struct iio_channel *chn)
Return True if the given channel is a scan element.
Definition: channel.c:318
unsigned int iio_channel_get_attrs_count(const struct iio_channel *chn)
Enumerate the channel-specific attributes of the given channel.
Definition: channel.c:333
ssize_t iio_channel_attr_read(const struct iio_channel *chn, const char *attr, char *dst, size_t len)
Read the content of the given channel-specific attribute.
Definition: channel.c:387
ssize_t iio_channel_attr_write(const struct iio_channel *chn, const char *attr, const char *src)
Set the value of the given channel-specific attribute.
Definition: channel.c:417
const char * iio_channel_get_name(const struct iio_channel *chn)
Retrieve the channel name (e.g. vccint)
Definition: channel.c:308
bool iio_channel_is_output(const struct iio_channel *chn)
Return True if the given channel is an output channel.
Definition: channel.c:313
const char * iio_channel_get_attr(const struct iio_channel *chn, unsigned int index)
Get the channel-specific attribute present at the given index.
Definition: channel.c:338
const char * iio_channel_get_id(const struct iio_channel *chn)
Retrieve the channel ID (e.g. voltage0)
Definition: channel.c:303
struct iio_device * iio_context_get_device(const struct iio_context *ctx, unsigned int index)
Get the device present at the given index.
Definition: context.c:285
int iio_context_get_attr(const struct iio_context *ctx, unsigned int index, const char **name, const char **value)
Retrieve the name and value of a context-specific attribute.
Definition: context.c:470
const char * iio_context_get_attr_value(const struct iio_context *ctx, const char *name)
Retrieve the value of a context-specific attribute.
Definition: context.c:483
void iio_context_destroy(struct iio_context *ctx)
Destroy the given context.
Definition: context.c:258
unsigned int iio_context_get_attrs_count(const struct iio_context *ctx)
Get the number of context-specific attributes.
Definition: context.c:465
unsigned int iio_context_get_devices_count(const struct iio_context *ctx)
Enumerate the devices found in the given context.
Definition: context.c:280
ssize_t iio_device_debug_attr_read(const struct iio_device *dev, const char *attr, char *dst, size_t len)
Read the content of the given debug attribute.
Definition: device.c:635
unsigned int iio_device_get_debug_attrs_count(const struct iio_device *dev)
Enumerate the debug attributes of the given device.
Definition: device.c:661
const struct iio_data_format * iio_channel_get_data_format(const struct iio_channel *chn)
Get a pointer to a channel's data format structure.
Definition: channel.c:438
ssize_t iio_device_debug_attr_write(const struct iio_device *dev, const char *attr, const char *src)
Set the value of the given debug attribute.
Definition: device.c:655
long iio_channel_get_index(const struct iio_channel *chn)
Get the index of the given channel.
Definition: channel.c:433
const char * iio_device_get_debug_attr(const struct iio_device *dev, unsigned int index)
Get the debug attribute present at the given index.
Definition: device.c:666
unsigned int iio_device_get_attrs_count(const struct iio_device *dev)
Enumerate the device-specific attributes of the given device.
Definition: device.c:194
struct iio_channel * iio_device_get_channel(const struct iio_device *dev, unsigned int index)
Get the channel present at the given index.
Definition: device.c:148
unsigned int iio_device_get_buffer_attrs_count(const struct iio_device *dev)
Enumerate the buffer-specific attributes of the given device.
Definition: device.c:211
const char * iio_device_get_attr(const struct iio_device *dev, unsigned int index)
Get the device-specific attribute present at the given index.
Definition: device.c:199
const char * iio_device_get_name(const struct iio_device *dev)
Retrieve the device name (e.g. xadc)
Definition: device.c:133
const char * iio_device_get_buffer_attr(const struct iio_device *dev, unsigned int index)
Get the buffer-specific attribute present at the given index.
Definition: device.c:216
bool iio_device_is_trigger(const struct iio_device *dev)
Return True if the given device is a trigger.
Definition: device.c:368
ssize_t iio_device_buffer_attr_write(const struct iio_device *dev, const char *attr, const char *src)
Set the value of the given buffer-specific attribute.
Definition: device.c:352
const char * iio_device_get_id(const struct iio_device *dev)
Retrieve the device ID (e.g. iio:device0)
Definition: device.c:128
ssize_t iio_device_buffer_attr_read(const struct iio_device *dev, const char *attr, char *dst, size_t len)
Read the content of the given buffer-specific attribute.
Definition: device.c:332
const char * iio_device_get_label(const struct iio_device *dev)
Retrieve the device label (e.g. lo_pll0_rx_adf4351)
Definition: device.c:138
ssize_t iio_device_attr_write(const struct iio_device *dev, const char *attr, const char *src)
Set the value of the given device-specific attribute.
Definition: device.c:326
unsigned int iio_device_get_channels_count(const struct iio_device *dev)
Enumerate the channels of the given device.
Definition: device.c:143
ssize_t iio_device_attr_read(const struct iio_device *dev, const char *attr, char *dst, size_t len)
Read the content of the given device-specific attribute.
Definition: device.c:306
__api void iio_strerror(int err, char *dst, size_t len)
Get a string description of an error code.
Definition: utilities.c:198
Public interface.
Represents an input or output channel of a device.
Contains the representation of an IIO context.
Contains the format of a data sample.
Definition: iio.h:1678
bool is_signed
Contains True if the sample is signed.
Definition: iio.h:1689
bool is_be
Contains True if the sample is in big-endian format.
Definition: iio.h:1695
unsigned int repeat
Number of times length repeats (added in v0.8)
Definition: iio.h:1704
unsigned int length
Total length of the sample, in bits.
Definition: iio.h:1680
bool is_fully_defined
Contains True if the sample is fully defined, sign extended, etc.
Definition: iio.h:1692
unsigned int shift
Right-shift to apply when converting sample.
Definition: iio.h:1686
unsigned int bits
Length of valuable data in the sample, in bits.
Definition: iio.h:1683
Represents a device in the IIO context.