Paul Cercueil / libiio

Dependencies:   libserialport libxml2

Committer:
pcercuei
Date:
Mon Jun 26 14:30:10 2017 +0000
Revision:
4:ad69b39bf124
Parent:
3:d147beabba0e
Update to upstream version v0.10

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 0:df031b60ca29 22 #include <inttypes.h>
pcercuei 2:9eb0a9a1f958 23 #include <errno.h>
pcercuei 0:df031b60ca29 24 #include <stdio.h>
pcercuei 0:df031b60ca29 25 #include <string.h>
pcercuei 0:df031b60ca29 26
pcercuei 0:df031b60ca29 27 static char *get_attr_xml(const char *attr, size_t *length, bool is_debug)
pcercuei 0:df031b60ca29 28 {
pcercuei 0:df031b60ca29 29 size_t len = sizeof("<attribute name=\"\" />") + strlen(attr)
pcercuei 0:df031b60ca29 30 + (!is_debug ? 0 : sizeof("debug-") - 1);
pcercuei 0:df031b60ca29 31 char *str = malloc(len);
pcercuei 0:df031b60ca29 32 if (!str)
pcercuei 0:df031b60ca29 33 return NULL;
pcercuei 0:df031b60ca29 34
pcercuei 0:df031b60ca29 35 *length = len - 1; /* Skip the \0 */
pcercuei 0:df031b60ca29 36 if (is_debug)
pcercuei 3:d147beabba0e 37 iio_snprintf(str, len, "<debug-attribute name=\"%s\" />", attr);
pcercuei 0:df031b60ca29 38 else
pcercuei 3:d147beabba0e 39 iio_snprintf(str, len, "<attribute name=\"%s\" />", attr);
pcercuei 0:df031b60ca29 40 return str;
pcercuei 0:df031b60ca29 41 }
pcercuei 0:df031b60ca29 42
pcercuei 0:df031b60ca29 43 /* Returns a string containing the XML representation of this device */
pcercuei 0:df031b60ca29 44 char * iio_device_get_xml(const struct iio_device *dev, size_t *length)
pcercuei 0:df031b60ca29 45 {
pcercuei 0:df031b60ca29 46 size_t len = sizeof("<device id=\"\" name=\"\" ></device>")
pcercuei 0:df031b60ca29 47 + strlen(dev->id) + (dev->name ? strlen(dev->name) : 0);
pcercuei 0:df031b60ca29 48 char *ptr, *str, **attrs, **channels, **debug_attrs;
pcercuei 0:df031b60ca29 49 size_t *attrs_len, *channels_len, *debug_attrs_len;
pcercuei 0:df031b60ca29 50 unsigned int i, j, k;
pcercuei 0:df031b60ca29 51
pcercuei 0:df031b60ca29 52 attrs_len = malloc(dev->nb_attrs * sizeof(*attrs_len));
pcercuei 0:df031b60ca29 53 if (!attrs_len)
pcercuei 0:df031b60ca29 54 return NULL;
pcercuei 0:df031b60ca29 55
pcercuei 0:df031b60ca29 56 attrs = malloc(dev->nb_attrs * sizeof(*attrs));
pcercuei 0:df031b60ca29 57 if (!attrs)
pcercuei 0:df031b60ca29 58 goto err_free_attrs_len;
pcercuei 0:df031b60ca29 59
pcercuei 0:df031b60ca29 60 for (i = 0; i < dev->nb_attrs; i++) {
pcercuei 0:df031b60ca29 61 char *xml = get_attr_xml(dev->attrs[i], &attrs_len[i], false);
pcercuei 0:df031b60ca29 62 if (!xml)
pcercuei 0:df031b60ca29 63 goto err_free_attrs;
pcercuei 0:df031b60ca29 64 attrs[i] = xml;
pcercuei 0:df031b60ca29 65 len += attrs_len[i];
pcercuei 0:df031b60ca29 66 }
pcercuei 0:df031b60ca29 67
pcercuei 0:df031b60ca29 68 channels_len = malloc(dev->nb_channels * sizeof(*channels_len));
pcercuei 0:df031b60ca29 69 if (!channels_len)
pcercuei 0:df031b60ca29 70 goto err_free_attrs;
pcercuei 0:df031b60ca29 71
pcercuei 0:df031b60ca29 72 channels = malloc(dev->nb_channels * sizeof(*channels));
pcercuei 0:df031b60ca29 73 if (!channels)
pcercuei 0:df031b60ca29 74 goto err_free_channels_len;
pcercuei 0:df031b60ca29 75
pcercuei 0:df031b60ca29 76 for (j = 0; j < dev->nb_channels; j++) {
pcercuei 0:df031b60ca29 77 char *xml = iio_channel_get_xml(dev->channels[j],
pcercuei 0:df031b60ca29 78 &channels_len[j]);
pcercuei 0:df031b60ca29 79 if (!xml)
pcercuei 0:df031b60ca29 80 goto err_free_channels;
pcercuei 0:df031b60ca29 81 channels[j] = xml;
pcercuei 0:df031b60ca29 82 len += channels_len[j];
pcercuei 0:df031b60ca29 83 }
pcercuei 0:df031b60ca29 84
pcercuei 0:df031b60ca29 85 debug_attrs_len = malloc(dev->nb_debug_attrs *
pcercuei 0:df031b60ca29 86 sizeof(*debug_attrs_len));
pcercuei 0:df031b60ca29 87 if (!debug_attrs_len)
pcercuei 0:df031b60ca29 88 goto err_free_channels;
pcercuei 0:df031b60ca29 89
pcercuei 0:df031b60ca29 90 debug_attrs = malloc(dev->nb_debug_attrs * sizeof(*debug_attrs));
pcercuei 0:df031b60ca29 91 if (!debug_attrs)
pcercuei 0:df031b60ca29 92 goto err_free_debug_attrs_len;
pcercuei 0:df031b60ca29 93
pcercuei 0:df031b60ca29 94 for (k = 0; k < dev->nb_debug_attrs; k++) {
pcercuei 0:df031b60ca29 95 char *xml = get_attr_xml(dev->debug_attrs[k],
pcercuei 0:df031b60ca29 96 &debug_attrs_len[k], true);
pcercuei 0:df031b60ca29 97 if (!xml)
pcercuei 0:df031b60ca29 98 goto err_free_debug_attrs;
pcercuei 0:df031b60ca29 99 debug_attrs[k] = xml;
pcercuei 0:df031b60ca29 100 len += debug_attrs_len[k];
pcercuei 0:df031b60ca29 101 }
pcercuei 0:df031b60ca29 102
pcercuei 0:df031b60ca29 103 str = malloc(len);
pcercuei 0:df031b60ca29 104 if (!str)
pcercuei 0:df031b60ca29 105 goto err_free_debug_attrs;
pcercuei 0:df031b60ca29 106
pcercuei 3:d147beabba0e 107 iio_snprintf(str, len, "<device id=\"%s\"", dev->id);
pcercuei 0:df031b60ca29 108 ptr = strrchr(str, '\0');
pcercuei 0:df031b60ca29 109
pcercuei 0:df031b60ca29 110 if (dev->name) {
pcercuei 0:df031b60ca29 111 sprintf(ptr, " name=\"%s\"", dev->name);
pcercuei 0:df031b60ca29 112 ptr = strrchr(ptr, '\0');
pcercuei 0:df031b60ca29 113 }
pcercuei 0:df031b60ca29 114
pcercuei 0:df031b60ca29 115 strcpy(ptr, " >");
pcercuei 0:df031b60ca29 116 ptr += 2;
pcercuei 0:df031b60ca29 117
pcercuei 0:df031b60ca29 118 for (i = 0; i < dev->nb_channels; i++) {
pcercuei 0:df031b60ca29 119 strcpy(ptr, channels[i]);
pcercuei 0:df031b60ca29 120 ptr += channels_len[i];
pcercuei 0:df031b60ca29 121 free(channels[i]);
pcercuei 0:df031b60ca29 122 }
pcercuei 0:df031b60ca29 123
pcercuei 0:df031b60ca29 124 free(channels);
pcercuei 0:df031b60ca29 125 free(channels_len);
pcercuei 0:df031b60ca29 126
pcercuei 0:df031b60ca29 127 for (i = 0; i < dev->nb_attrs; i++) {
pcercuei 0:df031b60ca29 128 strcpy(ptr, attrs[i]);
pcercuei 0:df031b60ca29 129 ptr += attrs_len[i];
pcercuei 0:df031b60ca29 130 free(attrs[i]);
pcercuei 0:df031b60ca29 131 }
pcercuei 0:df031b60ca29 132
pcercuei 0:df031b60ca29 133 free(attrs);
pcercuei 0:df031b60ca29 134 free(attrs_len);
pcercuei 0:df031b60ca29 135
pcercuei 0:df031b60ca29 136 for (i = 0; i < dev->nb_debug_attrs; i++) {
pcercuei 0:df031b60ca29 137 strcpy(ptr, debug_attrs[i]);
pcercuei 0:df031b60ca29 138 ptr += debug_attrs_len[i];
pcercuei 0:df031b60ca29 139 free(debug_attrs[i]);
pcercuei 0:df031b60ca29 140 }
pcercuei 0:df031b60ca29 141
pcercuei 0:df031b60ca29 142 free(debug_attrs);
pcercuei 0:df031b60ca29 143 free(debug_attrs_len);
pcercuei 0:df031b60ca29 144
pcercuei 0:df031b60ca29 145 strcpy(ptr, "</device>");
pcercuei 0:df031b60ca29 146 *length = ptr - str + sizeof("</device>") - 1;
pcercuei 0:df031b60ca29 147 return str;
pcercuei 0:df031b60ca29 148
pcercuei 0:df031b60ca29 149 err_free_debug_attrs:
pcercuei 0:df031b60ca29 150 while (k--)
pcercuei 0:df031b60ca29 151 free(debug_attrs[k]);
pcercuei 0:df031b60ca29 152 free(debug_attrs);
pcercuei 0:df031b60ca29 153 err_free_debug_attrs_len:
pcercuei 0:df031b60ca29 154 free(debug_attrs_len);
pcercuei 0:df031b60ca29 155 err_free_channels:
pcercuei 0:df031b60ca29 156 while (j--)
pcercuei 0:df031b60ca29 157 free(channels[j]);
pcercuei 0:df031b60ca29 158 free(channels);
pcercuei 0:df031b60ca29 159 err_free_channels_len:
pcercuei 0:df031b60ca29 160 free(channels_len);
pcercuei 0:df031b60ca29 161 err_free_attrs:
pcercuei 0:df031b60ca29 162 while (i--)
pcercuei 0:df031b60ca29 163 free(attrs[i]);
pcercuei 0:df031b60ca29 164 free(attrs);
pcercuei 0:df031b60ca29 165 err_free_attrs_len:
pcercuei 0:df031b60ca29 166 free(attrs_len);
pcercuei 0:df031b60ca29 167 return NULL;
pcercuei 0:df031b60ca29 168 }
pcercuei 0:df031b60ca29 169
pcercuei 0:df031b60ca29 170 const char * iio_device_get_id(const struct iio_device *dev)
pcercuei 0:df031b60ca29 171 {
pcercuei 0:df031b60ca29 172 return dev->id;
pcercuei 0:df031b60ca29 173 }
pcercuei 0:df031b60ca29 174
pcercuei 0:df031b60ca29 175 const char * iio_device_get_name(const struct iio_device *dev)
pcercuei 0:df031b60ca29 176 {
pcercuei 0:df031b60ca29 177 return dev->name;
pcercuei 0:df031b60ca29 178 }
pcercuei 0:df031b60ca29 179
pcercuei 0:df031b60ca29 180 unsigned int iio_device_get_channels_count(const struct iio_device *dev)
pcercuei 0:df031b60ca29 181 {
pcercuei 0:df031b60ca29 182 return dev->nb_channels;
pcercuei 0:df031b60ca29 183 }
pcercuei 0:df031b60ca29 184
pcercuei 0:df031b60ca29 185 struct iio_channel * iio_device_get_channel(const struct iio_device *dev,
pcercuei 0:df031b60ca29 186 unsigned int index)
pcercuei 0:df031b60ca29 187 {
pcercuei 0:df031b60ca29 188 if (index >= dev->nb_channels)
pcercuei 0:df031b60ca29 189 return NULL;
pcercuei 0:df031b60ca29 190 else
pcercuei 0:df031b60ca29 191 return dev->channels[index];
pcercuei 0:df031b60ca29 192 }
pcercuei 0:df031b60ca29 193
pcercuei 0:df031b60ca29 194 struct iio_channel * iio_device_find_channel(const struct iio_device *dev,
pcercuei 0:df031b60ca29 195 const char *name, bool output)
pcercuei 0:df031b60ca29 196 {
pcercuei 0:df031b60ca29 197 unsigned int i;
pcercuei 0:df031b60ca29 198 for (i = 0; i < dev->nb_channels; i++) {
pcercuei 0:df031b60ca29 199 struct iio_channel *chn = dev->channels[i];
pcercuei 0:df031b60ca29 200 if (iio_channel_is_output(chn) != output)
pcercuei 0:df031b60ca29 201 continue;
pcercuei 0:df031b60ca29 202
pcercuei 0:df031b60ca29 203 if (!strcmp(chn->id, name) ||
pcercuei 0:df031b60ca29 204 (chn->name && !strcmp(chn->name, name)))
pcercuei 0:df031b60ca29 205 return chn;
pcercuei 0:df031b60ca29 206 }
pcercuei 0:df031b60ca29 207 return NULL;
pcercuei 0:df031b60ca29 208 }
pcercuei 0:df031b60ca29 209
pcercuei 0:df031b60ca29 210 unsigned int iio_device_get_attrs_count(const struct iio_device *dev)
pcercuei 0:df031b60ca29 211 {
pcercuei 0:df031b60ca29 212 return dev->nb_attrs;
pcercuei 0:df031b60ca29 213 }
pcercuei 0:df031b60ca29 214
pcercuei 0:df031b60ca29 215 const char * iio_device_get_attr(const struct iio_device *dev,
pcercuei 0:df031b60ca29 216 unsigned int index)
pcercuei 0:df031b60ca29 217 {
pcercuei 0:df031b60ca29 218 if (index >= dev->nb_attrs)
pcercuei 0:df031b60ca29 219 return NULL;
pcercuei 0:df031b60ca29 220 else
pcercuei 0:df031b60ca29 221 return dev->attrs[index];
pcercuei 0:df031b60ca29 222 }
pcercuei 0:df031b60ca29 223
pcercuei 0:df031b60ca29 224 const char * iio_device_find_attr(const struct iio_device *dev,
pcercuei 0:df031b60ca29 225 const char *name)
pcercuei 0:df031b60ca29 226 {
pcercuei 0:df031b60ca29 227 unsigned int i;
pcercuei 0:df031b60ca29 228 for (i = 0; i < dev->nb_attrs; i++) {
pcercuei 0:df031b60ca29 229 const char *attr = dev->attrs[i];
pcercuei 0:df031b60ca29 230 if (!strcmp(attr, name))
pcercuei 0:df031b60ca29 231 return attr;
pcercuei 0:df031b60ca29 232 }
pcercuei 0:df031b60ca29 233 return NULL;
pcercuei 0:df031b60ca29 234 }
pcercuei 0:df031b60ca29 235
pcercuei 0:df031b60ca29 236 const char * iio_device_find_debug_attr(const struct iio_device *dev,
pcercuei 0:df031b60ca29 237 const char *name)
pcercuei 0:df031b60ca29 238 {
pcercuei 0:df031b60ca29 239 unsigned int i;
pcercuei 0:df031b60ca29 240 for (i = 0; i < dev->nb_debug_attrs; i++) {
pcercuei 0:df031b60ca29 241 const char *attr = dev->debug_attrs[i];
pcercuei 0:df031b60ca29 242 if (!strcmp(attr, name))
pcercuei 0:df031b60ca29 243 return attr;
pcercuei 0:df031b60ca29 244 }
pcercuei 0:df031b60ca29 245 return NULL;
pcercuei 0:df031b60ca29 246 }
pcercuei 0:df031b60ca29 247
pcercuei 0:df031b60ca29 248 bool iio_device_is_tx(const struct iio_device *dev)
pcercuei 0:df031b60ca29 249 {
pcercuei 0:df031b60ca29 250 unsigned int i;
pcercuei 0:df031b60ca29 251
pcercuei 0:df031b60ca29 252 for (i = 0; i < dev->nb_channels; i++) {
pcercuei 0:df031b60ca29 253 struct iio_channel *ch = dev->channels[i];
pcercuei 0:df031b60ca29 254 if (iio_channel_is_output(ch) && iio_channel_is_enabled(ch))
pcercuei 0:df031b60ca29 255 return true;
pcercuei 0:df031b60ca29 256 }
pcercuei 0:df031b60ca29 257
pcercuei 0:df031b60ca29 258 return false;
pcercuei 0:df031b60ca29 259 }
pcercuei 0:df031b60ca29 260
pcercuei 0:df031b60ca29 261 int iio_device_open(const struct iio_device *dev,
pcercuei 0:df031b60ca29 262 size_t samples_count, bool cyclic)
pcercuei 0:df031b60ca29 263 {
pcercuei 0:df031b60ca29 264 unsigned int i;
pcercuei 0:df031b60ca29 265 bool has_channels = false;
pcercuei 0:df031b60ca29 266
pcercuei 0:df031b60ca29 267 for (i = 0; !has_channels && i < dev->words; i++)
pcercuei 0:df031b60ca29 268 has_channels = !!dev->mask[i];
pcercuei 0:df031b60ca29 269 if (!has_channels)
pcercuei 0:df031b60ca29 270 return -EINVAL;
pcercuei 0:df031b60ca29 271
pcercuei 0:df031b60ca29 272 if (dev->ctx->ops->open)
pcercuei 0:df031b60ca29 273 return dev->ctx->ops->open(dev, samples_count, cyclic);
pcercuei 0:df031b60ca29 274 else
pcercuei 0:df031b60ca29 275 return -ENOSYS;
pcercuei 0:df031b60ca29 276 }
pcercuei 0:df031b60ca29 277
pcercuei 0:df031b60ca29 278 int iio_device_close(const struct iio_device *dev)
pcercuei 0:df031b60ca29 279 {
pcercuei 0:df031b60ca29 280 if (dev->ctx->ops->close)
pcercuei 0:df031b60ca29 281 return dev->ctx->ops->close(dev);
pcercuei 0:df031b60ca29 282 else
pcercuei 0:df031b60ca29 283 return -ENOSYS;
pcercuei 0:df031b60ca29 284 }
pcercuei 0:df031b60ca29 285
pcercuei 0:df031b60ca29 286 int iio_device_get_poll_fd(const struct iio_device *dev)
pcercuei 0:df031b60ca29 287 {
pcercuei 0:df031b60ca29 288 if (dev->ctx->ops->get_fd)
pcercuei 0:df031b60ca29 289 return dev->ctx->ops->get_fd(dev);
pcercuei 0:df031b60ca29 290 else
pcercuei 0:df031b60ca29 291 return -ENOSYS;
pcercuei 0:df031b60ca29 292 }
pcercuei 0:df031b60ca29 293
pcercuei 0:df031b60ca29 294 int iio_device_set_blocking_mode(const struct iio_device *dev, bool blocking)
pcercuei 0:df031b60ca29 295 {
pcercuei 0:df031b60ca29 296 if (dev->ctx->ops->set_blocking_mode)
pcercuei 0:df031b60ca29 297 return dev->ctx->ops->set_blocking_mode(dev, blocking);
pcercuei 0:df031b60ca29 298 else
pcercuei 0:df031b60ca29 299 return -ENOSYS;
pcercuei 0:df031b60ca29 300 }
pcercuei 0:df031b60ca29 301
pcercuei 0:df031b60ca29 302 ssize_t iio_device_read_raw(const struct iio_device *dev,
pcercuei 0:df031b60ca29 303 void *dst, size_t len, uint32_t *mask, size_t words)
pcercuei 0:df031b60ca29 304 {
pcercuei 0:df031b60ca29 305 if (dev->ctx->ops->read)
pcercuei 0:df031b60ca29 306 return dev->ctx->ops->read(dev, dst, len, mask, words);
pcercuei 0:df031b60ca29 307 else
pcercuei 0:df031b60ca29 308 return -ENOSYS;
pcercuei 0:df031b60ca29 309 }
pcercuei 0:df031b60ca29 310
pcercuei 0:df031b60ca29 311 ssize_t iio_device_write_raw(const struct iio_device *dev,
pcercuei 0:df031b60ca29 312 const void *src, size_t len)
pcercuei 0:df031b60ca29 313 {
pcercuei 0:df031b60ca29 314 if (dev->ctx->ops->write)
pcercuei 0:df031b60ca29 315 return dev->ctx->ops->write(dev, src, len);
pcercuei 0:df031b60ca29 316 else
pcercuei 0:df031b60ca29 317 return -ENOSYS;
pcercuei 0:df031b60ca29 318 }
pcercuei 0:df031b60ca29 319
pcercuei 0:df031b60ca29 320 ssize_t iio_device_attr_read(const struct iio_device *dev,
pcercuei 0:df031b60ca29 321 const char *attr, char *dst, size_t len)
pcercuei 0:df031b60ca29 322 {
pcercuei 0:df031b60ca29 323 if (dev->ctx->ops->read_device_attr)
pcercuei 0:df031b60ca29 324 return dev->ctx->ops->read_device_attr(dev,
pcercuei 0:df031b60ca29 325 attr, dst, len, false);
pcercuei 0:df031b60ca29 326 else
pcercuei 0:df031b60ca29 327 return -ENOSYS;
pcercuei 0:df031b60ca29 328 }
pcercuei 0:df031b60ca29 329
pcercuei 0:df031b60ca29 330 ssize_t iio_device_attr_write_raw(const struct iio_device *dev,
pcercuei 0:df031b60ca29 331 const char *attr, const void *src, size_t len)
pcercuei 0:df031b60ca29 332 {
pcercuei 0:df031b60ca29 333 if (dev->ctx->ops->write_device_attr)
pcercuei 0:df031b60ca29 334 return dev->ctx->ops->write_device_attr(dev,
pcercuei 0:df031b60ca29 335 attr, src, len, false);
pcercuei 0:df031b60ca29 336 else
pcercuei 0:df031b60ca29 337 return -ENOSYS;
pcercuei 0:df031b60ca29 338 }
pcercuei 0:df031b60ca29 339
pcercuei 0:df031b60ca29 340 ssize_t iio_device_attr_write(const struct iio_device *dev,
pcercuei 0:df031b60ca29 341 const char *attr, const char *src)
pcercuei 0:df031b60ca29 342 {
pcercuei 0:df031b60ca29 343 return iio_device_attr_write_raw(dev, attr, src, strlen(src) + 1);
pcercuei 0:df031b60ca29 344 }
pcercuei 0:df031b60ca29 345
pcercuei 0:df031b60ca29 346 void iio_device_set_data(struct iio_device *dev, void *data)
pcercuei 0:df031b60ca29 347 {
pcercuei 0:df031b60ca29 348 dev->userdata = data;
pcercuei 0:df031b60ca29 349 }
pcercuei 0:df031b60ca29 350
pcercuei 0:df031b60ca29 351 void * iio_device_get_data(const struct iio_device *dev)
pcercuei 0:df031b60ca29 352 {
pcercuei 0:df031b60ca29 353 return dev->userdata;
pcercuei 0:df031b60ca29 354 }
pcercuei 0:df031b60ca29 355
pcercuei 0:df031b60ca29 356 bool iio_device_is_trigger(const struct iio_device *dev)
pcercuei 0:df031b60ca29 357 {
pcercuei 0:df031b60ca29 358 /* A trigger has a name, an id which starts by "trigger",
pcercuei 0:df031b60ca29 359 * and zero channels. */
pcercuei 0:df031b60ca29 360
pcercuei 0:df031b60ca29 361 unsigned int nb = iio_device_get_channels_count(dev);
pcercuei 0:df031b60ca29 362 const char *name = iio_device_get_name(dev),
pcercuei 0:df031b60ca29 363 *id = iio_device_get_id(dev);
pcercuei 0:df031b60ca29 364 return ((nb == 0) && !!name &&
pcercuei 0:df031b60ca29 365 !strncmp(id, "trigger", sizeof("trigger") - 1));
pcercuei 0:df031b60ca29 366 }
pcercuei 0:df031b60ca29 367
pcercuei 0:df031b60ca29 368 int iio_device_set_kernel_buffers_count(const struct iio_device *dev,
pcercuei 0:df031b60ca29 369 unsigned int nb_buffers)
pcercuei 0:df031b60ca29 370 {
pcercuei 0:df031b60ca29 371 if (nb_buffers == 0)
pcercuei 0:df031b60ca29 372 return -EINVAL;
pcercuei 0:df031b60ca29 373 else if (dev->ctx->ops->set_kernel_buffers_count)
pcercuei 0:df031b60ca29 374 return dev->ctx->ops->set_kernel_buffers_count(dev, nb_buffers);
pcercuei 0:df031b60ca29 375 else
pcercuei 0:df031b60ca29 376 return -ENOSYS;
pcercuei 0:df031b60ca29 377 }
pcercuei 0:df031b60ca29 378
pcercuei 0:df031b60ca29 379 int iio_device_get_trigger(const struct iio_device *dev,
pcercuei 0:df031b60ca29 380 const struct iio_device **trigger)
pcercuei 0:df031b60ca29 381 {
pcercuei 0:df031b60ca29 382 if (!trigger)
pcercuei 0:df031b60ca29 383 return -EINVAL;
pcercuei 0:df031b60ca29 384 else if (dev->ctx->ops->get_trigger)
pcercuei 0:df031b60ca29 385 return dev->ctx->ops->get_trigger(dev, trigger);
pcercuei 0:df031b60ca29 386 else
pcercuei 0:df031b60ca29 387 return -ENOSYS;
pcercuei 0:df031b60ca29 388 }
pcercuei 0:df031b60ca29 389
pcercuei 0:df031b60ca29 390 int iio_device_set_trigger(const struct iio_device *dev,
pcercuei 0:df031b60ca29 391 const struct iio_device *trigger)
pcercuei 0:df031b60ca29 392 {
pcercuei 0:df031b60ca29 393 if (trigger && !iio_device_is_trigger(trigger))
pcercuei 0:df031b60ca29 394 return -EINVAL;
pcercuei 0:df031b60ca29 395 else if (dev->ctx->ops->set_trigger)
pcercuei 0:df031b60ca29 396 return dev->ctx->ops->set_trigger(dev, trigger);
pcercuei 0:df031b60ca29 397 else
pcercuei 0:df031b60ca29 398 return -ENOSYS;
pcercuei 0:df031b60ca29 399 }
pcercuei 0:df031b60ca29 400
pcercuei 0:df031b60ca29 401 void free_device(struct iio_device *dev)
pcercuei 0:df031b60ca29 402 {
pcercuei 0:df031b60ca29 403 unsigned int i;
pcercuei 0:df031b60ca29 404 for (i = 0; i < dev->nb_attrs; i++)
pcercuei 0:df031b60ca29 405 free(dev->attrs[i]);
pcercuei 0:df031b60ca29 406 if (dev->nb_attrs)
pcercuei 0:df031b60ca29 407 free(dev->attrs);
pcercuei 0:df031b60ca29 408 for (i = 0; i < dev->nb_debug_attrs; i++)
pcercuei 0:df031b60ca29 409 free(dev->debug_attrs[i]);
pcercuei 0:df031b60ca29 410 if (dev->nb_debug_attrs)
pcercuei 0:df031b60ca29 411 free(dev->debug_attrs);
pcercuei 0:df031b60ca29 412 for (i = 0; i < dev->nb_channels; i++)
pcercuei 0:df031b60ca29 413 free_channel(dev->channels[i]);
pcercuei 0:df031b60ca29 414 if (dev->nb_channels)
pcercuei 0:df031b60ca29 415 free(dev->channels);
pcercuei 0:df031b60ca29 416 if (dev->mask)
pcercuei 0:df031b60ca29 417 free(dev->mask);
pcercuei 0:df031b60ca29 418 if (dev->name)
pcercuei 0:df031b60ca29 419 free(dev->name);
pcercuei 0:df031b60ca29 420 if (dev->id)
pcercuei 0:df031b60ca29 421 free(dev->id);
pcercuei 0:df031b60ca29 422 free(dev);
pcercuei 0:df031b60ca29 423 }
pcercuei 0:df031b60ca29 424
pcercuei 0:df031b60ca29 425 ssize_t iio_device_get_sample_size_mask(const struct iio_device *dev,
pcercuei 0:df031b60ca29 426 const uint32_t *mask, size_t words)
pcercuei 0:df031b60ca29 427 {
pcercuei 0:df031b60ca29 428 ssize_t size = 0;
pcercuei 0:df031b60ca29 429 unsigned int i;
pcercuei 4:ad69b39bf124 430 const struct iio_channel *prev = NULL;
pcercuei 0:df031b60ca29 431
pcercuei 0:df031b60ca29 432 if (words != (dev->nb_channels + 31) / 32)
pcercuei 0:df031b60ca29 433 return -EINVAL;
pcercuei 0:df031b60ca29 434
pcercuei 0:df031b60ca29 435 for (i = 0; i < dev->nb_channels; i++) {
pcercuei 0:df031b60ca29 436 const struct iio_channel *chn = dev->channels[i];
pcercuei 3:d147beabba0e 437 unsigned int length = chn->format.length / 8 *
pcercuei 3:d147beabba0e 438 chn->format.repeat;
pcercuei 0:df031b60ca29 439
pcercuei 0:df031b60ca29 440 if (chn->index < 0)
pcercuei 0:df031b60ca29 441 break;
pcercuei 4:ad69b39bf124 442 if (!TEST_BIT(mask, chn->number))
pcercuei 0:df031b60ca29 443 continue;
pcercuei 4:ad69b39bf124 444
pcercuei 4:ad69b39bf124 445 if (prev && chn->index == prev->index) {
pcercuei 4:ad69b39bf124 446 prev = chn;
pcercuei 3:d147beabba0e 447 continue;
pcercuei 4:ad69b39bf124 448 }
pcercuei 0:df031b60ca29 449
pcercuei 0:df031b60ca29 450 if (size % length)
pcercuei 0:df031b60ca29 451 size += 2 * length - (size % length);
pcercuei 0:df031b60ca29 452 else
pcercuei 0:df031b60ca29 453 size += length;
pcercuei 4:ad69b39bf124 454
pcercuei 4:ad69b39bf124 455 prev = chn;
pcercuei 0:df031b60ca29 456 }
pcercuei 0:df031b60ca29 457 return size;
pcercuei 0:df031b60ca29 458 }
pcercuei 0:df031b60ca29 459
pcercuei 0:df031b60ca29 460 ssize_t iio_device_get_sample_size(const struct iio_device *dev)
pcercuei 0:df031b60ca29 461 {
pcercuei 0:df031b60ca29 462 return iio_device_get_sample_size_mask(dev, dev->mask, dev->words);
pcercuei 0:df031b60ca29 463 }
pcercuei 0:df031b60ca29 464
pcercuei 0:df031b60ca29 465 int iio_device_attr_read_longlong(const struct iio_device *dev,
pcercuei 0:df031b60ca29 466 const char *attr, long long *val)
pcercuei 0:df031b60ca29 467 {
pcercuei 0:df031b60ca29 468 char *end, buf[1024];
pcercuei 0:df031b60ca29 469 long long value;
pcercuei 0:df031b60ca29 470 ssize_t ret = iio_device_attr_read(dev, attr, buf, sizeof(buf));
pcercuei 0:df031b60ca29 471 if (ret < 0)
pcercuei 0:df031b60ca29 472 return (int) ret;
pcercuei 0:df031b60ca29 473
pcercuei 0:df031b60ca29 474 value = strtoll(buf, &end, 0);
pcercuei 0:df031b60ca29 475 if (end == buf)
pcercuei 0:df031b60ca29 476 return -EINVAL;
pcercuei 0:df031b60ca29 477 *val = value;
pcercuei 0:df031b60ca29 478 return 0;
pcercuei 0:df031b60ca29 479 }
pcercuei 0:df031b60ca29 480
pcercuei 0:df031b60ca29 481 int iio_device_attr_read_bool(const struct iio_device *dev,
pcercuei 0:df031b60ca29 482 const char *attr, bool *val)
pcercuei 0:df031b60ca29 483 {
pcercuei 0:df031b60ca29 484 long long value;
pcercuei 0:df031b60ca29 485 int ret = iio_device_attr_read_longlong(dev, attr, &value);
pcercuei 0:df031b60ca29 486 if (ret < 0)
pcercuei 0:df031b60ca29 487 return ret;
pcercuei 0:df031b60ca29 488
pcercuei 0:df031b60ca29 489 *val = !!value;
pcercuei 0:df031b60ca29 490 return 0;
pcercuei 0:df031b60ca29 491 }
pcercuei 0:df031b60ca29 492
pcercuei 0:df031b60ca29 493 int iio_device_attr_read_double(const struct iio_device *dev,
pcercuei 0:df031b60ca29 494 const char *attr, double *val)
pcercuei 0:df031b60ca29 495 {
pcercuei 0:df031b60ca29 496 char buf[1024];
pcercuei 0:df031b60ca29 497 ssize_t ret = iio_device_attr_read(dev, attr, buf, sizeof(buf));
pcercuei 0:df031b60ca29 498 if (ret < 0)
pcercuei 0:df031b60ca29 499 return (int) ret;
pcercuei 0:df031b60ca29 500 else
pcercuei 0:df031b60ca29 501 return read_double(buf, val);
pcercuei 0:df031b60ca29 502 }
pcercuei 0:df031b60ca29 503
pcercuei 0:df031b60ca29 504 int iio_device_attr_write_longlong(const struct iio_device *dev,
pcercuei 0:df031b60ca29 505 const char *attr, long long val)
pcercuei 0:df031b60ca29 506 {
pcercuei 0:df031b60ca29 507 ssize_t ret;
pcercuei 0:df031b60ca29 508 char buf[1024];
pcercuei 0:df031b60ca29 509
pcercuei 3:d147beabba0e 510 iio_snprintf(buf, sizeof(buf), "%lld", val);
pcercuei 0:df031b60ca29 511 ret = iio_device_attr_write(dev, attr, buf);
pcercuei 0:df031b60ca29 512
pcercuei 0:df031b60ca29 513 return ret < 0 ? ret : 0;
pcercuei 0:df031b60ca29 514 }
pcercuei 0:df031b60ca29 515
pcercuei 0:df031b60ca29 516 int iio_device_attr_write_double(const struct iio_device *dev,
pcercuei 0:df031b60ca29 517 const char *attr, double val)
pcercuei 0:df031b60ca29 518 {
pcercuei 0:df031b60ca29 519 ssize_t ret;
pcercuei 0:df031b60ca29 520 char buf[1024];
pcercuei 0:df031b60ca29 521
pcercuei 0:df031b60ca29 522 ret = (ssize_t) write_double(buf, sizeof(buf), val);
pcercuei 0:df031b60ca29 523 if (!ret)
pcercuei 0:df031b60ca29 524 ret = iio_device_attr_write(dev, attr, buf);
pcercuei 0:df031b60ca29 525 return ret < 0 ? ret : 0;
pcercuei 0:df031b60ca29 526 }
pcercuei 0:df031b60ca29 527
pcercuei 0:df031b60ca29 528 int iio_device_attr_write_bool(const struct iio_device *dev,
pcercuei 0:df031b60ca29 529 const char *attr, bool val)
pcercuei 0:df031b60ca29 530 {
pcercuei 0:df031b60ca29 531 ssize_t ret;
pcercuei 0:df031b60ca29 532
pcercuei 0:df031b60ca29 533 if (val)
pcercuei 0:df031b60ca29 534 ret = iio_device_attr_write(dev, attr, "1");
pcercuei 0:df031b60ca29 535 else
pcercuei 0:df031b60ca29 536 ret = iio_device_attr_write(dev, attr, "0");
pcercuei 0:df031b60ca29 537
pcercuei 0:df031b60ca29 538 return ret < 0 ? ret : 0;
pcercuei 0:df031b60ca29 539 }
pcercuei 0:df031b60ca29 540
pcercuei 0:df031b60ca29 541 ssize_t iio_device_debug_attr_read(const struct iio_device *dev,
pcercuei 0:df031b60ca29 542 const char *attr, char *dst, size_t len)
pcercuei 0:df031b60ca29 543 {
pcercuei 0:df031b60ca29 544 if (dev->ctx->ops->read_device_attr)
pcercuei 0:df031b60ca29 545 return dev->ctx->ops->read_device_attr(dev,
pcercuei 0:df031b60ca29 546 attr, dst, len, true);
pcercuei 0:df031b60ca29 547 else
pcercuei 0:df031b60ca29 548 return -ENOSYS;
pcercuei 0:df031b60ca29 549 }
pcercuei 0:df031b60ca29 550
pcercuei 0:df031b60ca29 551 ssize_t iio_device_debug_attr_write_raw(const struct iio_device *dev,
pcercuei 0:df031b60ca29 552 const char *attr, const void *src, size_t len)
pcercuei 0:df031b60ca29 553 {
pcercuei 0:df031b60ca29 554 if (dev->ctx->ops->write_device_attr)
pcercuei 0:df031b60ca29 555 return dev->ctx->ops->write_device_attr(dev,
pcercuei 0:df031b60ca29 556 attr, src, len, true);
pcercuei 0:df031b60ca29 557 else
pcercuei 0:df031b60ca29 558 return -ENOSYS;
pcercuei 0:df031b60ca29 559 }
pcercuei 0:df031b60ca29 560
pcercuei 0:df031b60ca29 561 ssize_t iio_device_debug_attr_write(const struct iio_device *dev,
pcercuei 0:df031b60ca29 562 const char *attr, const char *src)
pcercuei 0:df031b60ca29 563 {
pcercuei 0:df031b60ca29 564 return iio_device_debug_attr_write_raw(dev, attr, src, strlen(src) + 1);
pcercuei 0:df031b60ca29 565 }
pcercuei 0:df031b60ca29 566
pcercuei 0:df031b60ca29 567 unsigned int iio_device_get_debug_attrs_count(const struct iio_device *dev)
pcercuei 0:df031b60ca29 568 {
pcercuei 0:df031b60ca29 569 return dev->nb_debug_attrs;
pcercuei 0:df031b60ca29 570 }
pcercuei 0:df031b60ca29 571
pcercuei 0:df031b60ca29 572 const char * iio_device_get_debug_attr(const struct iio_device *dev,
pcercuei 0:df031b60ca29 573 unsigned int index)
pcercuei 0:df031b60ca29 574 {
pcercuei 0:df031b60ca29 575 if (index >= dev->nb_debug_attrs)
pcercuei 0:df031b60ca29 576 return NULL;
pcercuei 0:df031b60ca29 577 else
pcercuei 0:df031b60ca29 578 return dev->debug_attrs[index];
pcercuei 0:df031b60ca29 579 }
pcercuei 0:df031b60ca29 580
pcercuei 0:df031b60ca29 581 int iio_device_debug_attr_read_longlong(const struct iio_device *dev,
pcercuei 0:df031b60ca29 582 const char *attr, long long *val)
pcercuei 0:df031b60ca29 583 {
pcercuei 0:df031b60ca29 584 char *end, buf[1024];
pcercuei 0:df031b60ca29 585 long long value;
pcercuei 0:df031b60ca29 586 ssize_t ret = iio_device_debug_attr_read(dev, attr, buf, sizeof(buf));
pcercuei 0:df031b60ca29 587 if (ret < 0)
pcercuei 0:df031b60ca29 588 return (int) ret;
pcercuei 0:df031b60ca29 589
pcercuei 0:df031b60ca29 590 value = strtoll(buf, &end, 0);
pcercuei 0:df031b60ca29 591 if (end == buf)
pcercuei 0:df031b60ca29 592 return -EINVAL;
pcercuei 0:df031b60ca29 593 *val = value;
pcercuei 0:df031b60ca29 594 return 0;
pcercuei 0:df031b60ca29 595 }
pcercuei 0:df031b60ca29 596
pcercuei 0:df031b60ca29 597 int iio_device_debug_attr_read_bool(const struct iio_device *dev,
pcercuei 0:df031b60ca29 598 const char *attr, bool *val)
pcercuei 0:df031b60ca29 599 {
pcercuei 0:df031b60ca29 600 long long value;
pcercuei 0:df031b60ca29 601 int ret = iio_device_debug_attr_read_longlong(dev, attr, &value);
pcercuei 0:df031b60ca29 602 if (ret < 0)
pcercuei 0:df031b60ca29 603 return ret;
pcercuei 0:df031b60ca29 604
pcercuei 0:df031b60ca29 605 *val = !!value;
pcercuei 0:df031b60ca29 606 return 0;
pcercuei 0:df031b60ca29 607 }
pcercuei 0:df031b60ca29 608
pcercuei 0:df031b60ca29 609 int iio_device_debug_attr_read_double(const struct iio_device *dev,
pcercuei 0:df031b60ca29 610 const char *attr, double *val)
pcercuei 0:df031b60ca29 611 {
pcercuei 0:df031b60ca29 612 char buf[1024];
pcercuei 0:df031b60ca29 613 ssize_t ret = iio_device_debug_attr_read(dev, attr, buf, sizeof(buf));
pcercuei 0:df031b60ca29 614 if (ret < 0)
pcercuei 0:df031b60ca29 615 return (int) ret;
pcercuei 0:df031b60ca29 616 else
pcercuei 0:df031b60ca29 617 return read_double(buf, val);
pcercuei 0:df031b60ca29 618 }
pcercuei 0:df031b60ca29 619
pcercuei 0:df031b60ca29 620 int iio_device_debug_attr_write_longlong(const struct iio_device *dev,
pcercuei 0:df031b60ca29 621 const char *attr, long long val)
pcercuei 0:df031b60ca29 622 {
pcercuei 0:df031b60ca29 623 ssize_t ret;
pcercuei 0:df031b60ca29 624 char buf[1024];
pcercuei 0:df031b60ca29 625
pcercuei 3:d147beabba0e 626 iio_snprintf(buf, sizeof(buf), "%lld", val);
pcercuei 0:df031b60ca29 627 ret = iio_device_debug_attr_write(dev, attr, buf);
pcercuei 0:df031b60ca29 628
pcercuei 0:df031b60ca29 629 return ret < 0 ? ret : 0;
pcercuei 0:df031b60ca29 630 }
pcercuei 0:df031b60ca29 631
pcercuei 0:df031b60ca29 632 int iio_device_debug_attr_write_double(const struct iio_device *dev,
pcercuei 0:df031b60ca29 633 const char *attr, double val)
pcercuei 0:df031b60ca29 634 {
pcercuei 0:df031b60ca29 635 ssize_t ret;
pcercuei 0:df031b60ca29 636 char buf[1024];
pcercuei 0:df031b60ca29 637
pcercuei 0:df031b60ca29 638 ret = (ssize_t) write_double(buf, sizeof(buf), val);
pcercuei 0:df031b60ca29 639 if (!ret)
pcercuei 0:df031b60ca29 640 ret = iio_device_debug_attr_write(dev, attr, buf);
pcercuei 0:df031b60ca29 641 return ret < 0 ? ret : 0;
pcercuei 0:df031b60ca29 642 }
pcercuei 0:df031b60ca29 643
pcercuei 0:df031b60ca29 644 int iio_device_debug_attr_write_bool(const struct iio_device *dev,
pcercuei 0:df031b60ca29 645 const char *attr, bool val)
pcercuei 0:df031b60ca29 646 {
pcercuei 0:df031b60ca29 647 ssize_t ret;
pcercuei 0:df031b60ca29 648
pcercuei 0:df031b60ca29 649 if (val)
pcercuei 0:df031b60ca29 650 ret = iio_device_debug_attr_write_raw(dev, attr, "1", 2);
pcercuei 0:df031b60ca29 651 else
pcercuei 0:df031b60ca29 652 ret = iio_device_debug_attr_write_raw(dev, attr, "0", 2);
pcercuei 0:df031b60ca29 653
pcercuei 0:df031b60ca29 654 return ret < 0 ? ret : 0;
pcercuei 0:df031b60ca29 655 }
pcercuei 0:df031b60ca29 656
pcercuei 0:df031b60ca29 657 int iio_device_identify_filename(const struct iio_device *dev,
pcercuei 0:df031b60ca29 658 const char *filename, struct iio_channel **chn,
pcercuei 0:df031b60ca29 659 const char **attr)
pcercuei 0:df031b60ca29 660 {
pcercuei 0:df031b60ca29 661 unsigned int i;
pcercuei 0:df031b60ca29 662
pcercuei 0:df031b60ca29 663 for (i = 0; i < dev->nb_channels; i++) {
pcercuei 0:df031b60ca29 664 struct iio_channel *ch = dev->channels[i];
pcercuei 0:df031b60ca29 665 unsigned int j;
pcercuei 0:df031b60ca29 666
pcercuei 0:df031b60ca29 667 for (j = 0; j < ch->nb_attrs; j++) {
pcercuei 0:df031b60ca29 668 if (!strcmp(ch->attrs[j].filename, filename)) {
pcercuei 0:df031b60ca29 669 *attr = ch->attrs[j].name;
pcercuei 0:df031b60ca29 670 *chn = ch;
pcercuei 0:df031b60ca29 671 return 0;
pcercuei 0:df031b60ca29 672 }
pcercuei 0:df031b60ca29 673 }
pcercuei 0:df031b60ca29 674 }
pcercuei 0:df031b60ca29 675
pcercuei 0:df031b60ca29 676 for (i = 0; i < dev->nb_attrs; i++) {
pcercuei 0:df031b60ca29 677 /* Devices attributes are named after their filename */
pcercuei 0:df031b60ca29 678 if (!strcmp(dev->attrs[i], filename)) {
pcercuei 0:df031b60ca29 679 *attr = dev->attrs[i];
pcercuei 0:df031b60ca29 680 *chn = NULL;
pcercuei 0:df031b60ca29 681 return 0;
pcercuei 0:df031b60ca29 682 }
pcercuei 0:df031b60ca29 683 }
pcercuei 0:df031b60ca29 684
pcercuei 0:df031b60ca29 685 for (i = 0; i < dev->nb_debug_attrs; i++) {
pcercuei 0:df031b60ca29 686 if (!strcmp(dev->debug_attrs[i], filename)) {
pcercuei 0:df031b60ca29 687 *attr = dev->debug_attrs[i];
pcercuei 0:df031b60ca29 688 *chn = NULL;
pcercuei 0:df031b60ca29 689 return 0;
pcercuei 0:df031b60ca29 690 }
pcercuei 0:df031b60ca29 691 }
pcercuei 0:df031b60ca29 692
pcercuei 0:df031b60ca29 693 return -EINVAL;
pcercuei 0:df031b60ca29 694 }
pcercuei 0:df031b60ca29 695
pcercuei 0:df031b60ca29 696 int iio_device_reg_write(struct iio_device *dev,
pcercuei 0:df031b60ca29 697 uint32_t address, uint32_t value)
pcercuei 0:df031b60ca29 698 {
pcercuei 0:df031b60ca29 699 ssize_t ret;
pcercuei 3:d147beabba0e 700 char buf[1024];
pcercuei 0:df031b60ca29 701
pcercuei 3:d147beabba0e 702 iio_snprintf(buf, sizeof(buf), "0x%" PRIx32 " 0x%" PRIx32,
pcercuei 3:d147beabba0e 703 address, value);
pcercuei 0:df031b60ca29 704 ret = iio_device_debug_attr_write(dev, "direct_reg_access", buf);
pcercuei 0:df031b60ca29 705
pcercuei 0:df031b60ca29 706 return ret < 0 ? ret : 0;
pcercuei 0:df031b60ca29 707 }
pcercuei 0:df031b60ca29 708
pcercuei 0:df031b60ca29 709 int iio_device_reg_read(struct iio_device *dev,
pcercuei 0:df031b60ca29 710 uint32_t address, uint32_t *value)
pcercuei 0:df031b60ca29 711 {
pcercuei 0:df031b60ca29 712 /* NOTE: There is a race condition here. But it is extremely unlikely to
pcercuei 0:df031b60ca29 713 * happen, and as this is a debug function, it shouldn't be used for
pcercuei 0:df031b60ca29 714 * something else than debug. */
pcercuei 0:df031b60ca29 715
pcercuei 0:df031b60ca29 716 long long val;
pcercuei 0:df031b60ca29 717 int ret = iio_device_debug_attr_write_longlong(dev,
pcercuei 0:df031b60ca29 718 "direct_reg_access", (long long) address);
pcercuei 0:df031b60ca29 719 if (ret < 0)
pcercuei 0:df031b60ca29 720 return ret;
pcercuei 0:df031b60ca29 721
pcercuei 0:df031b60ca29 722 ret = iio_device_debug_attr_read_longlong(dev,
pcercuei 0:df031b60ca29 723 "direct_reg_access", &val);
pcercuei 0:df031b60ca29 724 if (!ret)
pcercuei 0:df031b60ca29 725 *value = (uint32_t) val;
pcercuei 0:df031b60ca29 726 return ret;
pcercuei 0:df031b60ca29 727 }
pcercuei 0:df031b60ca29 728
pcercuei 0:df031b60ca29 729 static int read_each_attr(struct iio_device *dev, bool is_debug,
pcercuei 0:df031b60ca29 730 int (*cb)(struct iio_device *dev,
pcercuei 0:df031b60ca29 731 const char *attr, const char *val, size_t len, void *d),
pcercuei 0:df031b60ca29 732 void *data)
pcercuei 0:df031b60ca29 733 {
pcercuei 0:df031b60ca29 734 int ret;
pcercuei 0:df031b60ca29 735 char *buf, *ptr;
pcercuei 0:df031b60ca29 736 unsigned int i, count;
pcercuei 0:df031b60ca29 737
pcercuei 0:df031b60ca29 738 /* We need a big buffer here; 1 MiB should be enough */
pcercuei 0:df031b60ca29 739 buf = malloc(0x100000);
pcercuei 0:df031b60ca29 740 if (!buf)
pcercuei 0:df031b60ca29 741 return -ENOMEM;
pcercuei 0:df031b60ca29 742
pcercuei 0:df031b60ca29 743 if (is_debug) {
pcercuei 0:df031b60ca29 744 count = iio_device_get_debug_attrs_count(dev);
pcercuei 0:df031b60ca29 745 ret = (int) iio_device_debug_attr_read(dev,
pcercuei 0:df031b60ca29 746 NULL, buf, 0x100000);
pcercuei 0:df031b60ca29 747 } else {
pcercuei 0:df031b60ca29 748 count = iio_device_get_attrs_count(dev);
pcercuei 0:df031b60ca29 749 ret = (int) iio_device_attr_read(dev, NULL, buf, 0x100000);
pcercuei 0:df031b60ca29 750 }
pcercuei 0:df031b60ca29 751
pcercuei 0:df031b60ca29 752 if (ret < 0)
pcercuei 0:df031b60ca29 753 goto err_free_buf;
pcercuei 0:df031b60ca29 754
pcercuei 0:df031b60ca29 755 ptr = buf;
pcercuei 0:df031b60ca29 756
pcercuei 0:df031b60ca29 757 for (i = 0; i < count; i++) {
pcercuei 0:df031b60ca29 758 const char *attr;
pcercuei 0:df031b60ca29 759 int32_t len = (int32_t) iio_be32toh(*(uint32_t *) ptr);
pcercuei 0:df031b60ca29 760
pcercuei 0:df031b60ca29 761 if (is_debug)
pcercuei 0:df031b60ca29 762 attr = iio_device_get_debug_attr(dev, i);
pcercuei 0:df031b60ca29 763 else
pcercuei 0:df031b60ca29 764 attr = iio_device_get_attr(dev, i);
pcercuei 0:df031b60ca29 765
pcercuei 0:df031b60ca29 766 ptr += 4;
pcercuei 0:df031b60ca29 767 if (len > 0) {
pcercuei 0:df031b60ca29 768 ret = cb(dev, attr, ptr, (size_t) len, data);
pcercuei 0:df031b60ca29 769 if (ret < 0)
pcercuei 0:df031b60ca29 770 goto err_free_buf;
pcercuei 0:df031b60ca29 771
pcercuei 0:df031b60ca29 772 if (len & 0x3)
pcercuei 0:df031b60ca29 773 len = ((len >> 2) + 1) << 2;
pcercuei 0:df031b60ca29 774 ptr += len;
pcercuei 0:df031b60ca29 775 }
pcercuei 0:df031b60ca29 776 }
pcercuei 0:df031b60ca29 777
pcercuei 0:df031b60ca29 778 err_free_buf:
pcercuei 0:df031b60ca29 779 free(buf);
pcercuei 0:df031b60ca29 780 return ret < 0 ? ret : 0;
pcercuei 0:df031b60ca29 781 }
pcercuei 0:df031b60ca29 782
pcercuei 0:df031b60ca29 783 static int write_each_attr(struct iio_device *dev, bool is_debug,
pcercuei 0:df031b60ca29 784 ssize_t (*cb)(struct iio_device *dev,
pcercuei 0:df031b60ca29 785 const char *attr, void *buf, size_t len, void *d),
pcercuei 0:df031b60ca29 786 void *data)
pcercuei 0:df031b60ca29 787 {
pcercuei 0:df031b60ca29 788 char *buf, *ptr;
pcercuei 0:df031b60ca29 789 unsigned int i, count;
pcercuei 0:df031b60ca29 790 size_t len = 0x100000;
pcercuei 0:df031b60ca29 791 int ret;
pcercuei 0:df031b60ca29 792
pcercuei 0:df031b60ca29 793 /* We need a big buffer here; 1 MiB should be enough */
pcercuei 0:df031b60ca29 794 buf = malloc(len);
pcercuei 0:df031b60ca29 795 if (!buf)
pcercuei 0:df031b60ca29 796 return -ENOMEM;
pcercuei 0:df031b60ca29 797
pcercuei 0:df031b60ca29 798 ptr = buf;
pcercuei 0:df031b60ca29 799
pcercuei 0:df031b60ca29 800 if (is_debug)
pcercuei 0:df031b60ca29 801 count = iio_device_get_debug_attrs_count(dev);
pcercuei 0:df031b60ca29 802 else
pcercuei 0:df031b60ca29 803 count = iio_device_get_attrs_count(dev);
pcercuei 0:df031b60ca29 804
pcercuei 0:df031b60ca29 805 for (i = 0; i < count; i++) {
pcercuei 0:df031b60ca29 806 const char *attr;
pcercuei 0:df031b60ca29 807
pcercuei 0:df031b60ca29 808 if (is_debug)
pcercuei 0:df031b60ca29 809 attr = iio_device_get_debug_attr(dev, i);
pcercuei 0:df031b60ca29 810 else
pcercuei 0:df031b60ca29 811 attr = iio_device_get_attr(dev, i);
pcercuei 0:df031b60ca29 812
pcercuei 0:df031b60ca29 813 ret = (int) cb(dev, attr, ptr + 4, len - 4, data);
pcercuei 0:df031b60ca29 814 if (ret < 0)
pcercuei 0:df031b60ca29 815 goto err_free_buf;
pcercuei 0:df031b60ca29 816
pcercuei 0:df031b60ca29 817 *(int32_t *) ptr = (int32_t) iio_htobe32((uint32_t) ret);
pcercuei 0:df031b60ca29 818 ptr += 4;
pcercuei 0:df031b60ca29 819 len -= 4;
pcercuei 0:df031b60ca29 820
pcercuei 0:df031b60ca29 821 if (ret > 0) {
pcercuei 0:df031b60ca29 822 if (ret & 0x3)
pcercuei 0:df031b60ca29 823 ret = ((ret >> 2) + 1) << 2;
pcercuei 0:df031b60ca29 824 ptr += ret;
pcercuei 0:df031b60ca29 825 len -= ret;
pcercuei 0:df031b60ca29 826 }
pcercuei 0:df031b60ca29 827 }
pcercuei 0:df031b60ca29 828
pcercuei 0:df031b60ca29 829 if (is_debug)
pcercuei 0:df031b60ca29 830 ret = (int) iio_device_debug_attr_write_raw(dev,
pcercuei 0:df031b60ca29 831 NULL, buf, ptr - buf);
pcercuei 0:df031b60ca29 832 else
pcercuei 0:df031b60ca29 833 ret = (int) iio_device_attr_write_raw(dev,
pcercuei 0:df031b60ca29 834 NULL, buf, ptr - buf);
pcercuei 0:df031b60ca29 835
pcercuei 0:df031b60ca29 836 err_free_buf:
pcercuei 0:df031b60ca29 837 free(buf);
pcercuei 0:df031b60ca29 838 return ret < 0 ? ret : 0;
pcercuei 0:df031b60ca29 839 }
pcercuei 0:df031b60ca29 840
pcercuei 0:df031b60ca29 841 int iio_device_debug_attr_read_all(struct iio_device *dev,
pcercuei 0:df031b60ca29 842 int (*cb)(struct iio_device *dev,
pcercuei 0:df031b60ca29 843 const char *attr, const char *val, size_t len, void *d),
pcercuei 0:df031b60ca29 844 void *data)
pcercuei 0:df031b60ca29 845 {
pcercuei 0:df031b60ca29 846 return read_each_attr(dev, true, cb, data);
pcercuei 0:df031b60ca29 847 }
pcercuei 0:df031b60ca29 848
pcercuei 0:df031b60ca29 849 int iio_device_attr_read_all(struct iio_device *dev,
pcercuei 0:df031b60ca29 850 int (*cb)(struct iio_device *dev,
pcercuei 0:df031b60ca29 851 const char *attr, const char *val, size_t len, void *d),
pcercuei 0:df031b60ca29 852 void *data)
pcercuei 0:df031b60ca29 853 {
pcercuei 0:df031b60ca29 854 return read_each_attr(dev, false, cb, data);
pcercuei 0:df031b60ca29 855 }
pcercuei 0:df031b60ca29 856
pcercuei 0:df031b60ca29 857 int iio_device_debug_attr_write_all(struct iio_device *dev,
pcercuei 0:df031b60ca29 858 ssize_t (*cb)(struct iio_device *dev,
pcercuei 0:df031b60ca29 859 const char *attr, void *buf, size_t len, void *d),
pcercuei 0:df031b60ca29 860 void *data)
pcercuei 0:df031b60ca29 861 {
pcercuei 0:df031b60ca29 862 return write_each_attr(dev, true, cb, data);
pcercuei 0:df031b60ca29 863 }
pcercuei 0:df031b60ca29 864
pcercuei 0:df031b60ca29 865 int iio_device_attr_write_all(struct iio_device *dev,
pcercuei 0:df031b60ca29 866 ssize_t (*cb)(struct iio_device *dev,
pcercuei 0:df031b60ca29 867 const char *attr, void *buf, size_t len, void *d),
pcercuei 0:df031b60ca29 868 void *data)
pcercuei 0:df031b60ca29 869 {
pcercuei 0:df031b60ca29 870 return write_each_attr(dev, false, cb, data);
pcercuei 0:df031b60ca29 871 }
pcercuei 0:df031b60ca29 872
pcercuei 0:df031b60ca29 873 const struct iio_context * iio_device_get_context(const struct iio_device *dev)
pcercuei 0:df031b60ca29 874 {
pcercuei 0:df031b60ca29 875 return dev->ctx;
pcercuei 0:df031b60ca29 876 }
pcercuei 0:df031b60ca29 877