189 lines · c
1// SPDX-License-Identifier: GPL-2.0-only2/*3 * Industrial I/O utilities - lsiio.c4 *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 20static enum verbosity {21 VERBLEVEL_DEFAULT, /* 0 gives lspci behaviour */22 VERBLEVEL_SENSORS, /* 1 lists sensors */23} verblevel = VERBLEVEL_DEFAULT;24 25const char *type_device = "iio:device";26const char *type_trigger = "trigger";27 28static 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 34static 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 40static 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 58static 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 81static 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 101static 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 157error_close_dir:158 if (closedir(dp) == -1)159 perror("dump_devices(): Failed to close directory");160 161 return ret;162}163 164int 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