18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * Industrial I/O utilities - lsiio.c 48c2ecf20Sopenharmony_ci * 58c2ecf20Sopenharmony_ci * Copyright (c) 2010 Manuel Stahl <manuel.stahl@iis.fraunhofer.de> 68c2ecf20Sopenharmony_ci */ 78c2ecf20Sopenharmony_ci 88c2ecf20Sopenharmony_ci#include <string.h> 98c2ecf20Sopenharmony_ci#include <dirent.h> 108c2ecf20Sopenharmony_ci#include <stdio.h> 118c2ecf20Sopenharmony_ci#include <errno.h> 128c2ecf20Sopenharmony_ci#include <stdint.h> 138c2ecf20Sopenharmony_ci#include <stdlib.h> 148c2ecf20Sopenharmony_ci#include <unistd.h> 158c2ecf20Sopenharmony_ci#include <sys/types.h> 168c2ecf20Sopenharmony_ci#include <sys/stat.h> 178c2ecf20Sopenharmony_ci#include <sys/dir.h> 188c2ecf20Sopenharmony_ci#include "iio_utils.h" 198c2ecf20Sopenharmony_ci 208c2ecf20Sopenharmony_cistatic enum verbosity { 218c2ecf20Sopenharmony_ci VERBLEVEL_DEFAULT, /* 0 gives lspci behaviour */ 228c2ecf20Sopenharmony_ci VERBLEVEL_SENSORS, /* 1 lists sensors */ 238c2ecf20Sopenharmony_ci} verblevel = VERBLEVEL_DEFAULT; 248c2ecf20Sopenharmony_ci 258c2ecf20Sopenharmony_ciconst char *type_device = "iio:device"; 268c2ecf20Sopenharmony_ciconst char *type_trigger = "trigger"; 278c2ecf20Sopenharmony_ci 288c2ecf20Sopenharmony_cistatic inline int check_prefix(const char *str, const char *prefix) 298c2ecf20Sopenharmony_ci{ 308c2ecf20Sopenharmony_ci return strlen(str) > strlen(prefix) && 318c2ecf20Sopenharmony_ci strncmp(str, prefix, strlen(prefix)) == 0; 328c2ecf20Sopenharmony_ci} 338c2ecf20Sopenharmony_ci 348c2ecf20Sopenharmony_cistatic inline int check_postfix(const char *str, const char *postfix) 358c2ecf20Sopenharmony_ci{ 368c2ecf20Sopenharmony_ci return strlen(str) > strlen(postfix) && 378c2ecf20Sopenharmony_ci strcmp(str + strlen(str) - strlen(postfix), postfix) == 0; 388c2ecf20Sopenharmony_ci} 398c2ecf20Sopenharmony_ci 408c2ecf20Sopenharmony_cistatic int dump_channels(const char *dev_dir_name) 418c2ecf20Sopenharmony_ci{ 428c2ecf20Sopenharmony_ci DIR *dp; 438c2ecf20Sopenharmony_ci const struct dirent *ent; 448c2ecf20Sopenharmony_ci 458c2ecf20Sopenharmony_ci dp = opendir(dev_dir_name); 468c2ecf20Sopenharmony_ci if (!dp) 478c2ecf20Sopenharmony_ci return -errno; 488c2ecf20Sopenharmony_ci 498c2ecf20Sopenharmony_ci while (ent = readdir(dp), ent) 508c2ecf20Sopenharmony_ci if (check_prefix(ent->d_name, "in_") && 518c2ecf20Sopenharmony_ci (check_postfix(ent->d_name, "_raw") || 528c2ecf20Sopenharmony_ci check_postfix(ent->d_name, "_input"))) 538c2ecf20Sopenharmony_ci printf(" %-10s\n", ent->d_name); 548c2ecf20Sopenharmony_ci 558c2ecf20Sopenharmony_ci return (closedir(dp) == -1) ? -errno : 0; 568c2ecf20Sopenharmony_ci} 578c2ecf20Sopenharmony_ci 588c2ecf20Sopenharmony_cistatic int dump_one_device(const char *dev_dir_name) 598c2ecf20Sopenharmony_ci{ 608c2ecf20Sopenharmony_ci char name[IIO_MAX_NAME_LENGTH]; 618c2ecf20Sopenharmony_ci int dev_idx; 628c2ecf20Sopenharmony_ci int ret; 638c2ecf20Sopenharmony_ci 648c2ecf20Sopenharmony_ci ret = sscanf(dev_dir_name + strlen(iio_dir) + strlen(type_device), "%i", 658c2ecf20Sopenharmony_ci &dev_idx); 668c2ecf20Sopenharmony_ci if (ret != 1) 678c2ecf20Sopenharmony_ci return -EINVAL; 688c2ecf20Sopenharmony_ci 698c2ecf20Sopenharmony_ci ret = read_sysfs_string("name", dev_dir_name, name); 708c2ecf20Sopenharmony_ci if (ret < 0) 718c2ecf20Sopenharmony_ci return ret; 728c2ecf20Sopenharmony_ci 738c2ecf20Sopenharmony_ci printf("Device %03d: %s\n", dev_idx, name); 748c2ecf20Sopenharmony_ci 758c2ecf20Sopenharmony_ci if (verblevel >= VERBLEVEL_SENSORS) 768c2ecf20Sopenharmony_ci return dump_channels(dev_dir_name); 778c2ecf20Sopenharmony_ci 788c2ecf20Sopenharmony_ci return 0; 798c2ecf20Sopenharmony_ci} 808c2ecf20Sopenharmony_ci 818c2ecf20Sopenharmony_cistatic int dump_one_trigger(const char *dev_dir_name) 828c2ecf20Sopenharmony_ci{ 838c2ecf20Sopenharmony_ci char name[IIO_MAX_NAME_LENGTH]; 848c2ecf20Sopenharmony_ci int dev_idx; 858c2ecf20Sopenharmony_ci int ret; 868c2ecf20Sopenharmony_ci 878c2ecf20Sopenharmony_ci ret = sscanf(dev_dir_name + strlen(iio_dir) + strlen(type_trigger), 888c2ecf20Sopenharmony_ci "%i", &dev_idx); 898c2ecf20Sopenharmony_ci if (ret != 1) 908c2ecf20Sopenharmony_ci return -EINVAL; 918c2ecf20Sopenharmony_ci 928c2ecf20Sopenharmony_ci ret = read_sysfs_string("name", dev_dir_name, name); 938c2ecf20Sopenharmony_ci if (ret < 0) 948c2ecf20Sopenharmony_ci return ret; 958c2ecf20Sopenharmony_ci 968c2ecf20Sopenharmony_ci printf("Trigger %03d: %s\n", dev_idx, name); 978c2ecf20Sopenharmony_ci 988c2ecf20Sopenharmony_ci return 0; 998c2ecf20Sopenharmony_ci} 1008c2ecf20Sopenharmony_ci 1018c2ecf20Sopenharmony_cistatic int dump_devices(void) 1028c2ecf20Sopenharmony_ci{ 1038c2ecf20Sopenharmony_ci const struct dirent *ent; 1048c2ecf20Sopenharmony_ci int ret; 1058c2ecf20Sopenharmony_ci DIR *dp; 1068c2ecf20Sopenharmony_ci 1078c2ecf20Sopenharmony_ci dp = opendir(iio_dir); 1088c2ecf20Sopenharmony_ci if (!dp) { 1098c2ecf20Sopenharmony_ci fprintf(stderr, "No industrial I/O devices available\n"); 1108c2ecf20Sopenharmony_ci return -ENODEV; 1118c2ecf20Sopenharmony_ci } 1128c2ecf20Sopenharmony_ci 1138c2ecf20Sopenharmony_ci while (ent = readdir(dp), ent) { 1148c2ecf20Sopenharmony_ci if (check_prefix(ent->d_name, type_device)) { 1158c2ecf20Sopenharmony_ci char *dev_dir_name; 1168c2ecf20Sopenharmony_ci 1178c2ecf20Sopenharmony_ci if (asprintf(&dev_dir_name, "%s%s", iio_dir, 1188c2ecf20Sopenharmony_ci ent->d_name) < 0) { 1198c2ecf20Sopenharmony_ci ret = -ENOMEM; 1208c2ecf20Sopenharmony_ci goto error_close_dir; 1218c2ecf20Sopenharmony_ci } 1228c2ecf20Sopenharmony_ci 1238c2ecf20Sopenharmony_ci ret = dump_one_device(dev_dir_name); 1248c2ecf20Sopenharmony_ci if (ret) { 1258c2ecf20Sopenharmony_ci free(dev_dir_name); 1268c2ecf20Sopenharmony_ci goto error_close_dir; 1278c2ecf20Sopenharmony_ci } 1288c2ecf20Sopenharmony_ci 1298c2ecf20Sopenharmony_ci free(dev_dir_name); 1308c2ecf20Sopenharmony_ci if (verblevel >= VERBLEVEL_SENSORS) 1318c2ecf20Sopenharmony_ci printf("\n"); 1328c2ecf20Sopenharmony_ci } 1338c2ecf20Sopenharmony_ci } 1348c2ecf20Sopenharmony_ci rewinddir(dp); 1358c2ecf20Sopenharmony_ci while (ent = readdir(dp), ent) { 1368c2ecf20Sopenharmony_ci if (check_prefix(ent->d_name, type_trigger)) { 1378c2ecf20Sopenharmony_ci char *dev_dir_name; 1388c2ecf20Sopenharmony_ci 1398c2ecf20Sopenharmony_ci if (asprintf(&dev_dir_name, "%s%s", iio_dir, 1408c2ecf20Sopenharmony_ci ent->d_name) < 0) { 1418c2ecf20Sopenharmony_ci ret = -ENOMEM; 1428c2ecf20Sopenharmony_ci goto error_close_dir; 1438c2ecf20Sopenharmony_ci } 1448c2ecf20Sopenharmony_ci 1458c2ecf20Sopenharmony_ci ret = dump_one_trigger(dev_dir_name); 1468c2ecf20Sopenharmony_ci if (ret) { 1478c2ecf20Sopenharmony_ci free(dev_dir_name); 1488c2ecf20Sopenharmony_ci goto error_close_dir; 1498c2ecf20Sopenharmony_ci } 1508c2ecf20Sopenharmony_ci 1518c2ecf20Sopenharmony_ci free(dev_dir_name); 1528c2ecf20Sopenharmony_ci } 1538c2ecf20Sopenharmony_ci } 1548c2ecf20Sopenharmony_ci 1558c2ecf20Sopenharmony_ci return (closedir(dp) == -1) ? -errno : 0; 1568c2ecf20Sopenharmony_ci 1578c2ecf20Sopenharmony_cierror_close_dir: 1588c2ecf20Sopenharmony_ci if (closedir(dp) == -1) 1598c2ecf20Sopenharmony_ci perror("dump_devices(): Failed to close directory"); 1608c2ecf20Sopenharmony_ci 1618c2ecf20Sopenharmony_ci return ret; 1628c2ecf20Sopenharmony_ci} 1638c2ecf20Sopenharmony_ci 1648c2ecf20Sopenharmony_ciint main(int argc, char **argv) 1658c2ecf20Sopenharmony_ci{ 1668c2ecf20Sopenharmony_ci int c, err = 0; 1678c2ecf20Sopenharmony_ci 1688c2ecf20Sopenharmony_ci while ((c = getopt(argc, argv, "v")) != EOF) { 1698c2ecf20Sopenharmony_ci switch (c) { 1708c2ecf20Sopenharmony_ci case 'v': 1718c2ecf20Sopenharmony_ci verblevel++; 1728c2ecf20Sopenharmony_ci break; 1738c2ecf20Sopenharmony_ci 1748c2ecf20Sopenharmony_ci case '?': 1758c2ecf20Sopenharmony_ci default: 1768c2ecf20Sopenharmony_ci err++; 1778c2ecf20Sopenharmony_ci break; 1788c2ecf20Sopenharmony_ci } 1798c2ecf20Sopenharmony_ci } 1808c2ecf20Sopenharmony_ci if (err || argc > optind) { 1818c2ecf20Sopenharmony_ci fprintf(stderr, "Usage: lsiio [options]...\n" 1828c2ecf20Sopenharmony_ci "List industrial I/O devices\n" 1838c2ecf20Sopenharmony_ci " -v Increase verbosity (may be given multiple times)\n"); 1848c2ecf20Sopenharmony_ci exit(1); 1858c2ecf20Sopenharmony_ci } 1868c2ecf20Sopenharmony_ci 1878c2ecf20Sopenharmony_ci return dump_devices(); 1888c2ecf20Sopenharmony_ci} 189