18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only
28c2ecf20Sopenharmony_ci/* Industrialio buffer test code.
38c2ecf20Sopenharmony_ci *
48c2ecf20Sopenharmony_ci * Copyright (c) 2008 Jonathan Cameron
58c2ecf20Sopenharmony_ci *
68c2ecf20Sopenharmony_ci * This program is primarily intended as an example application.
78c2ecf20Sopenharmony_ci * Reads the current buffer setup from sysfs and starts a short capture
88c2ecf20Sopenharmony_ci * from the specified device, pretty printing the result after appropriate
98c2ecf20Sopenharmony_ci * conversion.
108c2ecf20Sopenharmony_ci *
118c2ecf20Sopenharmony_ci * Command line parameters
128c2ecf20Sopenharmony_ci * generic_buffer -n <device_name> -t <trigger_name>
138c2ecf20Sopenharmony_ci * If trigger name is not specified the program assumes you want a dataready
148c2ecf20Sopenharmony_ci * trigger associated with the device and goes looking for it.
158c2ecf20Sopenharmony_ci */
168c2ecf20Sopenharmony_ci
178c2ecf20Sopenharmony_ci#include <unistd.h>
188c2ecf20Sopenharmony_ci#include <stdlib.h>
198c2ecf20Sopenharmony_ci#include <dirent.h>
208c2ecf20Sopenharmony_ci#include <fcntl.h>
218c2ecf20Sopenharmony_ci#include <stdio.h>
228c2ecf20Sopenharmony_ci#include <errno.h>
238c2ecf20Sopenharmony_ci#include <sys/stat.h>
248c2ecf20Sopenharmony_ci#include <sys/dir.h>
258c2ecf20Sopenharmony_ci#include <linux/types.h>
268c2ecf20Sopenharmony_ci#include <string.h>
278c2ecf20Sopenharmony_ci#include <poll.h>
288c2ecf20Sopenharmony_ci#include <endian.h>
298c2ecf20Sopenharmony_ci#include <getopt.h>
308c2ecf20Sopenharmony_ci#include <inttypes.h>
318c2ecf20Sopenharmony_ci#include <stdbool.h>
328c2ecf20Sopenharmony_ci#include <signal.h>
338c2ecf20Sopenharmony_ci#include "iio_utils.h"
348c2ecf20Sopenharmony_ci
358c2ecf20Sopenharmony_ci/**
368c2ecf20Sopenharmony_ci * enum autochan - state for the automatic channel enabling mechanism
378c2ecf20Sopenharmony_ci */
388c2ecf20Sopenharmony_cienum autochan {
398c2ecf20Sopenharmony_ci	AUTOCHANNELS_DISABLED,
408c2ecf20Sopenharmony_ci	AUTOCHANNELS_ENABLED,
418c2ecf20Sopenharmony_ci	AUTOCHANNELS_ACTIVE,
428c2ecf20Sopenharmony_ci};
438c2ecf20Sopenharmony_ci
448c2ecf20Sopenharmony_ci/**
458c2ecf20Sopenharmony_ci * size_from_channelarray() - calculate the storage size of a scan
468c2ecf20Sopenharmony_ci * @channels:		the channel info array
478c2ecf20Sopenharmony_ci * @num_channels:	number of channels
488c2ecf20Sopenharmony_ci *
498c2ecf20Sopenharmony_ci * Has the side effect of filling the channels[i].location values used
508c2ecf20Sopenharmony_ci * in processing the buffer output.
518c2ecf20Sopenharmony_ci **/
528c2ecf20Sopenharmony_cistatic unsigned int size_from_channelarray(struct iio_channel_info *channels, int num_channels)
538c2ecf20Sopenharmony_ci{
548c2ecf20Sopenharmony_ci	unsigned int bytes = 0;
558c2ecf20Sopenharmony_ci	int i = 0, max = 0;
568c2ecf20Sopenharmony_ci	unsigned int misalignment;
578c2ecf20Sopenharmony_ci
588c2ecf20Sopenharmony_ci	while (i < num_channels) {
598c2ecf20Sopenharmony_ci		if (channels[i].bytes > max)
608c2ecf20Sopenharmony_ci			max = channels[i].bytes;
618c2ecf20Sopenharmony_ci		if (bytes % channels[i].bytes == 0)
628c2ecf20Sopenharmony_ci			channels[i].location = bytes;
638c2ecf20Sopenharmony_ci		else
648c2ecf20Sopenharmony_ci			channels[i].location = bytes - bytes % channels[i].bytes
658c2ecf20Sopenharmony_ci					       + channels[i].bytes;
668c2ecf20Sopenharmony_ci
678c2ecf20Sopenharmony_ci		bytes = channels[i].location + channels[i].bytes;
688c2ecf20Sopenharmony_ci		i++;
698c2ecf20Sopenharmony_ci	}
708c2ecf20Sopenharmony_ci	/*
718c2ecf20Sopenharmony_ci	 * We want the data in next sample to also be properly aligned so
728c2ecf20Sopenharmony_ci	 * we'll add padding at the end if needed. Adding padding only
738c2ecf20Sopenharmony_ci	 * works for channel data which size is 2^n bytes.
748c2ecf20Sopenharmony_ci	 */
758c2ecf20Sopenharmony_ci	misalignment = bytes % max;
768c2ecf20Sopenharmony_ci	if (misalignment)
778c2ecf20Sopenharmony_ci		bytes += max - misalignment;
788c2ecf20Sopenharmony_ci
798c2ecf20Sopenharmony_ci	return bytes;
808c2ecf20Sopenharmony_ci}
818c2ecf20Sopenharmony_ci
828c2ecf20Sopenharmony_cistatic void print1byte(uint8_t input, struct iio_channel_info *info)
838c2ecf20Sopenharmony_ci{
848c2ecf20Sopenharmony_ci	/*
858c2ecf20Sopenharmony_ci	 * Shift before conversion to avoid sign extension
868c2ecf20Sopenharmony_ci	 * of left aligned data
878c2ecf20Sopenharmony_ci	 */
888c2ecf20Sopenharmony_ci	input >>= info->shift;
898c2ecf20Sopenharmony_ci	input &= info->mask;
908c2ecf20Sopenharmony_ci	if (info->is_signed) {
918c2ecf20Sopenharmony_ci		int8_t val = (int8_t)(input << (8 - info->bits_used)) >>
928c2ecf20Sopenharmony_ci			     (8 - info->bits_used);
938c2ecf20Sopenharmony_ci		printf("%05f ", ((float)val + info->offset) * info->scale);
948c2ecf20Sopenharmony_ci	} else {
958c2ecf20Sopenharmony_ci		printf("%05f ", ((float)input + info->offset) * info->scale);
968c2ecf20Sopenharmony_ci	}
978c2ecf20Sopenharmony_ci}
988c2ecf20Sopenharmony_ci
998c2ecf20Sopenharmony_cistatic void print2byte(uint16_t input, struct iio_channel_info *info)
1008c2ecf20Sopenharmony_ci{
1018c2ecf20Sopenharmony_ci	/* First swap if incorrect endian */
1028c2ecf20Sopenharmony_ci	if (info->be)
1038c2ecf20Sopenharmony_ci		input = be16toh(input);
1048c2ecf20Sopenharmony_ci	else
1058c2ecf20Sopenharmony_ci		input = le16toh(input);
1068c2ecf20Sopenharmony_ci
1078c2ecf20Sopenharmony_ci	/*
1088c2ecf20Sopenharmony_ci	 * Shift before conversion to avoid sign extension
1098c2ecf20Sopenharmony_ci	 * of left aligned data
1108c2ecf20Sopenharmony_ci	 */
1118c2ecf20Sopenharmony_ci	input >>= info->shift;
1128c2ecf20Sopenharmony_ci	input &= info->mask;
1138c2ecf20Sopenharmony_ci	if (info->is_signed) {
1148c2ecf20Sopenharmony_ci		int16_t val = (int16_t)(input << (16 - info->bits_used)) >>
1158c2ecf20Sopenharmony_ci			      (16 - info->bits_used);
1168c2ecf20Sopenharmony_ci		printf("%05f ", ((float)val + info->offset) * info->scale);
1178c2ecf20Sopenharmony_ci	} else {
1188c2ecf20Sopenharmony_ci		printf("%05f ", ((float)input + info->offset) * info->scale);
1198c2ecf20Sopenharmony_ci	}
1208c2ecf20Sopenharmony_ci}
1218c2ecf20Sopenharmony_ci
1228c2ecf20Sopenharmony_cistatic void print4byte(uint32_t input, struct iio_channel_info *info)
1238c2ecf20Sopenharmony_ci{
1248c2ecf20Sopenharmony_ci	/* First swap if incorrect endian */
1258c2ecf20Sopenharmony_ci	if (info->be)
1268c2ecf20Sopenharmony_ci		input = be32toh(input);
1278c2ecf20Sopenharmony_ci	else
1288c2ecf20Sopenharmony_ci		input = le32toh(input);
1298c2ecf20Sopenharmony_ci
1308c2ecf20Sopenharmony_ci	/*
1318c2ecf20Sopenharmony_ci	 * Shift before conversion to avoid sign extension
1328c2ecf20Sopenharmony_ci	 * of left aligned data
1338c2ecf20Sopenharmony_ci	 */
1348c2ecf20Sopenharmony_ci	input >>= info->shift;
1358c2ecf20Sopenharmony_ci	input &= info->mask;
1368c2ecf20Sopenharmony_ci	if (info->is_signed) {
1378c2ecf20Sopenharmony_ci		int32_t val = (int32_t)(input << (32 - info->bits_used)) >>
1388c2ecf20Sopenharmony_ci			      (32 - info->bits_used);
1398c2ecf20Sopenharmony_ci		printf("%05f ", ((float)val + info->offset) * info->scale);
1408c2ecf20Sopenharmony_ci	} else {
1418c2ecf20Sopenharmony_ci		printf("%05f ", ((float)input + info->offset) * info->scale);
1428c2ecf20Sopenharmony_ci	}
1438c2ecf20Sopenharmony_ci}
1448c2ecf20Sopenharmony_ci
1458c2ecf20Sopenharmony_cistatic void print8byte(uint64_t input, struct iio_channel_info *info)
1468c2ecf20Sopenharmony_ci{
1478c2ecf20Sopenharmony_ci	/* First swap if incorrect endian */
1488c2ecf20Sopenharmony_ci	if (info->be)
1498c2ecf20Sopenharmony_ci		input = be64toh(input);
1508c2ecf20Sopenharmony_ci	else
1518c2ecf20Sopenharmony_ci		input = le64toh(input);
1528c2ecf20Sopenharmony_ci
1538c2ecf20Sopenharmony_ci	/*
1548c2ecf20Sopenharmony_ci	 * Shift before conversion to avoid sign extension
1558c2ecf20Sopenharmony_ci	 * of left aligned data
1568c2ecf20Sopenharmony_ci	 */
1578c2ecf20Sopenharmony_ci	input >>= info->shift;
1588c2ecf20Sopenharmony_ci	input &= info->mask;
1598c2ecf20Sopenharmony_ci	if (info->is_signed) {
1608c2ecf20Sopenharmony_ci		int64_t val = (int64_t)(input << (64 - info->bits_used)) >>
1618c2ecf20Sopenharmony_ci			      (64 - info->bits_used);
1628c2ecf20Sopenharmony_ci		/* special case for timestamp */
1638c2ecf20Sopenharmony_ci		if (info->scale == 1.0f && info->offset == 0.0f)
1648c2ecf20Sopenharmony_ci			printf("%" PRId64 " ", val);
1658c2ecf20Sopenharmony_ci		else
1668c2ecf20Sopenharmony_ci			printf("%05f ",
1678c2ecf20Sopenharmony_ci			       ((float)val + info->offset) * info->scale);
1688c2ecf20Sopenharmony_ci	} else {
1698c2ecf20Sopenharmony_ci		printf("%05f ", ((float)input + info->offset) * info->scale);
1708c2ecf20Sopenharmony_ci	}
1718c2ecf20Sopenharmony_ci}
1728c2ecf20Sopenharmony_ci
1738c2ecf20Sopenharmony_ci/**
1748c2ecf20Sopenharmony_ci * process_scan() - print out the values in SI units
1758c2ecf20Sopenharmony_ci * @data:		pointer to the start of the scan
1768c2ecf20Sopenharmony_ci * @channels:		information about the channels.
1778c2ecf20Sopenharmony_ci *			Note: size_from_channelarray must have been called first
1788c2ecf20Sopenharmony_ci *			      to fill the location offsets.
1798c2ecf20Sopenharmony_ci * @num_channels:	number of channels
1808c2ecf20Sopenharmony_ci **/
1818c2ecf20Sopenharmony_cistatic void process_scan(char *data, struct iio_channel_info *channels,
1828c2ecf20Sopenharmony_ci			 int num_channels)
1838c2ecf20Sopenharmony_ci{
1848c2ecf20Sopenharmony_ci	int k;
1858c2ecf20Sopenharmony_ci
1868c2ecf20Sopenharmony_ci	for (k = 0; k < num_channels; k++)
1878c2ecf20Sopenharmony_ci		switch (channels[k].bytes) {
1888c2ecf20Sopenharmony_ci			/* only a few cases implemented so far */
1898c2ecf20Sopenharmony_ci		case 1:
1908c2ecf20Sopenharmony_ci			print1byte(*(uint8_t *)(data + channels[k].location),
1918c2ecf20Sopenharmony_ci				   &channels[k]);
1928c2ecf20Sopenharmony_ci			break;
1938c2ecf20Sopenharmony_ci		case 2:
1948c2ecf20Sopenharmony_ci			print2byte(*(uint16_t *)(data + channels[k].location),
1958c2ecf20Sopenharmony_ci				   &channels[k]);
1968c2ecf20Sopenharmony_ci			break;
1978c2ecf20Sopenharmony_ci		case 4:
1988c2ecf20Sopenharmony_ci			print4byte(*(uint32_t *)(data + channels[k].location),
1998c2ecf20Sopenharmony_ci				   &channels[k]);
2008c2ecf20Sopenharmony_ci			break;
2018c2ecf20Sopenharmony_ci		case 8:
2028c2ecf20Sopenharmony_ci			print8byte(*(uint64_t *)(data + channels[k].location),
2038c2ecf20Sopenharmony_ci				   &channels[k]);
2048c2ecf20Sopenharmony_ci			break;
2058c2ecf20Sopenharmony_ci		default:
2068c2ecf20Sopenharmony_ci			break;
2078c2ecf20Sopenharmony_ci		}
2088c2ecf20Sopenharmony_ci	printf("\n");
2098c2ecf20Sopenharmony_ci}
2108c2ecf20Sopenharmony_ci
2118c2ecf20Sopenharmony_cistatic int enable_disable_all_channels(char *dev_dir_name, int enable)
2128c2ecf20Sopenharmony_ci{
2138c2ecf20Sopenharmony_ci	const struct dirent *ent;
2148c2ecf20Sopenharmony_ci	char scanelemdir[256];
2158c2ecf20Sopenharmony_ci	DIR *dp;
2168c2ecf20Sopenharmony_ci	int ret;
2178c2ecf20Sopenharmony_ci
2188c2ecf20Sopenharmony_ci	snprintf(scanelemdir, sizeof(scanelemdir),
2198c2ecf20Sopenharmony_ci		 FORMAT_SCAN_ELEMENTS_DIR, dev_dir_name);
2208c2ecf20Sopenharmony_ci	scanelemdir[sizeof(scanelemdir)-1] = '\0';
2218c2ecf20Sopenharmony_ci
2228c2ecf20Sopenharmony_ci	dp = opendir(scanelemdir);
2238c2ecf20Sopenharmony_ci	if (!dp) {
2248c2ecf20Sopenharmony_ci		fprintf(stderr, "Enabling/disabling channels: can't open %s\n",
2258c2ecf20Sopenharmony_ci			scanelemdir);
2268c2ecf20Sopenharmony_ci		return -EIO;
2278c2ecf20Sopenharmony_ci	}
2288c2ecf20Sopenharmony_ci
2298c2ecf20Sopenharmony_ci	ret = -ENOENT;
2308c2ecf20Sopenharmony_ci	while (ent = readdir(dp), ent) {
2318c2ecf20Sopenharmony_ci		if (iioutils_check_suffix(ent->d_name, "_en")) {
2328c2ecf20Sopenharmony_ci			printf("%sabling: %s\n",
2338c2ecf20Sopenharmony_ci			       enable ? "En" : "Dis",
2348c2ecf20Sopenharmony_ci			       ent->d_name);
2358c2ecf20Sopenharmony_ci			ret = write_sysfs_int(ent->d_name, scanelemdir,
2368c2ecf20Sopenharmony_ci					      enable);
2378c2ecf20Sopenharmony_ci			if (ret < 0)
2388c2ecf20Sopenharmony_ci				fprintf(stderr, "Failed to enable/disable %s\n",
2398c2ecf20Sopenharmony_ci					ent->d_name);
2408c2ecf20Sopenharmony_ci		}
2418c2ecf20Sopenharmony_ci	}
2428c2ecf20Sopenharmony_ci
2438c2ecf20Sopenharmony_ci	if (closedir(dp) == -1) {
2448c2ecf20Sopenharmony_ci		perror("Enabling/disabling channels: "
2458c2ecf20Sopenharmony_ci		       "Failed to close directory");
2468c2ecf20Sopenharmony_ci		return -errno;
2478c2ecf20Sopenharmony_ci	}
2488c2ecf20Sopenharmony_ci	return 0;
2498c2ecf20Sopenharmony_ci}
2508c2ecf20Sopenharmony_ci
2518c2ecf20Sopenharmony_cistatic void print_usage(void)
2528c2ecf20Sopenharmony_ci{
2538c2ecf20Sopenharmony_ci	fprintf(stderr, "Usage: generic_buffer [options]...\n"
2548c2ecf20Sopenharmony_ci		"Capture, convert and output data from IIO device buffer\n"
2558c2ecf20Sopenharmony_ci		"  -a         Auto-activate all available channels\n"
2568c2ecf20Sopenharmony_ci		"  -A         Force-activate ALL channels\n"
2578c2ecf20Sopenharmony_ci		"  -c <n>     Do n conversions, or loop forever if n < 0\n"
2588c2ecf20Sopenharmony_ci		"  -e         Disable wait for event (new data)\n"
2598c2ecf20Sopenharmony_ci		"  -g         Use trigger-less mode\n"
2608c2ecf20Sopenharmony_ci		"  -l <n>     Set buffer length to n samples\n"
2618c2ecf20Sopenharmony_ci		"  --device-name -n <name>\n"
2628c2ecf20Sopenharmony_ci		"  --device-num -N <num>\n"
2638c2ecf20Sopenharmony_ci		"        Set device by name or number (mandatory)\n"
2648c2ecf20Sopenharmony_ci		"  --trigger-name -t <name>\n"
2658c2ecf20Sopenharmony_ci		"  --trigger-num -T <num>\n"
2668c2ecf20Sopenharmony_ci		"        Set trigger by name or number\n"
2678c2ecf20Sopenharmony_ci		"  -w <n>     Set delay between reads in us (event-less mode)\n");
2688c2ecf20Sopenharmony_ci}
2698c2ecf20Sopenharmony_ci
2708c2ecf20Sopenharmony_cistatic enum autochan autochannels = AUTOCHANNELS_DISABLED;
2718c2ecf20Sopenharmony_cistatic char *dev_dir_name = NULL;
2728c2ecf20Sopenharmony_cistatic char *buf_dir_name = NULL;
2738c2ecf20Sopenharmony_cistatic bool current_trigger_set = false;
2748c2ecf20Sopenharmony_ci
2758c2ecf20Sopenharmony_cistatic void cleanup(void)
2768c2ecf20Sopenharmony_ci{
2778c2ecf20Sopenharmony_ci	int ret;
2788c2ecf20Sopenharmony_ci
2798c2ecf20Sopenharmony_ci	/* Disable trigger */
2808c2ecf20Sopenharmony_ci	if (dev_dir_name && current_trigger_set) {
2818c2ecf20Sopenharmony_ci		/* Disconnect the trigger - just write a dummy name. */
2828c2ecf20Sopenharmony_ci		ret = write_sysfs_string("trigger/current_trigger",
2838c2ecf20Sopenharmony_ci					 dev_dir_name, "NULL");
2848c2ecf20Sopenharmony_ci		if (ret < 0)
2858c2ecf20Sopenharmony_ci			fprintf(stderr, "Failed to disable trigger: %s\n",
2868c2ecf20Sopenharmony_ci				strerror(-ret));
2878c2ecf20Sopenharmony_ci		current_trigger_set = false;
2888c2ecf20Sopenharmony_ci	}
2898c2ecf20Sopenharmony_ci
2908c2ecf20Sopenharmony_ci	/* Disable buffer */
2918c2ecf20Sopenharmony_ci	if (buf_dir_name) {
2928c2ecf20Sopenharmony_ci		ret = write_sysfs_int("enable", buf_dir_name, 0);
2938c2ecf20Sopenharmony_ci		if (ret < 0)
2948c2ecf20Sopenharmony_ci			fprintf(stderr, "Failed to disable buffer: %s\n",
2958c2ecf20Sopenharmony_ci				strerror(-ret));
2968c2ecf20Sopenharmony_ci	}
2978c2ecf20Sopenharmony_ci
2988c2ecf20Sopenharmony_ci	/* Disable channels if auto-enabled */
2998c2ecf20Sopenharmony_ci	if (dev_dir_name && autochannels == AUTOCHANNELS_ACTIVE) {
3008c2ecf20Sopenharmony_ci		ret = enable_disable_all_channels(dev_dir_name, 0);
3018c2ecf20Sopenharmony_ci		if (ret)
3028c2ecf20Sopenharmony_ci			fprintf(stderr, "Failed to disable all channels\n");
3038c2ecf20Sopenharmony_ci		autochannels = AUTOCHANNELS_DISABLED;
3048c2ecf20Sopenharmony_ci	}
3058c2ecf20Sopenharmony_ci}
3068c2ecf20Sopenharmony_ci
3078c2ecf20Sopenharmony_cistatic void sig_handler(int signum)
3088c2ecf20Sopenharmony_ci{
3098c2ecf20Sopenharmony_ci	fprintf(stderr, "Caught signal %d\n", signum);
3108c2ecf20Sopenharmony_ci	cleanup();
3118c2ecf20Sopenharmony_ci	exit(-signum);
3128c2ecf20Sopenharmony_ci}
3138c2ecf20Sopenharmony_ci
3148c2ecf20Sopenharmony_cistatic void register_cleanup(void)
3158c2ecf20Sopenharmony_ci{
3168c2ecf20Sopenharmony_ci	struct sigaction sa = { .sa_handler = sig_handler };
3178c2ecf20Sopenharmony_ci	const int signums[] = { SIGINT, SIGTERM, SIGABRT };
3188c2ecf20Sopenharmony_ci	int ret, i;
3198c2ecf20Sopenharmony_ci
3208c2ecf20Sopenharmony_ci	for (i = 0; i < ARRAY_SIZE(signums); ++i) {
3218c2ecf20Sopenharmony_ci		ret = sigaction(signums[i], &sa, NULL);
3228c2ecf20Sopenharmony_ci		if (ret) {
3238c2ecf20Sopenharmony_ci			perror("Failed to register signal handler");
3248c2ecf20Sopenharmony_ci			exit(-1);
3258c2ecf20Sopenharmony_ci		}
3268c2ecf20Sopenharmony_ci	}
3278c2ecf20Sopenharmony_ci}
3288c2ecf20Sopenharmony_ci
3298c2ecf20Sopenharmony_cistatic const struct option longopts[] = {
3308c2ecf20Sopenharmony_ci	{ "device-name",	1, 0, 'n' },
3318c2ecf20Sopenharmony_ci	{ "device-num",		1, 0, 'N' },
3328c2ecf20Sopenharmony_ci	{ "trigger-name",	1, 0, 't' },
3338c2ecf20Sopenharmony_ci	{ "trigger-num",	1, 0, 'T' },
3348c2ecf20Sopenharmony_ci	{ },
3358c2ecf20Sopenharmony_ci};
3368c2ecf20Sopenharmony_ci
3378c2ecf20Sopenharmony_ciint main(int argc, char **argv)
3388c2ecf20Sopenharmony_ci{
3398c2ecf20Sopenharmony_ci	long long num_loops = 2;
3408c2ecf20Sopenharmony_ci	unsigned long timedelay = 1000000;
3418c2ecf20Sopenharmony_ci	unsigned long buf_len = 128;
3428c2ecf20Sopenharmony_ci
3438c2ecf20Sopenharmony_ci	ssize_t i;
3448c2ecf20Sopenharmony_ci	unsigned long long j;
3458c2ecf20Sopenharmony_ci	unsigned long toread;
3468c2ecf20Sopenharmony_ci	int ret, c;
3478c2ecf20Sopenharmony_ci	int fp = -1;
3488c2ecf20Sopenharmony_ci
3498c2ecf20Sopenharmony_ci	int num_channels = 0;
3508c2ecf20Sopenharmony_ci	char *trigger_name = NULL, *device_name = NULL;
3518c2ecf20Sopenharmony_ci
3528c2ecf20Sopenharmony_ci	char *data = NULL;
3538c2ecf20Sopenharmony_ci	ssize_t read_size;
3548c2ecf20Sopenharmony_ci	int dev_num = -1, trig_num = -1;
3558c2ecf20Sopenharmony_ci	char *buffer_access = NULL;
3568c2ecf20Sopenharmony_ci	unsigned int scan_size;
3578c2ecf20Sopenharmony_ci	int noevents = 0;
3588c2ecf20Sopenharmony_ci	int notrigger = 0;
3598c2ecf20Sopenharmony_ci	char *dummy;
3608c2ecf20Sopenharmony_ci	bool force_autochannels = false;
3618c2ecf20Sopenharmony_ci
3628c2ecf20Sopenharmony_ci	struct iio_channel_info *channels = NULL;
3638c2ecf20Sopenharmony_ci
3648c2ecf20Sopenharmony_ci	register_cleanup();
3658c2ecf20Sopenharmony_ci
3668c2ecf20Sopenharmony_ci	while ((c = getopt_long(argc, argv, "aAc:egl:n:N:t:T:w:?", longopts,
3678c2ecf20Sopenharmony_ci				NULL)) != -1) {
3688c2ecf20Sopenharmony_ci		switch (c) {
3698c2ecf20Sopenharmony_ci		case 'a':
3708c2ecf20Sopenharmony_ci			autochannels = AUTOCHANNELS_ENABLED;
3718c2ecf20Sopenharmony_ci			break;
3728c2ecf20Sopenharmony_ci		case 'A':
3738c2ecf20Sopenharmony_ci			autochannels = AUTOCHANNELS_ENABLED;
3748c2ecf20Sopenharmony_ci			force_autochannels = true;
3758c2ecf20Sopenharmony_ci			break;
3768c2ecf20Sopenharmony_ci		case 'c':
3778c2ecf20Sopenharmony_ci			errno = 0;
3788c2ecf20Sopenharmony_ci			num_loops = strtoll(optarg, &dummy, 10);
3798c2ecf20Sopenharmony_ci			if (errno) {
3808c2ecf20Sopenharmony_ci				ret = -errno;
3818c2ecf20Sopenharmony_ci				goto error;
3828c2ecf20Sopenharmony_ci			}
3838c2ecf20Sopenharmony_ci
3848c2ecf20Sopenharmony_ci			break;
3858c2ecf20Sopenharmony_ci		case 'e':
3868c2ecf20Sopenharmony_ci			noevents = 1;
3878c2ecf20Sopenharmony_ci			break;
3888c2ecf20Sopenharmony_ci		case 'g':
3898c2ecf20Sopenharmony_ci			notrigger = 1;
3908c2ecf20Sopenharmony_ci			break;
3918c2ecf20Sopenharmony_ci		case 'l':
3928c2ecf20Sopenharmony_ci			errno = 0;
3938c2ecf20Sopenharmony_ci			buf_len = strtoul(optarg, &dummy, 10);
3948c2ecf20Sopenharmony_ci			if (errno) {
3958c2ecf20Sopenharmony_ci				ret = -errno;
3968c2ecf20Sopenharmony_ci				goto error;
3978c2ecf20Sopenharmony_ci			}
3988c2ecf20Sopenharmony_ci
3998c2ecf20Sopenharmony_ci			break;
4008c2ecf20Sopenharmony_ci		case 'n':
4018c2ecf20Sopenharmony_ci			device_name = strdup(optarg);
4028c2ecf20Sopenharmony_ci			break;
4038c2ecf20Sopenharmony_ci		case 'N':
4048c2ecf20Sopenharmony_ci			errno = 0;
4058c2ecf20Sopenharmony_ci			dev_num = strtoul(optarg, &dummy, 10);
4068c2ecf20Sopenharmony_ci			if (errno) {
4078c2ecf20Sopenharmony_ci				ret = -errno;
4088c2ecf20Sopenharmony_ci				goto error;
4098c2ecf20Sopenharmony_ci			}
4108c2ecf20Sopenharmony_ci			break;
4118c2ecf20Sopenharmony_ci		case 't':
4128c2ecf20Sopenharmony_ci			trigger_name = strdup(optarg);
4138c2ecf20Sopenharmony_ci			break;
4148c2ecf20Sopenharmony_ci		case 'T':
4158c2ecf20Sopenharmony_ci			errno = 0;
4168c2ecf20Sopenharmony_ci			trig_num = strtoul(optarg, &dummy, 10);
4178c2ecf20Sopenharmony_ci			if (errno)
4188c2ecf20Sopenharmony_ci				return -errno;
4198c2ecf20Sopenharmony_ci			break;
4208c2ecf20Sopenharmony_ci		case 'w':
4218c2ecf20Sopenharmony_ci			errno = 0;
4228c2ecf20Sopenharmony_ci			timedelay = strtoul(optarg, &dummy, 10);
4238c2ecf20Sopenharmony_ci			if (errno) {
4248c2ecf20Sopenharmony_ci				ret = -errno;
4258c2ecf20Sopenharmony_ci				goto error;
4268c2ecf20Sopenharmony_ci			}
4278c2ecf20Sopenharmony_ci			break;
4288c2ecf20Sopenharmony_ci		case '?':
4298c2ecf20Sopenharmony_ci			print_usage();
4308c2ecf20Sopenharmony_ci			ret = -1;
4318c2ecf20Sopenharmony_ci			goto error;
4328c2ecf20Sopenharmony_ci		}
4338c2ecf20Sopenharmony_ci	}
4348c2ecf20Sopenharmony_ci
4358c2ecf20Sopenharmony_ci	/* Find the device requested */
4368c2ecf20Sopenharmony_ci	if (dev_num < 0 && !device_name) {
4378c2ecf20Sopenharmony_ci		fprintf(stderr, "Device not set\n");
4388c2ecf20Sopenharmony_ci		print_usage();
4398c2ecf20Sopenharmony_ci		ret = -1;
4408c2ecf20Sopenharmony_ci		goto error;
4418c2ecf20Sopenharmony_ci	} else if (dev_num >= 0 && device_name) {
4428c2ecf20Sopenharmony_ci		fprintf(stderr, "Only one of --device-num or --device-name needs to be set\n");
4438c2ecf20Sopenharmony_ci		print_usage();
4448c2ecf20Sopenharmony_ci		ret = -1;
4458c2ecf20Sopenharmony_ci		goto error;
4468c2ecf20Sopenharmony_ci	} else if (dev_num < 0) {
4478c2ecf20Sopenharmony_ci		dev_num = find_type_by_name(device_name, "iio:device");
4488c2ecf20Sopenharmony_ci		if (dev_num < 0) {
4498c2ecf20Sopenharmony_ci			fprintf(stderr, "Failed to find the %s\n", device_name);
4508c2ecf20Sopenharmony_ci			ret = dev_num;
4518c2ecf20Sopenharmony_ci			goto error;
4528c2ecf20Sopenharmony_ci		}
4538c2ecf20Sopenharmony_ci	}
4548c2ecf20Sopenharmony_ci	printf("iio device number being used is %d\n", dev_num);
4558c2ecf20Sopenharmony_ci
4568c2ecf20Sopenharmony_ci	ret = asprintf(&dev_dir_name, "%siio:device%d", iio_dir, dev_num);
4578c2ecf20Sopenharmony_ci	if (ret < 0)
4588c2ecf20Sopenharmony_ci		return -ENOMEM;
4598c2ecf20Sopenharmony_ci	/* Fetch device_name if specified by number */
4608c2ecf20Sopenharmony_ci	if (!device_name) {
4618c2ecf20Sopenharmony_ci		device_name = malloc(IIO_MAX_NAME_LENGTH);
4628c2ecf20Sopenharmony_ci		if (!device_name) {
4638c2ecf20Sopenharmony_ci			ret = -ENOMEM;
4648c2ecf20Sopenharmony_ci			goto error;
4658c2ecf20Sopenharmony_ci		}
4668c2ecf20Sopenharmony_ci		ret = read_sysfs_string("name", dev_dir_name, device_name);
4678c2ecf20Sopenharmony_ci		if (ret < 0) {
4688c2ecf20Sopenharmony_ci			fprintf(stderr, "Failed to read name of device %d\n", dev_num);
4698c2ecf20Sopenharmony_ci			goto error;
4708c2ecf20Sopenharmony_ci		}
4718c2ecf20Sopenharmony_ci	}
4728c2ecf20Sopenharmony_ci
4738c2ecf20Sopenharmony_ci	if (notrigger) {
4748c2ecf20Sopenharmony_ci		printf("trigger-less mode selected\n");
4758c2ecf20Sopenharmony_ci	} else if (trig_num >= 0) {
4768c2ecf20Sopenharmony_ci		char *trig_dev_name;
4778c2ecf20Sopenharmony_ci		ret = asprintf(&trig_dev_name, "%strigger%d", iio_dir, trig_num);
4788c2ecf20Sopenharmony_ci		if (ret < 0) {
4798c2ecf20Sopenharmony_ci			return -ENOMEM;
4808c2ecf20Sopenharmony_ci		}
4818c2ecf20Sopenharmony_ci		trigger_name = malloc(IIO_MAX_NAME_LENGTH);
4828c2ecf20Sopenharmony_ci		ret = read_sysfs_string("name", trig_dev_name, trigger_name);
4838c2ecf20Sopenharmony_ci		free(trig_dev_name);
4848c2ecf20Sopenharmony_ci		if (ret < 0) {
4858c2ecf20Sopenharmony_ci			fprintf(stderr, "Failed to read trigger%d name from\n", trig_num);
4868c2ecf20Sopenharmony_ci			return ret;
4878c2ecf20Sopenharmony_ci		}
4888c2ecf20Sopenharmony_ci		printf("iio trigger number being used is %d\n", trig_num);
4898c2ecf20Sopenharmony_ci	} else {
4908c2ecf20Sopenharmony_ci		if (!trigger_name) {
4918c2ecf20Sopenharmony_ci			/*
4928c2ecf20Sopenharmony_ci			 * Build the trigger name. If it is device associated
4938c2ecf20Sopenharmony_ci			 * its name is <device_name>_dev[n] where n matches
4948c2ecf20Sopenharmony_ci			 * the device number found above.
4958c2ecf20Sopenharmony_ci			 */
4968c2ecf20Sopenharmony_ci			ret = asprintf(&trigger_name,
4978c2ecf20Sopenharmony_ci				       "%s-dev%d", device_name, dev_num);
4988c2ecf20Sopenharmony_ci			if (ret < 0) {
4998c2ecf20Sopenharmony_ci				ret = -ENOMEM;
5008c2ecf20Sopenharmony_ci				goto error;
5018c2ecf20Sopenharmony_ci			}
5028c2ecf20Sopenharmony_ci		}
5038c2ecf20Sopenharmony_ci
5048c2ecf20Sopenharmony_ci		/* Look for this "-devN" trigger */
5058c2ecf20Sopenharmony_ci		trig_num = find_type_by_name(trigger_name, "trigger");
5068c2ecf20Sopenharmony_ci		if (trig_num < 0) {
5078c2ecf20Sopenharmony_ci			/* OK try the simpler "-trigger" suffix instead */
5088c2ecf20Sopenharmony_ci			free(trigger_name);
5098c2ecf20Sopenharmony_ci			ret = asprintf(&trigger_name,
5108c2ecf20Sopenharmony_ci				       "%s-trigger", device_name);
5118c2ecf20Sopenharmony_ci			if (ret < 0) {
5128c2ecf20Sopenharmony_ci				ret = -ENOMEM;
5138c2ecf20Sopenharmony_ci				goto error;
5148c2ecf20Sopenharmony_ci			}
5158c2ecf20Sopenharmony_ci		}
5168c2ecf20Sopenharmony_ci
5178c2ecf20Sopenharmony_ci		trig_num = find_type_by_name(trigger_name, "trigger");
5188c2ecf20Sopenharmony_ci		if (trig_num < 0) {
5198c2ecf20Sopenharmony_ci			fprintf(stderr, "Failed to find the trigger %s\n",
5208c2ecf20Sopenharmony_ci				trigger_name);
5218c2ecf20Sopenharmony_ci			ret = trig_num;
5228c2ecf20Sopenharmony_ci			goto error;
5238c2ecf20Sopenharmony_ci		}
5248c2ecf20Sopenharmony_ci
5258c2ecf20Sopenharmony_ci		printf("iio trigger number being used is %d\n", trig_num);
5268c2ecf20Sopenharmony_ci	}
5278c2ecf20Sopenharmony_ci
5288c2ecf20Sopenharmony_ci	/*
5298c2ecf20Sopenharmony_ci	 * Parse the files in scan_elements to identify what channels are
5308c2ecf20Sopenharmony_ci	 * present
5318c2ecf20Sopenharmony_ci	 */
5328c2ecf20Sopenharmony_ci	ret = build_channel_array(dev_dir_name, &channels, &num_channels);
5338c2ecf20Sopenharmony_ci	if (ret) {
5348c2ecf20Sopenharmony_ci		fprintf(stderr, "Problem reading scan element information\n"
5358c2ecf20Sopenharmony_ci			"diag %s\n", dev_dir_name);
5368c2ecf20Sopenharmony_ci		goto error;
5378c2ecf20Sopenharmony_ci	}
5388c2ecf20Sopenharmony_ci	if (num_channels && autochannels == AUTOCHANNELS_ENABLED &&
5398c2ecf20Sopenharmony_ci	    !force_autochannels) {
5408c2ecf20Sopenharmony_ci		fprintf(stderr, "Auto-channels selected but some channels "
5418c2ecf20Sopenharmony_ci			"are already activated in sysfs\n");
5428c2ecf20Sopenharmony_ci		fprintf(stderr, "Proceeding without activating any channels\n");
5438c2ecf20Sopenharmony_ci	}
5448c2ecf20Sopenharmony_ci
5458c2ecf20Sopenharmony_ci	if ((!num_channels && autochannels == AUTOCHANNELS_ENABLED) ||
5468c2ecf20Sopenharmony_ci	    (autochannels == AUTOCHANNELS_ENABLED && force_autochannels)) {
5478c2ecf20Sopenharmony_ci		fprintf(stderr, "Enabling all channels\n");
5488c2ecf20Sopenharmony_ci
5498c2ecf20Sopenharmony_ci		ret = enable_disable_all_channels(dev_dir_name, 1);
5508c2ecf20Sopenharmony_ci		if (ret) {
5518c2ecf20Sopenharmony_ci			fprintf(stderr, "Failed to enable all channels\n");
5528c2ecf20Sopenharmony_ci			goto error;
5538c2ecf20Sopenharmony_ci		}
5548c2ecf20Sopenharmony_ci
5558c2ecf20Sopenharmony_ci		/* This flags that we need to disable the channels again */
5568c2ecf20Sopenharmony_ci		autochannels = AUTOCHANNELS_ACTIVE;
5578c2ecf20Sopenharmony_ci
5588c2ecf20Sopenharmony_ci		ret = build_channel_array(dev_dir_name, &channels,
5598c2ecf20Sopenharmony_ci					  &num_channels);
5608c2ecf20Sopenharmony_ci		if (ret) {
5618c2ecf20Sopenharmony_ci			fprintf(stderr, "Problem reading scan element "
5628c2ecf20Sopenharmony_ci				"information\n"
5638c2ecf20Sopenharmony_ci				"diag %s\n", dev_dir_name);
5648c2ecf20Sopenharmony_ci			goto error;
5658c2ecf20Sopenharmony_ci		}
5668c2ecf20Sopenharmony_ci		if (!num_channels) {
5678c2ecf20Sopenharmony_ci			fprintf(stderr, "Still no channels after "
5688c2ecf20Sopenharmony_ci				"auto-enabling, giving up\n");
5698c2ecf20Sopenharmony_ci			goto error;
5708c2ecf20Sopenharmony_ci		}
5718c2ecf20Sopenharmony_ci	}
5728c2ecf20Sopenharmony_ci
5738c2ecf20Sopenharmony_ci	if (!num_channels && autochannels == AUTOCHANNELS_DISABLED) {
5748c2ecf20Sopenharmony_ci		fprintf(stderr,
5758c2ecf20Sopenharmony_ci			"No channels are enabled, we have nothing to scan.\n");
5768c2ecf20Sopenharmony_ci		fprintf(stderr, "Enable channels manually in "
5778c2ecf20Sopenharmony_ci			FORMAT_SCAN_ELEMENTS_DIR
5788c2ecf20Sopenharmony_ci			"/*_en or pass -a to autoenable channels and "
5798c2ecf20Sopenharmony_ci			"try again.\n", dev_dir_name);
5808c2ecf20Sopenharmony_ci		ret = -ENOENT;
5818c2ecf20Sopenharmony_ci		goto error;
5828c2ecf20Sopenharmony_ci	}
5838c2ecf20Sopenharmony_ci
5848c2ecf20Sopenharmony_ci	/*
5858c2ecf20Sopenharmony_ci	 * Construct the directory name for the associated buffer.
5868c2ecf20Sopenharmony_ci	 * As we know that the lis3l02dq has only one buffer this may
5878c2ecf20Sopenharmony_ci	 * be built rather than found.
5888c2ecf20Sopenharmony_ci	 */
5898c2ecf20Sopenharmony_ci	ret = asprintf(&buf_dir_name,
5908c2ecf20Sopenharmony_ci		       "%siio:device%d/buffer", iio_dir, dev_num);
5918c2ecf20Sopenharmony_ci	if (ret < 0) {
5928c2ecf20Sopenharmony_ci		ret = -ENOMEM;
5938c2ecf20Sopenharmony_ci		goto error;
5948c2ecf20Sopenharmony_ci	}
5958c2ecf20Sopenharmony_ci
5968c2ecf20Sopenharmony_ci	if (!notrigger) {
5978c2ecf20Sopenharmony_ci		printf("%s %s\n", dev_dir_name, trigger_name);
5988c2ecf20Sopenharmony_ci		/*
5998c2ecf20Sopenharmony_ci		 * Set the device trigger to be the data ready trigger found
6008c2ecf20Sopenharmony_ci		 * above
6018c2ecf20Sopenharmony_ci		 */
6028c2ecf20Sopenharmony_ci		ret = write_sysfs_string_and_verify("trigger/current_trigger",
6038c2ecf20Sopenharmony_ci						    dev_dir_name,
6048c2ecf20Sopenharmony_ci						    trigger_name);
6058c2ecf20Sopenharmony_ci		if (ret < 0) {
6068c2ecf20Sopenharmony_ci			fprintf(stderr,
6078c2ecf20Sopenharmony_ci				"Failed to write current_trigger file\n");
6088c2ecf20Sopenharmony_ci			goto error;
6098c2ecf20Sopenharmony_ci		}
6108c2ecf20Sopenharmony_ci	}
6118c2ecf20Sopenharmony_ci
6128c2ecf20Sopenharmony_ci	/* Setup ring buffer parameters */
6138c2ecf20Sopenharmony_ci	ret = write_sysfs_int("length", buf_dir_name, buf_len);
6148c2ecf20Sopenharmony_ci	if (ret < 0)
6158c2ecf20Sopenharmony_ci		goto error;
6168c2ecf20Sopenharmony_ci
6178c2ecf20Sopenharmony_ci	/* Enable the buffer */
6188c2ecf20Sopenharmony_ci	ret = write_sysfs_int("enable", buf_dir_name, 1);
6198c2ecf20Sopenharmony_ci	if (ret < 0) {
6208c2ecf20Sopenharmony_ci		fprintf(stderr,
6218c2ecf20Sopenharmony_ci			"Failed to enable buffer: %s\n", strerror(-ret));
6228c2ecf20Sopenharmony_ci		goto error;
6238c2ecf20Sopenharmony_ci	}
6248c2ecf20Sopenharmony_ci
6258c2ecf20Sopenharmony_ci	scan_size = size_from_channelarray(channels, num_channels);
6268c2ecf20Sopenharmony_ci
6278c2ecf20Sopenharmony_ci	size_t total_buf_len = scan_size * buf_len;
6288c2ecf20Sopenharmony_ci
6298c2ecf20Sopenharmony_ci	if (scan_size > 0 && total_buf_len / scan_size != buf_len) {
6308c2ecf20Sopenharmony_ci		ret = -EFAULT;
6318c2ecf20Sopenharmony_ci		perror("Integer overflow happened when calculate scan_size * buf_len");
6328c2ecf20Sopenharmony_ci		goto error;
6338c2ecf20Sopenharmony_ci	}
6348c2ecf20Sopenharmony_ci
6358c2ecf20Sopenharmony_ci	data = malloc(total_buf_len);
6368c2ecf20Sopenharmony_ci	if (!data) {
6378c2ecf20Sopenharmony_ci		ret = -ENOMEM;
6388c2ecf20Sopenharmony_ci		goto error;
6398c2ecf20Sopenharmony_ci	}
6408c2ecf20Sopenharmony_ci
6418c2ecf20Sopenharmony_ci	ret = asprintf(&buffer_access, "/dev/iio:device%d", dev_num);
6428c2ecf20Sopenharmony_ci	if (ret < 0) {
6438c2ecf20Sopenharmony_ci		ret = -ENOMEM;
6448c2ecf20Sopenharmony_ci		goto error;
6458c2ecf20Sopenharmony_ci	}
6468c2ecf20Sopenharmony_ci
6478c2ecf20Sopenharmony_ci	/* Attempt to open non blocking the access dev */
6488c2ecf20Sopenharmony_ci	fp = open(buffer_access, O_RDONLY | O_NONBLOCK);
6498c2ecf20Sopenharmony_ci	if (fp == -1) { /* TODO: If it isn't there make the node */
6508c2ecf20Sopenharmony_ci		ret = -errno;
6518c2ecf20Sopenharmony_ci		fprintf(stderr, "Failed to open %s\n", buffer_access);
6528c2ecf20Sopenharmony_ci		goto error;
6538c2ecf20Sopenharmony_ci	}
6548c2ecf20Sopenharmony_ci
6558c2ecf20Sopenharmony_ci	for (j = 0; j < num_loops || num_loops < 0; j++) {
6568c2ecf20Sopenharmony_ci		if (!noevents) {
6578c2ecf20Sopenharmony_ci			struct pollfd pfd = {
6588c2ecf20Sopenharmony_ci				.fd = fp,
6598c2ecf20Sopenharmony_ci				.events = POLLIN,
6608c2ecf20Sopenharmony_ci			};
6618c2ecf20Sopenharmony_ci
6628c2ecf20Sopenharmony_ci			ret = poll(&pfd, 1, -1);
6638c2ecf20Sopenharmony_ci			if (ret < 0) {
6648c2ecf20Sopenharmony_ci				ret = -errno;
6658c2ecf20Sopenharmony_ci				goto error;
6668c2ecf20Sopenharmony_ci			} else if (ret == 0) {
6678c2ecf20Sopenharmony_ci				continue;
6688c2ecf20Sopenharmony_ci			}
6698c2ecf20Sopenharmony_ci
6708c2ecf20Sopenharmony_ci			toread = buf_len;
6718c2ecf20Sopenharmony_ci		} else {
6728c2ecf20Sopenharmony_ci			usleep(timedelay);
6738c2ecf20Sopenharmony_ci			toread = 64;
6748c2ecf20Sopenharmony_ci		}
6758c2ecf20Sopenharmony_ci
6768c2ecf20Sopenharmony_ci		read_size = read(fp, data, toread * scan_size);
6778c2ecf20Sopenharmony_ci		if (read_size < 0) {
6788c2ecf20Sopenharmony_ci			if (errno == EAGAIN) {
6798c2ecf20Sopenharmony_ci				fprintf(stderr, "nothing available\n");
6808c2ecf20Sopenharmony_ci				continue;
6818c2ecf20Sopenharmony_ci			} else {
6828c2ecf20Sopenharmony_ci				break;
6838c2ecf20Sopenharmony_ci			}
6848c2ecf20Sopenharmony_ci		}
6858c2ecf20Sopenharmony_ci		for (i = 0; i < read_size / scan_size; i++)
6868c2ecf20Sopenharmony_ci			process_scan(data + scan_size * i, channels,
6878c2ecf20Sopenharmony_ci				     num_channels);
6888c2ecf20Sopenharmony_ci	}
6898c2ecf20Sopenharmony_ci
6908c2ecf20Sopenharmony_cierror:
6918c2ecf20Sopenharmony_ci	cleanup();
6928c2ecf20Sopenharmony_ci
6938c2ecf20Sopenharmony_ci	if (fp >= 0 && close(fp) == -1)
6948c2ecf20Sopenharmony_ci		perror("Failed to close buffer");
6958c2ecf20Sopenharmony_ci	free(buffer_access);
6968c2ecf20Sopenharmony_ci	free(data);
6978c2ecf20Sopenharmony_ci	free(buf_dir_name);
6988c2ecf20Sopenharmony_ci	for (i = num_channels - 1; i >= 0; i--) {
6998c2ecf20Sopenharmony_ci		free(channels[i].name);
7008c2ecf20Sopenharmony_ci		free(channels[i].generic_name);
7018c2ecf20Sopenharmony_ci	}
7028c2ecf20Sopenharmony_ci	free(channels);
7038c2ecf20Sopenharmony_ci	free(trigger_name);
7048c2ecf20Sopenharmony_ci	free(device_name);
7058c2ecf20Sopenharmony_ci	free(dev_dir_name);
7068c2ecf20Sopenharmony_ci
7078c2ecf20Sopenharmony_ci	return ret;
7088c2ecf20Sopenharmony_ci}
709