Commit e58537cc authored by Jonathan Cameron's avatar Jonathan Cameron Committed by Greg Kroah-Hartman

staging: iio: update example application.

The application is now considerably more generic and should cope
with all devices in tree.  The process function will need to be
extended to handle other type values as needed.
Signed-off-by: default avatarJonathan Cameron <jic23@cam.ac.uk>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@suse.de>
parent 1755b0ae
/* Industrialio ring buffer with a lis3l02dq accelerometer
/* Industrialio buffer test code.
*
* Copyright (c) 2008 Jonathan Cameron
*
......@@ -7,8 +7,18 @@
* the Free Software Foundation.
*
* This program is primarily intended as an example application.
* Reads the current buffer setup from sysfs and starts a short capture
* from the specified device, pretty printing the result after appropriate
* conversion.
*
* Command line parameters
* generic_buffer -n <device_name> -t <trigger_name>
* If trigger name is not specified the program assumes you want a dataready
* trigger associated with the device and goes looking for it.
*
*/
#include <unistd.h>
#include <dirent.h>
#include <fcntl.h>
#include <stdio.h>
......@@ -18,50 +28,130 @@
#include <linux/types.h>
#include "iio_utils.h"
const char *device_name = "lis3l02dq";
const char *trigger_name_base = "lis3l02dq-dev";
const int num_vals = 3;
const int scan_ts = 1;
const int buf_len = 128;
const int num_loops = 10;
const int num_loops = 2;
/*
* Could get this from ring bps, but only after starting the ring
* which is a bit late for it to be useful.
/**
* size_from_channelarray() - calculate the storage size of a scan
* @channels: the channel info array
* @num_channels: size of the channel info array
*
* Todo: replace with much more generic version based on scan_elements
* directory.
*/
int size_from_scanmode(int num_vals, int timestamp)
* Has the side effect of filling the channels[i].location values used
* in processing the buffer output.
**/
int size_from_channelarray(struct iio_channel_info *channels, int num_channels)
{
if (num_vals && timestamp)
return 16;
else if (timestamp)
return 8;
int bytes = 0;
int i = 0;
while (i < num_channels) {
if (bytes % channels[i].bytes == 0)
channels[i].location = bytes;
else
channels[i].location = bytes - bytes%channels[i].bytes
+ channels[i].bytes;
bytes = channels[i].location + channels[i].bytes;
i++;
}
return bytes;
}
/**
* process_scan() - print out the values in SI units
* @data: pointer to the start of the scan
* @infoarray: information about the channels. Note
* size_from_channelarray must have been called first to fill the
* location offsets.
* @num_channels: the number of active channels
**/
void process_scan(char *data,
struct iio_channel_info *infoarray,
int num_channels)
{
int k;
for (k = 0; k < num_channels; k++)
switch (infoarray[k].bytes) {
/* only a few cases implemented so far */
case 2:
if (infoarray[k].is_signed) {
int16_t val = *(int16_t *)
(data
+ infoarray[k].location);
if ((val >> infoarray[k].bits_used) & 1)
val = (val & infoarray[k].mask) |
~infoarray[k].mask;
printf("%05f ", ((float)val +
infoarray[k].offset)*
infoarray[k].scale);
} else {
uint16_t val = *(uint16_t *)
(data +
infoarray[k].location);
val = (val & infoarray[k].mask);
printf("%05f ", ((float)val +
infoarray[k].offset)*
infoarray[k].scale);
}
break;
case 8:
if (infoarray[k].is_signed) {
int64_t val = *(int64_t *)
(data +
infoarray[k].location);
if ((val >> infoarray[k].bits_used) & 1)
val = (val & infoarray[k].mask) |
~infoarray[k].mask;
/* special case for timestamp */
if (infoarray[k].scale == 1.0f &&
infoarray[k].offset == 0.0f)
printf(" %lld", val);
else
return num_vals*2;
printf("%05f ", ((float)val +
infoarray[k].offset)*
infoarray[k].scale);
}
break;
default:
break;
}
printf("\n");
}
int main(int argc, char **argv)
{
int ret;
int i, j, k, toread;
int ret, c, i, j, toread;
FILE *fp_ev;
int fp;
char *trigger_name, *dev_dir_name, *buf_dir_name;
int num_channels;
char *trigger_name = NULL, *device_name = NULL;
char *dev_dir_name, *buf_dir_name;
int datardytrigger = 1;
char *data;
size_t read_size;
struct iio_event_data dat;
int dev_num, trig_num;
char *buffer_access, *buffer_event;
const char *iio_dir = "/sys/bus/iio/devices/";
int scan_size;
float gain = 1;
struct iio_channel_info *infoarray;
/* Find out which iio device is the accelerometer. */
while ((c = getopt(argc, argv, "t:n:")) != -1) {
switch (c) {
case 'n':
device_name = optarg;
break;
case 't':
trigger_name = optarg;
datardytrigger = 0;
break;
case '?':
return -1;
}
}
/* Find the device requested */
dev_num = find_type_by_name(device_name, "device");
if (dev_num < 0) {
printf("Failed to find the %s\n", device_name);
......@@ -69,41 +159,40 @@ int main(int argc, char **argv)
goto error_ret;
}
printf("iio device number being used is %d\n", dev_num);
asprintf(&dev_dir_name, "%sdevice%d", iio_dir, dev_num);
asprintf(&dev_dir_name, "%sdevice%d", iio_dir, dev_num);
if (trigger_name == NULL) {
/*
* Build the trigger name.
* In this case we want the lis3l02dq's data ready trigger
* for this lis3l02dq. The naming is lis3l02dq_dev[n], where
* n matches the device number found above.
* Build the trigger name. If it is device associated it's
* name is <device_name>_dev[n] where n matches the device
* number found above
*/
ret = asprintf(&trigger_name, "%s%d", trigger_name_base, dev_num);
ret = asprintf(&trigger_name,
"%s-dev%d", device_name, dev_num);
if (ret < 0) {
ret = -ENOMEM;
goto error_free_dev_dir_name;
goto error_ret;
}
}
/*
* Find the trigger by name.
* This is techically unecessary here as we only need to
* refer to the trigger by name and that name is already
* known.
*/
/* Verify the trigger exists */
trig_num = find_type_by_name(trigger_name, "trigger");
if (trig_num < 0) {
printf("Failed to find the %s\n", trigger_name);
printf("Failed to find the trigger %s\n", trigger_name);
ret = -ENODEV;
goto error_free_triggername;
}
printf("iio trigger number being used is %d\n", trig_num);
/*
* Read in the scale value - in a more generic case, first
* check for accel_scale, then the indivual channel scales
* Parse the files in scan_elements to identify what channels are
* present
*/
ret = read_sysfs_float("accel_scale", dev_dir_name, &gain);
if (ret)
goto error_free_triggername;;
ret = build_channel_array(dev_dir_name, &infoarray, &num_channels);
if (ret) {
printf("Problem reading scan element information \n");
goto error_free_triggername;
}
/*
* Construct the directory name for the associated buffer.
......@@ -115,6 +204,7 @@ int main(int argc, char **argv)
ret = -ENOMEM;
goto error_free_triggername;
}
printf("%s %s\n", dev_dir_name, trigger_name);
/* Set the device trigger to be the data rdy trigger found above */
ret = write_sysfs_string_and_verify("trigger/current_trigger",
dev_dir_name,
......@@ -133,8 +223,8 @@ int main(int argc, char **argv)
ret = write_sysfs_int("enable", buf_dir_name, 1);
if (ret < 0)
goto error_free_buf_dir_name;
data = malloc(size_from_scanmode(num_vals, scan_ts)*buf_len);
scan_size = size_from_channelarray(infoarray, num_channels);
data = malloc(scan_size*buf_len);
if (!data) {
ret = -ENOMEM;
goto error_free_buf_dir_name;
......@@ -151,7 +241,7 @@ int main(int argc, char **argv)
ret = asprintf(&buffer_event, "/dev/device%d:buffer0:event0", dev_num);
if (ret < 0) {
ret = -ENOMEM;
goto error_free_data;
goto error_free_buffer_access;
}
/* Attempt to open non blocking the access dev */
fp = open(buffer_access, O_RDONLY | O_NONBLOCK);
......@@ -188,24 +278,15 @@ int main(int argc, char **argv)
}
read_size = read(fp,
data,
toread*size_from_scanmode(num_vals, scan_ts));
toread*scan_size);
if (read_size == -EAGAIN) {
printf("nothing available\n");
continue;
}
scan_size = size_from_scanmode(num_vals, scan_ts);
for (i = 0; i < read_size/scan_size; i++) {
for (k = 0; k < num_vals; k++) {
__s16 val = *(__s16 *)(&data[i*scan_size
+ (k)*2]);
printf("%05f ", (float)val*gain);
}
printf(" %lld\n",
*(__s64 *)(&data[(i + 1)
*size_from_scanmode(num_vals,
scan_ts)
- sizeof(__s64)]));
}
for (i = 0; i < read_size/scan_size; i++)
process_scan(data + scan_size*i,
infoarray,
num_channels);
}
/* Stop the ring buffer */
......@@ -230,9 +311,8 @@ int main(int argc, char **argv)
error_free_buf_dir_name:
free(buf_dir_name);
error_free_triggername:
if (datardytrigger)
free(trigger_name);
error_free_dev_dir_name:
free(dev_dir_name);
error_ret:
return ret;
}
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment