From 783a885c21da61fa9af83f366561a91edb7449c3 Mon Sep 17 00:00:00 2001 From: OSQZSS Date: Sun, 21 Aug 2022 15:30:46 +0900 Subject: [PATCH] Windows port of plutoplayer --- player/plutoplayer_win/ad9361.h | 227 ++ .../ad9361_baseband_auto_rate.c | 181 ++ player/plutoplayer_win/getopt.c | 110 + player/plutoplayer_win/getopt.h | 9 + player/plutoplayer_win/iio.h | 1974 +++++++++++++++++ player/plutoplayer_win/plutoplayer.c | 254 +++ 6 files changed, 2755 insertions(+) create mode 100644 player/plutoplayer_win/ad9361.h create mode 100644 player/plutoplayer_win/ad9361_baseband_auto_rate.c create mode 100644 player/plutoplayer_win/getopt.c create mode 100644 player/plutoplayer_win/getopt.h create mode 100644 player/plutoplayer_win/iio.h create mode 100644 player/plutoplayer_win/plutoplayer.c diff --git a/player/plutoplayer_win/ad9361.h b/player/plutoplayer_win/ad9361.h new file mode 100644 index 0000000..6b0aa79 --- /dev/null +++ b/player/plutoplayer_win/ad9361.h @@ -0,0 +1,227 @@ +/* + * Copyright (C) 2015 Analog Devices, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + */ + + /** @file ad9361.h + * @brief Public interface */ + +#ifndef __AD9361_H__ +#define __AD9361_H__ + +#ifdef __cplusplus +extern "C" { +#endif + + +/** + * @defgroup FLAGS MCS Flags + * + * @{ + */ +/** Flag for ad9361_multichip_sync which verifies interface timing between + master and all slaves is identical +*/ +#define FIXUP_INTERFACE_TIMING 1 +/** Flag for ad9361_multichip_sync which checks if master and associated slaves + have the same sample rate +*/ +#define CHECK_SAMPLE_RATES 2 + +/** @} */ + +#ifdef _WIN32 +# ifdef LIBAD9361_EXPORTS +# define __api __declspec(dllexport) +# else +# define __api __declspec(dllimport) +# endif +#elif __GNUC__ >= 4 && !defined(MATLAB_MEX_FILE) && !defined(MATLAB_LOADLIBRARY) +# define __api __attribute__((visibility ("default"))) +#else +# define __api +#endif + +struct iio_context; +struct iio_device; + +/** + * @struct filter_design_parameters + * @brief Custom Filter Design Parameters + * + * A structure for custom filter designs for the AD936X programmable FIR + * in both TX and RX paths. + */ +struct filter_design_parameters { + double Rdata; /**< Data rate of digital interface */ + double Fpass; /**< Stop edge frequency in hertz of passband */ + double Fstop; /**< Start edge frequency in hertz of stopband */ + double caldiv; /**< Baseband analog filter calibration divider setting [1-511] */ + double FIR; /**< Decimation/Interpolation setting of FIR [1,2,4] */ + double HB1; /**< Decimation/Interpolation setting of HB1 [1,2] */ + double DAC_div; /**< Divider enable setting of DAC clock [0,1] */ + const char *Type; /**< Designer mode (only Lowpass supported) */ + const char *RxTx; /**< Filter path [Tx,Rx] */ + double RFbw; /**< 3dB corner of analog filter in hertz */ + double converter_rate; /**< Rate of ADC in hertz */ + double PLL_rate; /**< Rate of PLL in hertz */ + double Fcenter; /**< Center frequency in hertz of bandpass (Unused) */ + double wnom; /**< RF bandwidth of analog filter in hertz */ + double FIRdBmin; /**< Minimum stop band attentuation of the FIR in dB */ + double int_FIR; /**< Enable use of internal FIR filter [0,1] */ + double PLL_mult; /**< Ratio of converter to PLL rate */ + double Apass; /**< Desired passband ripple in dB */ + double Astop; /**< Desired stopband attenuation in dB */ + double phEQ; /**< Enable phase equalization [0,1] */ + double HB2; /**< Decimation/Interpolation setting of HB2 [1,2] */ + double HB3; /**< Decimation/Interpolation setting of HB3 [1,2,3] */ + double maxTaps; /**< Maximum allowed FIR taps */ +}; + +/* ---------------------------------------------------------------------------*/ +/* ------------------------- Top-level functions -----------------------------*/ +/** @defgroup TopLevel Top-level functions + * @{ */ + + +/** @brief Multi-chip synchronization (MCS) management + * @param master A pointer to an iio_device structure + * @param slaves A double pointer to an iio_device structure + * @param num_slaves Number of slave devices associated with the master + * @param flags Control flags for MCS configuration + * @return On success, 0 is returned + * @return On error, a negative errno code is returned */ +__api int ad9361_multichip_sync(struct iio_device *master, + struct iio_device **slaves, unsigned int num_slaves, + unsigned int flags); + +/** @brief FMComms5 specific MCS management + * @param ctx A pointer to an iio_context structure + * @param flags Control flags for MCS configuration + * @return On success, 0 is returned + * @return On error, a negative errno code is returned */ +__api int ad9361_fmcomms5_multichip_sync( + struct iio_context *ctx, unsigned int flags); + +/** @brief Baseband rate configuration with generic filter support + * @param dev A pointer to an iio_device structure + * @param rate Rate in samples per second of desired baseband rate + * @return On success, 0 is returned + * @return On error, a negative errno code is returned + * + * NOTE: Three possible filters are loaded based on required rate and + * associated decimation/interpolation. These filters are generally very wide + * band and not waveform specific. */ +__api int ad9361_set_bb_rate(struct iio_device *dev, unsigned long rate); + +/** @brief Enable or disable transmit and receiver FIRs simultaneously + * @param dev A pointer to an iio_device structure + * @param enable Integer to enable FIRs when 1 or disable when 0 + * @return On success, 0 is returned + * @return On error, a negative errno code is returned */ +__api int ad9361_set_trx_fir_enable(struct iio_device *dev, int enable); + +/** @brief Get current enable value of transmit and receiver FIRs + * @param dev A pointer to an iio_device structure + * @param enable Returned integer value of FIR enabled + * @return On success, 0 is returned + * @return On error, a negative errno code is returned */ +__api int ad9361_get_trx_fir_enable(struct iio_device *dev, int *enable); + +/** @brief Design custom FIR filter from specific design criteria + * @param parameters A pointer filter designer structure + * @param taps A pointer to taps of designed filter + * @param num_taps A pointer to integer number of taps designed in taps + * @param gain Integer gain for designed filter + * @return On success, 0 is returned + * @return On error, a negative errno code is returned */ +__api int ad9361_generate_fir_taps(struct filter_design_parameters *parameters, + short *taps, int *num_taps, int *gain); + +/** @brief Calculate the clock path rates for both transmit and receiver paths + * @param tx_sample_rate Sample rate in samples per second of desired baseband rate + * @param rate_gov Rate governor enable setting forcing HB3=3 when enabled + * @param rx_path_clks A pointer to a unsigned long variable where the 6 RX path rates should be stored + * @param tx_path_clks A pointer to a unsigned long variable where the 6 TX path rates should be stored + * @return On success, 0 is returned + * @return On error, a negative errno code is returned */ +__api int ad9361_calculate_rf_clock_chain(unsigned long tx_sample_rate, + unsigned long rate_gov, + unsigned long *rx_path_clks, + unsigned long *tx_path_clks); + +/** @brief Calculate the clock path rates and default filter settings for both transmit and receiver for a desired baseband rate + * @param fdpTX Filter design parameters structure where TX filter design parameters will be stored + * @param fdpRX Filter design parameters structure where RX filter design parameters will be stored + * @param sample_rate Desired basedband sample rate in samples per second for both RX and TX filter configurations + * @return On success, 0 is returned + * @return On error, a negative errno code is returned */ +__api int ad9361_calculate_rf_clock_chain_fdp(struct filter_design_parameters *fdpTX, + struct filter_design_parameters *fdpRX, + unsigned long sample_rate); + +/** @brief Baseband rate configuration with custom filter support based on desired baseband sample rate + * @param dev A pointer to an iio_device structure + * @param rate Rate in samples per second of desired baseband rate + * @return On success, 0 is returned + * @return On error, a negative errno code is returned + * + * NOTE: Designed filter will have the following configuration: + * Fpass = rate / 3 + * Fstop = Fpass * 1.25 + * wnomTX = 1.6 * Fstop + * wnomRX = 1.4 * Fstop */ +__api int ad9361_set_bb_rate_custom_filter_auto(struct iio_device *dev, + unsigned long rate); + +/** @brief Baseband rate configuration with custom filter support based on desired baseband sample rate and simplified filter configuration + * @param dev A pointer to an iio_device structure + * @param rate Rate in samples per second of desired baseband rate + * @param Fpass Stop edge frequency in hertz of passband + * @param Fstop Start edge frequency in hertz of stopband + * @param wnom_tx TX RF bandwidth of analog filter in hertz + * @param wnom_rx RX RF bandwidth of analog filter in hertz + * @return On success, 0 is returned + * @return On error, a negative errno code is returned */ +__api int ad9361_set_bb_rate_custom_filter_manual(struct iio_device *dev, + unsigned long rate, unsigned long Fpass, + unsigned long Fstop, unsigned long wnom_tx, + unsigned long wnom_rx); + +/** @brief FMComms5 phase synchronize all TX and RX channels together + * @param ctx A pointer to an iio_context structure + * @param lo Frequency in hertz of LO for TX and RX + * @return On success, 0 is returned + * @return On error, a negative errno code is returned. If -2 is returned calibration failed + * + * NOTES: To perform calibration the following side effects occur: + * - RF bandwidths of both TX and RX are expanded to the current sample rate. It can be changed after calibration without effecting phase synchronization. + * - DDSs are enabled and left on after synchronization. Changing these DDSs or switching to DMA sources will not effect phase synchronization. + * - TX and RX LOs are set to the same frequency based on the input provided. LO changes can invalidate phase synchronization. + * - AGCs are set to manual mode at predetermined hardware gains for TX and RX. Gain changes can invalidate phase synchronization. + * + * Phase synchronization is valid until the LOs are retuned or sample rates change or gains are modified. + * + * External Links: + * - Detailed information on synchronization process + * - Phase synchronization performance can depend on revision of hardware*/ +__api int ad9361_fmcomms5_phase_sync(struct iio_context *ctx, long long lo); + +/** @} */ + +#ifdef __cplusplus +} +#endif + +#undef __api + +#endif /* __AD9361_H__ */ diff --git a/player/plutoplayer_win/ad9361_baseband_auto_rate.c b/player/plutoplayer_win/ad9361_baseband_auto_rate.c new file mode 100644 index 0000000..5a38973 --- /dev/null +++ b/player/plutoplayer_win/ad9361_baseband_auto_rate.c @@ -0,0 +1,181 @@ +/* + * Copyright (C) 2016 Analog Devices, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + */ +#define _CRT_SECURE_NO_WARNINGS + +#include "ad9361.h" + +#include +#include +#ifdef _WIN32 +#include +#include "iio.h" +#else +#include +#include +#endif + +#ifdef _MSC_BUILD +#define snprintf sprintf_s +#endif + +static int16_t fir_128_4[] = { + -15,-27,-23,-6,17,33,31,9,-23,-47,-45,-13,34,69,67,21,-49,-102,-99,-32,69,146,143,48,-96,-204,-200,-69,129,278,275,97,-170, + -372,-371,-135,222,494,497,187,-288,-654,-665,-258,376,875,902,363,-500,-1201,-1265,-530,699,1748,1906,845,-1089,-2922,-3424, + -1697,2326,7714,12821,15921,15921,12821,7714,2326,-1697,-3424,-2922,-1089,845,1906,1748,699,-530,-1265,-1201,-500,363,902,875, + 376,-258,-665,-654,-288,187,497,494,222,-135,-371,-372,-170,97,275,278,129,-69,-200,-204,-96,48,143,146,69,-32,-99,-102,-49,21, + 67,69,34,-13,-45,-47,-23,9,31,33,17,-6,-23,-27,-15}; + +static int16_t fir_128_2[] = { + -0,0,1,-0,-2,0,3,-0,-5,0,8,-0,-11,0,17,-0,-24,0,33,-0,-45,0,61,-0,-80,0,104,-0,-134,0,169,-0, + -213,0,264,-0,-327,0,401,-0,-489,0,595,-0,-724,0,880,-0,-1075,0,1323,-0,-1652,0,2114,-0,-2819,0,4056,-0,-6883,0,20837,32767, + 20837,0,-6883,-0,4056,0,-2819,-0,2114,0,-1652,-0,1323,0,-1075,-0,880,0,-724,-0,595,0,-489,-0,401,0,-327,-0,264,0,-213,-0, + 169,0,-134,-0,104,0,-80,-0,61,0,-45,-0,33,0,-24,-0,17,0,-11,-0,8,0,-5,-0,3,0,-2,-0,1,0,-0, 0 }; + +static int16_t fir_96_2[] = { + -4,0,8,-0,-14,0,23,-0,-36,0,52,-0,-75,0,104,-0,-140,0,186,-0,-243,0,314,-0,-400,0,505,-0,-634,0,793,-0, + -993,0,1247,-0,-1585,0,2056,-0,-2773,0,4022,-0,-6862,0,20830,32767,20830,0,-6862,-0,4022,0,-2773,-0,2056,0,-1585,-0,1247,0,-993,-0, + 793,0,-634,-0,505,0,-400,-0,314,0,-243,-0,186,0,-140,-0,104,0,-75,-0,52,0,-36,-0,23,0,-14,-0,8,0,-4,0}; + +static int16_t fir_64_2[] = { + -58,0,83,-0,-127,0,185,-0,-262,0,361,-0,-488,0,648,-0,-853,0,1117,-0,-1466,0,1954,-0,-2689,0,3960,-0,-6825,0,20818,32767, + 20818,0,-6825,-0,3960,0,-2689,-0,1954,0,-1466,-0,1117,0,-853,-0,648,0,-488,-0,361,0,-262,-0,185,0,-127,-0,83,0,-58,0}; + +#define FIR_BUF_SIZE 8192 + +int ad9361_set_trx_fir_enable(struct iio_device *dev, int enable) +{ + int ret = iio_device_attr_write_bool(dev, + "in_out_voltage_filter_fir_en", !!enable); + if (ret < 0) + ret = iio_channel_attr_write_bool(iio_device_find_channel(dev, "out", false), + "voltage_filter_fir_en", !!enable); + return ret; +} + +int ad9361_get_trx_fir_enable(struct iio_device *dev, int *enable) +{ + bool value; + + int ret = iio_device_attr_read_bool(dev, "in_out_voltage_filter_fir_en", &value); + + if (ret < 0) + ret = iio_channel_attr_read_bool(iio_device_find_channel(dev, "out", false), + "voltage_filter_fir_en", &value); + + if (!ret) + *enable = value; + + return ret; +} + +int ad9361_set_bb_rate(struct iio_device *dev, unsigned long rate) +{ + struct iio_channel *chan; + long long current_rate; + int dec, taps, ret, i, enable, len = 0; + int16_t *fir; + char *buf; + + if (rate <= 20000000UL) { + dec = 4; + taps = 128; + fir = fir_128_4; + } else if (rate <= 40000000UL) { + dec = 2; + fir = fir_128_2; + taps = 128; + } else if (rate <= 53333333UL) { + dec = 2; + fir = fir_96_2; + taps = 96; + } else { + dec = 2; + fir = fir_64_2; + taps = 64; + } + + chan = iio_device_find_channel(dev, "voltage0", true); + if (chan == NULL) + return -ENODEV; + + ret = iio_channel_attr_read_longlong(chan, "sampling_frequency", ¤t_rate); + if (ret < 0) + return ret; + + ret = ad9361_get_trx_fir_enable(dev, &enable); + if (ret < 0) + return ret; + + if (enable) { + if (current_rate <= (25000000 / 12)) + iio_channel_attr_write_longlong(chan, "sampling_frequency", 3000000); + + ret = ad9361_set_trx_fir_enable(dev, false); + if (ret < 0) + return ret; + } + + buf = malloc(FIR_BUF_SIZE); + if (!buf) + return -ENOMEM; + + len += snprintf(buf + len, FIR_BUF_SIZE - len, "RX 3 GAIN -6 DEC %d\n", dec); + len += snprintf(buf + len, FIR_BUF_SIZE - len, "TX 3 GAIN 0 INT %d\n", dec); + + for (i = 0; i < taps; i++) + len += snprintf(buf + len, FIR_BUF_SIZE - len, "%d,%d\n", fir[i], fir[i]); + + len += snprintf(buf + len, FIR_BUF_SIZE - len, "\n"); + + ret = iio_device_attr_write_raw(dev, "filter_fir_config", buf, len); + free (buf); + + if (ret < 0) + return ret; + + if (rate <= (25000000 / 12)) { + int dacrate, txrate, max; + char readbuf[100]; + + ret = iio_device_attr_read(dev, "tx_path_rates", readbuf, sizeof(readbuf)); + if (ret < 0) + return ret; + ret = sscanf(readbuf, "BBPLL:%*d DAC:%d T2:%*d T1:%*d TF:%*d TXSAMP:%d", &dacrate, &txrate); + if (ret != 2) + return -EFAULT; + + if (txrate == 0) + return -EINVAL; + + max = (dacrate / txrate) * 16; + if (max < taps) + iio_channel_attr_write_longlong(chan, "sampling_frequency", 3000000); + + ret = ad9361_set_trx_fir_enable(dev, true); + if (ret < 0) + return ret; + ret = iio_channel_attr_write_longlong(chan, "sampling_frequency", rate); + if (ret < 0) + return ret; + } else { + ret = iio_channel_attr_write_longlong(chan, "sampling_frequency", rate); + if (ret < 0) + return ret; + ret = ad9361_set_trx_fir_enable(dev, true); + if (ret < 0) + return ret; + } + + return 0; +} diff --git a/player/plutoplayer_win/getopt.c b/player/plutoplayer_win/getopt.c new file mode 100644 index 0000000..dab5fd8 --- /dev/null +++ b/player/plutoplayer_win/getopt.c @@ -0,0 +1,110 @@ +/* +* Copyright (c) 1987, 1993, 1994 +* The Regents of the University of California. All rights reserved. +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions +* are met: +* 1. Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* 2. Redistributions in binary form must reproduce the above copyright +* notice, this list of conditions and the following disclaimer in the +* documentation and/or other materials provided with the distribution. +* 3. All advertising materials mentioning features or use of this software +* must display the following acknowledgement: +* This product includes software developed by the University of +* California, Berkeley and its contributors. +* 4. Neither the name of the University nor the names of its contributors +* may be used to endorse or promote products derived from this software +* without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND +* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE +* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +* SUCH DAMAGE. +*/ + +#include "getopt.h" +#include +#include + +int opterr = 1, /* if error message should be printed */ + optind = 1, /* index into parent argv vector */ + optopt, /* character checked for validity */ + optreset; /* reset getopt */ +char *optarg; /* argument associated with option */ + +#define BADCH (int)'?' +#define BADARG (int)':' +#define EMSG "" + +/* + * getopt -- + * Parse argc/argv argument vector. + * + * Note: Unlike GNU getopt(), after a non-option argument, all further + * arguments are considered also non-options. This is similar to + * the way non-GNU Unix systems work. + */ +int getopt(int nargc, char * const nargv[], const char *ostr) +{ + static char *place = EMSG; /* option letter processing */ + const char *oli; /* option letter list index */ + + if (optreset || !*place) { /* update scanning pointer */ + optreset = 0; + if (optind >= nargc || *(place = nargv[optind]) != '-') { + place = EMSG; + return (-1); + } + if (place[1] && *++place == '-') { /* found "--" */ + ++optind; + place = EMSG; + return (-1); + } + } /* option letter okay? */ + if ((optopt = (int)*place++) == (int)':' || + !(oli = strchr(ostr, optopt))) { + /* + * if the user didn't specify '-' as an option, + * assume it means -1. + */ + if (optopt == (int)'-') + return (-1); + if (!*place) + ++optind; + if (opterr && *ostr != ':') + (void)printf("illegal option -- %c\n", optopt); + return (BADCH); + } + if (*++oli != ':') { /* don't need argument */ + optarg = NULL; + if (!*place) + ++optind; + } + else { /* need an argument */ + if (*place) /* no white space */ + optarg = place; + else if (nargc <= ++optind) { /* no arg */ + place = EMSG; + if (*ostr == ':') + return (BADARG); + if (opterr) + (void)printf("option requires an argument -- %c\n", optopt); + return (BADCH); + } + else /* white space */ + optarg = nargv[optind]; + place = EMSG; + ++optind; + } + return (optopt); /* dump back option letter */ +} + \ No newline at end of file diff --git a/player/plutoplayer_win/getopt.h b/player/plutoplayer_win/getopt.h new file mode 100644 index 0000000..5978e22 --- /dev/null +++ b/player/plutoplayer_win/getopt.h @@ -0,0 +1,9 @@ +#ifndef GETOPT_H +#define GETOPT_H + +extern char *optarg; +extern int optind; + +int getopt(int nargc, char * const nargv[], const char *ostr) ; + +#endif diff --git a/player/plutoplayer_win/iio.h b/player/plutoplayer_win/iio.h new file mode 100644 index 0000000..cefac60 --- /dev/null +++ b/player/plutoplayer_win/iio.h @@ -0,0 +1,1974 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +/* + * libiio - Library for interfacing industrial I/O (IIO) devices + * + * Copyright (C) 2014 Analog Devices, Inc. + * Author: Paul Cercueil + */ + +/** @file iio.h + * @brief Public interface */ + +#ifndef __IIO_H__ +#define __IIO_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include +#include +#include + +#if (defined(_WIN32) || defined(__MBED__)) +#ifndef _SSIZE_T_DEFINED +typedef ptrdiff_t ssize_t; +#define _SSIZE_T_DEFINED +#endif +#else +#include +#endif + +#if defined(_MSC_VER) && (_MSC_VER < 1800) && !defined(__BOOL_DEFINED) +#undef bool +#undef false +#undef true +#define bool char +#define false 0 +#define true 1 +#else +#include +#endif + +#if defined(__GNUC__) && !defined(MATLAB_MEX_FILE) && !defined(MATLAB_LOADLIBRARY) +#ifndef __cnst +#define __cnst __attribute__((const)) +#endif +#ifndef __pure +#define __pure __attribute__((pure)) +#endif +#define __notused __attribute__((unused)) +#ifdef IIO_CHECK_RET +#define __check_ret __attribute__((warn_unused_result)) +#else +#define __check_ret +#endif +#else +#define __cnst +#define __pure +#define __notused +#define __check_ret +#endif + +#ifdef _WIN32 +# ifdef LIBIIO_STATIC +# define __api +# elif defined(LIBIIO_EXPORTS) +# define __api __declspec(dllexport) +# else +# define __api __declspec(dllimport) +# endif +#elif __GNUC__ >= 4 && !defined(MATLAB_MEX_FILE) && !defined(MATLAB_LOADLIBRARY) +# define __api __attribute__((visibility ("default"))) +#else +# define __api +#endif + +struct iio_context; +struct iio_device; +struct iio_channel; +struct iio_buffer; + +struct iio_context_info; +struct iio_scan_context; +struct iio_scan_block; + +/* + * header guard to protect these enums from being defined + * twice + */ +#ifndef _IIO_TYPES_H_ +#define _IIO_TYPES_H_ + +/** + * @enum iio_chan_type + * @brief IIO channel type + * + * A IIO channel has a type specifying the type of data associated with the + * channel. + */ +enum iio_chan_type { + IIO_VOLTAGE, + IIO_CURRENT, + IIO_POWER, + IIO_ACCEL, + IIO_ANGL_VEL, + IIO_MAGN, + IIO_LIGHT, + IIO_INTENSITY, + IIO_PROXIMITY, + IIO_TEMP, + IIO_INCLI, + IIO_ROT, + IIO_ANGL, + IIO_TIMESTAMP, + IIO_CAPACITANCE, + IIO_ALTVOLTAGE, + IIO_CCT, + IIO_PRESSURE, + IIO_HUMIDITYRELATIVE, + IIO_ACTIVITY, + IIO_STEPS, + IIO_ENERGY, + IIO_DISTANCE, + IIO_VELOCITY, + IIO_CONCENTRATION, + IIO_RESISTANCE, + IIO_PH, + IIO_UVINDEX, + IIO_ELECTRICALCONDUCTIVITY, + IIO_COUNT, + IIO_INDEX, + IIO_GRAVITY, + IIO_POSITIONRELATIVE, + IIO_PHASE, + IIO_MASSCONCENTRATION, + IIO_CHAN_TYPE_UNKNOWN = INT_MAX +}; + +/** + * @enum iio_modifier + * @brief IIO channel modifier + * + * In a addition to a type a IIO channel can optionally have a channel modifier + * further specifying the data type of of the channel. + */ +enum iio_modifier { + IIO_NO_MOD, + IIO_MOD_X, + IIO_MOD_Y, + IIO_MOD_Z, + IIO_MOD_X_AND_Y, + IIO_MOD_X_AND_Z, + IIO_MOD_Y_AND_Z, + IIO_MOD_X_AND_Y_AND_Z, + IIO_MOD_X_OR_Y, + IIO_MOD_X_OR_Z, + IIO_MOD_Y_OR_Z, + IIO_MOD_X_OR_Y_OR_Z, + IIO_MOD_LIGHT_BOTH, + IIO_MOD_LIGHT_IR, + IIO_MOD_ROOT_SUM_SQUARED_X_Y, + IIO_MOD_SUM_SQUARED_X_Y_Z, + IIO_MOD_LIGHT_CLEAR, + IIO_MOD_LIGHT_RED, + IIO_MOD_LIGHT_GREEN, + IIO_MOD_LIGHT_BLUE, + IIO_MOD_QUATERNION, + IIO_MOD_TEMP_AMBIENT, + IIO_MOD_TEMP_OBJECT, + IIO_MOD_NORTH_MAGN, + IIO_MOD_NORTH_TRUE, + IIO_MOD_NORTH_MAGN_TILT_COMP, + IIO_MOD_NORTH_TRUE_TILT_COMP, + IIO_MOD_RUNNING, + IIO_MOD_JOGGING, + IIO_MOD_WALKING, + IIO_MOD_STILL, + IIO_MOD_ROOT_SUM_SQUARED_X_Y_Z, + IIO_MOD_I, + IIO_MOD_Q, + IIO_MOD_CO2, + IIO_MOD_VOC, + IIO_MOD_LIGHT_UV, + IIO_MOD_LIGHT_DUV, + IIO_MOD_PM1, + IIO_MOD_PM2P5, + IIO_MOD_PM4, + IIO_MOD_PM10, + IIO_MOD_ETHANOL, + IIO_MOD_H2, + IIO_MOD_O2, +}; + +/** + * @enum iio_event_type + * @brief IIO event type + * + * Some IIO devices can deliver events. The type of the event can be specified + * by one of the iio_event_type values. + */ +enum iio_event_type { + IIO_EV_TYPE_THRESH, + IIO_EV_TYPE_MAG, + IIO_EV_TYPE_ROC, + IIO_EV_TYPE_THRESH_ADAPTIVE, + IIO_EV_TYPE_MAG_ADAPTIVE, + IIO_EV_TYPE_CHANGE, +}; + +/** + * @enum iio_event_direction + * @brief IIO event direction + * + * When applicable, this enum specifies the direction of the iio_event_type. + */ +enum iio_event_direction { + IIO_EV_DIR_EITHER, + IIO_EV_DIR_RISING, + IIO_EV_DIR_FALLING, + IIO_EV_DIR_NONE, +}; + +#endif /* _IIO_TYPES_H_ */ + +/* ---------------------------------------------------------------------------*/ +/* ------------------------- Scan functions ----------------------------------*/ +/** @defgroup Scan Functions for scanning available contexts + * @{ + * @struct iio_scan_context + * @brief The scanning context + * + * @struct iio_context_info + * @brief The information related to a discovered context + */ + + +/** @brief Create a scan context + * @param backend A NULL-terminated string containing a comma-separated + * list of the backend(s) to use for scanning. + * @param flags Unused for now. Set to 0. + * @return on success, a pointer to a iio_scan_context structure + * @return On failure, NULL is returned and errno is set appropriately + * + * NOTE: Libiio version 0.20 and above can handle multiple + * strings, for instance "local:usb:", "ip:usb:", "local:usb:ip:", and + * require a colon as the delimiter. + * Libiio version 0.24 and above prefer a comma instead of colon as the + * delimiter, and handle specifying backend-specific information. For + * instance, "local,usb=0456:*" will scan the local backend and limit + * scans on USB to vendor ID 0x0456, and accept all product IDs. The + * "usb=0456:b673" string would limit the scan to the device with this + * particular VID/PID. Both IDs are expected in hexadecimal, no 0x + * prefix needed. */ +__api __check_ret struct iio_scan_context * iio_create_scan_context( + const char *backend, unsigned int flags); + + +/** @brief Destroy the given scan context + * @param ctx A pointer to an iio_scan_context structure + * + * NOTE: After that function, the iio_scan_context pointer shall be invalid. */ +__api void iio_scan_context_destroy(struct iio_scan_context *ctx); + + +/** @brief Enumerate available contexts + * @param ctx A pointer to an iio_scan_context structure + * @param info A pointer to a 'const struct iio_context_info **' typed variable. + * The pointed variable will be initialized on success. + * @returns On success, the number of contexts found. + * @returns On failure, a negative error number. + */ +__api __check_ret ssize_t iio_scan_context_get_info_list(struct iio_scan_context *ctx, + struct iio_context_info ***info); + + +/** @brief Free a context info list + * @param info A pointer to a 'const struct iio_context_info *' typed variable + */ +__api void iio_context_info_list_free(struct iio_context_info **info); + + +/** @brief Get a description of a discovered context + * @param info A pointer to an iio_context_info structure + * @return A pointer to a static NULL-terminated string + */ +__api __check_ret __pure const char * iio_context_info_get_description( + const struct iio_context_info *info); + + +/** @brief Get the URI of a discovered context + * @param info A pointer to an iio_context_info structure + * @return A pointer to a static NULL-terminated string + */ +__api __check_ret __pure const char * iio_context_info_get_uri( + const struct iio_context_info *info); + + +/** @brief Create a scan block + * @param backend A NULL-terminated string containing the backend to use for + * scanning. If NULL, all the available backends are used. + * @param flags Unused for now. Set to 0. + * @return on success, a pointer to a iio_scan_block structure + * @return On failure, NULL is returned and errno is set appropriately + * + * Introduced in version 0.20. */ +__api struct iio_scan_block * iio_create_scan_block( + const char *backend, unsigned int flags); + + +/** @brief Destroy the given scan block + * @param blk A pointer to an iio_scan_block structure + * + * NOTE: After that function, the iio_scan_block pointer shall be invalid. + * + * Introduced in version 0.20. */ +__api void iio_scan_block_destroy(struct iio_scan_block *blk); + + +/** @brief Enumerate available contexts via scan block + * @param blk A pointer to a iio_scan_block structure. + * @returns On success, the number of contexts found. + * @returns On failure, a negative error number. + * + * Introduced in version 0.20. */ +__api ssize_t iio_scan_block_scan(struct iio_scan_block *blk); + + +/** @brief Get the iio_context_info for a particular context + * @param blk A pointer to an iio_scan_block structure + * @param index The index corresponding to the context. + * @return A pointer to the iio_context_info for the context + * @returns On success, a pointer to the specified iio_context_info + * @returns On failure, NULL is returned and errno is set appropriately + * + * Introduced in version 0.20. */ +__api struct iio_context_info *iio_scan_block_get_info( + struct iio_scan_block *blk, unsigned int index); + + +/** @} *//* ------------------------------------------------------------------*/ +/* ------------------------- Top-level functions -----------------------------*/ +/** @defgroup TopLevel Top-level functions + * @{ */ + + +/** @brief Get the version of the libiio library + * @param major A pointer to an unsigned integer (NULL accepted) + * @param minor A pointer to an unsigned integer (NULL accepted) + * @param git_tag A pointer to a 8-characters buffer (NULL accepted) */ +__api void iio_library_get_version(unsigned int *major, + unsigned int *minor, char git_tag[8]); + + +/** @brief Get a string description of an error code + * @param err The error code + * @param dst A pointer to the memory area where the NULL-terminated string + * corresponding to the error message will be stored + * @param len The available length of the memory area, in bytes */ +__api void iio_strerror(int err, char *dst, size_t len); + + +/** @brief Check if the specified backend is available + * @param backend The name of the backend to query + * @return True if the backend is available, false otherwise + * + * Introduced in version 0.9. */ +__api __check_ret __cnst bool iio_has_backend(const char *backend); + + +/** @brief Get the number of available backends + * @return The number of available backends + * + * Introduced in version 0.9. */ +__api __check_ret __cnst unsigned int iio_get_backends_count(void); + + +/** @brief Retrieve the name of a given backend + * @param index The index corresponding to the attribute + * @return On success, a pointer to a static NULL-terminated string + * @return If the index is invalid, NULL is returned + * + * Introduced in version 0.9. */ +__api __check_ret __cnst const char * iio_get_backend(unsigned int index); + + +/** @} *//* ------------------------------------------------------------------*/ +/* ------------------------- Context functions -------------------------------*/ +/** @defgroup Context Context + * @{ + * @struct iio_context + * @brief Contains the representation of an IIO context */ + + +/** @brief Create a context from local or remote IIO devices + * @return On success, A pointer to an iio_context structure + * @return On failure, NULL is returned and errno is set appropriately + * + * NOTE: This function will create a context with the URI + * provided in the IIOD_REMOTE environment variable. If not set, a local + * context will be created instead. */ +__api __check_ret struct iio_context * iio_create_default_context(void); + + +/** @brief Create a context from local IIO devices (Linux only) + * @return On success, A pointer to an iio_context structure + * @return On failure, NULL is returned and errno is set appropriately */ +__api __check_ret struct iio_context * iio_create_local_context(void); + + +/** @brief Create a context from a XML file + * @param xml_file Path to the XML file to open + * @return On success, A pointer to an iio_context structure + * @return On failure, NULL is returned and errno is set appropriately + * + * NOTE: The format of the XML must comply to the one returned by + * iio_context_get_xml. */ +__api __check_ret struct iio_context * iio_create_xml_context(const char *xml_file); + + +/** @brief Create a context from XML data in memory + * @param xml Pointer to the XML data in memory + * @param len Length of the XML string in memory (excluding the final \0) + * @return On success, A pointer to an iio_context structure + * @return On failure, NULL is returned and errno is set appropriately + * + * NOTE: The format of the XML must comply to the one returned by + * iio_context_get_xml */ +__api __check_ret struct iio_context * iio_create_xml_context_mem( + const char *xml, size_t len); + + +/** @brief Create a context from the network + * @param host Hostname, IPv4 or IPv6 address where the IIO Daemon is running + * @return On success, a pointer to an iio_context structure + * @return On failure, NULL is returned and errno is set appropriately */ +__api __check_ret struct iio_context * iio_create_network_context(const char *host); + + +/** @brief Create a context from a URI description + * @param uri A URI describing the context location + * @return On success, a pointer to a iio_context structure + * @return On failure, NULL is returned and errno is set appropriately + * + * NOTE: The following URIs are supported based on compile time backend + * support: + * - Local backend, "local:"\n + * Does not have an address part. For example "local:" + * - XML backend, "xml:"\n Requires a path to the XML file for the address part. + * For example "xml:/home/user/file.xml" + * - Network backend, "ip:"\n Requires a hostname, IPv4, or IPv6 to connect to + * a specific running IIO Daemon or no address part for automatic discovery + * when library is compiled with ZeroConf support. For example + * "ip:192.168.2.1", or "ip:localhost", or "ip:" + * or "ip:plutosdr.local". To support alternative port numbers the + * standard ip:host:port format is used. A special format is required as + * defined in RFC2732 for IPv6 literal hostnames, (adding '[]' around the host) + * to use a ip:[x:x:x:x:x:x:x:x]:port format. + * Valid examples would be: + * - ip: Any host on default port + * - ip::40000 Any host on port 40000 + * - ip:analog.local Default port + * - ip:brain.local:40000 Port 40000 + * - ip:192.168.1.119 Default Port + * - ip:192.168.1.119:40000 Port 40000 + * - ip:2601:190:400:da:47b3:55ab:3914:bff1 Default Port + * - ip:[2601:190:400:da:9a90:96ff:feb5:acaa]:40000 Port 40000 + * - USB backend, "usb:"\n When more than one usb device is attached, requires + * bus, address, and interface parts separated with a dot. For example + * "usb:3.32.5". Where there is only one USB device attached, the shorthand + * "usb:" can be used. + * - Serial backend, "serial:"\n Requires: + * - a port (/dev/ttyUSB0), + * - baud_rate (default 115200) + * - serial port configuration + * - data bits (5 6 7 8 9) + * - parity ('n' none, 'o' odd, 'e' even, 'm' mark, 's' space) + * - stop bits (1 2) + * - flow control ('\0' none, 'x' Xon Xoff, 'r' RTSCTS, 'd' DTRDSR) + * + * For example "serial:/dev/ttyUSB0,115200" or "serial:/dev/ttyUSB0,115200,8n1"*/ +__api __check_ret struct iio_context * iio_create_context_from_uri(const char *uri); + + +/** @brief Duplicate a pre-existing IIO context + * @param ctx A pointer to an iio_context structure + * @return On success, A pointer to an iio_context structure + * @return On failure, NULL is returned and errno is set appropriately + * + * NOTE: This function is not supported on 'usb:' contexts, since libusb + * can only claim the interface once. "Function not implemented" is the expected errno. + * Any context which is cloned, must be destroyed via calling iio_context_destroy() */ +__api __check_ret struct iio_context * iio_context_clone(const struct iio_context *ctx); + + +/** @brief Destroy the given context + * @param ctx A pointer to an iio_context structure + * + * NOTE: After that function, the iio_context pointer shall be invalid. */ +__api void iio_context_destroy(struct iio_context *ctx); + + +/** @brief Get the version of the backend in use + * @param ctx A pointer to an iio_context structure + * @param major A pointer to an unsigned integer (NULL accepted) + * @param minor A pointer to an unsigned integer (NULL accepted) + * @param git_tag A pointer to a 8-characters buffer (NULL accepted) + * @return On success, 0 is returned + * @return On error, a negative errno code is returned */ +__api __check_ret int iio_context_get_version(const struct iio_context *ctx, + unsigned int *major, unsigned int *minor, char git_tag[8]); + + +/** @brief Obtain a XML representation of the given context + * @param ctx A pointer to an iio_context structure + * @return A pointer to a static NULL-terminated string */ +__api __check_ret __pure const char * iio_context_get_xml(const struct iio_context *ctx); + + +/** @brief Get the name of the given context + * @param ctx A pointer to an iio_context structure + * @return A pointer to a static NULL-terminated string + * + * NOTE:The returned string will be local, + * xml or network when the context has been + * created with the local, xml and network backends respectively.*/ +__api __check_ret __pure const char * iio_context_get_name(const struct iio_context *ctx); + + +/** @brief Get a description of the given context + * @param ctx A pointer to an iio_context structure + * @return A pointer to a static NULL-terminated string + * + * NOTE:The returned string will contain human-readable information about + * the current context. */ +__api __check_ret __pure const char * iio_context_get_description( + const struct iio_context *ctx); + + +/** @brief Get the number of context-specific attributes + * @param ctx A pointer to an iio_context structure + * @return The number of context-specific attributes + * + * Introduced in version 0.9. */ +__api __check_ret __pure unsigned int iio_context_get_attrs_count( + const struct iio_context *ctx); + + +/** @brief Retrieve the name and value of a context-specific attribute + * @param ctx A pointer to an iio_context structure + * @param index The index corresponding to the attribute + * @param name A pointer to a const char * pointer (NULL accepted) + * @param value A pointer to a const char * pointer (NULL accepted) + * @return On success, 0 is returned + * @return On error, a negative errno code is returned + * + * Introduced in version 0.9. */ +__api __check_ret int iio_context_get_attr( + const struct iio_context *ctx, unsigned int index, + const char **name, const char **value); + + +/** @brief Retrieve the value of a context-specific attribute + * @param ctx A pointer to an iio_context structure + * @param name The name of the context attribute to read + * @return On success, a pointer to a static NULL-terminated string + * @return If the name does not correspond to any attribute, NULL is + * returned + * + * Introduced in version 0.9. */ +__api __check_ret const char * iio_context_get_attr_value( + const struct iio_context *ctx, const char *name); + + +/** @brief Enumerate the devices found in the given context + * @param ctx A pointer to an iio_context structure + * @return The number of devices found */ +__api __check_ret __pure unsigned int iio_context_get_devices_count( + const struct iio_context *ctx); + + +/** @brief Get the device present at the given index + * @param ctx A pointer to an iio_context structure + * @param index The index corresponding to the device + * @return On success, a pointer to an iio_device structure + * @return If the index is invalid, NULL is returned */ +__api __check_ret __pure struct iio_device * iio_context_get_device( + const struct iio_context *ctx, unsigned int index); + + +/** @brief Try to find a device structure by its ID, label or name + * @param ctx A pointer to an iio_context structure + * @param name A NULL-terminated string corresponding to the ID, label or name + * of the device to search for + * @return On success, a pointer to an iio_device structure + * @return If the parameter does not correspond to the ID, label or name of + * any known device, NULL is returned */ +__api __check_ret __pure struct iio_device * iio_context_find_device( + const struct iio_context *ctx, const char *name); + + +/** @brief Set a timeout for I/O operations + * @param ctx A pointer to an iio_context structure + * @param timeout_ms A positive integer representing the time in milliseconds + * after which a timeout occurs. A value of 0 is used to specify that no + * timeout should occur. + * @return On success, 0 is returned + * @return On error, a negative errno code is returned */ +__api __check_ret int iio_context_set_timeout( + struct iio_context *ctx, unsigned int timeout_ms); + + +/** @} *//* ------------------------------------------------------------------*/ +/* ------------------------- Device functions --------------------------------*/ +/** @defgroup Device Device + * @{ + * @struct iio_device + * @brief Represents a device in the IIO context */ + + +/** @brief Retrieve a pointer to the iio_context structure + * @param dev A pointer to an iio_device structure + * @return A pointer to an iio_context structure */ +__api __check_ret __pure const struct iio_context * iio_device_get_context( + const struct iio_device *dev); + + +/** @brief Retrieve the device ID (e.g. iio:device0) + * @param dev A pointer to an iio_device structure + * @return A pointer to a static NULL-terminated string */ +__api __check_ret __pure const char * iio_device_get_id(const struct iio_device *dev); + + +/** @brief Retrieve the device name (e.g. xadc) + * @param dev A pointer to an iio_device structure + * @return A pointer to a static NULL-terminated string + * + * NOTE: if the device has no name, NULL is returned. */ +__api __check_ret __pure const char * iio_device_get_name(const struct iio_device *dev); + + +/** @brief Retrieve the device label (e.g. lo_pll0_rx_adf4351) + * @param dev A pointer to an iio_device structure + * @return A pointer to a static NULL-terminated string + * + * NOTE: if the device has no label, NULL is returned. */ +__api __check_ret __pure const char * iio_device_get_label(const struct iio_device *dev); + + +/** @brief Enumerate the channels of the given device + * @param dev A pointer to an iio_device structure + * @return The number of channels found */ +__api __check_ret __pure unsigned int iio_device_get_channels_count( + const struct iio_device *dev); + + +/** @brief Enumerate the device-specific attributes of the given device + * @param dev A pointer to an iio_device structure + * @return The number of device-specific attributes found */ +__api __check_ret __pure unsigned int iio_device_get_attrs_count( + const struct iio_device *dev); + +/** @brief Enumerate the buffer-specific attributes of the given device + * @param dev A pointer to an iio_device structure + * @return The number of buffer-specific attributes found */ +__api __check_ret __pure unsigned int iio_device_get_buffer_attrs_count( + const struct iio_device *dev); + +/** @brief Get the channel present at the given index + * @param dev A pointer to an iio_device structure + * @param index The index corresponding to the channel + * @return On success, a pointer to an iio_channel structure + * @return If the index is invalid, NULL is returned */ +__api __check_ret __pure struct iio_channel * iio_device_get_channel( + const struct iio_device *dev, unsigned int index); + + +/** @brief Get the device-specific attribute present at the given index + * @param dev A pointer to an iio_device structure + * @param index The index corresponding to the attribute + * @return On success, a pointer to a static NULL-terminated string + * @return If the index is invalid, NULL is returned */ +__api __check_ret __pure const char * iio_device_get_attr( + const struct iio_device *dev, unsigned int index); + +/** @brief Get the buffer-specific attribute present at the given index + * @param dev A pointer to an iio_device structure + * @param index The index corresponding to the attribute + * @return On success, a pointer to a static NULL-terminated string + * @return If the index is invalid, NULL is returned */ +__api __check_ret __pure const char * iio_device_get_buffer_attr( + const struct iio_device *dev, unsigned int index); + +/** @brief Try to find a channel structure by its name of ID + * @param dev A pointer to an iio_device structure + * @param name A NULL-terminated string corresponding to the name or the ID of + * the channel to search for + * @param output True if the searched channel is output, False otherwise + * @return On success, a pointer to an iio_channel structure + * @return If the name or ID does not correspond to any known channel of the + * given device, NULL is returned */ +__api __check_ret __pure struct iio_channel * iio_device_find_channel( + const struct iio_device *dev, const char *name, bool output); + + +/** @brief Try to find a device-specific attribute by its name + * @param dev A pointer to an iio_device structure + * @param name A NULL-terminated string corresponding to the name of the + * attribute + * @return On success, a pointer to a static NULL-terminated string + * @return If the name does not correspond to any known attribute of the given + * device, NULL is returned + * + * NOTE: This function is useful to detect the presence of an attribute. + * It can also be used to retrieve the name of an attribute as a pointer to a + * static string from a dynamically allocated string. */ +__api __check_ret __pure const char * iio_device_find_attr( + const struct iio_device *dev, const char *name); + +/** @brief Try to find a buffer-specific attribute by its name + * @param dev A pointer to an iio_device structure + * @param name A NULL-terminated string corresponding to the name of the + * attribute + * @return On success, a pointer to a static NULL-terminated string + * @return If the name does not correspond to any known attribute of the given + * device, NULL is returned + * + * NOTE: This function is useful to detect the presence of an attribute. + * It can also be used to retrieve the name of an attribute as a pointer to a + * static string from a dynamically allocated string. */ +__api __check_ret __pure const char * iio_device_find_buffer_attr( + const struct iio_device *dev, const char *name); + +/** @brief Read the content of the given device-specific attribute + * @param dev A pointer to an iio_device structure + * @param attr A NULL-terminated string corresponding to the name of the + * attribute + * @param dst A pointer to the memory area where the NULL-terminated string + * corresponding to the value read will be stored + * @param len The available length of the memory area, in bytes + * @return On success, the number of bytes written to the buffer + * @return On error, a negative errno code is returned + * + * NOTE:By passing NULL as the "attr" argument to iio_device_attr_read, + * it is now possible to read all of the attributes of a device. + * + * The buffer is filled with one block of data per attribute of the device, + * by the order they appear in the iio_device structure. + * + * The first four bytes of one block correspond to a 32-bit signed value in + * network order. If negative, it corresponds to the errno code that were + * returned when reading the attribute; if positive, it corresponds to the + * length of the data read. In that case, the rest of the block contains + * the data. */ +__api __check_ret ssize_t iio_device_attr_read(const struct iio_device *dev, + const char *attr, char *dst, size_t len); + + +/** @brief Read the content of all device-specific attributes + * @param dev A pointer to an iio_device structure + * @param cb A pointer to a callback function + * @param data A pointer that will be passed to the callback function + * @return On success, 0 is returned + * @return On error, a negative errno code is returned + * + * NOTE: This function is especially useful when used with the network + * backend, as all the device-specific attributes are read in one single + * command. */ +__api __check_ret int iio_device_attr_read_all(struct iio_device *dev, + int (*cb)(struct iio_device *dev, const char *attr, + const char *value, size_t len, void *d), + void *data); + + +/** @brief Read the content of the given device-specific attribute + * @param dev A pointer to an iio_device structure + * @param attr A NULL-terminated string corresponding to the name of the + * attribute + * @param val A pointer to a bool variable where the value should be stored + * @return On success, 0 is returned + * @return On error, a negative errno code is returned */ +__api __check_ret int iio_device_attr_read_bool(const struct iio_device *dev, + const char *attr, bool *val); + + +/** @brief Read the content of the given device-specific attribute + * @param dev A pointer to an iio_device structure + * @param attr A NULL-terminated string corresponding to the name of the + * attribute + * @param val A pointer to a long long variable where the value should be stored + * @return On success, 0 is returned + * @return On error, a negative errno code is returned */ +__api __check_ret int iio_device_attr_read_longlong(const struct iio_device *dev, + const char *attr, long long *val); + + +/** @brief Read the content of the given device-specific attribute + * @param dev A pointer to an iio_device structure + * @param attr A NULL-terminated string corresponding to the name of the + * attribute + * @param val A pointer to a double variable where the value should be stored + * @return On success, 0 is returned + * @return On error, a negative errno code is returned */ +__api __check_ret int iio_device_attr_read_double(const struct iio_device *dev, + const char *attr, double *val); + + +/** @brief Set the value of the given device-specific attribute + * @param dev A pointer to an iio_device structure + * @param attr A NULL-terminated string corresponding to the name of the + * attribute + * @param src A NULL-terminated string to set the attribute to + * @return On success, the number of bytes written + * @return On error, a negative errno code is returned + * + * NOTE:By passing NULL as the "attr" argument to iio_device_attr_write, + * it is now possible to write all of the attributes of a device. + * + * The buffer must contain one block of data per attribute of the device, + * by the order they appear in the iio_device structure. + * + * The first four bytes of one block correspond to a 32-bit signed value in + * network order. If negative, the attribute is not written; if positive, + * it corresponds to the length of the data to write. In that case, the rest + * of the block must contain the data. */ +__api __check_ret ssize_t iio_device_attr_write(const struct iio_device *dev, + const char *attr, const char *src); + + +/** @brief Set the value of the given device-specific attribute + * @param dev A pointer to an iio_device structure + * @param attr A NULL-terminated string corresponding to the name of the + * attribute + * @param src A pointer to the data to be written + * @param len The number of bytes that should be written + * @return On success, the number of bytes written + * @return On error, a negative errno code is returned */ +__api __check_ret ssize_t iio_device_attr_write_raw(const struct iio_device *dev, + const char *attr, const void *src, size_t len); + + +/** @brief Set the values of all device-specific attributes + * @param dev A pointer to an iio_device structure + * @param cb A pointer to a callback function + * @param data A pointer that will be passed to the callback function + * @return On success, 0 is returned + * @return On error, a negative errno code is returned + * + * NOTE: This function is especially useful when used with the network + * backend, as all the device-specific attributes are written in one single + * command. */ +__api __check_ret int iio_device_attr_write_all(struct iio_device *dev, + ssize_t (*cb)(struct iio_device *dev, + const char *attr, void *buf, size_t len, void *d), + void *data); + + +/** @brief Set the value of the given device-specific attribute + * @param dev A pointer to an iio_device structure + * @param attr A NULL-terminated string corresponding to the name of the + * attribute + * @param val A bool value to set the attribute to + * @return On success, 0 is returned + * @return On error, a negative errno code is returned */ +__api __check_ret int iio_device_attr_write_bool(const struct iio_device *dev, + const char *attr, bool val); + + +/** @brief Set the value of the given device-specific attribute + * @param dev A pointer to an iio_device structure + * @param attr A NULL-terminated string corresponding to the name of the + * attribute + * @param val A long long value to set the attribute to + * @return On success, 0 is returned + * @return On error, a negative errno code is returned */ +__api __check_ret int iio_device_attr_write_longlong(const struct iio_device *dev, + const char *attr, long long val); + + +/** @brief Set the value of the given device-specific attribute + * @param dev A pointer to an iio_device structure + * @param attr A NULL-terminated string corresponding to the name of the + * attribute + * @param val A double value to set the attribute to + * @return On success, 0 is returned + * @return On error, a negative errno code is returned */ +__api __check_ret int iio_device_attr_write_double(const struct iio_device *dev, + const char *attr, double val); + +/** @brief Read the content of the given buffer-specific attribute + * @param dev A pointer to an iio_device structure + * @param attr A NULL-terminated string corresponding to the name of the + * attribute + * @param dst A pointer to the memory area where the NULL-terminated string + * corresponding to the value read will be stored + * @param len The available length of the memory area, in bytes + * @return On success, the number of bytes written to the buffer + * @return On error, a negative errno code is returned + * + * NOTE:By passing NULL as the "attr" argument to + * iio_device_buffer_attr_read, it is now possible to read all of the attributes + * of a device. + * + * The buffer is filled with one block of data per attribute of the buffer, + * by the order they appear in the iio_device structure. + * + * The first four bytes of one block correspond to a 32-bit signed value in + * network order. If negative, it corresponds to the errno code that were + * returned when reading the attribute; if positive, it corresponds to the + * length of the data read. In that case, the rest of the block contains + * the data. */ +__api __check_ret ssize_t iio_device_buffer_attr_read(const struct iio_device *dev, + const char *attr, char *dst, size_t len); + +/** @brief Read the content of all buffer-specific attributes + * @param dev A pointer to an iio_device structure + * @param cb A pointer to a callback function + * @param data A pointer that will be passed to the callback function + * @return On success, 0 is returned + * @return On error, a negative errno code is returned + * + * NOTE: This function is especially useful when used with the network + * backend, as all the buffer-specific attributes are read in one single + * command. */ +__api __check_ret int iio_device_buffer_attr_read_all(struct iio_device *dev, + int (*cb)(struct iio_device *dev, const char *attr, + const char *value, size_t len, void *d), + void *data); + + +/** @brief Read the content of the given buffer-specific attribute + * @param dev A pointer to an iio_device structure + * @param attr A NULL-terminated string corresponding to the name of the + * attribute + * @param val A pointer to a bool variable where the value should be stored + * @return On success, 0 is returned + * @return On error, a negative errno code is returned */ +__api __check_ret int iio_device_buffer_attr_read_bool(const struct iio_device *dev, + const char *attr, bool *val); + + +/** @brief Read the content of the given buffer-specific attribute + * @param dev A pointer to an iio_device structure + * @param attr A NULL-terminated string corresponding to the name of the + * attribute + * @param val A pointer to a long long variable where the value should be stored + * @return On success, 0 is returned + * @return On error, a negative errno code is returned */ +__api __check_ret int iio_device_buffer_attr_read_longlong(const struct iio_device *dev, + const char *attr, long long *val); + + +/** @brief Read the content of the given buffer-specific attribute + * @param dev A pointer to an iio_device structure + * @param attr A NULL-terminated string corresponding to the name of the + * attribute + * @param val A pointer to a double variable where the value should be stored + * @return On success, 0 is returned + * @return On error, a negative errno code is returned */ +__api __check_ret int iio_device_buffer_attr_read_double(const struct iio_device *dev, + const char *attr, double *val); + + +/** @brief Set the value of the given buffer-specific attribute + * @param dev A pointer to an iio_device structure + * @param attr A NULL-terminated string corresponding to the name of the + * attribute + * @param src A NULL-terminated string to set the attribute to + * @return On success, the number of bytes written + * @return On error, a negative errno code is returned + * + * NOTE:By passing NULL as the "attr" argument to + * iio_device_buffer_attr_write, it is now possible to write all of the + * attributes of a device. + * + * The buffer must contain one block of data per attribute of the buffer, + * by the order they appear in the iio_device structure. + * + * The first four bytes of one block correspond to a 32-bit signed value in + * network order. If negative, the attribute is not written; if positive, + * it corresponds to the length of the data to write. In that case, the rest + * of the block must contain the data. */ +__api __check_ret ssize_t iio_device_buffer_attr_write(const struct iio_device *dev, + const char *attr, const char *src); + + +/** @brief Set the value of the given buffer-specific attribute + * @param dev A pointer to an iio_device structure + * @param attr A NULL-terminated string corresponding to the name of the + * attribute + * @param src A pointer to the data to be written + * @param len The number of bytes that should be written + * @return On success, the number of bytes written + * @return On error, a negative errno code is returned */ +__api __check_ret ssize_t iio_device_buffer_attr_write_raw(const struct iio_device *dev, + const char *attr, const void *src, size_t len); + + +/** @brief Set the values of all buffer-specific attributes + * @param dev A pointer to an iio_device structure + * @param cb A pointer to a callback function + * @param data A pointer that will be passed to the callback function + * @return On success, 0 is returned + * @return On error, a negative errno code is returned + * + * NOTE: This function is especially useful when used with the network + * backend, as all the buffer-specific attributes are written in one single + * command. */ +__api __check_ret int iio_device_buffer_attr_write_all(struct iio_device *dev, + ssize_t (*cb)(struct iio_device *dev, + const char *attr, void *buf, size_t len, void *d), + void *data); + + +/** @brief Set the value of the given buffer-specific attribute + * @param dev A pointer to an iio_device structure + * @param attr A NULL-terminated string corresponding to the name of the + * attribute + * @param val A bool value to set the attribute to + * @return On success, 0 is returned + * @return On error, a negative errno code is returned */ +__api __check_ret int iio_device_buffer_attr_write_bool(const struct iio_device *dev, + const char *attr, bool val); + + +/** @brief Set the value of the given buffer-specific attribute + * @param dev A pointer to an iio_device structure + * @param attr A NULL-terminated string corresponding to the name of the + * attribute + * @param val A long long value to set the attribute to + * @return On success, 0 is returned + * @return On error, a negative errno code is returned */ +__api __check_ret int iio_device_buffer_attr_write_longlong(const struct iio_device *dev, + const char *attr, long long val); + + +/** @brief Set the value of the given buffer-specific attribute + * @param dev A pointer to an iio_device structure + * @param attr A NULL-terminated string corresponding to the name of the + * attribute + * @param val A double value to set the attribute to + * @return On success, 0 is returned + * @return On error, a negative errno code is returned */ +__api __check_ret int iio_device_buffer_attr_write_double(const struct iio_device *dev, + const char *attr, double val); + + +/** @brief Associate a pointer to an iio_device structure + * @param dev A pointer to an iio_device structure + * @param data The pointer to be associated */ +__api void iio_device_set_data(struct iio_device *dev, void *data); + + +/** @brief Retrieve a previously associated pointer of an iio_device structure + * @param dev A pointer to an iio_device structure + * @return The pointer previously associated if present, or NULL */ +__api void * iio_device_get_data(const struct iio_device *dev); + + +/** @brief Retrieve the trigger of a given device + * @param dev A pointer to an iio_device structure + * @param trigger a pointer to a pointer of an iio_device structure. The pointed + * pointer will be set to the address of the iio_device structure corresponding + * to the associated trigger device. + * @return On success, 0 is returned + * @return On error, a negative errno code is returned */ +__api __check_ret int iio_device_get_trigger(const struct iio_device *dev, + const struct iio_device **trigger); + + +/** @brief Associate a trigger to a given device + * @param dev A pointer to an iio_device structure + * @param trigger a pointer to the iio_device structure corresponding to the + * trigger that should be associated. + * @return On success, 0 is returned + * @return On error, a negative errno code is returned */ +__api __check_ret int iio_device_set_trigger(const struct iio_device *dev, + const struct iio_device *trigger); + + +/** @brief Return True if the given device is a trigger + * @param dev A pointer to an iio_device structure + * @return True if the device is a trigger, False otherwise */ +__api __check_ret __pure bool iio_device_is_trigger(const struct iio_device *dev); + +/** @brief Configure the number of kernel buffers for a device + * + * This function allows to change the number of buffers on kernel side. + * @param dev A pointer to an iio_device structure + * @param nb_buffers The number of buffers + * @return On success, 0 is returned + * @return On error, a negative errno code is returned */ +__api __check_ret int iio_device_set_kernel_buffers_count(const struct iio_device *dev, + unsigned int nb_buffers); + +/** @} *//* ------------------------------------------------------------------*/ +/* ------------------------- Channel functions -------------------------------*/ +/** @defgroup Channel Channel + * @{ + * @struct iio_channel + * @brief Represents an input or output channel of a device */ + + +/** @brief Retrieve a pointer to the iio_device structure + * @param chn A pointer to an iio_channel structure + * @return A pointer to an iio_device structure */ +__api __check_ret __pure const struct iio_device * iio_channel_get_device( + const struct iio_channel *chn); + + +/** @brief Retrieve the channel ID (e.g. voltage0) + * @param chn A pointer to an iio_channel structure + * @return A pointer to a static NULL-terminated string */ +__api __check_ret __pure const char * iio_channel_get_id(const struct iio_channel *chn); + + +/** @brief Retrieve the channel name (e.g. vccint) + * @param chn A pointer to an iio_channel structure + * @return A pointer to a static NULL-terminated string + * + * NOTE: if the channel has no name, NULL is returned. */ +__api __check_ret __pure const char * iio_channel_get_name(const struct iio_channel *chn); + + +/** @brief Return True if the given channel is an output channel + * @param chn A pointer to an iio_channel structure + * @return True if the channel is an output channel, False otherwise */ +__api __check_ret __pure bool iio_channel_is_output(const struct iio_channel *chn); + + +/** @brief Return True if the given channel is a scan element + * @param chn A pointer to an iio_channel structure + * @return True if the channel is a scan element, False otherwise + * + * NOTE: a channel that is a scan element is a channel that can + * generate samples (for an input channel) or receive samples (for an output + * channel) after being enabled. */ +__api __check_ret __pure bool iio_channel_is_scan_element(const struct iio_channel *chn); + + +/** @brief Enumerate the channel-specific attributes of the given channel + * @param chn A pointer to an iio_channel structure + * @return The number of channel-specific attributes found */ +__api __check_ret __pure unsigned int iio_channel_get_attrs_count( + const struct iio_channel *chn); + + +/** @brief Get the channel-specific attribute present at the given index + * @param chn A pointer to an iio_channel structure + * @param index The index corresponding to the attribute + * @return On success, a pointer to a static NULL-terminated string + * @return If the index is invalid, NULL is returned */ +__api __check_ret __pure const char * iio_channel_get_attr( + const struct iio_channel *chn, unsigned int index); + + +/** @brief Try to find a channel-specific attribute by its name + * @param chn A pointer to an iio_channel structure + * @param name A NULL-terminated string corresponding to the name of the + * attribute + * @return On success, a pointer to a static NULL-terminated string + * @return If the name does not correspond to any known attribute of the given + * channel, NULL is returned + * + * NOTE: This function is useful to detect the presence of an attribute. + * It can also be used to retrieve the name of an attribute as a pointer to a + * static string from a dynamically allocated string. */ +__api __check_ret __pure const char * iio_channel_find_attr( + const struct iio_channel *chn, const char *name); + + +/** @brief Retrieve the filename of an attribute + * @param chn A pointer to an iio_channel structure + * @param attr a NULL-terminated string corresponding to the name of the + * attribute + * @return On success, a pointer to a static NULL-terminated string + * @return If the attribute name is unknown, NULL is returned */ +__api __check_ret __pure const char * iio_channel_attr_get_filename( + const struct iio_channel *chn, const char *attr); + + +/** @brief Read the content of the given channel-specific attribute + * @param chn A pointer to an iio_channel structure + * @param attr A NULL-terminated string corresponding to the name of the + * attribute + * @param dst A pointer to the memory area where the NULL-terminated string + * corresponding to the value read will be stored + * @param len The available length of the memory area, in bytes + * @return On success, the number of bytes written to the buffer + * @return On error, a negative errno code is returned + * + * NOTE:By passing NULL as the "attr" argument to iio_channel_attr_read, + * it is now possible to read all of the attributes of a channel. + * + * The buffer is filled with one block of data per attribute of the channel, + * by the order they appear in the iio_channel structure. + * + * The first four bytes of one block correspond to a 32-bit signed value in + * network order. If negative, it corresponds to the errno code that were + * returned when reading the attribute; if positive, it corresponds to the + * length of the data read. In that case, the rest of the block contains + * the data. */ +__api __check_ret ssize_t iio_channel_attr_read(const struct iio_channel *chn, + const char *attr, char *dst, size_t len); + + +/** @brief Read the content of all channel-specific attributes + * @param chn A pointer to an iio_channel structure + * @param cb A pointer to a callback function + * @param data A pointer that will be passed to the callback function + * @return On success, 0 is returned + * @return On error, a negative errno code is returned + * + * NOTE: This function is especially useful when used with the network + * backend, as all the channel-specific attributes are read in one single + * command. */ +__api __check_ret int iio_channel_attr_read_all(struct iio_channel *chn, + int (*cb)(struct iio_channel *chn, + const char *attr, const char *val, size_t len, void *d), + void *data); + + +/** @brief Read the content of the given channel-specific attribute + * @param chn A pointer to an iio_channel structure + * @param attr A NULL-terminated string corresponding to the name of the + * attribute + * @param val A pointer to a bool variable where the value should be stored + * @return On success, 0 is returned + * @return On error, a negative errno code is returned */ +__api __check_ret int iio_channel_attr_read_bool(const struct iio_channel *chn, + const char *attr, bool *val); + + +/** @brief Read the content of the given channel-specific attribute + * @param chn A pointer to an iio_channel structure + * @param attr A NULL-terminated string corresponding to the name of the + * attribute + * @param val A pointer to a long long variable where the value should be stored + * @return On success, 0 is returned + * @return On error, a negative errno code is returned */ +__api __check_ret int iio_channel_attr_read_longlong(const struct iio_channel *chn, + const char *attr, long long *val); + + +/** @brief Read the content of the given channel-specific attribute + * @param chn A pointer to an iio_channel structure + * @param attr A NULL-terminated string corresponding to the name of the + * attribute + * @param val A pointer to a double variable where the value should be stored + * @return On success, 0 is returned + * @return On error, a negative errno code is returned */ +__api __check_ret int iio_channel_attr_read_double(const struct iio_channel *chn, + const char *attr, double *val); + + +/** @brief Set the value of the given channel-specific attribute + * @param chn A pointer to an iio_channel structure + * @param attr A NULL-terminated string corresponding to the name of the + * attribute + * @param src A NULL-terminated string to set the attribute to + * @return On success, the number of bytes written + * @return On error, a negative errno code is returned + * + * NOTE:By passing NULL as the "attr" argument to iio_channel_attr_write, + * it is now possible to write all of the attributes of a channel. + * + * The buffer must contain one block of data per attribute of the channel, + * by the order they appear in the iio_channel structure. + * + * The first four bytes of one block correspond to a 32-bit signed value in + * network order. If negative, the attribute is not written; if positive, + * it corresponds to the length of the data to write. In that case, the rest + * of the block must contain the data. */ +__api __check_ret ssize_t iio_channel_attr_write(const struct iio_channel *chn, + const char *attr, const char *src); + + +/** @brief Set the value of the given channel-specific attribute + * @param chn A pointer to an iio_channel structure + * @param attr A NULL-terminated string corresponding to the name of the + * attribute + * @param src A pointer to the data to be written + * @param len The number of bytes that should be written + * @return On success, the number of bytes written + * @return On error, a negative errno code is returned */ +__api __check_ret ssize_t iio_channel_attr_write_raw(const struct iio_channel *chn, + const char *attr, const void *src, size_t len); + + +/** @brief Set the values of all channel-specific attributes + * @param chn A pointer to an iio_channel structure + * @param cb A pointer to a callback function + * @param data A pointer that will be passed to the callback function + * @return On success, 0 is returned + * @return On error, a negative errno code is returned + * + * NOTE: This function is especially useful when used with the network + * backend, as all the channel-specific attributes are written in one single + * command. */ +__api __check_ret int iio_channel_attr_write_all(struct iio_channel *chn, + ssize_t (*cb)(struct iio_channel *chn, + const char *attr, void *buf, size_t len, void *d), + void *data); + + +/** @brief Set the value of the given channel-specific attribute + * @param chn A pointer to an iio_channel structure + * @param attr A NULL-terminated string corresponding to the name of the + * attribute + * @param val A bool value to set the attribute to + * @return On success, 0 is returned + * @return On error, a negative errno code is returned */ +__api __check_ret int iio_channel_attr_write_bool(const struct iio_channel *chn, + const char *attr, bool val); + + +/** @brief Set the value of the given channel-specific attribute + * @param chn A pointer to an iio_channel structure + * @param attr A NULL-terminated string corresponding to the name of the + * attribute + * @param val A long long value to set the attribute to + * @return On success, 0 is returned + * @return On error, a negative errno code is returned */ +__api __check_ret int iio_channel_attr_write_longlong(const struct iio_channel *chn, + const char *attr, long long val); + + +/** @brief Set the value of the given channel-specific attribute + * @param chn A pointer to an iio_channel structure + * @param attr A NULL-terminated string corresponding to the name of the + * attribute + * @param val A double value to set the attribute to + * @return On success, 0 is returned + * @return On error, a negative errno code is returned */ +__api __check_ret int iio_channel_attr_write_double(const struct iio_channel *chn, + const char *attr, double val); + + +/** @brief Enable the given channel + * @param chn A pointer to an iio_channel structure + * + * NOTE:Before creating an iio_buffer structure with + * iio_device_create_buffer, it is required to enable at least one channel of + * the device to read from. */ +__api void iio_channel_enable(struct iio_channel *chn); + + +/** @brief Disable the given channel + * @param chn A pointer to an iio_channel structure */ +__api void iio_channel_disable(struct iio_channel *chn); + + +/** @brief Returns True if the channel is enabled + * @param chn A pointer to an iio_channel structure + * @return True if the channel is enabled, False otherwise */ +__api __check_ret bool iio_channel_is_enabled(const struct iio_channel *chn); + + +/** @brief Demultiplex the samples of a given channel + * @param chn A pointer to an iio_channel structure + * @param buffer A pointer to an iio_buffer structure + * @param dst A pointer to the memory area where the demultiplexed data will be + * stored + * @param len The available length of the memory area, in bytes + * @return The size of the demultiplexed data, in bytes */ +__api __check_ret size_t iio_channel_read_raw(const struct iio_channel *chn, + struct iio_buffer *buffer, void *dst, size_t len); + + +/** @brief Demultiplex and convert the samples of a given channel + * @param chn A pointer to an iio_channel structure + * @param buffer A pointer to an iio_buffer structure + * @param dst A pointer to the memory area where the converted data will be + * stored + * @param len The available length of the memory area, in bytes + * @return The size of the converted data, in bytes */ +__api __check_ret size_t iio_channel_read(const struct iio_channel *chn, + struct iio_buffer *buffer, void *dst, size_t len); + + +/** @brief Multiplex the samples of a given channel + * @param chn A pointer to an iio_channel structure + * @param buffer A pointer to an iio_buffer structure + * @param src A pointer to the memory area where the sequential data will + * be read from + * @param len The length of the memory area, in bytes + * @return The number of bytes actually multiplexed */ +__api __check_ret size_t iio_channel_write_raw(const struct iio_channel *chn, + struct iio_buffer *buffer, const void *src, size_t len); + + +/** @brief Convert and multiplex the samples of a given channel + * @param chn A pointer to an iio_channel structure + * @param buffer A pointer to an iio_buffer structure + * @param src A pointer to the memory area where the sequential data will + * be read from + * @param len The length of the memory area, in bytes + * @return The number of bytes actually converted and multiplexed */ +__api __check_ret size_t iio_channel_write(const struct iio_channel *chn, + struct iio_buffer *buffer, const void *src, size_t len); + + +/** @brief Associate a pointer to an iio_channel structure + * @param chn A pointer to an iio_channel structure + * @param data The pointer to be associated */ +__api void iio_channel_set_data(struct iio_channel *chn, void *data); + + +/** @brief Retrieve a previously associated pointer of an iio_channel structure + * @param chn A pointer to an iio_channel structure + * @return The pointer previously associated if present, or NULL */ +__api void * iio_channel_get_data(const struct iio_channel *chn); + + +/** @brief Get the type of the given channel + * @param chn A pointer to an iio_channel structure + * @return The type of the channel */ +__api __check_ret __pure enum iio_chan_type iio_channel_get_type( + const struct iio_channel *chn); + + +/** @brief Get the modifier type of the given channel + * @param chn A pointer to an iio_channel structure + * @return The modifier type of the channel */ +__api __check_ret __pure enum iio_modifier iio_channel_get_modifier( + const struct iio_channel *chn); + + +/** @} *//* ------------------------------------------------------------------*/ +/* ------------------------- Buffer functions --------------------------------*/ +/** @defgroup Buffer Buffer + * @{ + * @struct iio_buffer + * @brief An input or output buffer, used to read or write samples */ + + +/** @brief Retrieve a pointer to the iio_device structure + * @param buf A pointer to an iio_buffer structure + * @return A pointer to an iio_device structure */ +__api __check_ret __pure const struct iio_device * iio_buffer_get_device( + const struct iio_buffer *buf); + + +/** @brief Create an input or output buffer associated to the given device + * @param dev A pointer to an iio_device structure + * @param samples_count The number of samples that the buffer should contain + * @param cyclic If True, enable cyclic mode + * @return On success, a pointer to an iio_buffer structure + * @return On error, NULL is returned, and errno is set to the error code + * + * NOTE: Channels that have to be written to / read from must be enabled + * before creating the buffer. */ +__api __check_ret struct iio_buffer * iio_device_create_buffer(const struct iio_device *dev, + size_t samples_count, bool cyclic); + + +/** @brief Destroy the given buffer + * @param buf A pointer to an iio_buffer structure + * + * NOTE: After that function, the iio_buffer pointer shall be invalid. */ +__api void iio_buffer_destroy(struct iio_buffer *buf); + +/** @brief Get a pollable file descriptor + * + * Can be used to know when iio_buffer_refill() or iio_buffer_push() can be + * called + * @param buf A pointer to an iio_buffer structure + * @return On success, valid file descriptor + * @return On error, a negative errno code is returned + */ +__api __check_ret int iio_buffer_get_poll_fd(struct iio_buffer *buf); + +/** @brief Make iio_buffer_refill() and iio_buffer_push() blocking or not + * + * After this function has been called with blocking == false, + * iio_buffer_refill() and iio_buffer_push() will return -EAGAIN if no data is + * ready. + * A device is blocking by default. + * @param buf A pointer to an iio_buffer structure + * @param blocking true if the buffer API should be blocking, else false + * @return On success, 0 + * @return On error, a negative errno code is returned + */ +__api __check_ret int iio_buffer_set_blocking_mode(struct iio_buffer *buf, bool blocking); + + +/** @brief Fetch more samples from the hardware + * @param buf A pointer to an iio_buffer structure + * @return On success, the number of bytes read is returned + * @return On error, a negative errno code is returned + * + * NOTE: Only valid for input buffers */ +__api __check_ret ssize_t iio_buffer_refill(struct iio_buffer *buf); + + +/** @brief Send the samples to the hardware + * @param buf A pointer to an iio_buffer structure + * @return On success, the number of bytes written is returned + * @return On error, a negative errno code is returned + * + * NOTE: Only valid for output buffers */ +__api __check_ret ssize_t iio_buffer_push(struct iio_buffer *buf); + + +/** @brief Send a given number of samples to the hardware + * @param buf A pointer to an iio_buffer structure + * @param samples_count The number of samples to submit + * @return On success, the number of bytes written is returned + * @return On error, a negative errno code is returned + * + * NOTE: Only valid for output buffers */ +__api __check_ret ssize_t iio_buffer_push_partial(struct iio_buffer *buf, + size_t samples_count); + +/** @brief Cancel all buffer operations + * @param buf The buffer for which operations should be canceled + * + * This function cancels all outstanding buffer operations previously scheduled. + * This means any pending iio_buffer_push() or iio_buffer_refill() operation + * will abort and return immediately, any further invocations of these functions + * on the same buffer will return immediately with an error. + * + * Usually iio_buffer_push() and iio_buffer_refill() will block until either all + * data has been transferred or a timeout occurs. This can depending on the + * configuration take a significant amount of time. iio_buffer_cancel() is + * useful to bypass these conditions if the buffer operation is supposed to be + * stopped in response to an external event (e.g. user input). + * + * To be able to capture additional data after calling this function the buffer + * should be destroyed and then re-created. + * + * This function can be called multiple times for the same buffer, but all but + * the first invocation will be without additional effect. + * + * This function is thread-safe, but not signal-safe, i.e. it must not be called + * from a signal handler. + */ +__api void iio_buffer_cancel(struct iio_buffer *buf); + + +/** @brief Get the start address of the buffer + * @param buf A pointer to an iio_buffer structure + * @return A pointer corresponding to the start address of the buffer */ +__api void * iio_buffer_start(const struct iio_buffer *buf); + + +/** @brief Find the first sample of a channel in a buffer + * @param buf A pointer to an iio_buffer structure + * @param chn A pointer to an iio_channel structure + * @return A pointer to the first sample found, or to the end of the buffer if + * no sample for the given channel is present in the buffer + * + * NOTE: This function, coupled with iio_buffer_step and iio_buffer_end, + * can be used to iterate on all the samples of a given channel present in the + * buffer, doing the following: + * + * @verbatim + for (void *ptr = iio_buffer_first(buffer, chn); ptr < iio_buffer_end(buffer); ptr += iio_buffer_step(buffer)) { + .... + } + @endverbatim */ +__api void * iio_buffer_first(const struct iio_buffer *buf, + const struct iio_channel *chn); + + +/** @brief Get the step size between two samples of one channel + * @param buf A pointer to an iio_buffer structure + * @return the difference between the addresses of two consecutive samples of + * one same channel */ +__api __check_ret ptrdiff_t iio_buffer_step(const struct iio_buffer *buf); + + +/** @brief Get the address that follows the last sample in a buffer + * @param buf A pointer to an iio_buffer structure + * @return A pointer corresponding to the address that follows the last sample + * present in the buffer */ +__api void * iio_buffer_end(const struct iio_buffer *buf); + + +/** @brief Call the supplied callback for each sample found in a buffer + * @param buf A pointer to an iio_buffer structure + * @param callback A pointer to a function to call for each sample found + * @param data A user-specified pointer that will be passed to the callback + * @return number of bytes processed. + * + * NOTE: The callback receives four arguments: + * * A pointer to the iio_channel structure corresponding to the sample, + * * A pointer to the sample itself, + * * The length of the sample in bytes, + * * The user-specified pointer passed to iio_buffer_foreach_sample. */ +__api __check_ret ssize_t iio_buffer_foreach_sample(struct iio_buffer *buf, + ssize_t (*callback)(const struct iio_channel *chn, + void *src, size_t bytes, void *d), void *data); + + +/** @brief Associate a pointer to an iio_buffer structure + * @param buf A pointer to an iio_buffer structure + * @param data The pointer to be associated */ +__api void iio_buffer_set_data(struct iio_buffer *buf, void *data); + + +/** @brief Retrieve a previously associated pointer of an iio_buffer structure + * @param buf A pointer to an iio_buffer structure + * @return The pointer previously associated if present, or NULL */ +__api void * iio_buffer_get_data(const struct iio_buffer *buf); + +/** @} *//* ------------------------------------------------------------------*/ +/* ---------------------------- HWMON support --------------------------------*/ +/** @defgroup Hwmon Compatibility with hardware monitoring (hwmon) devices + * @{ + * @enum hwmon_chan_type + * @brief Hwmon channel type + * + * Libiio support hardware-monitoring (hwmon) devices as well. This enum + * specifies the type of data associated with the hwmon channel. + * + * NOTE: as of 2021 only the current hwmon API is supported. The old + * and deprecated APIs are not supported, and won't be supported unless we + * have a case where updating a hwmon driver is not possible. + */ +enum hwmon_chan_type { + HWMON_VOLTAGE, + HWMON_FAN, + HWMON_PWM, + HWMON_TEMP, + HWMON_CURRENT, + HWMON_POWER, + HWMON_ENERGY, + HWMON_HUMIDITY, + HWMON_INTRUSION, + HWMON_CHAN_TYPE_UNKNOWN = IIO_CHAN_TYPE_UNKNOWN, +}; + +/** + * @brief Get the type of the given hwmon channel + * @param chn A pointer to an iio_channel structure + * @return The type of the hwmon channel */ +static inline enum hwmon_chan_type +hwmon_channel_get_type(const struct iio_channel *chn) +{ + return (enum hwmon_chan_type) iio_channel_get_type(chn); +} + +/** + * @brief Get whether or not the device is a hardware monitoring device + * @param dev A pointer to an iio_device structure + * @return True if the device is a hardware monitoring device, + * false if it is a IIO device */ +static inline bool iio_device_is_hwmon(const struct iio_device *dev) +{ + const char *id = iio_device_get_id(dev); + + return id[0] == 'h'; +} + + +/** @} *//* ------------------------------------------------------------------*/ +/* ------------------------- Low-level functions -----------------------------*/ +/** @defgroup Debug Debug and low-level functions + * @{ + * @struct iio_data_format + * @brief Contains the format of a data sample. + * + * The different fields inform about the correct way to convert one sample from + * its raw format (as read from / generated by the hardware) to its real-world + * value. + */ +struct iio_data_format { + /** @brief Total length of the sample, in bits */ + unsigned int length; + + /** @brief Length of valuable data in the sample, in bits */ + unsigned int bits; + + /** @brief Right-shift to apply when converting sample */ + unsigned int shift; + + /** @brief Contains True if the sample is signed */ + bool is_signed; + + /** @brief Contains True if the sample is fully defined, sign extended, etc. */ + bool is_fully_defined; + + /** @brief Contains True if the sample is in big-endian format */ + bool is_be; + + /** @brief Contains True if the sample should be scaled when converted */ + bool with_scale; + + /** @brief Contains the scale to apply if with_scale is set */ + double scale; + + /** @brief Number of times length repeats (added in v0.8) */ + unsigned int repeat; +}; + + +/** @brief Get the current sample size + * @param dev A pointer to an iio_device structure + * @return On success, the sample size in bytes + * @return On error, a negative errno code is returned + * + * NOTE: The sample size is not constant and will change when channels + * get enabled or disabled. */ +__api __check_ret ssize_t iio_device_get_sample_size(const struct iio_device *dev); + + +/** @brief Get the index of the given channel + * @param chn A pointer to an iio_channel structure + * @return On success, the index of the specified channel + * @return On error, a negative errno code is returned */ +__api __check_ret __pure long iio_channel_get_index(const struct iio_channel *chn); + + +/** @brief Get a pointer to a channel's data format structure + * @param chn A pointer to an iio_channel structure + * @return A pointer to the channel's iio_data_format structure */ +__api __check_ret __cnst const struct iio_data_format * iio_channel_get_data_format( + const struct iio_channel *chn); + + +/** @brief Convert the sample from hardware format to host format + * @param chn A pointer to an iio_channel structure + * @param dst A pointer to the destination buffer where the converted sample + * should be written + * @param src A pointer to the source buffer containing the sample */ +__api void iio_channel_convert(const struct iio_channel *chn, + void *dst, const void *src); + + +/** @brief Convert the sample from host format to hardware format + * @param chn A pointer to an iio_channel structure + * @param dst A pointer to the destination buffer where the converted sample + * should be written + * @param src A pointer to the source buffer containing the sample */ +__api void iio_channel_convert_inverse(const struct iio_channel *chn, + void *dst, const void *src); + + +/** @brief Enumerate the debug attributes of the given device + * @param dev A pointer to an iio_device structure + * @return The number of debug attributes found */ +__api __check_ret __pure unsigned int iio_device_get_debug_attrs_count( + const struct iio_device *dev); + + +/** @brief Get the debug attribute present at the given index + * @param dev A pointer to an iio_device structure + * @param index The index corresponding to the debug attribute + * @return On success, a pointer to a static NULL-terminated string + * @return If the index is invalid, NULL is returned */ +__api __check_ret __pure const char * iio_device_get_debug_attr( + const struct iio_device *dev, unsigned int index); + + +/** @brief Try to find a debug attribute by its name + * @param dev A pointer to an iio_device structure + * @param name A NULL-terminated string corresponding to the name of the + * debug attribute + * @return On success, a pointer to a static NULL-terminated string + * @return If the name does not correspond to any known debug attribute of the + * given device, NULL is returned + * + * NOTE: This function is useful to detect the presence of a debug + * attribute. + * It can also be used to retrieve the name of a debug attribute as a pointer + * to a static string from a dynamically allocated string. */ +__api __check_ret __pure const char * iio_device_find_debug_attr( + const struct iio_device *dev, const char *name); + + +/** @brief Read the content of the given debug attribute + * @param dev A pointer to an iio_device structure + * @param attr A NULL-terminated string corresponding to the name of the + * debug attribute + * @param dst A pointer to the memory area where the NULL-terminated string + * corresponding to the value read will be stored + * @param len The available length of the memory area, in bytes + * @return On success, the number of bytes written to the buffer + * @return On error, a negative errno code is returned + * + * NOTE:By passing NULL as the "attr" argument to + * iio_device_debug_attr_read, it is now possible to read all of the debug + * attributes of a device. + * + * The buffer is filled with one block of data per debug attribute of the + * device, by the order they appear in the iio_device structure. + * + * The first four bytes of one block correspond to a 32-bit signed value in + * network order. If negative, it corresponds to the errno code that were + * returned when reading the debug attribute; if positive, it corresponds + * to the length of the data read. In that case, the rest of the block contains + * the data. */ +__api __check_ret ssize_t iio_device_debug_attr_read(const struct iio_device *dev, + const char *attr, char *dst, size_t len); + + +/** @brief Read the content of all debug attributes + * @param dev A pointer to an iio_device structure + * @param cb A pointer to a callback function + * @param data A pointer that will be passed to the callback function + * @return On success, 0 is returned + * @return On error, a negative errno code is returned + * + * NOTE: This function is especially useful when used with the network + * backend, as all the debug attributes are read in one single command. */ +__api __check_ret int iio_device_debug_attr_read_all(struct iio_device *dev, + int (*cb)(struct iio_device *dev, const char *attr, + const char *value, size_t len, void *d), + void *data); + + +/** @brief Set the value of the given debug attribute + * @param dev A pointer to an iio_device structure + * @param attr A NULL-terminated string corresponding to the name of the + * debug attribute + * @param src A NULL-terminated string to set the debug attribute to + * @return On success, the number of bytes written + * @return On error, a negative errno code is returned + * + * NOTE:By passing NULL as the "attr" argument to + * iio_device_debug_attr_write, it is now possible to write all of the + * debug attributes of a device. + * + * The buffer must contain one block of data per debug attribute of the device, + * by the order they appear in the iio_device structure. + * + * The first four bytes of one block correspond to a 32-bit signed value in + * network order. If negative, the debug attribute is not written; if positive, + * it corresponds to the length of the data to write. In that case, the rest + * of the block must contain the data. */ +__api __check_ret ssize_t iio_device_debug_attr_write(const struct iio_device *dev, + const char *attr, const char *src); + + +/** @brief Set the value of the given debug attribute + * @param dev A pointer to an iio_device structure + * @param attr A NULL-terminated string corresponding to the name of the + * debug attribute + * @param src A pointer to the data to be written + * @param len The number of bytes that should be written + * @return On success, the number of bytes written + * @return On error, a negative errno code is returned */ +__api __check_ret ssize_t iio_device_debug_attr_write_raw(const struct iio_device *dev, + const char *attr, const void *src, size_t len); + + +/** @brief Set the values of all debug attributes + * @param dev A pointer to an iio_device structure + * @param cb A pointer to a callback function + * @param data A pointer that will be passed to the callback function + * @return On success, 0 is returned + * @return On error, a negative errno code is returned + * + * NOTE: This function is especially useful when used with the network + * backend, as all the debug attributes are written in one single command. */ +__api __check_ret int iio_device_debug_attr_write_all(struct iio_device *dev, + ssize_t (*cb)(struct iio_device *dev, + const char *attr, void *buf, size_t len, void *d), + void *data); + + +/** @brief Read the content of the given debug attribute + * @param dev A pointer to an iio_device structure + * @param attr A NULL-terminated string corresponding to the name of the + * debug attribute + * @param val A pointer to a bool variable where the value should be stored + * @return On success, 0 is returned + * @return On error, a negative errno code is returned */ +__api __check_ret int iio_device_debug_attr_read_bool(const struct iio_device *dev, + const char *attr, bool *val); + + +/** @brief Read the content of the given debug attribute + * @param dev A pointer to an iio_device structure + * @param attr A NULL-terminated string corresponding to the name of the + * debug attribute + * @param val A pointer to a long long variable where the value should be stored + * @return On success, 0 is returned + * @return On error, a negative errno code is returned */ +__api __check_ret int iio_device_debug_attr_read_longlong(const struct iio_device *dev, + const char *attr, long long *val); + + +/** @brief Read the content of the given debug attribute + * @param dev A pointer to an iio_device structure + * @param attr A NULL-terminated string corresponding to the name of the + * debug attribute + * @param val A pointer to a double variable where the value should be stored + * @return On success, 0 is returned + * @return On error, a negative errno code is returned */ +__api __check_ret int iio_device_debug_attr_read_double(const struct iio_device *dev, + const char *attr, double *val); + + +/** @brief Set the value of the given debug attribute + * @param dev A pointer to an iio_device structure + * @param attr A NULL-terminated string corresponding to the name of the + * debug attribute + * @param val A bool value to set the debug attribute to + * @return On success, 0 is returned + * @return On error, a negative errno code is returned */ +__api __check_ret int iio_device_debug_attr_write_bool(const struct iio_device *dev, + const char *attr, bool val); + + +/** @brief Set the value of the given debug attribute + * @param dev A pointer to an iio_device structure + * @param attr A NULL-terminated string corresponding to the name of the + * debug attribute + * @param val A long long value to set the debug attribute to + * @return On success, 0 is returned + * @return On error, a negative errno code is returned */ +__api __check_ret int iio_device_debug_attr_write_longlong(const struct iio_device *dev, + const char *attr, long long val); + + +/** @brief Set the value of the given debug attribute + * @param dev A pointer to an iio_device structure + * @param attr A NULL-terminated string corresponding to the name of the + * debug attribute + * @param val A double value to set the debug attribute to + * @return On success, 0 is returned + * @return On error, a negative errno code is returned */ +__api __check_ret int iio_device_debug_attr_write_double(const struct iio_device *dev, + const char *attr, double val); + + +/** @brief Identify the channel or debug attribute corresponding to a filename + * @param dev A pointer to an iio_device structure + * @param filename A NULL-terminated string corresponding to the filename + * @param chn A pointer to a pointer of an iio_channel structure. The pointed + * pointer will be set to the address of the iio_channel structure if the + * filename correspond to the attribute of a channel, or NULL otherwise. + * @param attr A pointer to a NULL-terminated string. The pointer + * pointer will be set to point to the name of the attribute corresponding to + * the filename. + * @return On success, 0 is returned, and *chn and *attr are modified. + * @return On error, a negative errno code is returned. *chn and *attr are not + * modified. */ +__api __check_ret int iio_device_identify_filename(const struct iio_device *dev, + const char *filename, struct iio_channel **chn, + const char **attr); + + +/** @brief Set the value of a hardware register + * @param dev A pointer to an iio_device structure + * @param address The address of the register + * @param value The value to set the register to + * @return On success, 0 is returned + * @return On error, a negative errno code is returned */ +__api __check_ret int iio_device_reg_write(struct iio_device *dev, + uint32_t address, uint32_t value); + + +/** @brief Get the value of a hardware register + * @param dev A pointer to an iio_device structure + * @param address The address of the register + * @param value A pointer to the variable where the value will be written + * @return On success, 0 is returned + * @return On error, a negative errno code is returned */ +__api __check_ret int iio_device_reg_read(struct iio_device *dev, + uint32_t address, uint32_t *value); + + +/** @} */ + +#ifdef __cplusplus +} +#endif + +#undef __api + +#endif /* __IIO_H__ */ diff --git a/player/plutoplayer_win/plutoplayer.c b/player/plutoplayer_win/plutoplayer.c new file mode 100644 index 0000000..b16b608 --- /dev/null +++ b/player/plutoplayer_win/plutoplayer.c @@ -0,0 +1,254 @@ +#define _CRT_SECURE_NO_WARNINGS + +#include +#include +#ifdef _WIN32 +#include "getopt.h" +#include "ad9361.h" +#include "iio.h" +#else +#include +#include +#include +#endif +#include +#include +#include + +#define NOTUSED(V) ((void) V) +#define MHZ(x) ((long long)(x*1000000.0 + .5)) +#define GHZ(x) ((long long)(x*1000000000.0 + .5)) +#define NUM_SAMPLES 2600000 +#define BUFFER_SIZE (NUM_SAMPLES * 2 * sizeof(int16_t)) + + +struct stream_cfg { + long long bw_hz; // Analog banwidth in Hz + long long fs_hz; // Baseband sample rate in Hz + long long lo_hz; // Local oscillator frequency in Hz + const char* rfport; // Port name + double gain_db; // Hardware gain +}; + +static void usage() { + fprintf(stderr, "Usage: plutoplayer [options]\n" + " -t Transmit data from file (required)\n" + " -a Set TX attenuation [dB] (default -20.0)\n" + " -b Set RF bandwidth [MHz] (default 5.0)\n" + " -u ADALM-Pluto URI\n" + " -n ADALM-Pluto network IP or hostname (default pluto.local)\n"); + return; +} + +static bool stop = false; + +static void handle_sig(int sig) +{ + NOTUSED(sig); + stop = true; +} + +static char* readable_fs(double size, char* buf, size_t buf_size) { + int i = 0; + const char* units[] = { "B", "kB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB" }; + while (size > 1024) { + size /= 1024; + i++; + } + snprintf(buf, buf_size, "%.*f %s", i, size, units[i]); + return buf; +} + +/* + * + */ +int main(int argc, char** argv) { + char buf[1024]; + int opt; + const char* path = NULL; + struct stream_cfg txcfg; + FILE* fp = NULL; + const char* uri = NULL; + const char* ip = NULL; + + // TX stream default config + txcfg.bw_hz = MHZ(3.0); // 3.0 MHz RF bandwidth + txcfg.fs_hz = MHZ(2.6); // 2.6 MS/s TX sample rate + txcfg.lo_hz = GHZ(1.575420); // 1.57542 GHz RF frequency + txcfg.rfport = "A"; + txcfg.gain_db = -20.0; + + struct iio_context* ctx = NULL; + struct iio_device* tx = NULL; + struct iio_device* phydev = NULL; + struct iio_channel* tx0_i = NULL; + struct iio_channel* tx0_q = NULL; + struct iio_buffer* tx_buffer = NULL; + + while ((opt = getopt(argc, argv, "t:a:b:n:u:")) != EOF) { + switch (opt) { + case 't': + path = optarg; + break; + case 'a': + txcfg.gain_db = atof(optarg); + if (txcfg.gain_db > 0.0) txcfg.gain_db = 0.0; + if (txcfg.gain_db < -80.0) txcfg.gain_db = -80.0; + break; + case 'b': + txcfg.bw_hz = MHZ(atof(optarg)); + if (txcfg.bw_hz > MHZ(5.0)) txcfg.bw_hz = MHZ(5.0); + if (txcfg.bw_hz < MHZ(1.0)) txcfg.bw_hz = MHZ(1.0); + break; + case 'u': + uri = optarg; + break; + case 'n': + ip = optarg; + break; + default: + printf("Unknown argument '-%c %s'\n", opt, optarg); + usage(); + return EXIT_FAILURE; + } + } + + //signal(SIGINT, handle_sig); + + if (path == NULL) { + printf("Specify a path to a file to transmit\n"); + usage(); + return EXIT_FAILURE; + } + + fp = fopen(path, "rb"); + if (fp == NULL) { + fprintf(stderr, "ERROR: Failed to open TX file: %s\n", path); + return EXIT_FAILURE; + } + fseek(fp, 0L, SEEK_END); + size_t sz = ftell(fp); + fseek(fp, 0L, SEEK_SET); + readable_fs((double)sz, buf, sizeof(buf)); + printf("* Transmit file size: %s\n", buf); + + printf("* Acquiring IIO context\n"); + ctx = iio_create_default_context(); + if (ctx == NULL) { + if (ip != NULL) { + ctx = iio_create_network_context(ip); + } + else if (uri != NULL) { + ctx = iio_create_context_from_uri(uri); + } + else { + ctx = iio_create_network_context("pluto.local"); + } + } + + if (ctx == NULL) { + iio_strerror(errno, buf, sizeof(buf)); + fprintf(stderr, "Failed creating IIO context: %s\n", buf); + return false; + } + + struct iio_scan_context* scan_ctx; + struct iio_context_info** info; + scan_ctx = iio_create_scan_context(NULL, 0); + if (scan_ctx) { + int info_count = iio_scan_context_get_info_list(scan_ctx, &info); + if (info_count > 0) { + printf("* Found %s\n", iio_context_info_get_description(info[0])); + iio_context_info_list_free(info); + } + iio_scan_context_destroy(scan_ctx); + } + + printf("* Acquiring devices\n"); + int device_count = iio_context_get_devices_count(ctx); + if (!device_count) { + fprintf(stderr, "No supported PLUTOSDR devices found.\n"); + goto error_exit; + } + fprintf(stderr, "* Context has %d device(s).\n", device_count); + + printf("* Acquiring TX device\n"); + tx = iio_context_find_device(ctx, "cf-ad9361-dds-core-lpc"); + if (tx == NULL) { + iio_strerror(errno, buf, sizeof(buf)); + fprintf(stderr, "Error opening PLUTOSDR TX device: %s\n", buf); + goto error_exit; + } + + iio_device_set_kernel_buffers_count(tx, 8); + + phydev = iio_context_find_device(ctx, "ad9361-phy"); + struct iio_channel* phy_chn = iio_device_find_channel(phydev, "voltage0", true); + iio_channel_attr_write(phy_chn, "rf_port_select", txcfg.rfport); + iio_channel_attr_write_longlong(phy_chn, "rf_bandwidth", txcfg.bw_hz); + iio_channel_attr_write_longlong(phy_chn, "sampling_frequency", txcfg.fs_hz); + iio_channel_attr_write_double(phy_chn, "hardwaregain", txcfg.gain_db); + + iio_channel_attr_write_bool( + iio_device_find_channel(phydev, "altvoltage0", true) + , "powerdown", true); // Turn OFF RX LO + + iio_channel_attr_write_longlong( + iio_device_find_channel(phydev, "altvoltage1", true) + , "frequency", txcfg.lo_hz); // Set TX LO frequency + + printf("* Initializing streaming channels\n"); + tx0_i = iio_device_find_channel(tx, "voltage0", true); + if (!tx0_i) + tx0_i = iio_device_find_channel(tx, "altvoltage0", true); + + tx0_q = iio_device_find_channel(tx, "voltage1", true); + if (!tx0_q) + tx0_q = iio_device_find_channel(tx, "altvoltage1", true); + + printf("* Enabling IIO streaming channels\n"); + iio_channel_enable(tx0_i); + iio_channel_enable(tx0_q); + + ad9361_set_bb_rate(iio_context_find_device(ctx, "ad9361-phy"), txcfg.fs_hz); + + printf("* Creating TX buffer\n"); + + tx_buffer = iio_device_create_buffer(tx, NUM_SAMPLES, false); + if (!tx_buffer) { + fprintf(stderr, "Could not create TX buffer.\n"); + goto error_exit; + } + + iio_channel_attr_write_bool( + iio_device_find_channel(iio_context_find_device(ctx, "ad9361-phy"), "altvoltage1", true) + , "powerdown", false); // Turn ON TX LO + + int32_t ntx = 0; + short* ptx_buffer = (short*)iio_buffer_start(tx_buffer); + + printf("* Transmit starts...\n"); + // Keep writing samples while there is more data to send and no failures have occurred. + while (!feof(fp) && !stop) { + fread(ptx_buffer, sizeof(short), BUFFER_SIZE / sizeof(short), fp); + // Schedule TX buffer + ntx = iio_buffer_push(tx_buffer); + if (ntx < 0) { + printf("Error pushing buf %d\n", (int)ntx); + break; + } + } + printf("Done.\n"); + +error_exit: + fclose(fp); + iio_channel_attr_write_bool( + iio_device_find_channel(iio_context_find_device(ctx, "ad9361-phy"), "altvoltage1", true) + , "powerdown", true); // Turn OFF TX LO + + if (tx_buffer) { iio_buffer_destroy(tx_buffer); } + if (tx0_i) { iio_channel_disable(tx0_i); } + if (tx0_q) { iio_channel_disable(tx0_q); } + if (ctx) { iio_context_destroy(ctx); } + return EXIT_SUCCESS; +}