xref: /kernel/linux/linux-6.6/tools/iio/lsiio.c (revision 62306a36)
162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only
262306a36Sopenharmony_ci/*
362306a36Sopenharmony_ci * Industrial I/O utilities - lsiio.c
462306a36Sopenharmony_ci *
562306a36Sopenharmony_ci * Copyright (c) 2010 Manuel Stahl <manuel.stahl@iis.fraunhofer.de>
662306a36Sopenharmony_ci */
762306a36Sopenharmony_ci
862306a36Sopenharmony_ci#include <string.h>
962306a36Sopenharmony_ci#include <dirent.h>
1062306a36Sopenharmony_ci#include <stdio.h>
1162306a36Sopenharmony_ci#include <errno.h>
1262306a36Sopenharmony_ci#include <stdint.h>
1362306a36Sopenharmony_ci#include <stdlib.h>
1462306a36Sopenharmony_ci#include <unistd.h>
1562306a36Sopenharmony_ci#include <sys/types.h>
1662306a36Sopenharmony_ci#include <sys/stat.h>
1762306a36Sopenharmony_ci#include <sys/dir.h>
1862306a36Sopenharmony_ci#include "iio_utils.h"
1962306a36Sopenharmony_ci
2062306a36Sopenharmony_cistatic enum verbosity {
2162306a36Sopenharmony_ci	VERBLEVEL_DEFAULT,	/* 0 gives lspci behaviour */
2262306a36Sopenharmony_ci	VERBLEVEL_SENSORS,	/* 1 lists sensors */
2362306a36Sopenharmony_ci} verblevel = VERBLEVEL_DEFAULT;
2462306a36Sopenharmony_ci
2562306a36Sopenharmony_ciconst char *type_device = "iio:device";
2662306a36Sopenharmony_ciconst char *type_trigger = "trigger";
2762306a36Sopenharmony_ci
2862306a36Sopenharmony_cistatic inline int check_prefix(const char *str, const char *prefix)
2962306a36Sopenharmony_ci{
3062306a36Sopenharmony_ci	return strlen(str) > strlen(prefix) &&
3162306a36Sopenharmony_ci	       strncmp(str, prefix, strlen(prefix)) == 0;
3262306a36Sopenharmony_ci}
3362306a36Sopenharmony_ci
3462306a36Sopenharmony_cistatic inline int check_postfix(const char *str, const char *postfix)
3562306a36Sopenharmony_ci{
3662306a36Sopenharmony_ci	return strlen(str) > strlen(postfix) &&
3762306a36Sopenharmony_ci	       strcmp(str + strlen(str) - strlen(postfix), postfix) == 0;
3862306a36Sopenharmony_ci}
3962306a36Sopenharmony_ci
4062306a36Sopenharmony_cistatic int dump_channels(const char *dev_dir_name)
4162306a36Sopenharmony_ci{
4262306a36Sopenharmony_ci	DIR *dp;
4362306a36Sopenharmony_ci	const struct dirent *ent;
4462306a36Sopenharmony_ci
4562306a36Sopenharmony_ci	dp = opendir(dev_dir_name);
4662306a36Sopenharmony_ci	if (!dp)
4762306a36Sopenharmony_ci		return -errno;
4862306a36Sopenharmony_ci
4962306a36Sopenharmony_ci	while (ent = readdir(dp), ent)
5062306a36Sopenharmony_ci		if (check_prefix(ent->d_name, "in_") &&
5162306a36Sopenharmony_ci		   (check_postfix(ent->d_name, "_raw") ||
5262306a36Sopenharmony_ci		    check_postfix(ent->d_name, "_input")))
5362306a36Sopenharmony_ci			printf("   %-10s\n", ent->d_name);
5462306a36Sopenharmony_ci
5562306a36Sopenharmony_ci	return (closedir(dp) == -1) ? -errno : 0;
5662306a36Sopenharmony_ci}
5762306a36Sopenharmony_ci
5862306a36Sopenharmony_cistatic int dump_one_device(const char *dev_dir_name)
5962306a36Sopenharmony_ci{
6062306a36Sopenharmony_ci	char name[IIO_MAX_NAME_LENGTH];
6162306a36Sopenharmony_ci	int dev_idx;
6262306a36Sopenharmony_ci	int ret;
6362306a36Sopenharmony_ci
6462306a36Sopenharmony_ci	ret = sscanf(dev_dir_name + strlen(iio_dir) + strlen(type_device), "%i",
6562306a36Sopenharmony_ci		     &dev_idx);
6662306a36Sopenharmony_ci	if (ret != 1)
6762306a36Sopenharmony_ci		return -EINVAL;
6862306a36Sopenharmony_ci
6962306a36Sopenharmony_ci	ret = read_sysfs_string("name", dev_dir_name, name);
7062306a36Sopenharmony_ci	if (ret < 0)
7162306a36Sopenharmony_ci		return ret;
7262306a36Sopenharmony_ci
7362306a36Sopenharmony_ci	printf("Device %03d: %s\n", dev_idx, name);
7462306a36Sopenharmony_ci
7562306a36Sopenharmony_ci	if (verblevel >= VERBLEVEL_SENSORS)
7662306a36Sopenharmony_ci		return dump_channels(dev_dir_name);
7762306a36Sopenharmony_ci
7862306a36Sopenharmony_ci	return 0;
7962306a36Sopenharmony_ci}
8062306a36Sopenharmony_ci
8162306a36Sopenharmony_cistatic int dump_one_trigger(const char *dev_dir_name)
8262306a36Sopenharmony_ci{
8362306a36Sopenharmony_ci	char name[IIO_MAX_NAME_LENGTH];
8462306a36Sopenharmony_ci	int dev_idx;
8562306a36Sopenharmony_ci	int ret;
8662306a36Sopenharmony_ci
8762306a36Sopenharmony_ci	ret = sscanf(dev_dir_name + strlen(iio_dir) + strlen(type_trigger),
8862306a36Sopenharmony_ci		     "%i", &dev_idx);
8962306a36Sopenharmony_ci	if (ret != 1)
9062306a36Sopenharmony_ci		return -EINVAL;
9162306a36Sopenharmony_ci
9262306a36Sopenharmony_ci	ret = read_sysfs_string("name", dev_dir_name, name);
9362306a36Sopenharmony_ci	if (ret < 0)
9462306a36Sopenharmony_ci		return ret;
9562306a36Sopenharmony_ci
9662306a36Sopenharmony_ci	printf("Trigger %03d: %s\n", dev_idx, name);
9762306a36Sopenharmony_ci
9862306a36Sopenharmony_ci	return 0;
9962306a36Sopenharmony_ci}
10062306a36Sopenharmony_ci
10162306a36Sopenharmony_cistatic int dump_devices(void)
10262306a36Sopenharmony_ci{
10362306a36Sopenharmony_ci	const struct dirent *ent;
10462306a36Sopenharmony_ci	int ret;
10562306a36Sopenharmony_ci	DIR *dp;
10662306a36Sopenharmony_ci
10762306a36Sopenharmony_ci	dp = opendir(iio_dir);
10862306a36Sopenharmony_ci	if (!dp) {
10962306a36Sopenharmony_ci		fprintf(stderr, "No industrial I/O devices available\n");
11062306a36Sopenharmony_ci		return -ENODEV;
11162306a36Sopenharmony_ci	}
11262306a36Sopenharmony_ci
11362306a36Sopenharmony_ci	while (ent = readdir(dp), ent) {
11462306a36Sopenharmony_ci		if (check_prefix(ent->d_name, type_device)) {
11562306a36Sopenharmony_ci			char *dev_dir_name;
11662306a36Sopenharmony_ci
11762306a36Sopenharmony_ci			if (asprintf(&dev_dir_name, "%s%s", iio_dir,
11862306a36Sopenharmony_ci				     ent->d_name) < 0) {
11962306a36Sopenharmony_ci				ret = -ENOMEM;
12062306a36Sopenharmony_ci				goto error_close_dir;
12162306a36Sopenharmony_ci			}
12262306a36Sopenharmony_ci
12362306a36Sopenharmony_ci			ret = dump_one_device(dev_dir_name);
12462306a36Sopenharmony_ci			if (ret) {
12562306a36Sopenharmony_ci				free(dev_dir_name);
12662306a36Sopenharmony_ci				goto error_close_dir;
12762306a36Sopenharmony_ci			}
12862306a36Sopenharmony_ci
12962306a36Sopenharmony_ci			free(dev_dir_name);
13062306a36Sopenharmony_ci			if (verblevel >= VERBLEVEL_SENSORS)
13162306a36Sopenharmony_ci				printf("\n");
13262306a36Sopenharmony_ci		}
13362306a36Sopenharmony_ci	}
13462306a36Sopenharmony_ci	rewinddir(dp);
13562306a36Sopenharmony_ci	while (ent = readdir(dp), ent) {
13662306a36Sopenharmony_ci		if (check_prefix(ent->d_name, type_trigger)) {
13762306a36Sopenharmony_ci			char *dev_dir_name;
13862306a36Sopenharmony_ci
13962306a36Sopenharmony_ci			if (asprintf(&dev_dir_name, "%s%s", iio_dir,
14062306a36Sopenharmony_ci				     ent->d_name) < 0) {
14162306a36Sopenharmony_ci				ret = -ENOMEM;
14262306a36Sopenharmony_ci				goto error_close_dir;
14362306a36Sopenharmony_ci			}
14462306a36Sopenharmony_ci
14562306a36Sopenharmony_ci			ret = dump_one_trigger(dev_dir_name);
14662306a36Sopenharmony_ci			if (ret) {
14762306a36Sopenharmony_ci				free(dev_dir_name);
14862306a36Sopenharmony_ci				goto error_close_dir;
14962306a36Sopenharmony_ci			}
15062306a36Sopenharmony_ci
15162306a36Sopenharmony_ci			free(dev_dir_name);
15262306a36Sopenharmony_ci		}
15362306a36Sopenharmony_ci	}
15462306a36Sopenharmony_ci
15562306a36Sopenharmony_ci	return (closedir(dp) == -1) ? -errno : 0;
15662306a36Sopenharmony_ci
15762306a36Sopenharmony_cierror_close_dir:
15862306a36Sopenharmony_ci	if (closedir(dp) == -1)
15962306a36Sopenharmony_ci		perror("dump_devices(): Failed to close directory");
16062306a36Sopenharmony_ci
16162306a36Sopenharmony_ci	return ret;
16262306a36Sopenharmony_ci}
16362306a36Sopenharmony_ci
16462306a36Sopenharmony_ciint main(int argc, char **argv)
16562306a36Sopenharmony_ci{
16662306a36Sopenharmony_ci	int c, err = 0;
16762306a36Sopenharmony_ci
16862306a36Sopenharmony_ci	while ((c = getopt(argc, argv, "v")) != EOF) {
16962306a36Sopenharmony_ci		switch (c) {
17062306a36Sopenharmony_ci		case 'v':
17162306a36Sopenharmony_ci			verblevel++;
17262306a36Sopenharmony_ci			break;
17362306a36Sopenharmony_ci
17462306a36Sopenharmony_ci		case '?':
17562306a36Sopenharmony_ci		default:
17662306a36Sopenharmony_ci			err++;
17762306a36Sopenharmony_ci			break;
17862306a36Sopenharmony_ci		}
17962306a36Sopenharmony_ci	}
18062306a36Sopenharmony_ci	if (err || argc > optind) {
18162306a36Sopenharmony_ci		fprintf(stderr, "Usage: lsiio [options]...\n"
18262306a36Sopenharmony_ci			"List industrial I/O devices\n"
18362306a36Sopenharmony_ci			"  -v  Increase verbosity (may be given multiple times)\n");
18462306a36Sopenharmony_ci		exit(1);
18562306a36Sopenharmony_ci	}
18662306a36Sopenharmony_ci
18762306a36Sopenharmony_ci	return dump_devices();
18862306a36Sopenharmony_ci}
189