at v4.2 10 kB view raw
1/* Industrialio buffer test code. 2 * 3 * Copyright (c) 2008 Jonathan Cameron 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 * Command line parameters 15 * generic_buffer -n <device_name> -t <trigger_name> 16 * If trigger name is not specified the program assumes you want a dataready 17 * trigger associated with the device and goes looking for it. 18 * 19 */ 20 21#include <unistd.h> 22#include <stdlib.h> 23#include <dirent.h> 24#include <fcntl.h> 25#include <stdio.h> 26#include <errno.h> 27#include <sys/stat.h> 28#include <sys/dir.h> 29#include <linux/types.h> 30#include <string.h> 31#include <poll.h> 32#include <endian.h> 33#include <getopt.h> 34#include <inttypes.h> 35#include "iio_utils.h" 36 37/** 38 * size_from_channelarray() - calculate the storage size of a scan 39 * @channels: the channel info array 40 * @num_channels: number of channels 41 * 42 * Has the side effect of filling the channels[i].location values used 43 * in processing the buffer output. 44 **/ 45int size_from_channelarray(struct iio_channel_info *channels, int num_channels) 46{ 47 int bytes = 0; 48 int i = 0; 49 50 while (i < num_channels) { 51 if (bytes % channels[i].bytes == 0) 52 channels[i].location = bytes; 53 else 54 channels[i].location = bytes - bytes%channels[i].bytes 55 + channels[i].bytes; 56 bytes = channels[i].location + channels[i].bytes; 57 i++; 58 } 59 return bytes; 60} 61 62void print2byte(uint16_t input, struct iio_channel_info *info) 63{ 64 /* First swap if incorrect endian */ 65 if (info->be) 66 input = be16toh(input); 67 else 68 input = le16toh(input); 69 70 /* 71 * Shift before conversion to avoid sign extension 72 * of left aligned data 73 */ 74 input >>= info->shift; 75 input &= info->mask; 76 if (info->is_signed) { 77 int16_t val = (int16_t)(input << (16 - info->bits_used)) >> 78 (16 - info->bits_used); 79 printf("%05f ", ((float)val + info->offset) * info->scale); 80 } else { 81 printf("%05f ", ((float)input + info->offset) * info->scale); 82 } 83} 84 85void print4byte(uint32_t input, struct iio_channel_info *info) 86{ 87 /* First swap if incorrect endian */ 88 if (info->be) 89 input = be32toh(input); 90 else 91 input = le32toh(input); 92 93 /* 94 * Shift before conversion to avoid sign extension 95 * of left aligned data 96 */ 97 input >>= info->shift; 98 input &= info->mask; 99 if (info->is_signed) { 100 int32_t val = (int32_t)(input << (32 - info->bits_used)) >> 101 (32 - info->bits_used); 102 printf("%05f ", ((float)val + info->offset) * info->scale); 103 } else { 104 printf("%05f ", ((float)input + info->offset) * info->scale); 105 } 106} 107 108void print8byte(uint64_t input, struct iio_channel_info *info) 109{ 110 /* First swap if incorrect endian */ 111 if (info->be) 112 input = be64toh(input); 113 else 114 input = le64toh(input); 115 116 /* 117 * Shift before conversion to avoid sign extension 118 * of left aligned data 119 */ 120 input >>= info->shift; 121 input &= info->mask; 122 if (info->is_signed) { 123 int64_t val = (int64_t)(input << (64 - info->bits_used)) >> 124 (64 - info->bits_used); 125 /* special case for timestamp */ 126 if (info->scale == 1.0f && info->offset == 0.0f) 127 printf("%" PRId64 " ", val); 128 else 129 printf("%05f ", 130 ((float)val + info->offset) * info->scale); 131 } else { 132 printf("%05f ", ((float)input + info->offset) * info->scale); 133 } 134} 135 136/** 137 * process_scan() - print out the values in SI units 138 * @data: pointer to the start of the scan 139 * @channels: information about the channels. Note 140 * size_from_channelarray must have been called first to fill the 141 * location offsets. 142 * @num_channels: number of channels 143 **/ 144void process_scan(char *data, 145 struct iio_channel_info *channels, 146 int num_channels) 147{ 148 int k; 149 150 for (k = 0; k < num_channels; k++) 151 switch (channels[k].bytes) { 152 /* only a few cases implemented so far */ 153 case 2: 154 print2byte(*(uint16_t *)(data + channels[k].location), 155 &channels[k]); 156 break; 157 case 4: 158 print4byte(*(uint32_t *)(data + channels[k].location), 159 &channels[k]); 160 break; 161 case 8: 162 print8byte(*(uint64_t *)(data + channels[k].location), 163 &channels[k]); 164 break; 165 default: 166 break; 167 } 168 printf("\n"); 169} 170 171void print_usage(void) 172{ 173 printf("Usage: generic_buffer [options]...\n" 174 "Capture, convert and output data from IIO device buffer\n" 175 " -c <n> Do n conversions\n" 176 " -e Disable wait for event (new data)\n" 177 " -g Use trigger-less mode\n" 178 " -l <n> Set buffer length to n samples\n" 179 " -n <name> Set device name (mandatory)\n" 180 " -t <name> Set trigger name\n" 181 " -w <n> Set delay between reads in us (event-less mode)\n"); 182} 183 184int main(int argc, char **argv) 185{ 186 unsigned long num_loops = 2; 187 unsigned long timedelay = 1000000; 188 unsigned long buf_len = 128; 189 190 int ret, c, i, j, toread; 191 int fp; 192 193 int num_channels; 194 char *trigger_name = NULL, *device_name = NULL; 195 char *dev_dir_name, *buf_dir_name; 196 197 int datardytrigger = 1; 198 char *data; 199 ssize_t read_size; 200 int dev_num, trig_num; 201 char *buffer_access; 202 int scan_size; 203 int noevents = 0; 204 int notrigger = 0; 205 char *dummy; 206 207 struct iio_channel_info *channels; 208 209 while ((c = getopt(argc, argv, "c:egl:n:t:w:")) != -1) { 210 switch (c) { 211 case 'c': 212 errno = 0; 213 num_loops = strtoul(optarg, &dummy, 10); 214 if (errno) 215 return -errno; 216 break; 217 case 'e': 218 noevents = 1; 219 break; 220 case 'g': 221 notrigger = 1; 222 break; 223 case 'l': 224 errno = 0; 225 buf_len = strtoul(optarg, &dummy, 10); 226 if (errno) 227 return -errno; 228 break; 229 case 'n': 230 device_name = optarg; 231 break; 232 case 't': 233 trigger_name = optarg; 234 datardytrigger = 0; 235 break; 236 case 'w': 237 errno = 0; 238 timedelay = strtoul(optarg, &dummy, 10); 239 if (errno) 240 return -errno; 241 break; 242 case '?': 243 print_usage(); 244 return -1; 245 } 246 } 247 248 if (device_name == NULL) { 249 printf("Device name not set\n"); 250 print_usage(); 251 return -1; 252 } 253 254 /* Find the device requested */ 255 dev_num = find_type_by_name(device_name, "iio:device"); 256 if (dev_num < 0) { 257 printf("Failed to find the %s\n", device_name); 258 return dev_num; 259 } 260 printf("iio device number being used is %d\n", dev_num); 261 262 ret = asprintf(&dev_dir_name, "%siio:device%d", iio_dir, dev_num); 263 if (ret < 0) 264 return -ENOMEM; 265 266 if (!notrigger) { 267 if (trigger_name == NULL) { 268 /* 269 * Build the trigger name. If it is device associated 270 * its name is <device_name>_dev[n] where n matches 271 * the device number found above. 272 */ 273 ret = asprintf(&trigger_name, 274 "%s-dev%d", device_name, dev_num); 275 if (ret < 0) { 276 ret = -ENOMEM; 277 goto error_free_dev_dir_name; 278 } 279 } 280 281 /* Verify the trigger exists */ 282 trig_num = find_type_by_name(trigger_name, "trigger"); 283 if (trig_num < 0) { 284 printf("Failed to find the trigger %s\n", trigger_name); 285 ret = trig_num; 286 goto error_free_triggername; 287 } 288 printf("iio trigger number being used is %d\n", trig_num); 289 } else 290 printf("trigger-less mode selected\n"); 291 292 /* 293 * Parse the files in scan_elements to identify what channels are 294 * present 295 */ 296 ret = build_channel_array(dev_dir_name, &channels, &num_channels); 297 if (ret) { 298 printf("Problem reading scan element information\n"); 299 printf("diag %s\n", dev_dir_name); 300 goto error_free_triggername; 301 } 302 303 /* 304 * Construct the directory name for the associated buffer. 305 * As we know that the lis3l02dq has only one buffer this may 306 * be built rather than found. 307 */ 308 ret = asprintf(&buf_dir_name, 309 "%siio:device%d/buffer", iio_dir, dev_num); 310 if (ret < 0) { 311 ret = -ENOMEM; 312 goto error_free_channels; 313 } 314 315 if (!notrigger) { 316 printf("%s %s\n", dev_dir_name, trigger_name); 317 /* Set the device trigger to be the data ready trigger found 318 * above */ 319 ret = write_sysfs_string_and_verify("trigger/current_trigger", 320 dev_dir_name, 321 trigger_name); 322 if (ret < 0) { 323 printf("Failed to write current_trigger file\n"); 324 goto error_free_buf_dir_name; 325 } 326 } 327 328 /* Setup ring buffer parameters */ 329 ret = write_sysfs_int("length", buf_dir_name, buf_len); 330 if (ret < 0) 331 goto error_free_buf_dir_name; 332 333 /* Enable the buffer */ 334 ret = write_sysfs_int("enable", buf_dir_name, 1); 335 if (ret < 0) 336 goto error_free_buf_dir_name; 337 scan_size = size_from_channelarray(channels, num_channels); 338 data = malloc(scan_size*buf_len); 339 if (!data) { 340 ret = -ENOMEM; 341 goto error_free_buf_dir_name; 342 } 343 344 ret = asprintf(&buffer_access, "/dev/iio:device%d", dev_num); 345 if (ret < 0) { 346 ret = -ENOMEM; 347 goto error_free_data; 348 } 349 350 /* Attempt to open non blocking the access dev */ 351 fp = open(buffer_access, O_RDONLY | O_NONBLOCK); 352 if (fp == -1) { /* If it isn't there make the node */ 353 ret = -errno; 354 printf("Failed to open %s\n", buffer_access); 355 goto error_free_buffer_access; 356 } 357 358 /* Wait for events 10 times */ 359 for (j = 0; j < num_loops; j++) { 360 if (!noevents) { 361 struct pollfd pfd = { 362 .fd = fp, 363 .events = POLLIN, 364 }; 365 366 ret = poll(&pfd, 1, -1); 367 if (ret < 0) { 368 ret = -errno; 369 goto error_close_buffer_access; 370 } else if (ret == 0) { 371 continue; 372 } 373 374 toread = buf_len; 375 376 } else { 377 usleep(timedelay); 378 toread = 64; 379 } 380 381 read_size = read(fp, 382 data, 383 toread*scan_size); 384 if (read_size < 0) { 385 if (errno == EAGAIN) { 386 printf("nothing available\n"); 387 continue; 388 } else 389 break; 390 } 391 for (i = 0; i < read_size/scan_size; i++) 392 process_scan(data + scan_size*i, 393 channels, 394 num_channels); 395 } 396 397 /* Stop the buffer */ 398 ret = write_sysfs_int("enable", buf_dir_name, 0); 399 if (ret < 0) 400 goto error_close_buffer_access; 401 402 if (!notrigger) 403 /* Disconnect the trigger - just write a dummy name. */ 404 ret = write_sysfs_string("trigger/current_trigger", 405 dev_dir_name, "NULL"); 406 if (ret < 0) 407 printf("Failed to write to %s\n", dev_dir_name); 408 409error_close_buffer_access: 410 if (close(fp) == -1) 411 perror("Failed to close buffer"); 412error_free_buffer_access: 413 free(buffer_access); 414error_free_data: 415 free(data); 416error_free_buf_dir_name: 417 free(buf_dir_name); 418error_free_channels: 419 for (i = num_channels - 1; i >= 0; i--) { 420 free(channels[i].name); 421 free(channels[i].generic_name); 422 } 423 free(channels); 424error_free_triggername: 425 if (datardytrigger) 426 free(trigger_name); 427error_free_dev_dir_name: 428 free(dev_dir_name); 429 430 return ret; 431}