blob: e1639cad715261c5a1533c490698d6a39a3eaf26 [file] [log] [blame]
Paul Cercueilbb4401d2014-02-28 16:10:49 +01001/*
2 * libiio - Library for interfacing industrial I/O (IIO) devices
3 *
4 * Copyright (C) 2014 Analog Devices, Inc.
5 * Author: Paul Cercueil <paul.cercueil@analog.com>
6 *
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
11 *
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
16 *
17 * */
18
Paul Cercueil42090d12014-02-24 12:32:23 +010019#include "debug.h"
Paul Cercueil0b2ce712014-02-17 15:04:18 +010020#include "iio-private.h"
21
Paul Cercueil4c6729d2014-04-04 17:24:41 +020022#include <errno.h>
Paul Cercueil42090d12014-02-24 12:32:23 +010023#include <string.h>
24
25static const char xml_header[] = "<?xml version=\"1.0\" encoding=\"utf-8\"?>"
26"<!DOCTYPE context ["
27"<!ELEMENT context (device)*>"
Paul Cercueild9d9f9f2014-04-15 10:08:17 +020028"<!ELEMENT device (channel | attribute | debug-attribute)*>"
Paul Cercueila7e80022014-06-11 11:41:26 +020029"<!ELEMENT channel (scan-element?, attribute*)>"
Paul Cercueil42090d12014-02-24 12:32:23 +010030"<!ELEMENT attribute EMPTY>"
Paul Cercueila7e80022014-06-11 11:41:26 +020031"<!ELEMENT scan-element EMPTY>"
Paul Cercueild9d9f9f2014-04-15 10:08:17 +020032"<!ELEMENT debug-attribute EMPTY>"
Paul Cercueil42090d12014-02-24 12:32:23 +010033"<!ATTLIST context name CDATA #REQUIRED>"
34"<!ATTLIST device id CDATA #REQUIRED name CDATA #IMPLIED>"
Paul Cercueila7e80022014-06-11 11:41:26 +020035"<!ATTLIST channel id CDATA #REQUIRED type (input|output) #REQUIRED name CDATA #IMPLIED>"
36"<!ATTLIST scan-element index CDATA #REQUIRED format CDATA #REQUIRED scale CDATA #IMPLIED>"
Paul Cercueil42d12352014-05-05 16:11:58 +020037"<!ATTLIST attribute name CDATA #REQUIRED filename CDATA #IMPLIED>"
Paul Cercueild9d9f9f2014-04-15 10:08:17 +020038"<!ATTLIST debug-attribute name CDATA #REQUIRED>"
Paul Cercueil42090d12014-02-24 12:32:23 +010039"]>";
40
41/* Returns a string containing the XML representation of this context */
Paul Cercueilc1ed8482014-06-11 16:29:43 +020042char * iio_context_create_xml(const struct iio_context *ctx)
Paul Cercueil42090d12014-02-24 12:32:23 +010043{
Paul Cercueil9aab0192014-04-07 11:04:30 +020044 size_t len = strlen(ctx->name) + sizeof(xml_header) - 1 +
Paul Cercueil42090d12014-02-24 12:32:23 +010045 sizeof("<context name=\"\" ></context>");
Paul Cercueil5822ab62014-04-04 13:29:17 +020046 size_t *devices_len;
47 char *str, *ptr, **devices;
Paul Cercueil42090d12014-02-24 12:32:23 +010048 unsigned int i;
49
Paul Cercueil9aab0192014-04-07 11:04:30 +020050 if (!ctx->nb_devices) {
51 str = malloc(len);
52 if (str)
53 snprintf(str, len, "%s<context name=\"%s\" ></context>",
54 xml_header, ctx->name);
55 return str;
56 }
57
Paul Cercueil5822ab62014-04-04 13:29:17 +020058 devices_len = malloc(ctx->nb_devices * sizeof(*devices_len));
59 if (!devices_len)
60 return NULL;
61
62 devices = malloc(ctx->nb_devices * sizeof(*devices));
63 if (!devices)
64 goto err_free_devices_len;
65
Paul Cercueil42090d12014-02-24 12:32:23 +010066 for (i = 0; i < ctx->nb_devices; i++) {
67 char *xml = iio_device_get_xml(ctx->devices[i],
68 &devices_len[i]);
69 if (!xml)
70 goto err_free_devices;
71 devices[i] = xml;
72 len += devices_len[i];
73 }
74
75 str = malloc(len);
76 if (!str)
77 goto err_free_devices;
78
Paul Cercueil8c29e412014-04-07 09:46:45 +020079 snprintf(str, len, "%s<context name=\"%s\" >", xml_header, ctx->name);
Paul Cercueil42090d12014-02-24 12:32:23 +010080 ptr = strrchr(str, '\0');
81
82 for (i = 0; i < ctx->nb_devices; i++) {
83 strcpy(ptr, devices[i]);
84 ptr += devices_len[i];
85 free(devices[i]);
86 }
87
Paul Cercueil5822ab62014-04-04 13:29:17 +020088 free(devices);
89 free(devices_len);
Paul Cercueil42090d12014-02-24 12:32:23 +010090 strcpy(ptr, "</context>");
91 return str;
92
93err_free_devices:
94 while (i--)
95 free(devices[i]);
Paul Cercueil5822ab62014-04-04 13:29:17 +020096 free(devices);
97err_free_devices_len:
98 free(devices_len);
Paul Cercueil42090d12014-02-24 12:32:23 +010099 return NULL;
100}
101
Paul Cercueil4c6729d2014-04-04 17:24:41 +0200102const char * iio_context_get_xml(const struct iio_context *ctx)
103{
104 return ctx->xml;
105}
106
Paul Cercueil0b2ce712014-02-17 15:04:18 +0100107const char * iio_context_get_name(const struct iio_context *ctx)
108{
109 return ctx->name;
110}
111
112void iio_context_destroy(struct iio_context *ctx)
113{
Paul Cercueil50363542014-02-18 16:04:28 +0100114 unsigned int i;
115 if (ctx->ops->shutdown)
116 ctx->ops->shutdown(ctx);
117
118 for (i = 0; i < ctx->nb_devices; i++)
119 free_device(ctx->devices[i]);
120 if (ctx->nb_devices)
121 free(ctx->devices);
Paul Cercueil4c6729d2014-04-04 17:24:41 +0200122 if (ctx->xml)
123 free(ctx->xml);
Paul Cercueil0b2ce712014-02-17 15:04:18 +0100124 free(ctx);
125}
126
127unsigned int iio_context_get_devices_count(const struct iio_context *ctx)
128{
129 return ctx->nb_devices;
130}
131
132struct iio_device * iio_context_get_device(const struct iio_context *ctx,
133 unsigned int index)
134{
135 if (index >= ctx->nb_devices)
136 return NULL;
137 else
138 return ctx->devices[index];
139}
Paul Cercueilae88fde2014-03-12 11:47:10 +0100140
Paul Cercueil17512b02014-03-28 11:15:24 +0100141struct iio_device * iio_context_find_device(const struct iio_context *ctx,
142 const char *name)
143{
144 unsigned int i;
145 for (i = 0; i < ctx->nb_devices; i++) {
146 struct iio_device *dev = ctx->devices[i];
147 if (!strcmp(dev->id, name) ||
148 (dev->name && !strcmp(dev->name, name)))
149 return dev;
150 }
151 return NULL;
152}
153
Paul Cercueil1f7bc152014-03-14 13:48:43 +0100154static void reorder_channels(struct iio_device *dev)
155{
156 bool found;
157 unsigned int i;
158
159 /* Reorder channels by index */
160 do {
161 found = false;
162 for (i = 1; i < dev->nb_channels; i++) {
163 struct iio_channel **channels = dev->channels;
164 long ch1 = channels[i - 1]->index;
165 long ch2 = channels[i]->index;
166
167 if (ch2 >= 0 && ((ch1 > ch2) || ch1 < 0)) {
168 struct iio_channel *bak = channels[i];
169 channels[i] = channels[i - 1];
170 channels[i - 1] = bak;
171 found = true;
172 }
173 }
174 } while (found);
175}
176
Paul Cercueilc1ed8482014-06-11 16:29:43 +0200177void iio_context_init(struct iio_context *ctx)
Paul Cercueilae88fde2014-03-12 11:47:10 +0100178{
179 unsigned int i;
Paul Cercueila7e80022014-06-11 11:41:26 +0200180 for (i = 0; i < ctx->nb_devices; i++)
181 reorder_channels(ctx->devices[i]);
Paul Cercueilae88fde2014-03-12 11:47:10 +0100182}
Paul Cercueile45f8762014-05-02 11:19:26 +0200183
184int iio_context_get_version(const struct iio_context *ctx,
Paul Cercueil9de9e9d2014-05-20 13:18:19 +0200185 unsigned int *major, unsigned int *minor, char git_tag[8])
Paul Cercueile45f8762014-05-02 11:19:26 +0200186{
187 if (ctx->ops->get_version)
Paul Cercueil9de9e9d2014-05-20 13:18:19 +0200188 return ctx->ops->get_version(ctx, major, minor, git_tag);
Paul Cercueild15d9952014-05-20 11:40:08 +0200189 if (major)
190 *major = LIBIIO_VERSION_MAJOR;
191 if (minor)
192 *minor = LIBIIO_VERSION_MINOR;
Paul Cercueil9de9e9d2014-05-20 13:18:19 +0200193 if (git_tag) {
194 strncpy(git_tag, LIBIIO_VERSION_GIT, 8);
195 git_tag[7] = '\0';
196 }
Paul Cercueile45f8762014-05-02 11:19:26 +0200197 return 0;
198}
Paul Cercueil4ca73542014-06-10 16:23:29 +0200199
200int iio_context_set_timeout(struct iio_context *ctx, unsigned int timeout)
201{
202 if (ctx->ops->set_timeout)
203 return ctx->ops->set_timeout(ctx, timeout);
204 else
205 return -ENOSYS;
206}