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 #include <unistd.h> 20 #include <stdlib.h> 21 #include <stdbool.h> 22 #include <stdio.h> 23 #include <errno.h> 24 #include <string.h> 25 #include <poll.h> 26 #include <fcntl.h> 27 #include <sys/ioctl.h> 28 #include "iio_utils.h" 29 #include <linux/iio/events.h> 30 #include <linux/iio/types.h> 31 32 static 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 [IIO_ACTIVITY] = "activity", 53 [IIO_STEPS] = "steps", 54 }; 55 56 static const char * const iio_ev_type_text[] = { 57 [IIO_EV_TYPE_THRESH] = "thresh", 58 [IIO_EV_TYPE_MAG] = "mag", 59 [IIO_EV_TYPE_ROC] = "roc", 60 [IIO_EV_TYPE_THRESH_ADAPTIVE] = "thresh_adaptive", 61 [IIO_EV_TYPE_MAG_ADAPTIVE] = "mag_adaptive", 62 [IIO_EV_TYPE_CHANGE] = "change", 63 }; 64 65 static const char * const iio_ev_dir_text[] = { 66 [IIO_EV_DIR_EITHER] = "either", 67 [IIO_EV_DIR_RISING] = "rising", 68 [IIO_EV_DIR_FALLING] = "falling" 69 }; 70 71 static const char * const iio_modifier_names[] = { 72 [IIO_MOD_X] = "x", 73 [IIO_MOD_Y] = "y", 74 [IIO_MOD_Z] = "z", 75 [IIO_MOD_X_AND_Y] = "x&y", 76 [IIO_MOD_X_AND_Z] = "x&z", 77 [IIO_MOD_Y_AND_Z] = "y&z", 78 [IIO_MOD_X_AND_Y_AND_Z] = "x&y&z", 79 [IIO_MOD_X_OR_Y] = "x|y", 80 [IIO_MOD_X_OR_Z] = "x|z", 81 [IIO_MOD_Y_OR_Z] = "y|z", 82 [IIO_MOD_X_OR_Y_OR_Z] = "x|y|z", 83 [IIO_MOD_LIGHT_BOTH] = "both", 84 [IIO_MOD_LIGHT_IR] = "ir", 85 [IIO_MOD_ROOT_SUM_SQUARED_X_Y] = "sqrt(x^2+y^2)", 86 [IIO_MOD_SUM_SQUARED_X_Y_Z] = "x^2+y^2+z^2", 87 [IIO_MOD_LIGHT_CLEAR] = "clear", 88 [IIO_MOD_LIGHT_RED] = "red", 89 [IIO_MOD_LIGHT_GREEN] = "green", 90 [IIO_MOD_LIGHT_BLUE] = "blue", 91 [IIO_MOD_QUATERNION] = "quaternion", 92 [IIO_MOD_TEMP_AMBIENT] = "ambient", 93 [IIO_MOD_TEMP_OBJECT] = "object", 94 [IIO_MOD_NORTH_MAGN] = "from_north_magnetic", 95 [IIO_MOD_NORTH_TRUE] = "from_north_true", 96 [IIO_MOD_NORTH_MAGN_TILT_COMP] = "from_north_magnetic_tilt_comp", 97 [IIO_MOD_NORTH_TRUE_TILT_COMP] = "from_north_true_tilt_comp", 98 [IIO_MOD_RUNNING] = "running", 99 [IIO_MOD_JOGGING] = "jogging", 100 [IIO_MOD_WALKING] = "walking", 101 [IIO_MOD_STILL] = "still", 102 }; 103 104 static bool event_is_known(struct iio_event_data *event) 105 { 106 enum iio_chan_type type = IIO_EVENT_CODE_EXTRACT_CHAN_TYPE(event->id); 107 enum iio_modifier mod = IIO_EVENT_CODE_EXTRACT_MODIFIER(event->id); 108 enum iio_event_type ev_type = IIO_EVENT_CODE_EXTRACT_TYPE(event->id); 109 enum iio_event_direction dir = IIO_EVENT_CODE_EXTRACT_DIR(event->id); 110 111 switch (type) { 112 case IIO_VOLTAGE: 113 case IIO_CURRENT: 114 case IIO_POWER: 115 case IIO_ACCEL: 116 case IIO_ANGL_VEL: 117 case IIO_MAGN: 118 case IIO_LIGHT: 119 case IIO_INTENSITY: 120 case IIO_PROXIMITY: 121 case IIO_TEMP: 122 case IIO_INCLI: 123 case IIO_ROT: 124 case IIO_ANGL: 125 case IIO_TIMESTAMP: 126 case IIO_CAPACITANCE: 127 case IIO_ALTVOLTAGE: 128 case IIO_CCT: 129 case IIO_PRESSURE: 130 case IIO_HUMIDITYRELATIVE: 131 case IIO_ACTIVITY: 132 case IIO_STEPS: 133 break; 134 default: 135 return false; 136 } 137 138 switch (mod) { 139 case IIO_NO_MOD: 140 case IIO_MOD_X: 141 case IIO_MOD_Y: 142 case IIO_MOD_Z: 143 case IIO_MOD_X_AND_Y: 144 case IIO_MOD_X_AND_Z: 145 case IIO_MOD_Y_AND_Z: 146 case IIO_MOD_X_AND_Y_AND_Z: 147 case IIO_MOD_X_OR_Y: 148 case IIO_MOD_X_OR_Z: 149 case IIO_MOD_Y_OR_Z: 150 case IIO_MOD_X_OR_Y_OR_Z: 151 case IIO_MOD_LIGHT_BOTH: 152 case IIO_MOD_LIGHT_IR: 153 case IIO_MOD_ROOT_SUM_SQUARED_X_Y: 154 case IIO_MOD_SUM_SQUARED_X_Y_Z: 155 case IIO_MOD_LIGHT_CLEAR: 156 case IIO_MOD_LIGHT_RED: 157 case IIO_MOD_LIGHT_GREEN: 158 case IIO_MOD_LIGHT_BLUE: 159 case IIO_MOD_QUATERNION: 160 case IIO_MOD_TEMP_AMBIENT: 161 case IIO_MOD_TEMP_OBJECT: 162 case IIO_MOD_NORTH_MAGN: 163 case IIO_MOD_NORTH_TRUE: 164 case IIO_MOD_NORTH_MAGN_TILT_COMP: 165 case IIO_MOD_NORTH_TRUE_TILT_COMP: 166 case IIO_MOD_RUNNING: 167 case IIO_MOD_JOGGING: 168 case IIO_MOD_WALKING: 169 case IIO_MOD_STILL: 170 break; 171 default: 172 return false; 173 } 174 175 switch (ev_type) { 176 case IIO_EV_TYPE_THRESH: 177 case IIO_EV_TYPE_MAG: 178 case IIO_EV_TYPE_ROC: 179 case IIO_EV_TYPE_THRESH_ADAPTIVE: 180 case IIO_EV_TYPE_MAG_ADAPTIVE: 181 case IIO_EV_TYPE_CHANGE: 182 break; 183 default: 184 return false; 185 } 186 187 switch (dir) { 188 case IIO_EV_DIR_EITHER: 189 case IIO_EV_DIR_RISING: 190 case IIO_EV_DIR_FALLING: 191 case IIO_EV_DIR_NONE: 192 break; 193 default: 194 return false; 195 } 196 197 return true; 198 } 199 200 static void print_event(struct iio_event_data *event) 201 { 202 enum iio_chan_type type = IIO_EVENT_CODE_EXTRACT_CHAN_TYPE(event->id); 203 enum iio_modifier mod = IIO_EVENT_CODE_EXTRACT_MODIFIER(event->id); 204 enum iio_event_type ev_type = IIO_EVENT_CODE_EXTRACT_TYPE(event->id); 205 enum iio_event_direction dir = IIO_EVENT_CODE_EXTRACT_DIR(event->id); 206 int chan = IIO_EVENT_CODE_EXTRACT_CHAN(event->id); 207 int chan2 = IIO_EVENT_CODE_EXTRACT_CHAN2(event->id); 208 bool diff = IIO_EVENT_CODE_EXTRACT_DIFF(event->id); 209 210 if (!event_is_known(event)) { 211 printf("Unknown event: time: %lld, id: %llx\n", 212 event->timestamp, event->id); 213 return; 214 } 215 216 printf("Event: time: %lld, type: %s", event->timestamp, 217 iio_chan_type_name_spec[type]); 218 219 if (mod != IIO_NO_MOD) 220 printf("(%s)", iio_modifier_names[mod]); 221 222 if (chan >= 0) { 223 printf(", channel: %d", chan); 224 if (diff && chan2 >= 0) 225 printf("-%d", chan2); 226 } 227 228 printf(", evtype: %s", iio_ev_type_text[ev_type]); 229 230 if (dir != IIO_EV_DIR_NONE) 231 printf(", direction: %s", iio_ev_dir_text[dir]); 232 printf("\n"); 233 } 234 235 int main(int argc, char **argv) 236 { 237 struct iio_event_data event; 238 const char *device_name; 239 char *chrdev_name; 240 int ret; 241 int dev_num; 242 int fd, event_fd; 243 244 if (argc <= 1) { 245 printf("Usage: %s <device_name>\n", argv[0]); 246 return -1; 247 } 248 249 device_name = argv[1]; 250 251 dev_num = find_type_by_name(device_name, "iio:device"); 252 if (dev_num >= 0) { 253 printf("Found IIO device with name %s with device number %d\n", 254 device_name, dev_num); 255 ret = asprintf(&chrdev_name, "/dev/iio:device%d", dev_num); 256 if (ret < 0) { 257 return -ENOMEM; 258 } 259 } else { 260 /* If we can't find a IIO device by name assume device_name is a 261 IIO chrdev */ 262 chrdev_name = strdup(device_name); 263 if (!chrdev_name) 264 return -ENOMEM; 265 } 266 267 fd = open(chrdev_name, 0); 268 if (fd == -1) { 269 ret = -errno; 270 fprintf(stdout, "Failed to open %s\n", chrdev_name); 271 goto error_free_chrdev_name; 272 } 273 274 ret = ioctl(fd, IIO_GET_EVENT_FD_IOCTL, &event_fd); 275 if (ret == -1 || event_fd == -1) { 276 ret = -errno; 277 fprintf(stdout, "Failed to retrieve event fd\n"); 278 if (close(fd) == -1) 279 perror("Failed to close character device file"); 280 281 goto error_free_chrdev_name; 282 } 283 284 if (close(fd) == -1) { 285 ret = -errno; 286 goto error_free_chrdev_name; 287 } 288 289 while (true) { 290 ret = read(event_fd, &event, sizeof(event)); 291 if (ret == -1) { 292 if (errno == EAGAIN) { 293 printf("nothing available\n"); 294 continue; 295 } else { 296 ret = -errno; 297 perror("Failed to read event from device"); 298 break; 299 } 300 } 301 302 print_event(&event); 303 } 304 305 if (close(event_fd) == -1) 306 perror("Failed to close event file"); 307 308 error_free_chrdev_name: 309 free(chrdev_name); 310 311 return ret; 312 } 313