Paul Cercueil / libiio

Dependencies:   libserialport libxml2

Committer:
pcercuei
Date:
Mon Jan 30 13:00:39 2017 +0000
Revision:
3:d147beabba0e
Parent:
2:9eb0a9a1f958
Child:
4:ad69b39bf124
Update to libiio v0.9

Who changed what in which revision?

UserRevisionLine numberNew contents of line
pcercuei 0:df031b60ca29 1 /*
pcercuei 0:df031b60ca29 2 * libiio - Library for interfacing industrial I/O (IIO) devices
pcercuei 0:df031b60ca29 3 *
pcercuei 0:df031b60ca29 4 * Copyright (C) 2014 Analog Devices, Inc.
pcercuei 0:df031b60ca29 5 * Author: Paul Cercueil <paul.cercueil@analog.com>
pcercuei 0:df031b60ca29 6 *
pcercuei 0:df031b60ca29 7 * This library is free software; you can redistribute it and/or
pcercuei 0:df031b60ca29 8 * modify it under the terms of the GNU Lesser General Public
pcercuei 0:df031b60ca29 9 * License as published by the Free Software Foundation; either
pcercuei 0:df031b60ca29 10 * version 2.1 of the License, or (at your option) any later version.
pcercuei 0:df031b60ca29 11 *
pcercuei 0:df031b60ca29 12 * This library is distributed in the hope that it will be useful,
pcercuei 0:df031b60ca29 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
pcercuei 0:df031b60ca29 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
pcercuei 0:df031b60ca29 15 * Lesser General Public License for more details.
pcercuei 0:df031b60ca29 16 *
pcercuei 0:df031b60ca29 17 * */
pcercuei 0:df031b60ca29 18
pcercuei 0:df031b60ca29 19 #include "debug.h"
pcercuei 0:df031b60ca29 20 #include "iio-private.h"
pcercuei 0:df031b60ca29 21
pcercuei 2:9eb0a9a1f958 22 #include <errno.h>
pcercuei 0:df031b60ca29 23 #include <stdio.h>
pcercuei 0:df031b60ca29 24 #include <string.h>
pcercuei 0:df031b60ca29 25
pcercuei 0:df031b60ca29 26 static const char * const iio_chan_type_name_spec[] = {
pcercuei 0:df031b60ca29 27 [IIO_VOLTAGE] = "voltage",
pcercuei 0:df031b60ca29 28 [IIO_CURRENT] = "current",
pcercuei 0:df031b60ca29 29 [IIO_POWER] = "power",
pcercuei 0:df031b60ca29 30 [IIO_ACCEL] = "accel",
pcercuei 0:df031b60ca29 31 [IIO_ANGL_VEL] = "anglvel",
pcercuei 0:df031b60ca29 32 [IIO_MAGN] = "magn",
pcercuei 0:df031b60ca29 33 [IIO_LIGHT] = "illuminance",
pcercuei 0:df031b60ca29 34 [IIO_INTENSITY] = "intensity",
pcercuei 0:df031b60ca29 35 [IIO_PROXIMITY] = "proximity",
pcercuei 0:df031b60ca29 36 [IIO_TEMP] = "temp",
pcercuei 0:df031b60ca29 37 [IIO_INCLI] = "incli",
pcercuei 0:df031b60ca29 38 [IIO_ROT] = "rot",
pcercuei 0:df031b60ca29 39 [IIO_ANGL] = "angl",
pcercuei 0:df031b60ca29 40 [IIO_TIMESTAMP] = "timestamp",
pcercuei 0:df031b60ca29 41 [IIO_CAPACITANCE] = "capacitance",
pcercuei 0:df031b60ca29 42 [IIO_ALTVOLTAGE] = "altvoltage",
pcercuei 0:df031b60ca29 43 [IIO_CCT] = "cct",
pcercuei 0:df031b60ca29 44 [IIO_PRESSURE] = "pressure",
pcercuei 0:df031b60ca29 45 [IIO_HUMIDITYRELATIVE] = "humidityrelative",
pcercuei 0:df031b60ca29 46 [IIO_ACTIVITY] = "activity",
pcercuei 0:df031b60ca29 47 [IIO_STEPS] = "steps",
pcercuei 0:df031b60ca29 48 [IIO_ENERGY] = "energy",
pcercuei 0:df031b60ca29 49 [IIO_DISTANCE] = "distance",
pcercuei 0:df031b60ca29 50 [IIO_VELOCITY] = "velocity",
pcercuei 0:df031b60ca29 51 [IIO_CONCENTRATION] = "concentration",
pcercuei 0:df031b60ca29 52 [IIO_RESISTANCE] = "resistance",
pcercuei 0:df031b60ca29 53 [IIO_PH] = "ph",
pcercuei 0:df031b60ca29 54 };
pcercuei 0:df031b60ca29 55
pcercuei 0:df031b60ca29 56 static const char * const modifier_names[] = {
pcercuei 0:df031b60ca29 57 [IIO_MOD_X] = "x",
pcercuei 0:df031b60ca29 58 [IIO_MOD_Y] = "y",
pcercuei 0:df031b60ca29 59 [IIO_MOD_Z] = "z",
pcercuei 0:df031b60ca29 60 [IIO_MOD_X_AND_Y] = "x&y",
pcercuei 0:df031b60ca29 61 [IIO_MOD_X_AND_Z] = "x&z",
pcercuei 0:df031b60ca29 62 [IIO_MOD_Y_AND_Z] = "y&z",
pcercuei 0:df031b60ca29 63 [IIO_MOD_X_AND_Y_AND_Z] = "x&y&z",
pcercuei 0:df031b60ca29 64 [IIO_MOD_X_OR_Y] = "x|y",
pcercuei 0:df031b60ca29 65 [IIO_MOD_X_OR_Z] = "x|z",
pcercuei 0:df031b60ca29 66 [IIO_MOD_Y_OR_Z] = "y|z",
pcercuei 0:df031b60ca29 67 [IIO_MOD_X_OR_Y_OR_Z] = "x|y|z",
pcercuei 0:df031b60ca29 68 [IIO_MOD_ROOT_SUM_SQUARED_X_Y] = "sqrt(x^2+y^2)",
pcercuei 0:df031b60ca29 69 [IIO_MOD_SUM_SQUARED_X_Y_Z] = "x^2+y^2+z^2",
pcercuei 0:df031b60ca29 70 [IIO_MOD_LIGHT_BOTH] = "both",
pcercuei 0:df031b60ca29 71 [IIO_MOD_LIGHT_IR] = "ir",
pcercuei 0:df031b60ca29 72 [IIO_MOD_LIGHT_CLEAR] = "clear",
pcercuei 0:df031b60ca29 73 [IIO_MOD_LIGHT_RED] = "red",
pcercuei 0:df031b60ca29 74 [IIO_MOD_LIGHT_GREEN] = "green",
pcercuei 0:df031b60ca29 75 [IIO_MOD_LIGHT_BLUE] = "blue",
pcercuei 0:df031b60ca29 76 [IIO_MOD_QUATERNION] = "quaternion",
pcercuei 0:df031b60ca29 77 [IIO_MOD_TEMP_AMBIENT] = "ambient",
pcercuei 0:df031b60ca29 78 [IIO_MOD_TEMP_OBJECT] = "object",
pcercuei 0:df031b60ca29 79 [IIO_MOD_NORTH_MAGN] = "from_north_magnetic",
pcercuei 0:df031b60ca29 80 [IIO_MOD_NORTH_TRUE] = "from_north_true",
pcercuei 0:df031b60ca29 81 [IIO_MOD_NORTH_MAGN_TILT_COMP] = "from_north_magnetic_tilt_comp",
pcercuei 0:df031b60ca29 82 [IIO_MOD_NORTH_TRUE_TILT_COMP] = "from_north_true_tilt_comp",
pcercuei 0:df031b60ca29 83 [IIO_MOD_RUNNING] = "running",
pcercuei 0:df031b60ca29 84 [IIO_MOD_JOGGING] = "jogging",
pcercuei 0:df031b60ca29 85 [IIO_MOD_WALKING] = "walking",
pcercuei 0:df031b60ca29 86 [IIO_MOD_STILL] = "still",
pcercuei 0:df031b60ca29 87 [IIO_MOD_ROOT_SUM_SQUARED_X_Y_Z] = "sqrt(x^2+y^2+z^2)",
pcercuei 0:df031b60ca29 88 [IIO_MOD_I] = "i",
pcercuei 0:df031b60ca29 89 [IIO_MOD_Q] = "q",
pcercuei 0:df031b60ca29 90 [IIO_MOD_CO2] = "co2",
pcercuei 0:df031b60ca29 91 [IIO_MOD_VOC] = "voc",
pcercuei 0:df031b60ca29 92 };
pcercuei 0:df031b60ca29 93
pcercuei 0:df031b60ca29 94 /*
pcercuei 0:df031b60ca29 95 * Looks for a IIO channel modifier at the beginning of the string s. If a
pcercuei 0:df031b60ca29 96 * modifier was found the symbolic constant (IIO_MOD_*) is returned, otherwise
pcercuei 0:df031b60ca29 97 * IIO_NO_MOD is returned. If a modifier was found len_p will be updated with
pcercuei 0:df031b60ca29 98 * the length of the modifier.
pcercuei 0:df031b60ca29 99 */
pcercuei 0:df031b60ca29 100 unsigned int find_channel_modifier(const char *s, size_t *len_p)
pcercuei 0:df031b60ca29 101 {
pcercuei 0:df031b60ca29 102 unsigned int i;
pcercuei 0:df031b60ca29 103 size_t len;
pcercuei 0:df031b60ca29 104
pcercuei 0:df031b60ca29 105 for (i = 0; i < ARRAY_SIZE(modifier_names); i++) {
pcercuei 0:df031b60ca29 106 if (!modifier_names[i])
pcercuei 0:df031b60ca29 107 continue;
pcercuei 0:df031b60ca29 108 len = strlen(modifier_names[i]);
pcercuei 0:df031b60ca29 109 if (strncmp(s, modifier_names[i], len) == 0 &&
pcercuei 0:df031b60ca29 110 (s[len] == '\0' || s[len] == '_')) {
pcercuei 0:df031b60ca29 111 if (len_p)
pcercuei 0:df031b60ca29 112 *len_p = len;
pcercuei 0:df031b60ca29 113 return i;
pcercuei 0:df031b60ca29 114 }
pcercuei 0:df031b60ca29 115 }
pcercuei 0:df031b60ca29 116
pcercuei 0:df031b60ca29 117 return IIO_NO_MOD;
pcercuei 0:df031b60ca29 118 }
pcercuei 0:df031b60ca29 119
pcercuei 0:df031b60ca29 120 /*
pcercuei 0:df031b60ca29 121 * Initializes all auto-detected fields of the channel struct. Must be called
pcercuei 0:df031b60ca29 122 * after the channel has been otherwise fully initialized.
pcercuei 0:df031b60ca29 123 */
pcercuei 0:df031b60ca29 124 void iio_channel_init_finalize(struct iio_channel *chn)
pcercuei 0:df031b60ca29 125 {
pcercuei 0:df031b60ca29 126 unsigned int i;
pcercuei 0:df031b60ca29 127 size_t len;
pcercuei 0:df031b60ca29 128 char *mod;
pcercuei 0:df031b60ca29 129
pcercuei 0:df031b60ca29 130 chn->type = IIO_CHAN_TYPE_UNKNOWN;
pcercuei 0:df031b60ca29 131 chn->modifier = IIO_NO_MOD;
pcercuei 0:df031b60ca29 132
pcercuei 0:df031b60ca29 133 for (i = 0; i < ARRAY_SIZE(iio_chan_type_name_spec); i++) {
pcercuei 0:df031b60ca29 134 len = strlen(iio_chan_type_name_spec[i]);
pcercuei 0:df031b60ca29 135 if (strncmp(iio_chan_type_name_spec[i], chn->id, len) != 0)
pcercuei 0:df031b60ca29 136 continue;
pcercuei 0:df031b60ca29 137 /* Type must be followed by either a '_' or a digit */
pcercuei 0:df031b60ca29 138 if (chn->id[len] != '_' && chn->id[len] < '0' && chn->id[len] > '9')
pcercuei 0:df031b60ca29 139 continue;
pcercuei 0:df031b60ca29 140
pcercuei 0:df031b60ca29 141 chn->type = (enum iio_chan_type) i;
pcercuei 0:df031b60ca29 142 }
pcercuei 0:df031b60ca29 143
pcercuei 0:df031b60ca29 144 mod = strchr(chn->id, '_');
pcercuei 0:df031b60ca29 145 if (!mod)
pcercuei 0:df031b60ca29 146 return;
pcercuei 0:df031b60ca29 147
pcercuei 0:df031b60ca29 148 mod++;
pcercuei 0:df031b60ca29 149
pcercuei 0:df031b60ca29 150 for (i = 0; i < ARRAY_SIZE(modifier_names); i++) {
pcercuei 0:df031b60ca29 151 if (!modifier_names[i])
pcercuei 0:df031b60ca29 152 continue;
pcercuei 0:df031b60ca29 153 len = strlen(modifier_names[i]);
pcercuei 0:df031b60ca29 154 if (strncmp(modifier_names[i], mod, len) != 0)
pcercuei 0:df031b60ca29 155 continue;
pcercuei 0:df031b60ca29 156 /* Modifier must be followed by a '_' */
pcercuei 0:df031b60ca29 157 if (mod[len] != '_')
pcercuei 0:df031b60ca29 158 continue;
pcercuei 0:df031b60ca29 159
pcercuei 0:df031b60ca29 160 chn->modifier = (enum iio_modifier) i;
pcercuei 0:df031b60ca29 161 break;
pcercuei 0:df031b60ca29 162 }
pcercuei 0:df031b60ca29 163 }
pcercuei 0:df031b60ca29 164
pcercuei 0:df031b60ca29 165 static char *get_attr_xml(struct iio_channel_attr *attr, size_t *length)
pcercuei 0:df031b60ca29 166 {
pcercuei 0:df031b60ca29 167 char *str;
pcercuei 0:df031b60ca29 168 size_t len = strlen(attr->name) + sizeof("<attribute name=\"\" />");
pcercuei 0:df031b60ca29 169 if (attr->filename)
pcercuei 0:df031b60ca29 170 len += strlen(attr->filename) + sizeof("filename=\"\"");
pcercuei 0:df031b60ca29 171
pcercuei 0:df031b60ca29 172 str = malloc(len);
pcercuei 0:df031b60ca29 173 if (!str)
pcercuei 0:df031b60ca29 174 return NULL;
pcercuei 0:df031b60ca29 175
pcercuei 0:df031b60ca29 176 *length = len - 1; /* Skip the \0 */
pcercuei 0:df031b60ca29 177 if (attr->filename)
pcercuei 3:d147beabba0e 178 iio_snprintf(str, len, "<attribute name=\"%s\" filename=\"%s\" />",
pcercuei 0:df031b60ca29 179 attr->name, attr->filename);
pcercuei 0:df031b60ca29 180 else
pcercuei 3:d147beabba0e 181 iio_snprintf(str, len, "<attribute name=\"%s\" />", attr->name);
pcercuei 0:df031b60ca29 182 return str;
pcercuei 0:df031b60ca29 183 }
pcercuei 0:df031b60ca29 184
pcercuei 0:df031b60ca29 185 static char * get_scan_element(const struct iio_channel *chn, size_t *length)
pcercuei 0:df031b60ca29 186 {
pcercuei 3:d147beabba0e 187 char buf[1024], repeat[8] = "", *str;
pcercuei 0:df031b60ca29 188 char processed = (chn->format.is_fully_defined ? 'A' - 'a' : 0);
pcercuei 0:df031b60ca29 189
pcercuei 3:d147beabba0e 190 if (chn->format.repeat > 1)
pcercuei 3:d147beabba0e 191 iio_snprintf(repeat, sizeof(repeat), "X%u", chn->format.repeat);
pcercuei 3:d147beabba0e 192
pcercuei 3:d147beabba0e 193 iio_snprintf(buf, sizeof(buf), "<scan-element index=\"%li\" "
pcercuei 3:d147beabba0e 194 "format=\"%ce:%c%u/%u%s&gt;&gt;%u\" />",
pcercuei 0:df031b60ca29 195 chn->index, chn->format.is_be ? 'b' : 'l',
pcercuei 0:df031b60ca29 196 chn->format.is_signed ? 's' + processed : 'u' + processed,
pcercuei 3:d147beabba0e 197 chn->format.bits, chn->format.length, repeat,
pcercuei 0:df031b60ca29 198 chn->format.shift);
pcercuei 0:df031b60ca29 199
pcercuei 0:df031b60ca29 200 if (chn->format.with_scale) {
pcercuei 0:df031b60ca29 201 char *ptr = strrchr(buf, '\0');
pcercuei 3:d147beabba0e 202 iio_snprintf(ptr - 2, buf + sizeof(buf) - ptr + 2,
pcercuei 0:df031b60ca29 203 "scale=\"%f\" />", chn->format.scale);
pcercuei 0:df031b60ca29 204 }
pcercuei 0:df031b60ca29 205
pcercuei 0:df031b60ca29 206 str = iio_strdup(buf);
pcercuei 0:df031b60ca29 207 if (str)
pcercuei 0:df031b60ca29 208 *length = strlen(str);
pcercuei 0:df031b60ca29 209 return str;
pcercuei 0:df031b60ca29 210 }
pcercuei 0:df031b60ca29 211
pcercuei 0:df031b60ca29 212 /* Returns a string containing the XML representation of this channel */
pcercuei 0:df031b60ca29 213 char * iio_channel_get_xml(const struct iio_channel *chn, size_t *length)
pcercuei 0:df031b60ca29 214 {
pcercuei 0:df031b60ca29 215 size_t len = sizeof("<channel id=\"\" name=\"\" "
pcercuei 0:df031b60ca29 216 "type=\"output\" ></channel>")
pcercuei 0:df031b60ca29 217 + strlen(chn->id) + (chn->name ? strlen(chn->name) : 0);
pcercuei 0:df031b60ca29 218 char *ptr, *str, **attrs, *scan_element = NULL;
pcercuei 0:df031b60ca29 219 size_t *attrs_len, scan_element_len = 0;
pcercuei 0:df031b60ca29 220 unsigned int i;
pcercuei 0:df031b60ca29 221
pcercuei 0:df031b60ca29 222 if (chn->is_scan_element) {
pcercuei 0:df031b60ca29 223 scan_element = get_scan_element(chn, &scan_element_len);
pcercuei 0:df031b60ca29 224 if (!scan_element)
pcercuei 0:df031b60ca29 225 return NULL;
pcercuei 0:df031b60ca29 226 else
pcercuei 0:df031b60ca29 227 len += scan_element_len;
pcercuei 0:df031b60ca29 228 }
pcercuei 0:df031b60ca29 229
pcercuei 0:df031b60ca29 230 attrs_len = malloc(chn->nb_attrs * sizeof(*attrs_len));
pcercuei 0:df031b60ca29 231 if (!attrs_len)
pcercuei 0:df031b60ca29 232 goto err_free_scan_element;
pcercuei 0:df031b60ca29 233
pcercuei 0:df031b60ca29 234 attrs = malloc(chn->nb_attrs * sizeof(*attrs));
pcercuei 0:df031b60ca29 235 if (!attrs)
pcercuei 0:df031b60ca29 236 goto err_free_attrs_len;
pcercuei 0:df031b60ca29 237
pcercuei 0:df031b60ca29 238 for (i = 0; i < chn->nb_attrs; i++) {
pcercuei 0:df031b60ca29 239 char *xml = get_attr_xml(&chn->attrs[i], &attrs_len[i]);
pcercuei 0:df031b60ca29 240 if (!xml)
pcercuei 0:df031b60ca29 241 goto err_free_attrs;
pcercuei 0:df031b60ca29 242 attrs[i] = xml;
pcercuei 0:df031b60ca29 243 len += attrs_len[i];
pcercuei 0:df031b60ca29 244 }
pcercuei 0:df031b60ca29 245
pcercuei 0:df031b60ca29 246 str = malloc(len);
pcercuei 0:df031b60ca29 247 if (!str)
pcercuei 0:df031b60ca29 248 goto err_free_attrs;
pcercuei 0:df031b60ca29 249
pcercuei 3:d147beabba0e 250 iio_snprintf(str, len, "<channel id=\"%s\"", chn->id);
pcercuei 0:df031b60ca29 251 ptr = strrchr(str, '\0');
pcercuei 0:df031b60ca29 252
pcercuei 0:df031b60ca29 253 if (chn->name) {
pcercuei 0:df031b60ca29 254 sprintf(ptr, " name=\"%s\"", chn->name);
pcercuei 0:df031b60ca29 255 ptr = strrchr(ptr, '\0');
pcercuei 0:df031b60ca29 256 }
pcercuei 0:df031b60ca29 257
pcercuei 0:df031b60ca29 258 sprintf(ptr, " type=\"%s\" >", chn->is_output ? "output" : "input");
pcercuei 0:df031b60ca29 259 ptr = strrchr(ptr, '\0');
pcercuei 0:df031b60ca29 260
pcercuei 0:df031b60ca29 261 if (chn->is_scan_element) {
pcercuei 0:df031b60ca29 262 strcpy(ptr, scan_element);
pcercuei 0:df031b60ca29 263 ptr += scan_element_len;
pcercuei 0:df031b60ca29 264 }
pcercuei 0:df031b60ca29 265
pcercuei 0:df031b60ca29 266 for (i = 0; i < chn->nb_attrs; i++) {
pcercuei 0:df031b60ca29 267 strcpy(ptr, attrs[i]);
pcercuei 0:df031b60ca29 268 ptr += attrs_len[i];
pcercuei 0:df031b60ca29 269 free(attrs[i]);
pcercuei 0:df031b60ca29 270 }
pcercuei 0:df031b60ca29 271
pcercuei 0:df031b60ca29 272 free(scan_element);
pcercuei 0:df031b60ca29 273 free(attrs);
pcercuei 0:df031b60ca29 274 free(attrs_len);
pcercuei 0:df031b60ca29 275
pcercuei 0:df031b60ca29 276 strcpy(ptr, "</channel>");
pcercuei 0:df031b60ca29 277 *length = ptr - str + sizeof("</channel>") - 1;
pcercuei 0:df031b60ca29 278 return str;
pcercuei 0:df031b60ca29 279
pcercuei 0:df031b60ca29 280 err_free_attrs:
pcercuei 0:df031b60ca29 281 while (i--)
pcercuei 0:df031b60ca29 282 free(attrs[i]);
pcercuei 0:df031b60ca29 283 free(attrs);
pcercuei 0:df031b60ca29 284 err_free_attrs_len:
pcercuei 0:df031b60ca29 285 free(attrs_len);
pcercuei 0:df031b60ca29 286 err_free_scan_element:
pcercuei 0:df031b60ca29 287 if (chn->is_scan_element)
pcercuei 0:df031b60ca29 288 free(scan_element);
pcercuei 0:df031b60ca29 289 return NULL;
pcercuei 0:df031b60ca29 290 }
pcercuei 0:df031b60ca29 291
pcercuei 0:df031b60ca29 292 const char * iio_channel_get_id(const struct iio_channel *chn)
pcercuei 0:df031b60ca29 293 {
pcercuei 0:df031b60ca29 294 return chn->id;
pcercuei 0:df031b60ca29 295 }
pcercuei 0:df031b60ca29 296
pcercuei 0:df031b60ca29 297 const char * iio_channel_get_name(const struct iio_channel *chn)
pcercuei 0:df031b60ca29 298 {
pcercuei 0:df031b60ca29 299 return chn->name;
pcercuei 0:df031b60ca29 300 }
pcercuei 0:df031b60ca29 301
pcercuei 0:df031b60ca29 302 bool iio_channel_is_output(const struct iio_channel *chn)
pcercuei 0:df031b60ca29 303 {
pcercuei 0:df031b60ca29 304 return chn->is_output;
pcercuei 0:df031b60ca29 305 }
pcercuei 0:df031b60ca29 306
pcercuei 0:df031b60ca29 307 bool iio_channel_is_scan_element(const struct iio_channel *chn)
pcercuei 0:df031b60ca29 308 {
pcercuei 0:df031b60ca29 309 return chn->is_scan_element;
pcercuei 0:df031b60ca29 310 }
pcercuei 0:df031b60ca29 311
pcercuei 0:df031b60ca29 312 enum iio_modifier iio_channel_get_modifier(const struct iio_channel *chn)
pcercuei 0:df031b60ca29 313 {
pcercuei 0:df031b60ca29 314 return chn->modifier;
pcercuei 0:df031b60ca29 315 }
pcercuei 0:df031b60ca29 316
pcercuei 0:df031b60ca29 317 enum iio_chan_type iio_channel_get_type(const struct iio_channel *chn)
pcercuei 0:df031b60ca29 318 {
pcercuei 0:df031b60ca29 319 return chn->type;
pcercuei 0:df031b60ca29 320 }
pcercuei 0:df031b60ca29 321
pcercuei 0:df031b60ca29 322 unsigned int iio_channel_get_attrs_count(const struct iio_channel *chn)
pcercuei 0:df031b60ca29 323 {
pcercuei 0:df031b60ca29 324 return chn->nb_attrs;
pcercuei 0:df031b60ca29 325 }
pcercuei 0:df031b60ca29 326
pcercuei 0:df031b60ca29 327 const char * iio_channel_get_attr(const struct iio_channel *chn,
pcercuei 0:df031b60ca29 328 unsigned int index)
pcercuei 0:df031b60ca29 329 {
pcercuei 0:df031b60ca29 330 if (index >= chn->nb_attrs)
pcercuei 0:df031b60ca29 331 return NULL;
pcercuei 0:df031b60ca29 332 else
pcercuei 0:df031b60ca29 333 return chn->attrs[index].name;
pcercuei 0:df031b60ca29 334 }
pcercuei 0:df031b60ca29 335
pcercuei 0:df031b60ca29 336 const char * iio_channel_find_attr(const struct iio_channel *chn,
pcercuei 0:df031b60ca29 337 const char *name)
pcercuei 0:df031b60ca29 338 {
pcercuei 0:df031b60ca29 339 unsigned int i;
pcercuei 0:df031b60ca29 340 for (i = 0; i < chn->nb_attrs; i++) {
pcercuei 0:df031b60ca29 341 const char *attr = chn->attrs[i].name;
pcercuei 0:df031b60ca29 342 if (!strcmp(attr, name))
pcercuei 0:df031b60ca29 343 return attr;
pcercuei 0:df031b60ca29 344 }
pcercuei 0:df031b60ca29 345 return NULL;
pcercuei 0:df031b60ca29 346 }
pcercuei 0:df031b60ca29 347
pcercuei 0:df031b60ca29 348 ssize_t iio_channel_attr_read(const struct iio_channel *chn,
pcercuei 0:df031b60ca29 349 const char *attr, char *dst, size_t len)
pcercuei 0:df031b60ca29 350 {
pcercuei 0:df031b60ca29 351 if (chn->dev->ctx->ops->read_channel_attr)
pcercuei 0:df031b60ca29 352 return chn->dev->ctx->ops->read_channel_attr(chn,
pcercuei 0:df031b60ca29 353 attr, dst, len);
pcercuei 0:df031b60ca29 354 else
pcercuei 0:df031b60ca29 355 return -ENOSYS;
pcercuei 0:df031b60ca29 356 }
pcercuei 0:df031b60ca29 357
pcercuei 0:df031b60ca29 358 ssize_t iio_channel_attr_write_raw(const struct iio_channel *chn,
pcercuei 0:df031b60ca29 359 const char *attr, const void *src, size_t len)
pcercuei 0:df031b60ca29 360 {
pcercuei 0:df031b60ca29 361 if (chn->dev->ctx->ops->write_channel_attr)
pcercuei 0:df031b60ca29 362 return chn->dev->ctx->ops->write_channel_attr(chn,
pcercuei 0:df031b60ca29 363 attr, src, len);
pcercuei 0:df031b60ca29 364 else
pcercuei 0:df031b60ca29 365 return -ENOSYS;
pcercuei 0:df031b60ca29 366 }
pcercuei 0:df031b60ca29 367
pcercuei 0:df031b60ca29 368 ssize_t iio_channel_attr_write(const struct iio_channel *chn,
pcercuei 0:df031b60ca29 369 const char *attr, const char *src)
pcercuei 0:df031b60ca29 370 {
pcercuei 0:df031b60ca29 371 return iio_channel_attr_write_raw(chn, attr, src, strlen(src) + 1);
pcercuei 0:df031b60ca29 372 }
pcercuei 0:df031b60ca29 373
pcercuei 0:df031b60ca29 374 void iio_channel_set_data(struct iio_channel *chn, void *data)
pcercuei 0:df031b60ca29 375 {
pcercuei 0:df031b60ca29 376 chn->userdata = data;
pcercuei 0:df031b60ca29 377 }
pcercuei 0:df031b60ca29 378
pcercuei 0:df031b60ca29 379 void * iio_channel_get_data(const struct iio_channel *chn)
pcercuei 0:df031b60ca29 380 {
pcercuei 0:df031b60ca29 381 return chn->userdata;
pcercuei 0:df031b60ca29 382 }
pcercuei 0:df031b60ca29 383
pcercuei 0:df031b60ca29 384 long iio_channel_get_index(const struct iio_channel *chn)
pcercuei 0:df031b60ca29 385 {
pcercuei 0:df031b60ca29 386 return chn->index;
pcercuei 0:df031b60ca29 387 }
pcercuei 0:df031b60ca29 388
pcercuei 0:df031b60ca29 389 const struct iio_data_format * iio_channel_get_data_format(
pcercuei 0:df031b60ca29 390 const struct iio_channel *chn)
pcercuei 0:df031b60ca29 391 {
pcercuei 0:df031b60ca29 392 return &chn->format;
pcercuei 0:df031b60ca29 393 }
pcercuei 0:df031b60ca29 394
pcercuei 0:df031b60ca29 395 bool iio_channel_is_enabled(const struct iio_channel *chn)
pcercuei 0:df031b60ca29 396 {
pcercuei 0:df031b60ca29 397 return chn->index >= 0 && chn->dev->mask &&
pcercuei 0:df031b60ca29 398 TEST_BIT(chn->dev->mask, chn->index);
pcercuei 0:df031b60ca29 399 }
pcercuei 0:df031b60ca29 400
pcercuei 0:df031b60ca29 401 void iio_channel_enable(struct iio_channel *chn)
pcercuei 0:df031b60ca29 402 {
pcercuei 0:df031b60ca29 403 if (chn->is_scan_element && chn->index >= 0 && chn->dev->mask)
pcercuei 0:df031b60ca29 404 SET_BIT(chn->dev->mask, chn->index);
pcercuei 0:df031b60ca29 405 }
pcercuei 0:df031b60ca29 406
pcercuei 0:df031b60ca29 407 void iio_channel_disable(struct iio_channel *chn)
pcercuei 0:df031b60ca29 408 {
pcercuei 0:df031b60ca29 409 if (chn->index >= 0 && chn->dev->mask)
pcercuei 0:df031b60ca29 410 CLEAR_BIT(chn->dev->mask, chn->index);
pcercuei 0:df031b60ca29 411 }
pcercuei 0:df031b60ca29 412
pcercuei 0:df031b60ca29 413 void free_channel(struct iio_channel *chn)
pcercuei 0:df031b60ca29 414 {
pcercuei 0:df031b60ca29 415 size_t i;
pcercuei 0:df031b60ca29 416 for (i = 0; i < chn->nb_attrs; i++) {
pcercuei 0:df031b60ca29 417 free(chn->attrs[i].name);
pcercuei 0:df031b60ca29 418 free(chn->attrs[i].filename);
pcercuei 0:df031b60ca29 419 }
pcercuei 0:df031b60ca29 420 if (chn->nb_attrs)
pcercuei 0:df031b60ca29 421 free(chn->attrs);
pcercuei 0:df031b60ca29 422 if (chn->name)
pcercuei 0:df031b60ca29 423 free(chn->name);
pcercuei 0:df031b60ca29 424 if (chn->id)
pcercuei 0:df031b60ca29 425 free(chn->id);
pcercuei 0:df031b60ca29 426 free(chn);
pcercuei 0:df031b60ca29 427 }
pcercuei 0:df031b60ca29 428
pcercuei 0:df031b60ca29 429 static void byte_swap(uint8_t *dst, const uint8_t *src, size_t len)
pcercuei 0:df031b60ca29 430 {
pcercuei 0:df031b60ca29 431 size_t i;
pcercuei 0:df031b60ca29 432 for (i = 0; i < len; i++)
pcercuei 0:df031b60ca29 433 dst[i] = src[len - i - 1];
pcercuei 0:df031b60ca29 434 }
pcercuei 0:df031b60ca29 435
pcercuei 0:df031b60ca29 436 static void shift_bits(uint8_t *dst, size_t shift, size_t len, bool left)
pcercuei 0:df031b60ca29 437 {
pcercuei 0:df031b60ca29 438 size_t i, shift_bytes = shift / 8;
pcercuei 0:df031b60ca29 439 shift %= 8;
pcercuei 0:df031b60ca29 440
pcercuei 0:df031b60ca29 441 #if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
pcercuei 0:df031b60ca29 442 if (!left)
pcercuei 0:df031b60ca29 443 #else
pcercuei 0:df031b60ca29 444 if (left)
pcercuei 0:df031b60ca29 445 #endif
pcercuei 0:df031b60ca29 446 {
pcercuei 0:df031b60ca29 447 if (shift_bytes) {
pcercuei 0:df031b60ca29 448 memmove(dst, dst + shift_bytes, len - shift_bytes);
pcercuei 0:df031b60ca29 449 memset(dst + len - shift_bytes, 0, shift_bytes);
pcercuei 0:df031b60ca29 450 }
pcercuei 0:df031b60ca29 451 if (shift) {
pcercuei 0:df031b60ca29 452 for (i = 0; i < len; i++) {
pcercuei 0:df031b60ca29 453 #if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
pcercuei 0:df031b60ca29 454 dst[i] >>= shift;
pcercuei 0:df031b60ca29 455 if (i < len - 1)
pcercuei 0:df031b60ca29 456 dst[i] |= dst[i + 1] << (8 - shift);
pcercuei 0:df031b60ca29 457 #else
pcercuei 0:df031b60ca29 458 dst[i] <<= shift;
pcercuei 0:df031b60ca29 459 if (i < len - 1)
pcercuei 0:df031b60ca29 460 dst[i] |= dst[i + 1] >> (8 - shift);
pcercuei 0:df031b60ca29 461 #endif
pcercuei 0:df031b60ca29 462 }
pcercuei 0:df031b60ca29 463 }
pcercuei 0:df031b60ca29 464 } else {
pcercuei 0:df031b60ca29 465 if (shift_bytes) {
pcercuei 0:df031b60ca29 466 memmove(dst + shift_bytes, dst, len - shift_bytes);
pcercuei 0:df031b60ca29 467 memset(dst, 0, shift_bytes);
pcercuei 0:df031b60ca29 468 }
pcercuei 0:df031b60ca29 469 if (shift) {
pcercuei 0:df031b60ca29 470 for (i = len; i > 0; i--) {
pcercuei 0:df031b60ca29 471 #if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
pcercuei 0:df031b60ca29 472 dst[i - 1] <<= shift;
pcercuei 0:df031b60ca29 473 if (i > 1)
pcercuei 0:df031b60ca29 474 dst[i - 1] |= dst[i - 2] >> (8 - shift);
pcercuei 0:df031b60ca29 475 #else
pcercuei 0:df031b60ca29 476 dst[i - 1] >>= shift;
pcercuei 0:df031b60ca29 477 if (i > 1)
pcercuei 0:df031b60ca29 478 dst[i - 1] |= dst[i - 2] << (8 - shift);
pcercuei 0:df031b60ca29 479 #endif
pcercuei 0:df031b60ca29 480 }
pcercuei 0:df031b60ca29 481 }
pcercuei 0:df031b60ca29 482 }
pcercuei 0:df031b60ca29 483 }
pcercuei 0:df031b60ca29 484
pcercuei 0:df031b60ca29 485 static void sign_extend(uint8_t *dst, size_t bits, size_t len)
pcercuei 0:df031b60ca29 486 {
pcercuei 0:df031b60ca29 487 size_t upper_bytes = ((len * 8 - bits) / 8);
pcercuei 0:df031b60ca29 488 uint8_t msb, msb_bit = 1 << ((bits - 1) % 8);
pcercuei 0:df031b60ca29 489
pcercuei 0:df031b60ca29 490 #if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
pcercuei 0:df031b60ca29 491 msb = dst[len - 1 - upper_bytes] & msb_bit;
pcercuei 0:df031b60ca29 492 if (upper_bytes)
pcercuei 0:df031b60ca29 493 memset(dst + len - upper_bytes, msb ? 0xff : 0x00, upper_bytes);
pcercuei 0:df031b60ca29 494 if (msb)
pcercuei 0:df031b60ca29 495 dst[len - 1 - upper_bytes] |= ~(msb_bit - 1);
pcercuei 0:df031b60ca29 496 else
pcercuei 0:df031b60ca29 497 dst[len - 1 - upper_bytes] &= (msb_bit - 1);
pcercuei 0:df031b60ca29 498 #else
pcercuei 0:df031b60ca29 499 /* XXX: untested */
pcercuei 0:df031b60ca29 500 msb = dst[upper_bytes] & msb_bit;
pcercuei 0:df031b60ca29 501 if (upper_bytes)
pcercuei 0:df031b60ca29 502 memset(dst, msb ? 0xff : 0x00, upper_bytes);
pcercuei 0:df031b60ca29 503 if (msb)
pcercuei 0:df031b60ca29 504 dst[upper_bytes] |= ~(msb_bit - 1);
pcercuei 0:df031b60ca29 505 #endif
pcercuei 0:df031b60ca29 506 }
pcercuei 0:df031b60ca29 507
pcercuei 0:df031b60ca29 508 static void mask_upper_bits(uint8_t *dst, size_t bits, size_t len)
pcercuei 0:df031b60ca29 509 {
pcercuei 0:df031b60ca29 510 size_t i;
pcercuei 0:df031b60ca29 511
pcercuei 0:df031b60ca29 512 /* Clear upper bits */
pcercuei 0:df031b60ca29 513 if (bits % 8)
pcercuei 0:df031b60ca29 514 dst[bits / 8] &= (1 << (bits % 8)) - 1;
pcercuei 0:df031b60ca29 515
pcercuei 0:df031b60ca29 516 /* Clear upper bytes */
pcercuei 0:df031b60ca29 517 for (i = (bits + 7) / 8; i < len; i++)
pcercuei 0:df031b60ca29 518 dst[i] = 0;
pcercuei 0:df031b60ca29 519 }
pcercuei 0:df031b60ca29 520
pcercuei 0:df031b60ca29 521
pcercuei 0:df031b60ca29 522 void iio_channel_convert(const struct iio_channel *chn,
pcercuei 0:df031b60ca29 523 void *dst, const void *src)
pcercuei 0:df031b60ca29 524 {
pcercuei 3:d147beabba0e 525 uintptr_t src_ptr = (uintptr_t) src, dst_ptr = (uintptr_t) dst;
pcercuei 0:df031b60ca29 526 unsigned int len = chn->format.length / 8;
pcercuei 3:d147beabba0e 527 ptrdiff_t end = len * chn->format.repeat;
pcercuei 3:d147beabba0e 528 uintptr_t end_ptr = src_ptr + end;
pcercuei 0:df031b60ca29 529 #if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
pcercuei 0:df031b60ca29 530 bool swap = chn->format.is_be;
pcercuei 0:df031b60ca29 531 #else
pcercuei 0:df031b60ca29 532 bool swap = !chn->format.is_be;
pcercuei 0:df031b60ca29 533 #endif
pcercuei 0:df031b60ca29 534
pcercuei 3:d147beabba0e 535 for (src_ptr = (uintptr_t) src; src_ptr < end_ptr;
pcercuei 3:d147beabba0e 536 src_ptr += len, dst_ptr += len) {
pcercuei 3:d147beabba0e 537 if (len == 1 || !swap)
pcercuei 3:d147beabba0e 538 memcpy((void *) dst_ptr, (const void *) src_ptr, len);
pcercuei 3:d147beabba0e 539 else
pcercuei 3:d147beabba0e 540 byte_swap((void *) dst_ptr, (const void *) src_ptr,
pcercuei 3:d147beabba0e 541 len);
pcercuei 0:df031b60ca29 542
pcercuei 3:d147beabba0e 543 if (chn->format.shift)
pcercuei 3:d147beabba0e 544 shift_bits((void *) dst_ptr, chn->format.shift, len,
pcercuei 3:d147beabba0e 545 false);
pcercuei 0:df031b60ca29 546
pcercuei 3:d147beabba0e 547 if (!chn->format.is_fully_defined) {
pcercuei 3:d147beabba0e 548 if (chn->format.is_signed)
pcercuei 3:d147beabba0e 549 sign_extend((void *) dst_ptr,
pcercuei 3:d147beabba0e 550 chn->format.bits, len);
pcercuei 3:d147beabba0e 551 else
pcercuei 3:d147beabba0e 552 mask_upper_bits((void *) dst_ptr,
pcercuei 3:d147beabba0e 553 chn->format.bits, len);
pcercuei 3:d147beabba0e 554 }
pcercuei 0:df031b60ca29 555 }
pcercuei 0:df031b60ca29 556 }
pcercuei 0:df031b60ca29 557
pcercuei 0:df031b60ca29 558 void iio_channel_convert_inverse(const struct iio_channel *chn,
pcercuei 0:df031b60ca29 559 void *dst, const void *src)
pcercuei 0:df031b60ca29 560 {
pcercuei 3:d147beabba0e 561 uintptr_t src_ptr = (uintptr_t) src, dst_ptr = (uintptr_t) dst;
pcercuei 0:df031b60ca29 562 unsigned int len = chn->format.length / 8;
pcercuei 3:d147beabba0e 563 ptrdiff_t end = len * chn->format.repeat;
pcercuei 3:d147beabba0e 564 uintptr_t end_ptr = dst_ptr + end;
pcercuei 0:df031b60ca29 565 #if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
pcercuei 0:df031b60ca29 566 bool swap = chn->format.is_be;
pcercuei 0:df031b60ca29 567 #else
pcercuei 0:df031b60ca29 568 bool swap = !chn->format.is_be;
pcercuei 0:df031b60ca29 569 #endif
pcercuei 0:df031b60ca29 570 uint8_t buf[1024];
pcercuei 0:df031b60ca29 571
pcercuei 0:df031b60ca29 572 /* Somehow I doubt we will have samples of 8192 bits each. */
pcercuei 0:df031b60ca29 573 if (len > sizeof(buf))
pcercuei 0:df031b60ca29 574 return;
pcercuei 0:df031b60ca29 575
pcercuei 3:d147beabba0e 576 for (dst_ptr = (uintptr_t) dst; dst_ptr < end_ptr;
pcercuei 3:d147beabba0e 577 src_ptr += len, dst_ptr += len) {
pcercuei 3:d147beabba0e 578 memcpy(buf, (const void *) src_ptr, len);
pcercuei 3:d147beabba0e 579 mask_upper_bits(buf, chn->format.bits, len);
pcercuei 0:df031b60ca29 580
pcercuei 3:d147beabba0e 581 if (chn->format.shift)
pcercuei 3:d147beabba0e 582 shift_bits(buf, chn->format.shift, len, true);
pcercuei 0:df031b60ca29 583
pcercuei 3:d147beabba0e 584 if (len == 1 || !swap)
pcercuei 3:d147beabba0e 585 memcpy((void *) dst_ptr, buf, len);
pcercuei 3:d147beabba0e 586 else
pcercuei 3:d147beabba0e 587 byte_swap((void *) dst_ptr, buf, len);
pcercuei 3:d147beabba0e 588 }
pcercuei 0:df031b60ca29 589 }
pcercuei 0:df031b60ca29 590
pcercuei 0:df031b60ca29 591 size_t iio_channel_read_raw(const struct iio_channel *chn,
pcercuei 0:df031b60ca29 592 struct iio_buffer *buf, void *dst, size_t len)
pcercuei 0:df031b60ca29 593 {
pcercuei 0:df031b60ca29 594 uintptr_t src_ptr, dst_ptr = (uintptr_t) dst, end = dst_ptr + len;
pcercuei 3:d147beabba0e 595 unsigned int length = chn->format.length / 8 * chn->format.repeat;
pcercuei 0:df031b60ca29 596 uintptr_t buf_end = (uintptr_t) iio_buffer_end(buf);
pcercuei 0:df031b60ca29 597 ptrdiff_t buf_step = iio_buffer_step(buf);
pcercuei 0:df031b60ca29 598
pcercuei 0:df031b60ca29 599 for (src_ptr = (uintptr_t) iio_buffer_first(buf, chn);
pcercuei 0:df031b60ca29 600 src_ptr < buf_end && dst_ptr + length <= end;
pcercuei 0:df031b60ca29 601 src_ptr += buf_step, dst_ptr += length)
pcercuei 0:df031b60ca29 602 memcpy((void *) dst_ptr, (const void *) src_ptr, length);
pcercuei 0:df031b60ca29 603 return dst_ptr - (uintptr_t) dst;
pcercuei 0:df031b60ca29 604 }
pcercuei 0:df031b60ca29 605
pcercuei 0:df031b60ca29 606 size_t iio_channel_read(const struct iio_channel *chn,
pcercuei 0:df031b60ca29 607 struct iio_buffer *buf, void *dst, size_t len)
pcercuei 0:df031b60ca29 608 {
pcercuei 0:df031b60ca29 609 uintptr_t src_ptr, dst_ptr = (uintptr_t) dst, end = dst_ptr + len;
pcercuei 3:d147beabba0e 610 unsigned int length = chn->format.length / 8 * chn->format.repeat;
pcercuei 0:df031b60ca29 611 uintptr_t buf_end = (uintptr_t) iio_buffer_end(buf);
pcercuei 0:df031b60ca29 612 ptrdiff_t buf_step = iio_buffer_step(buf);
pcercuei 0:df031b60ca29 613
pcercuei 0:df031b60ca29 614 for (src_ptr = (uintptr_t) iio_buffer_first(buf, chn);
pcercuei 0:df031b60ca29 615 src_ptr < buf_end && dst_ptr + length <= end;
pcercuei 0:df031b60ca29 616 src_ptr += buf_step, dst_ptr += length)
pcercuei 0:df031b60ca29 617 iio_channel_convert(chn,
pcercuei 0:df031b60ca29 618 (void *) dst_ptr, (const void *) src_ptr);
pcercuei 0:df031b60ca29 619 return dst_ptr - (uintptr_t) dst;
pcercuei 0:df031b60ca29 620 }
pcercuei 0:df031b60ca29 621
pcercuei 0:df031b60ca29 622 size_t iio_channel_write_raw(const struct iio_channel *chn,
pcercuei 0:df031b60ca29 623 struct iio_buffer *buf, const void *src, size_t len)
pcercuei 0:df031b60ca29 624 {
pcercuei 0:df031b60ca29 625 uintptr_t dst_ptr, src_ptr = (uintptr_t) src, end = src_ptr + len;
pcercuei 3:d147beabba0e 626 unsigned int length = chn->format.length / 8 * chn->format.repeat;
pcercuei 0:df031b60ca29 627 uintptr_t buf_end = (uintptr_t) iio_buffer_end(buf);
pcercuei 0:df031b60ca29 628 ptrdiff_t buf_step = iio_buffer_step(buf);
pcercuei 0:df031b60ca29 629
pcercuei 0:df031b60ca29 630 for (dst_ptr = (uintptr_t) iio_buffer_first(buf, chn);
pcercuei 0:df031b60ca29 631 dst_ptr < buf_end && src_ptr + length <= end;
pcercuei 0:df031b60ca29 632 dst_ptr += buf_step, src_ptr += length)
pcercuei 0:df031b60ca29 633 memcpy((void *) dst_ptr, (const void *) src_ptr, length);
pcercuei 0:df031b60ca29 634 return src_ptr - (uintptr_t) src;
pcercuei 0:df031b60ca29 635 }
pcercuei 0:df031b60ca29 636
pcercuei 0:df031b60ca29 637 size_t iio_channel_write(const struct iio_channel *chn,
pcercuei 0:df031b60ca29 638 struct iio_buffer *buf, const void *src, size_t len)
pcercuei 0:df031b60ca29 639 {
pcercuei 0:df031b60ca29 640 uintptr_t dst_ptr, src_ptr = (uintptr_t) src, end = src_ptr + len;
pcercuei 3:d147beabba0e 641 unsigned int length = chn->format.length / 8 * chn->format.repeat;
pcercuei 0:df031b60ca29 642 uintptr_t buf_end = (uintptr_t) iio_buffer_end(buf);
pcercuei 0:df031b60ca29 643 ptrdiff_t buf_step = iio_buffer_step(buf);
pcercuei 0:df031b60ca29 644
pcercuei 0:df031b60ca29 645 for (dst_ptr = (uintptr_t) iio_buffer_first(buf, chn);
pcercuei 0:df031b60ca29 646 dst_ptr < buf_end && src_ptr + length <= end;
pcercuei 0:df031b60ca29 647 dst_ptr += buf_step, src_ptr += length)
pcercuei 0:df031b60ca29 648 iio_channel_convert_inverse(chn,
pcercuei 0:df031b60ca29 649 (void *) dst_ptr, (const void *) src_ptr);
pcercuei 0:df031b60ca29 650 return src_ptr - (uintptr_t) src;
pcercuei 0:df031b60ca29 651 }
pcercuei 0:df031b60ca29 652
pcercuei 0:df031b60ca29 653 int iio_channel_attr_read_longlong(const struct iio_channel *chn,
pcercuei 0:df031b60ca29 654 const char *attr, long long *val)
pcercuei 0:df031b60ca29 655 {
pcercuei 0:df031b60ca29 656 char *end, buf[1024];
pcercuei 0:df031b60ca29 657 long long value;
pcercuei 0:df031b60ca29 658 ssize_t ret = iio_channel_attr_read(chn, attr, buf, sizeof(buf));
pcercuei 0:df031b60ca29 659 if (ret < 0)
pcercuei 0:df031b60ca29 660 return (int) ret;
pcercuei 0:df031b60ca29 661
pcercuei 0:df031b60ca29 662 value = strtoll(buf, &end, 0);
pcercuei 0:df031b60ca29 663 if (end == buf)
pcercuei 0:df031b60ca29 664 return -EINVAL;
pcercuei 0:df031b60ca29 665 *val = value;
pcercuei 0:df031b60ca29 666 return 0;
pcercuei 0:df031b60ca29 667 }
pcercuei 0:df031b60ca29 668
pcercuei 0:df031b60ca29 669 int iio_channel_attr_read_bool(const struct iio_channel *chn,
pcercuei 0:df031b60ca29 670 const char *attr, bool *val)
pcercuei 0:df031b60ca29 671 {
pcercuei 0:df031b60ca29 672 long long value;
pcercuei 0:df031b60ca29 673 int ret = iio_channel_attr_read_longlong(chn, attr, &value);
pcercuei 0:df031b60ca29 674 if (ret < 0)
pcercuei 0:df031b60ca29 675 return ret;
pcercuei 0:df031b60ca29 676
pcercuei 0:df031b60ca29 677 *val = !!value;
pcercuei 0:df031b60ca29 678 return 0;
pcercuei 0:df031b60ca29 679 }
pcercuei 0:df031b60ca29 680
pcercuei 0:df031b60ca29 681 int iio_channel_attr_read_double(const struct iio_channel *chn,
pcercuei 0:df031b60ca29 682 const char *attr, double *val)
pcercuei 0:df031b60ca29 683 {
pcercuei 0:df031b60ca29 684 char buf[1024];
pcercuei 0:df031b60ca29 685 ssize_t ret = iio_channel_attr_read(chn, attr, buf, sizeof(buf));
pcercuei 0:df031b60ca29 686 if (ret < 0)
pcercuei 0:df031b60ca29 687 return (int) ret;
pcercuei 0:df031b60ca29 688 else
pcercuei 0:df031b60ca29 689 return read_double(buf, val);
pcercuei 0:df031b60ca29 690 }
pcercuei 0:df031b60ca29 691
pcercuei 0:df031b60ca29 692 int iio_channel_attr_write_longlong(const struct iio_channel *chn,
pcercuei 0:df031b60ca29 693 const char *attr, long long val)
pcercuei 0:df031b60ca29 694 {
pcercuei 0:df031b60ca29 695 ssize_t ret;
pcercuei 0:df031b60ca29 696 char buf[1024];
pcercuei 3:d147beabba0e 697 iio_snprintf(buf, sizeof(buf), "%lld", val);
pcercuei 0:df031b60ca29 698 ret = iio_channel_attr_write(chn, attr, buf);
pcercuei 0:df031b60ca29 699 return ret < 0 ? ret : 0;
pcercuei 0:df031b60ca29 700 }
pcercuei 0:df031b60ca29 701
pcercuei 0:df031b60ca29 702 int iio_channel_attr_write_double(const struct iio_channel *chn,
pcercuei 0:df031b60ca29 703 const char *attr, double val)
pcercuei 0:df031b60ca29 704 {
pcercuei 0:df031b60ca29 705 ssize_t ret;
pcercuei 0:df031b60ca29 706 char buf[1024];
pcercuei 0:df031b60ca29 707
pcercuei 0:df031b60ca29 708 ret = (ssize_t) write_double(buf, sizeof(buf), val);
pcercuei 0:df031b60ca29 709 if (!ret)
pcercuei 0:df031b60ca29 710 ret = iio_channel_attr_write(chn, attr, buf);
pcercuei 0:df031b60ca29 711 return ret < 0 ? ret : 0;
pcercuei 0:df031b60ca29 712 }
pcercuei 0:df031b60ca29 713
pcercuei 0:df031b60ca29 714 int iio_channel_attr_write_bool(const struct iio_channel *chn,
pcercuei 0:df031b60ca29 715 const char *attr, bool val)
pcercuei 0:df031b60ca29 716 {
pcercuei 0:df031b60ca29 717 ssize_t ret;
pcercuei 0:df031b60ca29 718 if (val)
pcercuei 0:df031b60ca29 719 ret = iio_channel_attr_write_raw(chn, attr, "1", 2);
pcercuei 0:df031b60ca29 720 else
pcercuei 0:df031b60ca29 721 ret = iio_channel_attr_write_raw(chn, attr, "0", 2);
pcercuei 0:df031b60ca29 722 return ret < 0 ? ret : 0;
pcercuei 0:df031b60ca29 723 }
pcercuei 0:df031b60ca29 724
pcercuei 0:df031b60ca29 725 const char * iio_channel_attr_get_filename(
pcercuei 0:df031b60ca29 726 const struct iio_channel *chn, const char *attr)
pcercuei 0:df031b60ca29 727 {
pcercuei 0:df031b60ca29 728 unsigned int i;
pcercuei 0:df031b60ca29 729 for (i = 0; i < chn->nb_attrs; i++) {
pcercuei 0:df031b60ca29 730 if (!strcmp(chn->attrs[i].name, attr))
pcercuei 0:df031b60ca29 731 return chn->attrs[i].filename;
pcercuei 0:df031b60ca29 732 }
pcercuei 0:df031b60ca29 733 return NULL;
pcercuei 0:df031b60ca29 734 }
pcercuei 0:df031b60ca29 735
pcercuei 0:df031b60ca29 736 int iio_channel_attr_read_all(struct iio_channel *chn,
pcercuei 0:df031b60ca29 737 int (*cb)(struct iio_channel *chn,
pcercuei 0:df031b60ca29 738 const char *attr, const char *val, size_t len, void *d),
pcercuei 0:df031b60ca29 739 void *data)
pcercuei 0:df031b60ca29 740 {
pcercuei 0:df031b60ca29 741 int ret;
pcercuei 0:df031b60ca29 742 char *buf, *ptr;
pcercuei 0:df031b60ca29 743 unsigned int i;
pcercuei 0:df031b60ca29 744
pcercuei 0:df031b60ca29 745 /* We need a big buffer here; 1 MiB should be enough */
pcercuei 0:df031b60ca29 746 buf = malloc(0x100000);
pcercuei 0:df031b60ca29 747 if (!buf)
pcercuei 0:df031b60ca29 748 return -ENOMEM;
pcercuei 0:df031b60ca29 749
pcercuei 0:df031b60ca29 750 ret = (int) iio_channel_attr_read(chn, NULL, buf, 0x100000);
pcercuei 0:df031b60ca29 751 if (ret < 0)
pcercuei 0:df031b60ca29 752 goto err_free_buf;
pcercuei 0:df031b60ca29 753
pcercuei 0:df031b60ca29 754 ptr = buf;
pcercuei 0:df031b60ca29 755
pcercuei 0:df031b60ca29 756 for (i = 0; i < iio_channel_get_attrs_count(chn); i++) {
pcercuei 0:df031b60ca29 757 const char *attr = iio_channel_get_attr(chn, i);
pcercuei 0:df031b60ca29 758 int32_t len = (int32_t) iio_be32toh(*(uint32_t *) ptr);
pcercuei 0:df031b60ca29 759
pcercuei 0:df031b60ca29 760 ptr += 4;
pcercuei 0:df031b60ca29 761 if (len > 0) {
pcercuei 0:df031b60ca29 762 ret = cb(chn, attr, ptr, (size_t) len, data);
pcercuei 0:df031b60ca29 763 if (ret < 0)
pcercuei 0:df031b60ca29 764 goto err_free_buf;
pcercuei 0:df031b60ca29 765
pcercuei 0:df031b60ca29 766 if (len & 0x3)
pcercuei 0:df031b60ca29 767 len = ((len >> 2) + 1) << 2;
pcercuei 0:df031b60ca29 768 ptr += len;
pcercuei 0:df031b60ca29 769 }
pcercuei 0:df031b60ca29 770 }
pcercuei 0:df031b60ca29 771
pcercuei 0:df031b60ca29 772 err_free_buf:
pcercuei 0:df031b60ca29 773 free(buf);
pcercuei 0:df031b60ca29 774 return ret < 0 ? ret : 0;
pcercuei 0:df031b60ca29 775 }
pcercuei 0:df031b60ca29 776
pcercuei 0:df031b60ca29 777 int iio_channel_attr_write_all(struct iio_channel *chn,
pcercuei 0:df031b60ca29 778 ssize_t (*cb)(struct iio_channel *chn,
pcercuei 0:df031b60ca29 779 const char *attr, void *buf, size_t len, void *d),
pcercuei 0:df031b60ca29 780 void *data)
pcercuei 0:df031b60ca29 781 {
pcercuei 0:df031b60ca29 782 char *buf, *ptr;
pcercuei 0:df031b60ca29 783 unsigned int i;
pcercuei 0:df031b60ca29 784 size_t len = 0x100000;
pcercuei 0:df031b60ca29 785 int ret;
pcercuei 0:df031b60ca29 786
pcercuei 0:df031b60ca29 787 /* We need a big buffer here; 1 MiB should be enough */
pcercuei 0:df031b60ca29 788 buf = malloc(len);
pcercuei 0:df031b60ca29 789 if (!buf)
pcercuei 0:df031b60ca29 790 return -ENOMEM;
pcercuei 0:df031b60ca29 791
pcercuei 0:df031b60ca29 792 ptr = buf;
pcercuei 0:df031b60ca29 793
pcercuei 0:df031b60ca29 794 for (i = 0; i < iio_channel_get_attrs_count(chn); i++) {
pcercuei 0:df031b60ca29 795 const char *attr = iio_channel_get_attr(chn, i);
pcercuei 0:df031b60ca29 796
pcercuei 0:df031b60ca29 797 ret = (int) cb(chn, attr, ptr + 4, len - 4, data);
pcercuei 0:df031b60ca29 798 if (ret < 0)
pcercuei 0:df031b60ca29 799 goto err_free_buf;
pcercuei 0:df031b60ca29 800
pcercuei 0:df031b60ca29 801 *(int32_t *) ptr = (int32_t) iio_htobe32((uint32_t) ret);
pcercuei 0:df031b60ca29 802 ptr += 4;
pcercuei 0:df031b60ca29 803 len -= 4;
pcercuei 0:df031b60ca29 804
pcercuei 0:df031b60ca29 805 if (ret > 0) {
pcercuei 0:df031b60ca29 806 if (ret & 0x3)
pcercuei 0:df031b60ca29 807 ret = ((ret >> 2) + 1) << 2;
pcercuei 0:df031b60ca29 808 ptr += ret;
pcercuei 0:df031b60ca29 809 len -= ret;
pcercuei 0:df031b60ca29 810 }
pcercuei 0:df031b60ca29 811 }
pcercuei 0:df031b60ca29 812
pcercuei 0:df031b60ca29 813 ret = (int) iio_channel_attr_write_raw(chn, NULL, buf, ptr - buf);
pcercuei 0:df031b60ca29 814
pcercuei 0:df031b60ca29 815 err_free_buf:
pcercuei 0:df031b60ca29 816 free(buf);
pcercuei 0:df031b60ca29 817 return ret < 0 ? ret : 0;
pcercuei 0:df031b60ca29 818 }
pcercuei 0:df031b60ca29 819
pcercuei 0:df031b60ca29 820 const struct iio_device * iio_channel_get_device(const struct iio_channel *chn)
pcercuei 0:df031b60ca29 821 {
pcercuei 0:df031b60ca29 822 return chn->dev;
pcercuei 0:df031b60ca29 823 }
pcercuei 0:df031b60ca29 824