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