Paul Cercueil / libiio

Dependencies:   libserialport libxml2

Committer:
pcercuei
Date:
Tue Sep 20 15:34:31 2016 +0000
Revision:
2:9eb0a9a1f958
Parent:
0:df031b60ca29
Child:
3:d147beabba0e
Update latest libiio master (git tag 6d1923f)

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 0:df031b60ca29 178 snprintf(str, len, "<attribute name=\"%s\" filename=\"%s\" />",
pcercuei 0:df031b60ca29 179 attr->name, attr->filename);
pcercuei 0:df031b60ca29 180 else
pcercuei 0:df031b60ca29 181 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 0:df031b60ca29 187 char buf[1024], *str;
pcercuei 0:df031b60ca29 188 char processed = (chn->format.is_fully_defined ? 'A' - 'a' : 0);
pcercuei 0:df031b60ca29 189
pcercuei 0:df031b60ca29 190 snprintf(buf, sizeof(buf), "<scan-element index=\"%li\" "
pcercuei 0:df031b60ca29 191 "format=\"%ce:%c%u/%u&gt;&gt;%u\" />",
pcercuei 0:df031b60ca29 192 chn->index, chn->format.is_be ? 'b' : 'l',
pcercuei 0:df031b60ca29 193 chn->format.is_signed ? 's' + processed : 'u' + processed,
pcercuei 0:df031b60ca29 194 chn->format.bits, chn->format.length,
pcercuei 0:df031b60ca29 195 chn->format.shift);
pcercuei 0:df031b60ca29 196
pcercuei 0:df031b60ca29 197 if (chn->format.with_scale) {
pcercuei 0:df031b60ca29 198 char *ptr = strrchr(buf, '\0');
pcercuei 0:df031b60ca29 199 snprintf(ptr - 2, buf + sizeof(buf) - ptr + 2,
pcercuei 0:df031b60ca29 200 "scale=\"%f\" />", chn->format.scale);
pcercuei 0:df031b60ca29 201 }
pcercuei 0:df031b60ca29 202
pcercuei 0:df031b60ca29 203 str = iio_strdup(buf);
pcercuei 0:df031b60ca29 204 if (str)
pcercuei 0:df031b60ca29 205 *length = strlen(str);
pcercuei 0:df031b60ca29 206 return str;
pcercuei 0:df031b60ca29 207 }
pcercuei 0:df031b60ca29 208
pcercuei 0:df031b60ca29 209 /* Returns a string containing the XML representation of this channel */
pcercuei 0:df031b60ca29 210 char * iio_channel_get_xml(const struct iio_channel *chn, size_t *length)
pcercuei 0:df031b60ca29 211 {
pcercuei 0:df031b60ca29 212 size_t len = sizeof("<channel id=\"\" name=\"\" "
pcercuei 0:df031b60ca29 213 "type=\"output\" ></channel>")
pcercuei 0:df031b60ca29 214 + strlen(chn->id) + (chn->name ? strlen(chn->name) : 0);
pcercuei 0:df031b60ca29 215 char *ptr, *str, **attrs, *scan_element = NULL;
pcercuei 0:df031b60ca29 216 size_t *attrs_len, scan_element_len = 0;
pcercuei 0:df031b60ca29 217 unsigned int i;
pcercuei 0:df031b60ca29 218
pcercuei 0:df031b60ca29 219 if (chn->is_scan_element) {
pcercuei 0:df031b60ca29 220 scan_element = get_scan_element(chn, &scan_element_len);
pcercuei 0:df031b60ca29 221 if (!scan_element)
pcercuei 0:df031b60ca29 222 return NULL;
pcercuei 0:df031b60ca29 223 else
pcercuei 0:df031b60ca29 224 len += scan_element_len;
pcercuei 0:df031b60ca29 225 }
pcercuei 0:df031b60ca29 226
pcercuei 0:df031b60ca29 227 attrs_len = malloc(chn->nb_attrs * sizeof(*attrs_len));
pcercuei 0:df031b60ca29 228 if (!attrs_len)
pcercuei 0:df031b60ca29 229 goto err_free_scan_element;
pcercuei 0:df031b60ca29 230
pcercuei 0:df031b60ca29 231 attrs = malloc(chn->nb_attrs * sizeof(*attrs));
pcercuei 0:df031b60ca29 232 if (!attrs)
pcercuei 0:df031b60ca29 233 goto err_free_attrs_len;
pcercuei 0:df031b60ca29 234
pcercuei 0:df031b60ca29 235 for (i = 0; i < chn->nb_attrs; i++) {
pcercuei 0:df031b60ca29 236 char *xml = get_attr_xml(&chn->attrs[i], &attrs_len[i]);
pcercuei 0:df031b60ca29 237 if (!xml)
pcercuei 0:df031b60ca29 238 goto err_free_attrs;
pcercuei 0:df031b60ca29 239 attrs[i] = xml;
pcercuei 0:df031b60ca29 240 len += attrs_len[i];
pcercuei 0:df031b60ca29 241 }
pcercuei 0:df031b60ca29 242
pcercuei 0:df031b60ca29 243 str = malloc(len);
pcercuei 0:df031b60ca29 244 if (!str)
pcercuei 0:df031b60ca29 245 goto err_free_attrs;
pcercuei 0:df031b60ca29 246
pcercuei 0:df031b60ca29 247 snprintf(str, len, "<channel id=\"%s\"", chn->id);
pcercuei 0:df031b60ca29 248 ptr = strrchr(str, '\0');
pcercuei 0:df031b60ca29 249
pcercuei 0:df031b60ca29 250 if (chn->name) {
pcercuei 0:df031b60ca29 251 sprintf(ptr, " name=\"%s\"", chn->name);
pcercuei 0:df031b60ca29 252 ptr = strrchr(ptr, '\0');
pcercuei 0:df031b60ca29 253 }
pcercuei 0:df031b60ca29 254
pcercuei 0:df031b60ca29 255 sprintf(ptr, " type=\"%s\" >", chn->is_output ? "output" : "input");
pcercuei 0:df031b60ca29 256 ptr = strrchr(ptr, '\0');
pcercuei 0:df031b60ca29 257
pcercuei 0:df031b60ca29 258 if (chn->is_scan_element) {
pcercuei 0:df031b60ca29 259 strcpy(ptr, scan_element);
pcercuei 0:df031b60ca29 260 ptr += scan_element_len;
pcercuei 0:df031b60ca29 261 }
pcercuei 0:df031b60ca29 262
pcercuei 0:df031b60ca29 263 for (i = 0; i < chn->nb_attrs; i++) {
pcercuei 0:df031b60ca29 264 strcpy(ptr, attrs[i]);
pcercuei 0:df031b60ca29 265 ptr += attrs_len[i];
pcercuei 0:df031b60ca29 266 free(attrs[i]);
pcercuei 0:df031b60ca29 267 }
pcercuei 0:df031b60ca29 268
pcercuei 0:df031b60ca29 269 free(scan_element);
pcercuei 0:df031b60ca29 270 free(attrs);
pcercuei 0:df031b60ca29 271 free(attrs_len);
pcercuei 0:df031b60ca29 272
pcercuei 0:df031b60ca29 273 strcpy(ptr, "</channel>");
pcercuei 0:df031b60ca29 274 *length = ptr - str + sizeof("</channel>") - 1;
pcercuei 0:df031b60ca29 275 return str;
pcercuei 0:df031b60ca29 276
pcercuei 0:df031b60ca29 277 err_free_attrs:
pcercuei 0:df031b60ca29 278 while (i--)
pcercuei 0:df031b60ca29 279 free(attrs[i]);
pcercuei 0:df031b60ca29 280 free(attrs);
pcercuei 0:df031b60ca29 281 err_free_attrs_len:
pcercuei 0:df031b60ca29 282 free(attrs_len);
pcercuei 0:df031b60ca29 283 err_free_scan_element:
pcercuei 0:df031b60ca29 284 if (chn->is_scan_element)
pcercuei 0:df031b60ca29 285 free(scan_element);
pcercuei 0:df031b60ca29 286 return NULL;
pcercuei 0:df031b60ca29 287 }
pcercuei 0:df031b60ca29 288
pcercuei 0:df031b60ca29 289 const char * iio_channel_get_id(const struct iio_channel *chn)
pcercuei 0:df031b60ca29 290 {
pcercuei 0:df031b60ca29 291 return chn->id;
pcercuei 0:df031b60ca29 292 }
pcercuei 0:df031b60ca29 293
pcercuei 0:df031b60ca29 294 const char * iio_channel_get_name(const struct iio_channel *chn)
pcercuei 0:df031b60ca29 295 {
pcercuei 0:df031b60ca29 296 return chn->name;
pcercuei 0:df031b60ca29 297 }
pcercuei 0:df031b60ca29 298
pcercuei 0:df031b60ca29 299 bool iio_channel_is_output(const struct iio_channel *chn)
pcercuei 0:df031b60ca29 300 {
pcercuei 0:df031b60ca29 301 return chn->is_output;
pcercuei 0:df031b60ca29 302 }
pcercuei 0:df031b60ca29 303
pcercuei 0:df031b60ca29 304 bool iio_channel_is_scan_element(const struct iio_channel *chn)
pcercuei 0:df031b60ca29 305 {
pcercuei 0:df031b60ca29 306 return chn->is_scan_element;
pcercuei 0:df031b60ca29 307 }
pcercuei 0:df031b60ca29 308
pcercuei 0:df031b60ca29 309 enum iio_modifier iio_channel_get_modifier(const struct iio_channel *chn)
pcercuei 0:df031b60ca29 310 {
pcercuei 0:df031b60ca29 311 return chn->modifier;
pcercuei 0:df031b60ca29 312 }
pcercuei 0:df031b60ca29 313
pcercuei 0:df031b60ca29 314 enum iio_chan_type iio_channel_get_type(const struct iio_channel *chn)
pcercuei 0:df031b60ca29 315 {
pcercuei 0:df031b60ca29 316 return chn->type;
pcercuei 0:df031b60ca29 317 }
pcercuei 0:df031b60ca29 318
pcercuei 0:df031b60ca29 319 unsigned int iio_channel_get_attrs_count(const struct iio_channel *chn)
pcercuei 0:df031b60ca29 320 {
pcercuei 0:df031b60ca29 321 return chn->nb_attrs;
pcercuei 0:df031b60ca29 322 }
pcercuei 0:df031b60ca29 323
pcercuei 0:df031b60ca29 324 const char * iio_channel_get_attr(const struct iio_channel *chn,
pcercuei 0:df031b60ca29 325 unsigned int index)
pcercuei 0:df031b60ca29 326 {
pcercuei 0:df031b60ca29 327 if (index >= chn->nb_attrs)
pcercuei 0:df031b60ca29 328 return NULL;
pcercuei 0:df031b60ca29 329 else
pcercuei 0:df031b60ca29 330 return chn->attrs[index].name;
pcercuei 0:df031b60ca29 331 }
pcercuei 0:df031b60ca29 332
pcercuei 0:df031b60ca29 333 const char * iio_channel_find_attr(const struct iio_channel *chn,
pcercuei 0:df031b60ca29 334 const char *name)
pcercuei 0:df031b60ca29 335 {
pcercuei 0:df031b60ca29 336 unsigned int i;
pcercuei 0:df031b60ca29 337 for (i = 0; i < chn->nb_attrs; i++) {
pcercuei 0:df031b60ca29 338 const char *attr = chn->attrs[i].name;
pcercuei 0:df031b60ca29 339 if (!strcmp(attr, name))
pcercuei 0:df031b60ca29 340 return attr;
pcercuei 0:df031b60ca29 341 }
pcercuei 0:df031b60ca29 342 return NULL;
pcercuei 0:df031b60ca29 343 }
pcercuei 0:df031b60ca29 344
pcercuei 0:df031b60ca29 345 ssize_t iio_channel_attr_read(const struct iio_channel *chn,
pcercuei 0:df031b60ca29 346 const char *attr, char *dst, size_t len)
pcercuei 0:df031b60ca29 347 {
pcercuei 0:df031b60ca29 348 if (chn->dev->ctx->ops->read_channel_attr)
pcercuei 0:df031b60ca29 349 return chn->dev->ctx->ops->read_channel_attr(chn,
pcercuei 0:df031b60ca29 350 attr, dst, len);
pcercuei 0:df031b60ca29 351 else
pcercuei 0:df031b60ca29 352 return -ENOSYS;
pcercuei 0:df031b60ca29 353 }
pcercuei 0:df031b60ca29 354
pcercuei 0:df031b60ca29 355 ssize_t iio_channel_attr_write_raw(const struct iio_channel *chn,
pcercuei 0:df031b60ca29 356 const char *attr, const void *src, size_t len)
pcercuei 0:df031b60ca29 357 {
pcercuei 0:df031b60ca29 358 if (chn->dev->ctx->ops->write_channel_attr)
pcercuei 0:df031b60ca29 359 return chn->dev->ctx->ops->write_channel_attr(chn,
pcercuei 0:df031b60ca29 360 attr, src, len);
pcercuei 0:df031b60ca29 361 else
pcercuei 0:df031b60ca29 362 return -ENOSYS;
pcercuei 0:df031b60ca29 363 }
pcercuei 0:df031b60ca29 364
pcercuei 0:df031b60ca29 365 ssize_t iio_channel_attr_write(const struct iio_channel *chn,
pcercuei 0:df031b60ca29 366 const char *attr, const char *src)
pcercuei 0:df031b60ca29 367 {
pcercuei 0:df031b60ca29 368 return iio_channel_attr_write_raw(chn, attr, src, strlen(src) + 1);
pcercuei 0:df031b60ca29 369 }
pcercuei 0:df031b60ca29 370
pcercuei 0:df031b60ca29 371 void iio_channel_set_data(struct iio_channel *chn, void *data)
pcercuei 0:df031b60ca29 372 {
pcercuei 0:df031b60ca29 373 chn->userdata = data;
pcercuei 0:df031b60ca29 374 }
pcercuei 0:df031b60ca29 375
pcercuei 0:df031b60ca29 376 void * iio_channel_get_data(const struct iio_channel *chn)
pcercuei 0:df031b60ca29 377 {
pcercuei 0:df031b60ca29 378 return chn->userdata;
pcercuei 0:df031b60ca29 379 }
pcercuei 0:df031b60ca29 380
pcercuei 0:df031b60ca29 381 long iio_channel_get_index(const struct iio_channel *chn)
pcercuei 0:df031b60ca29 382 {
pcercuei 0:df031b60ca29 383 return chn->index;
pcercuei 0:df031b60ca29 384 }
pcercuei 0:df031b60ca29 385
pcercuei 0:df031b60ca29 386 const struct iio_data_format * iio_channel_get_data_format(
pcercuei 0:df031b60ca29 387 const struct iio_channel *chn)
pcercuei 0:df031b60ca29 388 {
pcercuei 0:df031b60ca29 389 return &chn->format;
pcercuei 0:df031b60ca29 390 }
pcercuei 0:df031b60ca29 391
pcercuei 0:df031b60ca29 392 bool iio_channel_is_enabled(const struct iio_channel *chn)
pcercuei 0:df031b60ca29 393 {
pcercuei 0:df031b60ca29 394 return chn->index >= 0 && chn->dev->mask &&
pcercuei 0:df031b60ca29 395 TEST_BIT(chn->dev->mask, chn->index);
pcercuei 0:df031b60ca29 396 }
pcercuei 0:df031b60ca29 397
pcercuei 0:df031b60ca29 398 void iio_channel_enable(struct iio_channel *chn)
pcercuei 0:df031b60ca29 399 {
pcercuei 0:df031b60ca29 400 if (chn->is_scan_element && chn->index >= 0 && chn->dev->mask)
pcercuei 0:df031b60ca29 401 SET_BIT(chn->dev->mask, chn->index);
pcercuei 0:df031b60ca29 402 }
pcercuei 0:df031b60ca29 403
pcercuei 0:df031b60ca29 404 void iio_channel_disable(struct iio_channel *chn)
pcercuei 0:df031b60ca29 405 {
pcercuei 0:df031b60ca29 406 if (chn->index >= 0 && chn->dev->mask)
pcercuei 0:df031b60ca29 407 CLEAR_BIT(chn->dev->mask, chn->index);
pcercuei 0:df031b60ca29 408 }
pcercuei 0:df031b60ca29 409
pcercuei 0:df031b60ca29 410 void free_channel(struct iio_channel *chn)
pcercuei 0:df031b60ca29 411 {
pcercuei 0:df031b60ca29 412 size_t i;
pcercuei 0:df031b60ca29 413 for (i = 0; i < chn->nb_attrs; i++) {
pcercuei 0:df031b60ca29 414 free(chn->attrs[i].name);
pcercuei 0:df031b60ca29 415 free(chn->attrs[i].filename);
pcercuei 0:df031b60ca29 416 }
pcercuei 0:df031b60ca29 417 if (chn->nb_attrs)
pcercuei 0:df031b60ca29 418 free(chn->attrs);
pcercuei 0:df031b60ca29 419 if (chn->name)
pcercuei 0:df031b60ca29 420 free(chn->name);
pcercuei 0:df031b60ca29 421 if (chn->id)
pcercuei 0:df031b60ca29 422 free(chn->id);
pcercuei 0:df031b60ca29 423 free(chn);
pcercuei 0:df031b60ca29 424 }
pcercuei 0:df031b60ca29 425
pcercuei 0:df031b60ca29 426 static void byte_swap(uint8_t *dst, const uint8_t *src, size_t len)
pcercuei 0:df031b60ca29 427 {
pcercuei 0:df031b60ca29 428 size_t i;
pcercuei 0:df031b60ca29 429 for (i = 0; i < len; i++)
pcercuei 0:df031b60ca29 430 dst[i] = src[len - i - 1];
pcercuei 0:df031b60ca29 431 }
pcercuei 0:df031b60ca29 432
pcercuei 0:df031b60ca29 433 static void shift_bits(uint8_t *dst, size_t shift, size_t len, bool left)
pcercuei 0:df031b60ca29 434 {
pcercuei 0:df031b60ca29 435 size_t i, shift_bytes = shift / 8;
pcercuei 0:df031b60ca29 436 shift %= 8;
pcercuei 0:df031b60ca29 437
pcercuei 0:df031b60ca29 438 #if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
pcercuei 0:df031b60ca29 439 if (!left)
pcercuei 0:df031b60ca29 440 #else
pcercuei 0:df031b60ca29 441 if (left)
pcercuei 0:df031b60ca29 442 #endif
pcercuei 0:df031b60ca29 443 {
pcercuei 0:df031b60ca29 444 if (shift_bytes) {
pcercuei 0:df031b60ca29 445 memmove(dst, dst + shift_bytes, len - shift_bytes);
pcercuei 0:df031b60ca29 446 memset(dst + len - shift_bytes, 0, shift_bytes);
pcercuei 0:df031b60ca29 447 }
pcercuei 0:df031b60ca29 448 if (shift) {
pcercuei 0:df031b60ca29 449 for (i = 0; i < len; i++) {
pcercuei 0:df031b60ca29 450 #if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
pcercuei 0:df031b60ca29 451 dst[i] >>= shift;
pcercuei 0:df031b60ca29 452 if (i < len - 1)
pcercuei 0:df031b60ca29 453 dst[i] |= dst[i + 1] << (8 - shift);
pcercuei 0:df031b60ca29 454 #else
pcercuei 0:df031b60ca29 455 dst[i] <<= shift;
pcercuei 0:df031b60ca29 456 if (i < len - 1)
pcercuei 0:df031b60ca29 457 dst[i] |= dst[i + 1] >> (8 - shift);
pcercuei 0:df031b60ca29 458 #endif
pcercuei 0:df031b60ca29 459 }
pcercuei 0:df031b60ca29 460 }
pcercuei 0:df031b60ca29 461 } else {
pcercuei 0:df031b60ca29 462 if (shift_bytes) {
pcercuei 0:df031b60ca29 463 memmove(dst + shift_bytes, dst, len - shift_bytes);
pcercuei 0:df031b60ca29 464 memset(dst, 0, shift_bytes);
pcercuei 0:df031b60ca29 465 }
pcercuei 0:df031b60ca29 466 if (shift) {
pcercuei 0:df031b60ca29 467 for (i = len; i > 0; i--) {
pcercuei 0:df031b60ca29 468 #if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
pcercuei 0:df031b60ca29 469 dst[i - 1] <<= shift;
pcercuei 0:df031b60ca29 470 if (i > 1)
pcercuei 0:df031b60ca29 471 dst[i - 1] |= dst[i - 2] >> (8 - shift);
pcercuei 0:df031b60ca29 472 #else
pcercuei 0:df031b60ca29 473 dst[i - 1] >>= shift;
pcercuei 0:df031b60ca29 474 if (i > 1)
pcercuei 0:df031b60ca29 475 dst[i - 1] |= dst[i - 2] << (8 - shift);
pcercuei 0:df031b60ca29 476 #endif
pcercuei 0:df031b60ca29 477 }
pcercuei 0:df031b60ca29 478 }
pcercuei 0:df031b60ca29 479 }
pcercuei 0:df031b60ca29 480 }
pcercuei 0:df031b60ca29 481
pcercuei 0:df031b60ca29 482 static void sign_extend(uint8_t *dst, size_t bits, size_t len)
pcercuei 0:df031b60ca29 483 {
pcercuei 0:df031b60ca29 484 size_t upper_bytes = ((len * 8 - bits) / 8);
pcercuei 0:df031b60ca29 485 uint8_t msb, msb_bit = 1 << ((bits - 1) % 8);
pcercuei 0:df031b60ca29 486
pcercuei 0:df031b60ca29 487 #if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
pcercuei 0:df031b60ca29 488 msb = dst[len - 1 - upper_bytes] & msb_bit;
pcercuei 0:df031b60ca29 489 if (upper_bytes)
pcercuei 0:df031b60ca29 490 memset(dst + len - upper_bytes, msb ? 0xff : 0x00, upper_bytes);
pcercuei 0:df031b60ca29 491 if (msb)
pcercuei 0:df031b60ca29 492 dst[len - 1 - upper_bytes] |= ~(msb_bit - 1);
pcercuei 0:df031b60ca29 493 else
pcercuei 0:df031b60ca29 494 dst[len - 1 - upper_bytes] &= (msb_bit - 1);
pcercuei 0:df031b60ca29 495 #else
pcercuei 0:df031b60ca29 496 /* XXX: untested */
pcercuei 0:df031b60ca29 497 msb = dst[upper_bytes] & msb_bit;
pcercuei 0:df031b60ca29 498 if (upper_bytes)
pcercuei 0:df031b60ca29 499 memset(dst, msb ? 0xff : 0x00, upper_bytes);
pcercuei 0:df031b60ca29 500 if (msb)
pcercuei 0:df031b60ca29 501 dst[upper_bytes] |= ~(msb_bit - 1);
pcercuei 0:df031b60ca29 502 #endif
pcercuei 0:df031b60ca29 503 }
pcercuei 0:df031b60ca29 504
pcercuei 0:df031b60ca29 505 static void mask_upper_bits(uint8_t *dst, size_t bits, size_t len)
pcercuei 0:df031b60ca29 506 {
pcercuei 0:df031b60ca29 507 size_t i;
pcercuei 0:df031b60ca29 508
pcercuei 0:df031b60ca29 509 /* Clear upper bits */
pcercuei 0:df031b60ca29 510 if (bits % 8)
pcercuei 0:df031b60ca29 511 dst[bits / 8] &= (1 << (bits % 8)) - 1;
pcercuei 0:df031b60ca29 512
pcercuei 0:df031b60ca29 513 /* Clear upper bytes */
pcercuei 0:df031b60ca29 514 for (i = (bits + 7) / 8; i < len; i++)
pcercuei 0:df031b60ca29 515 dst[i] = 0;
pcercuei 0:df031b60ca29 516 }
pcercuei 0:df031b60ca29 517
pcercuei 0:df031b60ca29 518
pcercuei 0:df031b60ca29 519 void iio_channel_convert(const struct iio_channel *chn,
pcercuei 0:df031b60ca29 520 void *dst, const void *src)
pcercuei 0:df031b60ca29 521 {
pcercuei 0:df031b60ca29 522 unsigned int len = chn->format.length / 8;
pcercuei 0:df031b60ca29 523 #if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
pcercuei 0:df031b60ca29 524 bool swap = chn->format.is_be;
pcercuei 0:df031b60ca29 525 #else
pcercuei 0:df031b60ca29 526 bool swap = !chn->format.is_be;
pcercuei 0:df031b60ca29 527 #endif
pcercuei 0:df031b60ca29 528
pcercuei 0:df031b60ca29 529 if (len == 1 || !swap)
pcercuei 0:df031b60ca29 530 memcpy(dst, src, len);
pcercuei 0:df031b60ca29 531 else
pcercuei 0:df031b60ca29 532 byte_swap(dst, src, len);
pcercuei 0:df031b60ca29 533
pcercuei 0:df031b60ca29 534 if (chn->format.shift)
pcercuei 0:df031b60ca29 535 shift_bits(dst, chn->format.shift, len, false);
pcercuei 0:df031b60ca29 536
pcercuei 0:df031b60ca29 537 if (!chn->format.is_fully_defined) {
pcercuei 0:df031b60ca29 538 if (chn->format.is_signed)
pcercuei 0:df031b60ca29 539 sign_extend(dst, chn->format.bits, len);
pcercuei 0:df031b60ca29 540 else
pcercuei 0:df031b60ca29 541 mask_upper_bits(dst, chn->format.bits, len);
pcercuei 0:df031b60ca29 542 }
pcercuei 0:df031b60ca29 543 }
pcercuei 0:df031b60ca29 544
pcercuei 0:df031b60ca29 545 void iio_channel_convert_inverse(const struct iio_channel *chn,
pcercuei 0:df031b60ca29 546 void *dst, const void *src)
pcercuei 0:df031b60ca29 547 {
pcercuei 0:df031b60ca29 548 unsigned int len = chn->format.length / 8;
pcercuei 0:df031b60ca29 549 #if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
pcercuei 0:df031b60ca29 550 bool swap = chn->format.is_be;
pcercuei 0:df031b60ca29 551 #else
pcercuei 0:df031b60ca29 552 bool swap = !chn->format.is_be;
pcercuei 0:df031b60ca29 553 #endif
pcercuei 0:df031b60ca29 554 uint8_t buf[1024];
pcercuei 0:df031b60ca29 555
pcercuei 0:df031b60ca29 556 /* Somehow I doubt we will have samples of 8192 bits each. */
pcercuei 0:df031b60ca29 557 if (len > sizeof(buf))
pcercuei 0:df031b60ca29 558 return;
pcercuei 0:df031b60ca29 559
pcercuei 0:df031b60ca29 560 memcpy(buf, src, len);
pcercuei 0:df031b60ca29 561 mask_upper_bits(buf, chn->format.bits, len);
pcercuei 0:df031b60ca29 562
pcercuei 0:df031b60ca29 563 if (chn->format.shift)
pcercuei 0:df031b60ca29 564 shift_bits(buf, chn->format.shift, len, true);
pcercuei 0:df031b60ca29 565
pcercuei 0:df031b60ca29 566 if (len == 1 || !swap)
pcercuei 0:df031b60ca29 567 memcpy(dst, buf, len);
pcercuei 0:df031b60ca29 568 else
pcercuei 0:df031b60ca29 569 byte_swap(dst, buf, len);
pcercuei 0:df031b60ca29 570 }
pcercuei 0:df031b60ca29 571
pcercuei 0:df031b60ca29 572 size_t iio_channel_read_raw(const struct iio_channel *chn,
pcercuei 0:df031b60ca29 573 struct iio_buffer *buf, void *dst, size_t len)
pcercuei 0:df031b60ca29 574 {
pcercuei 0:df031b60ca29 575 uintptr_t src_ptr, dst_ptr = (uintptr_t) dst, end = dst_ptr + len;
pcercuei 0:df031b60ca29 576 unsigned int length = chn->format.length / 8;
pcercuei 0:df031b60ca29 577 uintptr_t buf_end = (uintptr_t) iio_buffer_end(buf);
pcercuei 0:df031b60ca29 578 ptrdiff_t buf_step = iio_buffer_step(buf);
pcercuei 0:df031b60ca29 579
pcercuei 0:df031b60ca29 580 for (src_ptr = (uintptr_t) iio_buffer_first(buf, chn);
pcercuei 0:df031b60ca29 581 src_ptr < buf_end && dst_ptr + length <= end;
pcercuei 0:df031b60ca29 582 src_ptr += buf_step, dst_ptr += length)
pcercuei 0:df031b60ca29 583 memcpy((void *) dst_ptr, (const void *) src_ptr, length);
pcercuei 0:df031b60ca29 584 return dst_ptr - (uintptr_t) dst;
pcercuei 0:df031b60ca29 585 }
pcercuei 0:df031b60ca29 586
pcercuei 0:df031b60ca29 587 size_t iio_channel_read(const struct iio_channel *chn,
pcercuei 0:df031b60ca29 588 struct iio_buffer *buf, void *dst, size_t len)
pcercuei 0:df031b60ca29 589 {
pcercuei 0:df031b60ca29 590 uintptr_t src_ptr, dst_ptr = (uintptr_t) dst, end = dst_ptr + len;
pcercuei 0:df031b60ca29 591 unsigned int length = chn->format.length / 8;
pcercuei 0:df031b60ca29 592 uintptr_t buf_end = (uintptr_t) iio_buffer_end(buf);
pcercuei 0:df031b60ca29 593 ptrdiff_t buf_step = iio_buffer_step(buf);
pcercuei 0:df031b60ca29 594
pcercuei 0:df031b60ca29 595 for (src_ptr = (uintptr_t) iio_buffer_first(buf, chn);
pcercuei 0:df031b60ca29 596 src_ptr < buf_end && dst_ptr + length <= end;
pcercuei 0:df031b60ca29 597 src_ptr += buf_step, dst_ptr += length)
pcercuei 0:df031b60ca29 598 iio_channel_convert(chn,
pcercuei 0:df031b60ca29 599 (void *) dst_ptr, (const void *) src_ptr);
pcercuei 0:df031b60ca29 600 return dst_ptr - (uintptr_t) dst;
pcercuei 0:df031b60ca29 601 }
pcercuei 0:df031b60ca29 602
pcercuei 0:df031b60ca29 603 size_t iio_channel_write_raw(const struct iio_channel *chn,
pcercuei 0:df031b60ca29 604 struct iio_buffer *buf, const void *src, size_t len)
pcercuei 0:df031b60ca29 605 {
pcercuei 0:df031b60ca29 606 uintptr_t dst_ptr, src_ptr = (uintptr_t) src, end = src_ptr + len;
pcercuei 0:df031b60ca29 607 unsigned int length = chn->format.length / 8;
pcercuei 0:df031b60ca29 608 uintptr_t buf_end = (uintptr_t) iio_buffer_end(buf);
pcercuei 0:df031b60ca29 609 ptrdiff_t buf_step = iio_buffer_step(buf);
pcercuei 0:df031b60ca29 610
pcercuei 0:df031b60ca29 611 for (dst_ptr = (uintptr_t) iio_buffer_first(buf, chn);
pcercuei 0:df031b60ca29 612 dst_ptr < buf_end && src_ptr + length <= end;
pcercuei 0:df031b60ca29 613 dst_ptr += buf_step, src_ptr += length)
pcercuei 0:df031b60ca29 614 memcpy((void *) dst_ptr, (const void *) src_ptr, length);
pcercuei 0:df031b60ca29 615 return src_ptr - (uintptr_t) src;
pcercuei 0:df031b60ca29 616 }
pcercuei 0:df031b60ca29 617
pcercuei 0:df031b60ca29 618 size_t iio_channel_write(const struct iio_channel *chn,
pcercuei 0:df031b60ca29 619 struct iio_buffer *buf, const void *src, size_t len)
pcercuei 0:df031b60ca29 620 {
pcercuei 0:df031b60ca29 621 uintptr_t dst_ptr, src_ptr = (uintptr_t) src, end = src_ptr + len;
pcercuei 0:df031b60ca29 622 unsigned int length = chn->format.length / 8;
pcercuei 0:df031b60ca29 623 uintptr_t buf_end = (uintptr_t) iio_buffer_end(buf);
pcercuei 0:df031b60ca29 624 ptrdiff_t buf_step = iio_buffer_step(buf);
pcercuei 0:df031b60ca29 625
pcercuei 0:df031b60ca29 626 for (dst_ptr = (uintptr_t) iio_buffer_first(buf, chn);
pcercuei 0:df031b60ca29 627 dst_ptr < buf_end && src_ptr + length <= end;
pcercuei 0:df031b60ca29 628 dst_ptr += buf_step, src_ptr += length)
pcercuei 0:df031b60ca29 629 iio_channel_convert_inverse(chn,
pcercuei 0:df031b60ca29 630 (void *) dst_ptr, (const void *) src_ptr);
pcercuei 0:df031b60ca29 631 return src_ptr - (uintptr_t) src;
pcercuei 0:df031b60ca29 632 }
pcercuei 0:df031b60ca29 633
pcercuei 0:df031b60ca29 634 int iio_channel_attr_read_longlong(const struct iio_channel *chn,
pcercuei 0:df031b60ca29 635 const char *attr, long long *val)
pcercuei 0:df031b60ca29 636 {
pcercuei 0:df031b60ca29 637 char *end, buf[1024];
pcercuei 0:df031b60ca29 638 long long value;
pcercuei 0:df031b60ca29 639 ssize_t ret = iio_channel_attr_read(chn, attr, buf, sizeof(buf));
pcercuei 0:df031b60ca29 640 if (ret < 0)
pcercuei 0:df031b60ca29 641 return (int) ret;
pcercuei 0:df031b60ca29 642
pcercuei 0:df031b60ca29 643 value = strtoll(buf, &end, 0);
pcercuei 0:df031b60ca29 644 if (end == buf)
pcercuei 0:df031b60ca29 645 return -EINVAL;
pcercuei 0:df031b60ca29 646 *val = value;
pcercuei 0:df031b60ca29 647 return 0;
pcercuei 0:df031b60ca29 648 }
pcercuei 0:df031b60ca29 649
pcercuei 0:df031b60ca29 650 int iio_channel_attr_read_bool(const struct iio_channel *chn,
pcercuei 0:df031b60ca29 651 const char *attr, bool *val)
pcercuei 0:df031b60ca29 652 {
pcercuei 0:df031b60ca29 653 long long value;
pcercuei 0:df031b60ca29 654 int ret = iio_channel_attr_read_longlong(chn, attr, &value);
pcercuei 0:df031b60ca29 655 if (ret < 0)
pcercuei 0:df031b60ca29 656 return ret;
pcercuei 0:df031b60ca29 657
pcercuei 0:df031b60ca29 658 *val = !!value;
pcercuei 0:df031b60ca29 659 return 0;
pcercuei 0:df031b60ca29 660 }
pcercuei 0:df031b60ca29 661
pcercuei 0:df031b60ca29 662 int iio_channel_attr_read_double(const struct iio_channel *chn,
pcercuei 0:df031b60ca29 663 const char *attr, double *val)
pcercuei 0:df031b60ca29 664 {
pcercuei 0:df031b60ca29 665 char buf[1024];
pcercuei 0:df031b60ca29 666 ssize_t ret = iio_channel_attr_read(chn, attr, buf, sizeof(buf));
pcercuei 0:df031b60ca29 667 if (ret < 0)
pcercuei 0:df031b60ca29 668 return (int) ret;
pcercuei 0:df031b60ca29 669 else
pcercuei 0:df031b60ca29 670 return read_double(buf, val);
pcercuei 0:df031b60ca29 671 }
pcercuei 0:df031b60ca29 672
pcercuei 0:df031b60ca29 673 int iio_channel_attr_write_longlong(const struct iio_channel *chn,
pcercuei 0:df031b60ca29 674 const char *attr, long long val)
pcercuei 0:df031b60ca29 675 {
pcercuei 0:df031b60ca29 676 ssize_t ret;
pcercuei 0:df031b60ca29 677 char buf[1024];
pcercuei 0:df031b60ca29 678 snprintf(buf, sizeof(buf), "%lld", val);
pcercuei 0:df031b60ca29 679 ret = iio_channel_attr_write(chn, attr, buf);
pcercuei 0:df031b60ca29 680 return ret < 0 ? ret : 0;
pcercuei 0:df031b60ca29 681 }
pcercuei 0:df031b60ca29 682
pcercuei 0:df031b60ca29 683 int iio_channel_attr_write_double(const struct iio_channel *chn,
pcercuei 0:df031b60ca29 684 const char *attr, double val)
pcercuei 0:df031b60ca29 685 {
pcercuei 0:df031b60ca29 686 ssize_t ret;
pcercuei 0:df031b60ca29 687 char buf[1024];
pcercuei 0:df031b60ca29 688
pcercuei 0:df031b60ca29 689 ret = (ssize_t) write_double(buf, sizeof(buf), val);
pcercuei 0:df031b60ca29 690 if (!ret)
pcercuei 0:df031b60ca29 691 ret = iio_channel_attr_write(chn, attr, buf);
pcercuei 0:df031b60ca29 692 return ret < 0 ? ret : 0;
pcercuei 0:df031b60ca29 693 }
pcercuei 0:df031b60ca29 694
pcercuei 0:df031b60ca29 695 int iio_channel_attr_write_bool(const struct iio_channel *chn,
pcercuei 0:df031b60ca29 696 const char *attr, bool val)
pcercuei 0:df031b60ca29 697 {
pcercuei 0:df031b60ca29 698 ssize_t ret;
pcercuei 0:df031b60ca29 699 if (val)
pcercuei 0:df031b60ca29 700 ret = iio_channel_attr_write_raw(chn, attr, "1", 2);
pcercuei 0:df031b60ca29 701 else
pcercuei 0:df031b60ca29 702 ret = iio_channel_attr_write_raw(chn, attr, "0", 2);
pcercuei 0:df031b60ca29 703 return ret < 0 ? ret : 0;
pcercuei 0:df031b60ca29 704 }
pcercuei 0:df031b60ca29 705
pcercuei 0:df031b60ca29 706 const char * iio_channel_attr_get_filename(
pcercuei 0:df031b60ca29 707 const struct iio_channel *chn, const char *attr)
pcercuei 0:df031b60ca29 708 {
pcercuei 0:df031b60ca29 709 unsigned int i;
pcercuei 0:df031b60ca29 710 for (i = 0; i < chn->nb_attrs; i++) {
pcercuei 0:df031b60ca29 711 if (!strcmp(chn->attrs[i].name, attr))
pcercuei 0:df031b60ca29 712 return chn->attrs[i].filename;
pcercuei 0:df031b60ca29 713 }
pcercuei 0:df031b60ca29 714 return NULL;
pcercuei 0:df031b60ca29 715 }
pcercuei 0:df031b60ca29 716
pcercuei 0:df031b60ca29 717 int iio_channel_attr_read_all(struct iio_channel *chn,
pcercuei 0:df031b60ca29 718 int (*cb)(struct iio_channel *chn,
pcercuei 0:df031b60ca29 719 const char *attr, const char *val, size_t len, void *d),
pcercuei 0:df031b60ca29 720 void *data)
pcercuei 0:df031b60ca29 721 {
pcercuei 0:df031b60ca29 722 int ret;
pcercuei 0:df031b60ca29 723 char *buf, *ptr;
pcercuei 0:df031b60ca29 724 unsigned int i;
pcercuei 0:df031b60ca29 725
pcercuei 0:df031b60ca29 726 /* We need a big buffer here; 1 MiB should be enough */
pcercuei 0:df031b60ca29 727 buf = malloc(0x100000);
pcercuei 0:df031b60ca29 728 if (!buf)
pcercuei 0:df031b60ca29 729 return -ENOMEM;
pcercuei 0:df031b60ca29 730
pcercuei 0:df031b60ca29 731 ret = (int) iio_channel_attr_read(chn, NULL, buf, 0x100000);
pcercuei 0:df031b60ca29 732 if (ret < 0)
pcercuei 0:df031b60ca29 733 goto err_free_buf;
pcercuei 0:df031b60ca29 734
pcercuei 0:df031b60ca29 735 ptr = buf;
pcercuei 0:df031b60ca29 736
pcercuei 0:df031b60ca29 737 for (i = 0; i < iio_channel_get_attrs_count(chn); i++) {
pcercuei 0:df031b60ca29 738 const char *attr = iio_channel_get_attr(chn, i);
pcercuei 0:df031b60ca29 739 int32_t len = (int32_t) iio_be32toh(*(uint32_t *) ptr);
pcercuei 0:df031b60ca29 740
pcercuei 0:df031b60ca29 741 ptr += 4;
pcercuei 0:df031b60ca29 742 if (len > 0) {
pcercuei 0:df031b60ca29 743 ret = cb(chn, attr, ptr, (size_t) len, data);
pcercuei 0:df031b60ca29 744 if (ret < 0)
pcercuei 0:df031b60ca29 745 goto err_free_buf;
pcercuei 0:df031b60ca29 746
pcercuei 0:df031b60ca29 747 if (len & 0x3)
pcercuei 0:df031b60ca29 748 len = ((len >> 2) + 1) << 2;
pcercuei 0:df031b60ca29 749 ptr += len;
pcercuei 0:df031b60ca29 750 }
pcercuei 0:df031b60ca29 751 }
pcercuei 0:df031b60ca29 752
pcercuei 0:df031b60ca29 753 err_free_buf:
pcercuei 0:df031b60ca29 754 free(buf);
pcercuei 0:df031b60ca29 755 return ret < 0 ? ret : 0;
pcercuei 0:df031b60ca29 756 }
pcercuei 0:df031b60ca29 757
pcercuei 0:df031b60ca29 758 int iio_channel_attr_write_all(struct iio_channel *chn,
pcercuei 0:df031b60ca29 759 ssize_t (*cb)(struct iio_channel *chn,
pcercuei 0:df031b60ca29 760 const char *attr, void *buf, size_t len, void *d),
pcercuei 0:df031b60ca29 761 void *data)
pcercuei 0:df031b60ca29 762 {
pcercuei 0:df031b60ca29 763 char *buf, *ptr;
pcercuei 0:df031b60ca29 764 unsigned int i;
pcercuei 0:df031b60ca29 765 size_t len = 0x100000;
pcercuei 0:df031b60ca29 766 int ret;
pcercuei 0:df031b60ca29 767
pcercuei 0:df031b60ca29 768 /* We need a big buffer here; 1 MiB should be enough */
pcercuei 0:df031b60ca29 769 buf = malloc(len);
pcercuei 0:df031b60ca29 770 if (!buf)
pcercuei 0:df031b60ca29 771 return -ENOMEM;
pcercuei 0:df031b60ca29 772
pcercuei 0:df031b60ca29 773 ptr = buf;
pcercuei 0:df031b60ca29 774
pcercuei 0:df031b60ca29 775 for (i = 0; i < iio_channel_get_attrs_count(chn); i++) {
pcercuei 0:df031b60ca29 776 const char *attr = iio_channel_get_attr(chn, i);
pcercuei 0:df031b60ca29 777
pcercuei 0:df031b60ca29 778 ret = (int) cb(chn, attr, ptr + 4, len - 4, data);
pcercuei 0:df031b60ca29 779 if (ret < 0)
pcercuei 0:df031b60ca29 780 goto err_free_buf;
pcercuei 0:df031b60ca29 781
pcercuei 0:df031b60ca29 782 *(int32_t *) ptr = (int32_t) iio_htobe32((uint32_t) ret);
pcercuei 0:df031b60ca29 783 ptr += 4;
pcercuei 0:df031b60ca29 784 len -= 4;
pcercuei 0:df031b60ca29 785
pcercuei 0:df031b60ca29 786 if (ret > 0) {
pcercuei 0:df031b60ca29 787 if (ret & 0x3)
pcercuei 0:df031b60ca29 788 ret = ((ret >> 2) + 1) << 2;
pcercuei 0:df031b60ca29 789 ptr += ret;
pcercuei 0:df031b60ca29 790 len -= ret;
pcercuei 0:df031b60ca29 791 }
pcercuei 0:df031b60ca29 792 }
pcercuei 0:df031b60ca29 793
pcercuei 0:df031b60ca29 794 ret = (int) iio_channel_attr_write_raw(chn, NULL, buf, ptr - buf);
pcercuei 0:df031b60ca29 795
pcercuei 0:df031b60ca29 796 err_free_buf:
pcercuei 0:df031b60ca29 797 free(buf);
pcercuei 0:df031b60ca29 798 return ret < 0 ? ret : 0;
pcercuei 0:df031b60ca29 799 }
pcercuei 0:df031b60ca29 800
pcercuei 0:df031b60ca29 801 const struct iio_device * iio_channel_get_device(const struct iio_channel *chn)
pcercuei 0:df031b60ca29 802 {
pcercuei 0:df031b60ca29 803 return chn->dev;
pcercuei 0:df031b60ca29 804 }
pcercuei 0:df031b60ca29 805