1/* Industrialio event test code. 2 * 3 * Copyright (c) 2011-2012 Lars-Peter Clausen <lars@metafoo.de> 4 * 5 * This program is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 as published by 7 * the Free Software Foundation. 8 * 9 * This program is primarily intended as an example application. 10 * Reads the current buffer setup from sysfs and starts a short capture 11 * from the specified device, pretty printing the result after appropriate 12 * conversion. 13 * 14 * Usage: 15 * iio_event_monitor <device_name> 16 * 17 */ 18 19#define _GNU_SOURCE 20 21#include <unistd.h> 22#include <stdbool.h> 23#include <stdio.h> 24#include <errno.h> 25#include <string.h> 26#include <poll.h> 27#include <fcntl.h> 28#include <sys/ioctl.h> 29#include "iio_utils.h" 30#include <linux/iio/events.h> 31 32static const char * const iio_chan_type_name_spec[] = { 33 [IIO_VOLTAGE] = "voltage", 34 [IIO_CURRENT] = "current", 35 [IIO_POWER] = "power", 36 [IIO_ACCEL] = "accel", 37 [IIO_ANGL_VEL] = "anglvel", 38 [IIO_MAGN] = "magn", 39 [IIO_LIGHT] = "illuminance", 40 [IIO_INTENSITY] = "intensity", 41 [IIO_PROXIMITY] = "proximity", 42 [IIO_TEMP] = "temp", 43 [IIO_INCLI] = "incli", 44 [IIO_ROT] = "rot", 45 [IIO_ANGL] = "angl", 46 [IIO_TIMESTAMP] = "timestamp", 47 [IIO_CAPACITANCE] = "capacitance", 48 [IIO_ALTVOLTAGE] = "altvoltage", 49 [IIO_CCT] = "cct", 50 [IIO_PRESSURE] = "pressure", 51 [IIO_HUMIDITYRELATIVE] = "humidityrelative", 52}; 53 54static const char * const iio_ev_type_text[] = { 55 [IIO_EV_TYPE_THRESH] = "thresh", 56 [IIO_EV_TYPE_MAG] = "mag", 57 [IIO_EV_TYPE_ROC] = "roc", 58 [IIO_EV_TYPE_THRESH_ADAPTIVE] = "thresh_adaptive", 59 [IIO_EV_TYPE_MAG_ADAPTIVE] = "mag_adaptive", 60}; 61 62static const char * const iio_ev_dir_text[] = { 63 [IIO_EV_DIR_EITHER] = "either", 64 [IIO_EV_DIR_RISING] = "rising", 65 [IIO_EV_DIR_FALLING] = "falling" 66}; 67 68static const char * const iio_modifier_names[] = { 69 [IIO_MOD_X] = "x", 70 [IIO_MOD_Y] = "y", 71 [IIO_MOD_Z] = "z", 72 [IIO_MOD_LIGHT_BOTH] = "both", 73 [IIO_MOD_LIGHT_IR] = "ir", 74 [IIO_MOD_ROOT_SUM_SQUARED_X_Y] = "sqrt(x^2+y^2)", 75 [IIO_MOD_SUM_SQUARED_X_Y_Z] = "x^2+y^2+z^2", 76 [IIO_MOD_LIGHT_BOTH] = "both", 77 [IIO_MOD_LIGHT_IR] = "ir", 78 [IIO_MOD_LIGHT_CLEAR] = "clear", 79 [IIO_MOD_LIGHT_RED] = "red", 80 [IIO_MOD_LIGHT_GREEN] = "green", 81 [IIO_MOD_LIGHT_BLUE] = "blue", 82}; 83 84static bool event_is_known(struct iio_event_data *event) 85{ 86 enum iio_chan_type type = IIO_EVENT_CODE_EXTRACT_CHAN_TYPE(event->id); 87 enum iio_modifier mod = IIO_EVENT_CODE_EXTRACT_MODIFIER(event->id); 88 enum iio_event_type ev_type = IIO_EVENT_CODE_EXTRACT_TYPE(event->id); 89 enum iio_event_direction dir = IIO_EVENT_CODE_EXTRACT_DIR(event->id); 90 91 switch (type) { 92 case IIO_VOLTAGE: 93 case IIO_CURRENT: 94 case IIO_POWER: 95 case IIO_ACCEL: 96 case IIO_ANGL_VEL: 97 case IIO_MAGN: 98 case IIO_LIGHT: 99 case IIO_INTENSITY: 100 case IIO_PROXIMITY: 101 case IIO_TEMP: 102 case IIO_INCLI: 103 case IIO_ROT: 104 case IIO_ANGL: 105 case IIO_TIMESTAMP: 106 case IIO_CAPACITANCE: 107 case IIO_ALTVOLTAGE: 108 case IIO_CCT: 109 case IIO_PRESSURE: 110 case IIO_HUMIDITYRELATIVE: 111 break; 112 default: 113 return false; 114 } 115 116 switch (mod) { 117 case IIO_NO_MOD: 118 case IIO_MOD_X: 119 case IIO_MOD_Y: 120 case IIO_MOD_Z: 121 case IIO_MOD_LIGHT_BOTH: 122 case IIO_MOD_LIGHT_IR: 123 case IIO_MOD_ROOT_SUM_SQUARED_X_Y: 124 case IIO_MOD_SUM_SQUARED_X_Y_Z: 125 case IIO_MOD_LIGHT_CLEAR: 126 case IIO_MOD_LIGHT_RED: 127 case IIO_MOD_LIGHT_GREEN: 128 case IIO_MOD_LIGHT_BLUE: 129 break; 130 default: 131 return false; 132 } 133 134 switch (ev_type) { 135 case IIO_EV_TYPE_THRESH: 136 case IIO_EV_TYPE_MAG: 137 case IIO_EV_TYPE_ROC: 138 case IIO_EV_TYPE_THRESH_ADAPTIVE: 139 case IIO_EV_TYPE_MAG_ADAPTIVE: 140 break; 141 default: 142 return false; 143 } 144 145 switch (dir) { 146 case IIO_EV_DIR_EITHER: 147 case IIO_EV_DIR_RISING: 148 case IIO_EV_DIR_FALLING: 149 break; 150 default: 151 return false; 152 } 153 154 return true; 155} 156 157static void print_event(struct iio_event_data *event) 158{ 159 enum iio_chan_type type = IIO_EVENT_CODE_EXTRACT_CHAN_TYPE(event->id); 160 enum iio_modifier mod = IIO_EVENT_CODE_EXTRACT_MODIFIER(event->id); 161 enum iio_event_type ev_type = IIO_EVENT_CODE_EXTRACT_TYPE(event->id); 162 enum iio_event_direction dir = IIO_EVENT_CODE_EXTRACT_DIR(event->id); 163 int chan = IIO_EVENT_CODE_EXTRACT_CHAN(event->id); 164 int chan2 = IIO_EVENT_CODE_EXTRACT_CHAN2(event->id); 165 bool diff = IIO_EVENT_CODE_EXTRACT_DIFF(event->id); 166 167 if (!event_is_known(event)) { 168 printf("Unknown event: time: %lld, id: %llx\n", 169 event->timestamp, event->id); 170 return; 171 } 172 173 printf("Event: time: %lld, ", event->timestamp); 174 175 if (mod != IIO_NO_MOD) { 176 printf("type: %s(%s), ", 177 iio_chan_type_name_spec[type], 178 iio_modifier_names[mod]); 179 } else { 180 printf("type: %s, ", 181 iio_chan_type_name_spec[type]); 182 } 183 184 if (diff && chan >= 0 && chan2 >= 0) 185 printf("channel: %d-%d, ", chan, chan2); 186 else if (chan >= 0) 187 printf("channel: %d, ", chan); 188 189 printf("evtype: %s, direction: %s\n", 190 iio_ev_type_text[ev_type], 191 iio_ev_dir_text[dir]); 192} 193 194int main(int argc, char **argv) 195{ 196 struct iio_event_data event; 197 const char *device_name; 198 char *chrdev_name; 199 int ret; 200 int dev_num; 201 int fd, event_fd; 202 203 if (argc <= 1) { 204 printf("Usage: %s <device_name>\n", argv[0]); 205 return -1; 206 } 207 208 device_name = argv[1]; 209 210 dev_num = find_type_by_name(device_name, "iio:device"); 211 if (dev_num >= 0) { 212 printf("Found IIO device with name %s with device number %d\n", 213 device_name, dev_num); 214 ret = asprintf(&chrdev_name, "/dev/iio:device%d", dev_num); 215 if (ret < 0) { 216 ret = -ENOMEM; 217 goto error_ret; 218 } 219 } else { 220 /* If we can't find a IIO device by name assume device_name is a 221 IIO chrdev */ 222 chrdev_name = strdup(device_name); 223 } 224 225 fd = open(chrdev_name, 0); 226 if (fd == -1) { 227 fprintf(stdout, "Failed to open %s\n", chrdev_name); 228 ret = -errno; 229 goto error_free_chrdev_name; 230 } 231 232 ret = ioctl(fd, IIO_GET_EVENT_FD_IOCTL, &event_fd); 233 234 close(fd); 235 236 if (ret == -1 || event_fd == -1) { 237 fprintf(stdout, "Failed to retrieve event fd\n"); 238 ret = -errno; 239 goto error_free_chrdev_name; 240 } 241 242 while (true) { 243 ret = read(event_fd, &event, sizeof(event)); 244 if (ret == -1) { 245 if (errno == EAGAIN) { 246 printf("nothing available\n"); 247 continue; 248 } else { 249 perror("Failed to read event from device"); 250 ret = -errno; 251 break; 252 } 253 } 254 255 print_event(&event); 256 } 257 258 close(event_fd); 259error_free_chrdev_name: 260 free(chrdev_name); 261error_ret: 262 return ret; 263} 264