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