1/* Industrialio ring buffer with a lis3l02dq accelerometer 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 */ 11 12#include <dirent.h> 13#include <fcntl.h> 14#include <stdio.h> 15#include <errno.h> 16#include <sys/stat.h> 17#include <sys/dir.h> 18#include <linux/types.h> 19#include "iio_utils.h" 20 21const char *device_name = "lis3l02dq"; 22const char *trigger_name_base = "lis3l02dq-dev"; 23const int num_vals = 3; 24const int scan_ts = 1; 25const int buf_len = 128; 26const int num_loops = 10; 27 28/* 29 * Could get this from ring bps, but only after starting the ring 30 * which is a bit late for it to be useful. 31 * 32 * Todo: replace with much more generic version based on scan_elements 33 * directory. 34 */ 35int size_from_scanmode(int num_vals, int timestamp) 36{ 37 if (num_vals && timestamp) 38 return 16; 39 else if (timestamp) 40 return 8; 41 else 42 return num_vals*2; 43} 44 45int main(int argc, char **argv) 46{ 47 int ret; 48 int i, j, k, toread; 49 FILE *fp_ev; 50 int fp; 51 52 char *trigger_name, *dev_dir_name, *buf_dir_name; 53 char *data; 54 size_t read_size; 55 struct iio_event_data dat; 56 int dev_num, trig_num; 57 58 char *buffer_access, *buffer_event; 59 const char *iio_dir = "/sys/bus/iio/devices/"; 60 int scan_size; 61 float gain = 1; 62 63 64 /* Find out which iio device is the accelerometer. */ 65 dev_num = find_type_by_name(device_name, "device"); 66 if (dev_num < 0) { 67 printf("Failed to find the %s\n", device_name); 68 ret = -ENODEV; 69 goto error_ret; 70 } 71 printf("iio device number being used is %d\n", dev_num); 72 asprintf(&dev_dir_name, "%sdevice%d", iio_dir, dev_num); 73 74 /* 75 * Build the trigger name. 76 * In this case we want the lis3l02dq's data ready trigger 77 * for this lis3l02dq. The naming is lis3l02dq_dev[n], where 78 * n matches the device number found above. 79 */ 80 ret = asprintf(&trigger_name, "%s%d", trigger_name_base, dev_num); 81 if (ret < 0) { 82 ret = -ENOMEM; 83 goto error_free_dev_dir_name; 84 } 85 86 /* 87 * Find the trigger by name. 88 * This is techically unecessary here as we only need to 89 * refer to the trigger by name and that name is already 90 * known. 91 */ 92 trig_num = find_type_by_name(trigger_name, "trigger"); 93 if (trig_num < 0) { 94 printf("Failed to find the %s\n", trigger_name); 95 ret = -ENODEV; 96 goto error_free_triggername; 97 } 98 printf("iio trigger number being used is %d\n", trig_num); 99 100 /* 101 * Read in the scale value - in a more generic case, first 102 * check for accel_scale, then the indivual channel scales 103 */ 104 ret = read_sysfs_float("accel_scale", dev_dir_name, &gain); 105 if (ret) 106 goto error_free_triggername;; 107 108 /* 109 * Construct the directory name for the associated buffer. 110 * As we know that the lis3l02dq has only one buffer this may 111 * be built rather than found. 112 */ 113 ret = asprintf(&buf_dir_name, "%sdevice%d:buffer0", iio_dir, dev_num); 114 if (ret < 0) { 115 ret = -ENOMEM; 116 goto error_free_triggername; 117 } 118 /* Set the device trigger to be the data rdy trigger found above */ 119 ret = write_sysfs_string_and_verify("trigger/current_trigger", 120 dev_dir_name, 121 trigger_name); 122 if (ret < 0) { 123 printf("Failed to write current_trigger file\n"); 124 goto error_free_buf_dir_name; 125 } 126 127 /* Setup ring buffer parameters */ 128 ret = write_sysfs_int("length", buf_dir_name, buf_len); 129 if (ret < 0) 130 goto error_free_buf_dir_name; 131 132 /* Enable the buffer */ 133 ret = write_sysfs_int("ring_enable", buf_dir_name, 1); 134 if (ret < 0) 135 goto error_free_buf_dir_name; 136 137 data = malloc(size_from_scanmode(num_vals, scan_ts)*buf_len); 138 if (!data) { 139 ret = -ENOMEM; 140 goto error_free_buf_dir_name; 141 } 142 143 ret = asprintf(&buffer_access, 144 "/dev/device%d:buffer0:access0", 145 dev_num); 146 if (ret < 0) { 147 ret = -ENOMEM; 148 goto error_free_data; 149 } 150 151 ret = asprintf(&buffer_event, "/dev/device%d:buffer0:event0", dev_num); 152 if (ret < 0) { 153 ret = -ENOMEM; 154 goto error_free_data; 155 } 156 /* Attempt to open non blocking the access dev */ 157 fp = open(buffer_access, O_RDONLY | O_NONBLOCK); 158 if (fp == -1) { /*If it isn't there make the node */ 159 printf("Failed to open %s\n", buffer_access); 160 ret = -errno; 161 goto error_free_buffer_event; 162 } 163 /* Attempt to open the event access dev (blocking this time) */ 164 fp_ev = fopen(buffer_event, "rb"); 165 if (fp_ev == NULL) { 166 printf("Failed to open %s\n", buffer_event); 167 ret = -errno; 168 goto error_close_buffer_access; 169 } 170 171 /* Wait for events 10 times */ 172 for (j = 0; j < num_loops; j++) { 173 read_size = fread(&dat, 1, sizeof(struct iio_event_data), 174 fp_ev); 175 switch (dat.id) { 176 case IIO_EVENT_CODE_RING_100_FULL: 177 toread = buf_len; 178 break; 179 case IIO_EVENT_CODE_RING_75_FULL: 180 toread = buf_len*3/4; 181 break; 182 case IIO_EVENT_CODE_RING_50_FULL: 183 toread = buf_len/2; 184 break; 185 default: 186 printf("Unexpecteded event code\n"); 187 continue; 188 } 189 read_size = read(fp, 190 data, 191 toread*size_from_scanmode(num_vals, scan_ts)); 192 if (read_size == -EAGAIN) { 193 printf("nothing available\n"); 194 continue; 195 } 196 scan_size = size_from_scanmode(num_vals, scan_ts); 197 for (i = 0; i < read_size/scan_size; i++) { 198 for (k = 0; k < num_vals; k++) { 199 __s16 val = *(__s16 *)(&data[i*scan_size 200 + (k)*2]); 201 printf("%05f ", (float)val*gain); 202 } 203 printf(" %lld\n", 204 *(__s64 *)(&data[(i + 1) 205 *size_from_scanmode(num_vals, 206 scan_ts) 207 - sizeof(__s64)])); 208 } 209 } 210 211 /* Stop the ring buffer */ 212 ret = write_sysfs_int("ring_enable", buf_dir_name, 0); 213 if (ret < 0) 214 goto error_close_buffer_event; 215 216 /* Disconnect from the trigger - just write a dummy name.*/ 217 write_sysfs_string("trigger/current_trigger", 218 dev_dir_name, "NULL"); 219 220error_close_buffer_event: 221 fclose(fp_ev); 222error_close_buffer_access: 223 close(fp); 224error_free_data: 225 free(data); 226error_free_buffer_access: 227 free(buffer_access); 228error_free_buffer_event: 229 free(buffer_event); 230error_free_buf_dir_name: 231 free(buf_dir_name); 232error_free_triggername: 233 free(trigger_name); 234error_free_dev_dir_name: 235 free(dev_dir_name); 236error_ret: 237 return ret; 238} 239