1 // SPDX-License-Identifier: GPL-2.0-only 2 /* 3 * Industrial I/O utilities - lsiio.c 4 * 5 * Copyright (c) 2010 Manuel Stahl <manuel.stahl@iis.fraunhofer.de> 6 */ 7 8 #include <string.h> 9 #include <dirent.h> 10 #include <stdio.h> 11 #include <errno.h> 12 #include <stdint.h> 13 #include <stdlib.h> 14 #include <unistd.h> 15 #include <sys/types.h> 16 #include <sys/stat.h> 17 #include <sys/dir.h> 18 #include "iio_utils.h" 19 20 static enum verbosity { 21 VERBLEVEL_DEFAULT, /* 0 gives lspci behaviour */ 22 VERBLEVEL_SENSORS, /* 1 lists sensors */ 23 } verblevel = VERBLEVEL_DEFAULT; 24 25 const char *type_device = "iio:device"; 26 const char *type_trigger = "trigger"; 27 28 static inline int check_prefix(const char *str, const char *prefix) 29 { 30 return strlen(str) > strlen(prefix) && 31 strncmp(str, prefix, strlen(prefix)) == 0; 32 } 33 34 static inline int check_postfix(const char *str, const char *postfix) 35 { 36 return strlen(str) > strlen(postfix) && 37 strcmp(str + strlen(str) - strlen(postfix), postfix) == 0; 38 } 39 40 static int dump_channels(const char *dev_dir_name) 41 { 42 DIR *dp; 43 const struct dirent *ent; 44 45 dp = opendir(dev_dir_name); 46 if (!dp) 47 return -errno; 48 49 while (ent = readdir(dp), ent) 50 if (check_prefix(ent->d_name, "in_") && 51 (check_postfix(ent->d_name, "_raw") || 52 check_postfix(ent->d_name, "_input"))) 53 printf(" %-10s\n", ent->d_name); 54 55 return (closedir(dp) == -1) ? -errno : 0; 56 } 57 58 static int dump_one_device(const char *dev_dir_name) 59 { 60 char name[IIO_MAX_NAME_LENGTH]; 61 int dev_idx; 62 int ret; 63 64 ret = sscanf(dev_dir_name + strlen(iio_dir) + strlen(type_device), "%i", 65 &dev_idx); 66 if (ret != 1) 67 return -EINVAL; 68 69 ret = read_sysfs_string("name", dev_dir_name, name); 70 if (ret < 0) 71 return ret; 72 73 printf("Device %03d: %s\n", dev_idx, name); 74 75 if (verblevel >= VERBLEVEL_SENSORS) 76 return dump_channels(dev_dir_name); 77 78 return 0; 79 } 80 81 static int dump_one_trigger(const char *dev_dir_name) 82 { 83 char name[IIO_MAX_NAME_LENGTH]; 84 int dev_idx; 85 int ret; 86 87 ret = sscanf(dev_dir_name + strlen(iio_dir) + strlen(type_trigger), 88 "%i", &dev_idx); 89 if (ret != 1) 90 return -EINVAL; 91 92 ret = read_sysfs_string("name", dev_dir_name, name); 93 if (ret < 0) 94 return ret; 95 96 printf("Trigger %03d: %s\n", dev_idx, name); 97 98 return 0; 99 } 100 101 static int dump_devices(void) 102 { 103 const struct dirent *ent; 104 int ret; 105 DIR *dp; 106 107 dp = opendir(iio_dir); 108 if (!dp) { 109 fprintf(stderr, "No industrial I/O devices available\n"); 110 return -ENODEV; 111 } 112 113 while (ent = readdir(dp), ent) { 114 if (check_prefix(ent->d_name, type_device)) { 115 char *dev_dir_name; 116 117 if (asprintf(&dev_dir_name, "%s%s", iio_dir, 118 ent->d_name) < 0) { 119 ret = -ENOMEM; 120 goto error_close_dir; 121 } 122 123 ret = dump_one_device(dev_dir_name); 124 if (ret) { 125 free(dev_dir_name); 126 goto error_close_dir; 127 } 128 129 free(dev_dir_name); 130 if (verblevel >= VERBLEVEL_SENSORS) 131 printf("\n"); 132 } 133 } 134 rewinddir(dp); 135 while (ent = readdir(dp), ent) { 136 if (check_prefix(ent->d_name, type_trigger)) { 137 char *dev_dir_name; 138 139 if (asprintf(&dev_dir_name, "%s%s", iio_dir, 140 ent->d_name) < 0) { 141 ret = -ENOMEM; 142 goto error_close_dir; 143 } 144 145 ret = dump_one_trigger(dev_dir_name); 146 if (ret) { 147 free(dev_dir_name); 148 goto error_close_dir; 149 } 150 151 free(dev_dir_name); 152 } 153 } 154 155 return (closedir(dp) == -1) ? -errno : 0; 156 157 error_close_dir: 158 if (closedir(dp) == -1) 159 perror("dump_devices(): Failed to close directory"); 160 161 return ret; 162 } 163 164 int main(int argc, char **argv) 165 { 166 int c, err = 0; 167 168 while ((c = getopt(argc, argv, "v")) != EOF) { 169 switch (c) { 170 case 'v': 171 verblevel++; 172 break; 173 174 case '?': 175 default: 176 err++; 177 break; 178 } 179 } 180 if (err || argc > optind) { 181 fprintf(stderr, "Usage: lsiio [options]...\n" 182 "List industrial I/O devices\n" 183 " -v Increase verbosity (may be given multiple times)\n"); 184 exit(1); 185 } 186 187 return dump_devices(); 188 } 189