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