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