linux/tools/iio/lsiio.c
<<
>>
Prefs
   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
  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