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