generic_buffer.c revision 1d633fd153844c8e954b0b72789279bf588cd025
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 <dirent.h> 23#include <fcntl.h> 24#include <stdio.h> 25#include <errno.h> 26#include <sys/stat.h> 27#include <sys/dir.h> 28#include <linux/types.h> 29#include <string.h> 30#include <poll.h> 31#include <endian.h> 32#include "iio_utils.h" 33 34/** 35 * size_from_channelarray() - calculate the storage size of a scan 36 * @channels: the channel info array 37 * @num_channels: size of the channel info array 38 * 39 * Has the side effect of filling the channels[i].location values used 40 * in processing the buffer output. 41 **/ 42int size_from_channelarray(struct iio_channel_info *channels, int num_channels) 43{ 44 int bytes = 0; 45 int i = 0; 46 while (i < num_channels) { 47 if (bytes % channels[i].bytes == 0) 48 channels[i].location = bytes; 49 else 50 channels[i].location = bytes - bytes%channels[i].bytes 51 + channels[i].bytes; 52 bytes = channels[i].location + channels[i].bytes; 53 i++; 54 } 55 return bytes; 56} 57 58void print2byte(int input, struct iio_channel_info *info) 59{ 60 /* First swap if incorrect endian */ 61 62 if (info->be) 63 input = be16toh((uint16_t)input); 64 else 65 input = le16toh((uint16_t)input); 66 67 /* shift before conversion to avoid sign extension 68 of left aligned data */ 69 input = input >> info->shift; 70 if (info->is_signed) { 71 int16_t val = input; 72 val &= (1 << info->bits_used) - 1; 73 val = (int16_t)(val << (16 - info->bits_used)) >> 74 (16 - info->bits_used); 75 printf("%05f ", ((float)val + info->offset)*info->scale); 76 } else { 77 uint16_t val = input; 78 val &= (1 << info->bits_used) - 1; 79 printf("%05f ", ((float)val + info->offset)*info->scale); 80 } 81} 82/** 83 * process_scan() - print out the values in SI units 84 * @data: pointer to the start of the scan 85 * @infoarray: information about the channels. Note 86 * size_from_channelarray must have been called first to fill the 87 * location offsets. 88 * @num_channels: the number of active channels 89 **/ 90void process_scan(char *data, 91 struct iio_channel_info *infoarray, 92 int num_channels) 93{ 94 int k; 95 for (k = 0; k < num_channels; k++) 96 switch (infoarray[k].bytes) { 97 /* only a few cases implemented so far */ 98 case 2: 99 print2byte(*(uint16_t *)(data + infoarray[k].location), 100 &infoarray[k]); 101 break; 102 case 8: 103 if (infoarray[k].is_signed) { 104 int64_t val = *(int64_t *) 105 (data + 106 infoarray[k].location); 107 if ((val >> infoarray[k].bits_used) & 1) 108 val = (val & infoarray[k].mask) | 109 ~infoarray[k].mask; 110 /* special case for timestamp */ 111 if (infoarray[k].scale == 1.0f && 112 infoarray[k].offset == 0.0f) 113 printf(" %lld", val); 114 else 115 printf("%05f ", ((float)val + 116 infoarray[k].offset)* 117 infoarray[k].scale); 118 } 119 break; 120 default: 121 break; 122 } 123 printf("\n"); 124} 125 126int main(int argc, char **argv) 127{ 128 unsigned long num_loops = 2; 129 unsigned long timedelay = 1000000; 130 unsigned long buf_len = 128; 131 132 133 int ret, c, i, j, toread; 134 135 FILE *fp_ev; 136 int fp; 137 138 int num_channels; 139 char *trigger_name = NULL, *device_name = NULL; 140 char *dev_dir_name, *buf_dir_name; 141 142 int datardytrigger = 1; 143 char *data; 144 ssize_t read_size; 145 int dev_num, trig_num; 146 char *buffer_access; 147 int scan_size; 148 int noevents = 0; 149 char *dummy; 150 151 struct iio_channel_info *infoarray; 152 153 while ((c = getopt(argc, argv, "l:w:c:et:n:")) != -1) { 154 switch (c) { 155 case 'n': 156 device_name = optarg; 157 break; 158 case 't': 159 trigger_name = optarg; 160 datardytrigger = 0; 161 break; 162 case 'e': 163 noevents = 1; 164 break; 165 case 'c': 166 num_loops = strtoul(optarg, &dummy, 10); 167 break; 168 case 'w': 169 timedelay = strtoul(optarg, &dummy, 10); 170 break; 171 case 'l': 172 buf_len = strtoul(optarg, &dummy, 10); 173 break; 174 case '?': 175 return -1; 176 } 177 } 178 179 if (device_name == NULL) 180 return -1; 181 182 /* Find the device requested */ 183 dev_num = find_type_by_name(device_name, "iio:device"); 184 if (dev_num < 0) { 185 printf("Failed to find the %s\n", device_name); 186 ret = -ENODEV; 187 goto error_ret; 188 } 189 printf("iio device number being used is %d\n", dev_num); 190 191 asprintf(&dev_dir_name, "%siio:device%d", iio_dir, dev_num); 192 if (trigger_name == NULL) { 193 /* 194 * Build the trigger name. If it is device associated it's 195 * name is <device_name>_dev[n] where n matches the device 196 * number found above 197 */ 198 ret = asprintf(&trigger_name, 199 "%s-dev%d", device_name, dev_num); 200 if (ret < 0) { 201 ret = -ENOMEM; 202 goto error_ret; 203 } 204 } 205 206 /* Verify the trigger exists */ 207 trig_num = find_type_by_name(trigger_name, "trigger"); 208 if (trig_num < 0) { 209 printf("Failed to find the trigger %s\n", trigger_name); 210 ret = -ENODEV; 211 goto error_free_triggername; 212 } 213 printf("iio trigger number being used is %d\n", trig_num); 214 215 /* 216 * Parse the files in scan_elements to identify what channels are 217 * present 218 */ 219 ret = build_channel_array(dev_dir_name, &infoarray, &num_channels); 220 if (ret) { 221 printf("Problem reading scan element information\n"); 222 printf("diag %s\n", dev_dir_name); 223 goto error_free_triggername; 224 } 225 226 /* 227 * Construct the directory name for the associated buffer. 228 * As we know that the lis3l02dq has only one buffer this may 229 * be built rather than found. 230 */ 231 ret = asprintf(&buf_dir_name, 232 "%siio:device%d/buffer", iio_dir, dev_num); 233 if (ret < 0) { 234 ret = -ENOMEM; 235 goto error_free_triggername; 236 } 237 printf("%s %s\n", dev_dir_name, trigger_name); 238 /* Set the device trigger to be the data rdy trigger found above */ 239 ret = write_sysfs_string_and_verify("trigger/current_trigger", 240 dev_dir_name, 241 trigger_name); 242 if (ret < 0) { 243 printf("Failed to write current_trigger file\n"); 244 goto error_free_buf_dir_name; 245 } 246 247 /* Setup ring buffer parameters */ 248 ret = write_sysfs_int("length", buf_dir_name, buf_len); 249 if (ret < 0) 250 goto error_free_buf_dir_name; 251 252 /* Enable the buffer */ 253 ret = write_sysfs_int("enable", buf_dir_name, 1); 254 if (ret < 0) 255 goto error_free_buf_dir_name; 256 scan_size = size_from_channelarray(infoarray, num_channels); 257 data = malloc(scan_size*buf_len); 258 if (!data) { 259 ret = -ENOMEM; 260 goto error_free_buf_dir_name; 261 } 262 263 ret = asprintf(&buffer_access, "/dev/iio:device%d", dev_num); 264 if (ret < 0) { 265 ret = -ENOMEM; 266 goto error_free_data; 267 } 268 269 /* Attempt to open non blocking the access dev */ 270 fp = open(buffer_access, O_RDONLY | O_NONBLOCK); 271 if (fp == -1) { /*If it isn't there make the node */ 272 printf("Failed to open %s\n", buffer_access); 273 ret = -errno; 274 goto error_free_buffer_access; 275 } 276 277 /* Wait for events 10 times */ 278 for (j = 0; j < num_loops; j++) { 279 if (!noevents) { 280 struct pollfd pfd = { 281 .fd = fp, 282 .events = POLLIN, 283 }; 284 285 poll(&pfd, 1, -1); 286 toread = buf_len; 287 288 } else { 289 usleep(timedelay); 290 toread = 64; 291 } 292 293 read_size = read(fp, 294 data, 295 toread*scan_size); 296 if (read_size == -EAGAIN) { 297 printf("nothing available\n"); 298 continue; 299 } 300 for (i = 0; i < read_size/scan_size; i++) 301 process_scan(data + scan_size*i, 302 infoarray, 303 num_channels); 304 } 305 306 /* Stop the ring buffer */ 307 ret = write_sysfs_int("enable", buf_dir_name, 0); 308 if (ret < 0) 309 goto error_close_buffer_access; 310 311 /* Disconnect from the trigger - just write a dummy name.*/ 312 write_sysfs_string("trigger/current_trigger", 313 dev_dir_name, "NULL"); 314 315error_close_buffer_access: 316 close(fp); 317error_free_data: 318 free(data); 319error_free_buffer_access: 320 free(buffer_access); 321error_free_buf_dir_name: 322 free(buf_dir_name); 323error_free_triggername: 324 if (datardytrigger) 325 free(trigger_name); 326error_ret: 327 return ret; 328} 329