Library for interfacing with IIO devices. Licensed under the LGPLv2+

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 2:9eb0a9a1f958 22 #include <errno.h>
pcercuei 0:df031b60ca29 23 #include <libxml/tree.h>
pcercuei 0:df031b60ca29 24 #include <string.h>
pcercuei 0:df031b60ca29 25
pcercuei 0:df031b60ca29 26 static int add_attr_to_channel(struct iio_channel *chn, xmlNode *n)
pcercuei 0:df031b60ca29 27 {
pcercuei 0:df031b60ca29 28 xmlAttr *attr;
pcercuei 0:df031b60ca29 29 char *name = NULL, *filename = NULL;
pcercuei 0:df031b60ca29 30 struct iio_channel_attr *attrs;
pcercuei 0:df031b60ca29 31
pcercuei 0:df031b60ca29 32 for (attr = n->properties; attr; attr = attr->next) {
pcercuei 0:df031b60ca29 33 if (!strcmp((char *) attr->name, "name")) {
pcercuei 0:df031b60ca29 34 name = iio_strdup((char *) attr->children->content);
pcercuei 0:df031b60ca29 35 } else if (!strcmp((char *) attr->name, "filename")) {
pcercuei 0:df031b60ca29 36 filename = iio_strdup((char *) attr->children->content);
pcercuei 0:df031b60ca29 37 } else {
pcercuei 0:df031b60ca29 38 WARNING("Unknown field \'%s\' in channel %s\n",
pcercuei 0:df031b60ca29 39 attr->name, chn->id);
pcercuei 0:df031b60ca29 40 }
pcercuei 0:df031b60ca29 41 }
pcercuei 0:df031b60ca29 42
pcercuei 0:df031b60ca29 43 if (!name) {
pcercuei 0:df031b60ca29 44 ERROR("Incomplete attribute in channel %s\n", chn->id);
pcercuei 0:df031b60ca29 45 goto err_free;
pcercuei 0:df031b60ca29 46 }
pcercuei 0:df031b60ca29 47
pcercuei 0:df031b60ca29 48 if (!filename) {
pcercuei 0:df031b60ca29 49 filename = iio_strdup(name);
pcercuei 0:df031b60ca29 50 if (!filename)
pcercuei 0:df031b60ca29 51 goto err_free;
pcercuei 0:df031b60ca29 52 }
pcercuei 0:df031b60ca29 53
pcercuei 0:df031b60ca29 54 attrs = realloc(chn->attrs, (1 + chn->nb_attrs) *
pcercuei 0:df031b60ca29 55 sizeof(struct iio_channel_attr));
pcercuei 0:df031b60ca29 56 if (!attrs)
pcercuei 0:df031b60ca29 57 goto err_free;
pcercuei 0:df031b60ca29 58
pcercuei 0:df031b60ca29 59 attrs[chn->nb_attrs].filename = filename;
pcercuei 0:df031b60ca29 60 attrs[chn->nb_attrs++].name = name;
pcercuei 0:df031b60ca29 61 chn->attrs = attrs;
pcercuei 0:df031b60ca29 62 return 0;
pcercuei 0:df031b60ca29 63
pcercuei 0:df031b60ca29 64 err_free:
pcercuei 0:df031b60ca29 65 if (name)
pcercuei 0:df031b60ca29 66 free(name);
pcercuei 0:df031b60ca29 67 if (filename)
pcercuei 0:df031b60ca29 68 free(filename);
pcercuei 0:df031b60ca29 69 return -1;
pcercuei 0:df031b60ca29 70 }
pcercuei 0:df031b60ca29 71
pcercuei 0:df031b60ca29 72 static int add_attr_to_device(struct iio_device *dev, xmlNode *n, bool is_debug)
pcercuei 0:df031b60ca29 73 {
pcercuei 0:df031b60ca29 74 xmlAttr *attr;
pcercuei 0:df031b60ca29 75 char **attrs, *name = NULL;
pcercuei 0:df031b60ca29 76
pcercuei 0:df031b60ca29 77 for (attr = n->properties; attr; attr = attr->next) {
pcercuei 0:df031b60ca29 78 if (!strcmp((char *) attr->name, "name")) {
pcercuei 0:df031b60ca29 79 name = iio_strdup((char *) attr->children->content);
pcercuei 0:df031b60ca29 80 } else {
pcercuei 0:df031b60ca29 81 WARNING("Unknown field \'%s\' in device %s\n",
pcercuei 0:df031b60ca29 82 attr->name, dev->id);
pcercuei 0:df031b60ca29 83 }
pcercuei 0:df031b60ca29 84 }
pcercuei 0:df031b60ca29 85
pcercuei 0:df031b60ca29 86 if (!name) {
pcercuei 0:df031b60ca29 87 ERROR("Incomplete attribute in device %s\n", dev->id);
pcercuei 0:df031b60ca29 88 goto err_free;
pcercuei 0:df031b60ca29 89 }
pcercuei 0:df031b60ca29 90
pcercuei 0:df031b60ca29 91 if (is_debug)
pcercuei 0:df031b60ca29 92 attrs = realloc(dev->debug_attrs,
pcercuei 0:df031b60ca29 93 (1 + dev->nb_debug_attrs) * sizeof(char *));
pcercuei 0:df031b60ca29 94 else
pcercuei 0:df031b60ca29 95 attrs = realloc(dev->attrs,
pcercuei 0:df031b60ca29 96 (1 + dev->nb_attrs) * sizeof(char *));
pcercuei 0:df031b60ca29 97 if (!attrs)
pcercuei 0:df031b60ca29 98 goto err_free;
pcercuei 0:df031b60ca29 99
pcercuei 0:df031b60ca29 100 if (is_debug) {
pcercuei 0:df031b60ca29 101 attrs[dev->nb_debug_attrs++] = name;
pcercuei 0:df031b60ca29 102 dev->debug_attrs = attrs;
pcercuei 0:df031b60ca29 103 } else {
pcercuei 0:df031b60ca29 104 attrs[dev->nb_attrs++] = name;
pcercuei 0:df031b60ca29 105 dev->attrs = attrs;
pcercuei 0:df031b60ca29 106 }
pcercuei 0:df031b60ca29 107 return 0;
pcercuei 0:df031b60ca29 108
pcercuei 0:df031b60ca29 109 err_free:
pcercuei 0:df031b60ca29 110 if (name)
pcercuei 0:df031b60ca29 111 free(name);
pcercuei 0:df031b60ca29 112 return -1;
pcercuei 0:df031b60ca29 113 }
pcercuei 0:df031b60ca29 114
pcercuei 0:df031b60ca29 115 static void setup_scan_element(struct iio_channel *chn, xmlNode *n)
pcercuei 0:df031b60ca29 116 {
pcercuei 0:df031b60ca29 117 xmlAttr *attr;
pcercuei 0:df031b60ca29 118
pcercuei 0:df031b60ca29 119 for (attr = n->properties; attr; attr = attr->next) {
pcercuei 0:df031b60ca29 120 const char *name = (const char *) attr->name,
pcercuei 0:df031b60ca29 121 *content = (const char *) attr->children->content;
pcercuei 0:df031b60ca29 122 if (!strcmp(name, "index")) {
pcercuei 0:df031b60ca29 123 chn->index = atol(content);
pcercuei 0:df031b60ca29 124 } else if (!strcmp(name, "format")) {
pcercuei 0:df031b60ca29 125 char e, s;
pcercuei 3:d147beabba0e 126 if (strchr(content, 'X')) {
pcercuei 3:d147beabba0e 127 sscanf(content, "%ce:%c%u/%uX%u>>%u", &e, &s,
pcercuei 3:d147beabba0e 128 &chn->format.bits,
pcercuei 3:d147beabba0e 129 &chn->format.length,
pcercuei 3:d147beabba0e 130 &chn->format.repeat,
pcercuei 3:d147beabba0e 131 &chn->format.shift);
pcercuei 3:d147beabba0e 132 } else {
pcercuei 3:d147beabba0e 133 chn->format.repeat = 1;
pcercuei 3:d147beabba0e 134 sscanf(content, "%ce:%c%u/%u>>%u", &e, &s,
pcercuei 0:df031b60ca29 135 &chn->format.bits,
pcercuei 0:df031b60ca29 136 &chn->format.length,
pcercuei 0:df031b60ca29 137 &chn->format.shift);
pcercuei 3:d147beabba0e 138 }
pcercuei 0:df031b60ca29 139 chn->format.is_be = e == 'b';
pcercuei 0:df031b60ca29 140 chn->format.is_signed = (s == 's' || s == 'S');
pcercuei 0:df031b60ca29 141 chn->format.is_fully_defined = (s == 'S' || s == 'U' ||
pcercuei 0:df031b60ca29 142 chn->format.bits == chn->format.length);
pcercuei 0:df031b60ca29 143 } else if (!strcmp(name, "scale")) {
pcercuei 0:df031b60ca29 144 chn->format.with_scale = true;
pcercuei 0:df031b60ca29 145 chn->format.scale = atof(content);
pcercuei 0:df031b60ca29 146 } else {
pcercuei 0:df031b60ca29 147 WARNING("Unknown attribute \'%s\' in <scan-element>\n",
pcercuei 0:df031b60ca29 148 name);
pcercuei 0:df031b60ca29 149 }
pcercuei 0:df031b60ca29 150 }
pcercuei 0:df031b60ca29 151 }
pcercuei 0:df031b60ca29 152
pcercuei 0:df031b60ca29 153 static struct iio_channel * create_channel(struct iio_device *dev, xmlNode *n)
pcercuei 0:df031b60ca29 154 {
pcercuei 0:df031b60ca29 155 xmlAttr *attr;
pcercuei 0:df031b60ca29 156 struct iio_channel *chn = zalloc(sizeof(*chn));
pcercuei 0:df031b60ca29 157 if (!chn)
pcercuei 0:df031b60ca29 158 return NULL;
pcercuei 0:df031b60ca29 159
pcercuei 0:df031b60ca29 160 chn->dev = dev;
pcercuei 0:df031b60ca29 161
pcercuei 0:df031b60ca29 162 /* Set the default index value < 0 (== no index) */
pcercuei 0:df031b60ca29 163 chn->index = -ENOENT;
pcercuei 0:df031b60ca29 164
pcercuei 0:df031b60ca29 165 for (attr = n->properties; attr; attr = attr->next) {
pcercuei 0:df031b60ca29 166 const char *name = (const char *) attr->name,
pcercuei 0:df031b60ca29 167 *content = (const char *) attr->children->content;
pcercuei 0:df031b60ca29 168 if (!strcmp(name, "name")) {
pcercuei 0:df031b60ca29 169 chn->name = iio_strdup(content);
pcercuei 0:df031b60ca29 170 } else if (!strcmp(name, "id")) {
pcercuei 0:df031b60ca29 171 chn->id = iio_strdup(content);
pcercuei 0:df031b60ca29 172 } else if (!strcmp(name, "type")) {
pcercuei 0:df031b60ca29 173 if (!strcmp(content, "output"))
pcercuei 0:df031b60ca29 174 chn->is_output = true;
pcercuei 0:df031b60ca29 175 else if (strcmp(content, "input"))
pcercuei 0:df031b60ca29 176 WARNING("Unknown channel type %s\n", content);
pcercuei 0:df031b60ca29 177 } else {
pcercuei 0:df031b60ca29 178 WARNING("Unknown attribute \'%s\' in <channel>\n",
pcercuei 0:df031b60ca29 179 name);
pcercuei 0:df031b60ca29 180 }
pcercuei 0:df031b60ca29 181 }
pcercuei 0:df031b60ca29 182
pcercuei 0:df031b60ca29 183 if (!chn->id) {
pcercuei 0:df031b60ca29 184 ERROR("Incomplete <attribute>\n");
pcercuei 0:df031b60ca29 185 goto err_free_channel;
pcercuei 0:df031b60ca29 186 }
pcercuei 0:df031b60ca29 187
pcercuei 0:df031b60ca29 188 for (n = n->children; n; n = n->next) {
pcercuei 0:df031b60ca29 189 if (!strcmp((char *) n->name, "attribute")) {
pcercuei 0:df031b60ca29 190 if (add_attr_to_channel(chn, n) < 0)
pcercuei 0:df031b60ca29 191 goto err_free_channel;
pcercuei 0:df031b60ca29 192 } else if (!strcmp((char *) n->name, "scan-element")) {
pcercuei 0:df031b60ca29 193 chn->is_scan_element = true;
pcercuei 0:df031b60ca29 194 setup_scan_element(chn, n);
pcercuei 0:df031b60ca29 195 } else if (strcmp((char *) n->name, "text")) {
pcercuei 0:df031b60ca29 196 WARNING("Unknown children \'%s\' in <channel>\n",
pcercuei 0:df031b60ca29 197 n->name);
pcercuei 0:df031b60ca29 198 continue;
pcercuei 0:df031b60ca29 199 }
pcercuei 0:df031b60ca29 200 }
pcercuei 0:df031b60ca29 201
pcercuei 0:df031b60ca29 202 iio_channel_init_finalize(chn);
pcercuei 0:df031b60ca29 203
pcercuei 0:df031b60ca29 204 return chn;
pcercuei 0:df031b60ca29 205
pcercuei 0:df031b60ca29 206 err_free_channel:
pcercuei 0:df031b60ca29 207 free_channel(chn);
pcercuei 0:df031b60ca29 208 return NULL;
pcercuei 0:df031b60ca29 209 }
pcercuei 0:df031b60ca29 210
pcercuei 0:df031b60ca29 211 static struct iio_device * create_device(struct iio_context *ctx, xmlNode *n)
pcercuei 0:df031b60ca29 212 {
pcercuei 0:df031b60ca29 213 xmlAttr *attr;
pcercuei 0:df031b60ca29 214 struct iio_device *dev = zalloc(sizeof(*dev));
pcercuei 0:df031b60ca29 215 if (!dev)
pcercuei 0:df031b60ca29 216 return NULL;
pcercuei 0:df031b60ca29 217
pcercuei 0:df031b60ca29 218 dev->ctx = ctx;
pcercuei 0:df031b60ca29 219
pcercuei 0:df031b60ca29 220 for (attr = n->properties; attr; attr = attr->next) {
pcercuei 0:df031b60ca29 221 if (!strcmp((char *) attr->name, "name")) {
pcercuei 0:df031b60ca29 222 dev->name = iio_strdup(
pcercuei 0:df031b60ca29 223 (char *) attr->children->content);
pcercuei 0:df031b60ca29 224 } else if (!strcmp((char *) attr->name, "id")) {
pcercuei 0:df031b60ca29 225 dev->id = iio_strdup((char *) attr->children->content);
pcercuei 0:df031b60ca29 226 } else {
pcercuei 0:df031b60ca29 227 WARNING("Unknown attribute \'%s\' in <device>\n",
pcercuei 0:df031b60ca29 228 attr->name);
pcercuei 0:df031b60ca29 229 }
pcercuei 0:df031b60ca29 230 }
pcercuei 0:df031b60ca29 231
pcercuei 0:df031b60ca29 232 if (!dev->id) {
pcercuei 0:df031b60ca29 233 ERROR("Unable to read device ID\n");
pcercuei 0:df031b60ca29 234 goto err_free_device;
pcercuei 0:df031b60ca29 235 }
pcercuei 0:df031b60ca29 236
pcercuei 0:df031b60ca29 237 for (n = n->children; n; n = n->next) {
pcercuei 0:df031b60ca29 238 if (!strcmp((char *) n->name, "channel")) {
pcercuei 0:df031b60ca29 239 struct iio_channel **chns,
pcercuei 0:df031b60ca29 240 *chn = create_channel(dev, n);
pcercuei 0:df031b60ca29 241 if (!chn) {
pcercuei 0:df031b60ca29 242 ERROR("Unable to create channel\n");
pcercuei 0:df031b60ca29 243 goto err_free_device;
pcercuei 0:df031b60ca29 244 }
pcercuei 0:df031b60ca29 245
pcercuei 0:df031b60ca29 246 chns = realloc(dev->channels, (1 + dev->nb_channels) *
pcercuei 0:df031b60ca29 247 sizeof(struct iio_channel *));
pcercuei 0:df031b60ca29 248 if (!chns) {
pcercuei 0:df031b60ca29 249 ERROR("Unable to allocate memory\n");
pcercuei 0:df031b60ca29 250 free(chn);
pcercuei 0:df031b60ca29 251 goto err_free_device;
pcercuei 0:df031b60ca29 252 }
pcercuei 0:df031b60ca29 253
pcercuei 0:df031b60ca29 254 chns[dev->nb_channels++] = chn;
pcercuei 0:df031b60ca29 255 dev->channels = chns;
pcercuei 0:df031b60ca29 256 } else if (!strcmp((char *) n->name, "attribute")) {
pcercuei 0:df031b60ca29 257 if (add_attr_to_device(dev, n, false) < 0)
pcercuei 0:df031b60ca29 258 goto err_free_device;
pcercuei 0:df031b60ca29 259 } else if (!strcmp((char *) n->name, "debug-attribute")) {
pcercuei 0:df031b60ca29 260 if (add_attr_to_device(dev, n, true) < 0)
pcercuei 0:df031b60ca29 261 goto err_free_device;
pcercuei 0:df031b60ca29 262 } else if (strcmp((char *) n->name, "text")) {
pcercuei 0:df031b60ca29 263 WARNING("Unknown children \'%s\' in <device>\n",
pcercuei 0:df031b60ca29 264 n->name);
pcercuei 0:df031b60ca29 265 continue;
pcercuei 0:df031b60ca29 266 }
pcercuei 0:df031b60ca29 267 }
pcercuei 0:df031b60ca29 268
pcercuei 0:df031b60ca29 269 dev->words = (dev->nb_channels + 31) / 32;
pcercuei 0:df031b60ca29 270 if (dev->words) {
pcercuei 0:df031b60ca29 271 dev->mask = calloc(dev->words, sizeof(*dev->mask));
pcercuei 0:df031b60ca29 272 if (!dev->mask) {
pcercuei 0:df031b60ca29 273 errno = ENOMEM;
pcercuei 0:df031b60ca29 274 goto err_free_device;
pcercuei 0:df031b60ca29 275 }
pcercuei 0:df031b60ca29 276 }
pcercuei 0:df031b60ca29 277
pcercuei 0:df031b60ca29 278 return dev;
pcercuei 0:df031b60ca29 279
pcercuei 0:df031b60ca29 280 err_free_device:
pcercuei 0:df031b60ca29 281 free_device(dev);
pcercuei 0:df031b60ca29 282 return NULL;
pcercuei 0:df031b60ca29 283 }
pcercuei 0:df031b60ca29 284
pcercuei 0:df031b60ca29 285 static struct iio_context * xml_clone(const struct iio_context *ctx)
pcercuei 0:df031b60ca29 286 {
pcercuei 0:df031b60ca29 287 return xml_create_context_mem(ctx->xml, strlen(ctx->xml));
pcercuei 0:df031b60ca29 288 }
pcercuei 0:df031b60ca29 289
pcercuei 0:df031b60ca29 290 static const struct iio_backend_ops xml_ops = {
pcercuei 0:df031b60ca29 291 .clone = xml_clone,
pcercuei 0:df031b60ca29 292 };
pcercuei 0:df031b60ca29 293
pcercuei 3:d147beabba0e 294 static int parse_context_attr(struct iio_context *ctx, xmlNode *n)
pcercuei 3:d147beabba0e 295 {
pcercuei 3:d147beabba0e 296 xmlAttr *attr;
pcercuei 3:d147beabba0e 297 const char *name = NULL, *value = NULL;
pcercuei 3:d147beabba0e 298
pcercuei 3:d147beabba0e 299 for (attr = n->properties; attr; attr = attr->next) {
pcercuei 3:d147beabba0e 300 if (!strcmp((const char *) attr->name, "name")) {
pcercuei 3:d147beabba0e 301 name = (const char *) attr->children->content;
pcercuei 3:d147beabba0e 302 } else if (!strcmp((const char *) attr->name, "value")) {
pcercuei 3:d147beabba0e 303 value = (const char *) attr->children->content;
pcercuei 3:d147beabba0e 304 }
pcercuei 3:d147beabba0e 305 }
pcercuei 3:d147beabba0e 306
pcercuei 3:d147beabba0e 307 if (!name || !value)
pcercuei 3:d147beabba0e 308 return -EINVAL;
pcercuei 3:d147beabba0e 309 else
pcercuei 3:d147beabba0e 310 return iio_context_add_attr(ctx, name, value);
pcercuei 3:d147beabba0e 311 }
pcercuei 3:d147beabba0e 312
pcercuei 0:df031b60ca29 313 static struct iio_context * iio_create_xml_context_helper(xmlDoc *doc)
pcercuei 0:df031b60ca29 314 {
pcercuei 0:df031b60ca29 315 unsigned int i;
pcercuei 0:df031b60ca29 316 xmlNode *root, *n;
pcercuei 0:df031b60ca29 317 xmlAttr *attr;
pcercuei 3:d147beabba0e 318 int err = -ENOMEM;
pcercuei 0:df031b60ca29 319 struct iio_context *ctx = zalloc(sizeof(*ctx));
pcercuei 0:df031b60ca29 320 if (!ctx)
pcercuei 0:df031b60ca29 321 goto err_set_errno;
pcercuei 0:df031b60ca29 322
pcercuei 0:df031b60ca29 323 ctx->name = "xml";
pcercuei 0:df031b60ca29 324 ctx->ops = &xml_ops;
pcercuei 0:df031b60ca29 325
pcercuei 0:df031b60ca29 326 root = xmlDocGetRootElement(doc);
pcercuei 0:df031b60ca29 327 if (strcmp((char *) root->name, "context")) {
pcercuei 0:df031b60ca29 328 ERROR("Unrecognized XML file\n");
pcercuei 3:d147beabba0e 329 err = -EINVAL;
pcercuei 0:df031b60ca29 330 goto err_free_ctx;
pcercuei 0:df031b60ca29 331 }
pcercuei 0:df031b60ca29 332
pcercuei 0:df031b60ca29 333 for (attr = root->properties; attr; attr = attr->next) {
pcercuei 0:df031b60ca29 334 if (!strcmp((char *) attr->name, "description"))
pcercuei 0:df031b60ca29 335 ctx->description = iio_strdup(
pcercuei 0:df031b60ca29 336 (char *) attr->children->content);
pcercuei 0:df031b60ca29 337 else if (strcmp((char *) attr->name, "name"))
pcercuei 0:df031b60ca29 338 WARNING("Unknown parameter \'%s\' in <context>\n",
pcercuei 0:df031b60ca29 339 (char *) attr->children->content);
pcercuei 0:df031b60ca29 340 }
pcercuei 0:df031b60ca29 341
pcercuei 0:df031b60ca29 342 for (n = root->children; n; n = n->next) {
pcercuei 0:df031b60ca29 343 struct iio_device **devs, *dev;
pcercuei 0:df031b60ca29 344
pcercuei 3:d147beabba0e 345 if (!strcmp((char *) n->name, "context-attribute")) {
pcercuei 3:d147beabba0e 346 err = parse_context_attr(ctx, n);
pcercuei 3:d147beabba0e 347 if (err)
pcercuei 3:d147beabba0e 348 goto err_free_devices;
pcercuei 3:d147beabba0e 349 else
pcercuei 3:d147beabba0e 350 continue;
pcercuei 3:d147beabba0e 351 } else if (strcmp((char *) n->name, "device")) {
pcercuei 0:df031b60ca29 352 if (strcmp((char *) n->name, "text"))
pcercuei 0:df031b60ca29 353 WARNING("Unknown children \'%s\' in "
pcercuei 0:df031b60ca29 354 "<context>\n", n->name);
pcercuei 0:df031b60ca29 355 continue;
pcercuei 0:df031b60ca29 356 }
pcercuei 0:df031b60ca29 357
pcercuei 0:df031b60ca29 358 dev = create_device(ctx, n);
pcercuei 0:df031b60ca29 359 if (!dev) {
pcercuei 0:df031b60ca29 360 ERROR("Unable to create device\n");
pcercuei 0:df031b60ca29 361 goto err_free_devices;
pcercuei 0:df031b60ca29 362 }
pcercuei 0:df031b60ca29 363
pcercuei 0:df031b60ca29 364 devs = realloc(ctx->devices, (1 + ctx->nb_devices) *
pcercuei 0:df031b60ca29 365 sizeof(struct iio_device *));
pcercuei 0:df031b60ca29 366 if (!devs) {
pcercuei 0:df031b60ca29 367 ERROR("Unable to allocate memory\n");
pcercuei 0:df031b60ca29 368 free(dev);
pcercuei 0:df031b60ca29 369 goto err_free_devices;
pcercuei 0:df031b60ca29 370 }
pcercuei 0:df031b60ca29 371
pcercuei 0:df031b60ca29 372 devs[ctx->nb_devices++] = dev;
pcercuei 0:df031b60ca29 373 ctx->devices = devs;
pcercuei 0:df031b60ca29 374 }
pcercuei 0:df031b60ca29 375
pcercuei 0:df031b60ca29 376 err = iio_context_init(ctx);
pcercuei 0:df031b60ca29 377 if (err)
pcercuei 0:df031b60ca29 378 goto err_free_devices;
pcercuei 0:df031b60ca29 379
pcercuei 0:df031b60ca29 380 return ctx;
pcercuei 0:df031b60ca29 381
pcercuei 0:df031b60ca29 382 err_free_devices:
pcercuei 0:df031b60ca29 383 for (i = 0; i < ctx->nb_devices; i++)
pcercuei 0:df031b60ca29 384 free_device(ctx->devices[i]);
pcercuei 0:df031b60ca29 385 if (ctx->nb_devices)
pcercuei 0:df031b60ca29 386 free(ctx->devices);
pcercuei 3:d147beabba0e 387 for (i = 0; i < ctx->nb_attrs; i++) {
pcercuei 3:d147beabba0e 388 free(ctx->attrs[i]);
pcercuei 3:d147beabba0e 389 free(ctx->values[i]);
pcercuei 3:d147beabba0e 390 }
pcercuei 3:d147beabba0e 391 free(ctx->attrs);
pcercuei 3:d147beabba0e 392 free(ctx->values);
pcercuei 0:df031b60ca29 393 err_free_ctx:
pcercuei 0:df031b60ca29 394 free(ctx);
pcercuei 0:df031b60ca29 395 err_set_errno:
pcercuei 3:d147beabba0e 396 errno = -err;
pcercuei 0:df031b60ca29 397 return NULL;
pcercuei 0:df031b60ca29 398 }
pcercuei 0:df031b60ca29 399
pcercuei 0:df031b60ca29 400 struct iio_context * xml_create_context(const char *xml_file)
pcercuei 0:df031b60ca29 401 {
pcercuei 0:df031b60ca29 402 struct iio_context *ctx;
pcercuei 0:df031b60ca29 403 xmlDoc *doc;
pcercuei 0:df031b60ca29 404
pcercuei 0:df031b60ca29 405 LIBXML_TEST_VERSION;
pcercuei 0:df031b60ca29 406
pcercuei 0:df031b60ca29 407 doc = xmlReadFile(xml_file, NULL, XML_PARSE_DTDVALID);
pcercuei 0:df031b60ca29 408 if (!doc) {
pcercuei 0:df031b60ca29 409 ERROR("Unable to parse XML file\n");
pcercuei 3:d147beabba0e 410 errno = EINVAL;
pcercuei 0:df031b60ca29 411 return NULL;
pcercuei 0:df031b60ca29 412 }
pcercuei 0:df031b60ca29 413
pcercuei 0:df031b60ca29 414 ctx = iio_create_xml_context_helper(doc);
pcercuei 0:df031b60ca29 415 xmlFreeDoc(doc);
pcercuei 0:df031b60ca29 416 return ctx;
pcercuei 0:df031b60ca29 417 }
pcercuei 0:df031b60ca29 418
pcercuei 0:df031b60ca29 419 struct iio_context * xml_create_context_mem(const char *xml, size_t len)
pcercuei 0:df031b60ca29 420 {
pcercuei 0:df031b60ca29 421 struct iio_context *ctx;
pcercuei 0:df031b60ca29 422 xmlDoc *doc;
pcercuei 0:df031b60ca29 423
pcercuei 0:df031b60ca29 424 LIBXML_TEST_VERSION;
pcercuei 0:df031b60ca29 425
pcercuei 0:df031b60ca29 426 doc = xmlReadMemory(xml, (int) len, NULL, NULL, XML_PARSE_DTDVALID);
pcercuei 0:df031b60ca29 427 if (!doc) {
pcercuei 0:df031b60ca29 428 ERROR("Unable to parse XML file\n");
pcercuei 3:d147beabba0e 429 errno = EINVAL;
pcercuei 0:df031b60ca29 430 return NULL;
pcercuei 0:df031b60ca29 431 }
pcercuei 0:df031b60ca29 432
pcercuei 0:df031b60ca29 433 ctx = iio_create_xml_context_helper(doc);
pcercuei 0:df031b60ca29 434 xmlFreeDoc(doc);
pcercuei 0:df031b60ca29 435 return ctx;
pcercuei 0:df031b60ca29 436 }
pcercuei 0:df031b60ca29 437