blob: 60edee38d2fe586db2e4bc957e830b78e83561a1 [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
Paul Cercueil8f56ea72014-10-28 15:18:18 +010025#ifdef _WIN32
26#define LOCAL_BACKEND 0
27#define NETWORK_BACKEND 1
28#endif
29
Paul Cercueil42090d12014-02-24 12:32:23 +010030static const char xml_header[] = "<?xml version=\"1.0\" encoding=\"utf-8\"?>"
31"<!DOCTYPE context ["
32"<!ELEMENT context (device)*>"
Paul Cercueild9d9f9f2014-04-15 10:08:17 +020033"<!ELEMENT device (channel | attribute | debug-attribute)*>"
Paul Cercueila7e80022014-06-11 11:41:26 +020034"<!ELEMENT channel (scan-element?, attribute*)>"
Paul Cercueil42090d12014-02-24 12:32:23 +010035"<!ELEMENT attribute EMPTY>"
Paul Cercueila7e80022014-06-11 11:41:26 +020036"<!ELEMENT scan-element EMPTY>"
Paul Cercueild9d9f9f2014-04-15 10:08:17 +020037"<!ELEMENT debug-attribute EMPTY>"
Paul Cercueil87350372015-03-16 13:24:37 +010038"<!ATTLIST context name CDATA #REQUIRED description CDATA #IMPLIED>"
Paul Cercueil42090d12014-02-24 12:32:23 +010039"<!ATTLIST device id CDATA #REQUIRED name CDATA #IMPLIED>"
Paul Cercueila7e80022014-06-11 11:41:26 +020040"<!ATTLIST channel id CDATA #REQUIRED type (input|output) #REQUIRED name CDATA #IMPLIED>"
41"<!ATTLIST scan-element index CDATA #REQUIRED format CDATA #REQUIRED scale CDATA #IMPLIED>"
Paul Cercueil42d12352014-05-05 16:11:58 +020042"<!ATTLIST attribute name CDATA #REQUIRED filename CDATA #IMPLIED>"
Paul Cercueild9d9f9f2014-04-15 10:08:17 +020043"<!ATTLIST debug-attribute name CDATA #REQUIRED>"
Paul Cercueil42090d12014-02-24 12:32:23 +010044"]>";
45
46/* Returns a string containing the XML representation of this context */
Paul Cercueilc1ed8482014-06-11 16:29:43 +020047char * iio_context_create_xml(const struct iio_context *ctx)
Paul Cercueil42090d12014-02-24 12:32:23 +010048{
Paul Cercueil87350372015-03-16 13:24:37 +010049 size_t len, *devices_len;
Paul Cercueil5822ab62014-04-04 13:29:17 +020050 char *str, *ptr, **devices;
Paul Cercueil42090d12014-02-24 12:32:23 +010051 unsigned int i;
52
Paul Cercueil87350372015-03-16 13:24:37 +010053 len = strlen(ctx->name) + sizeof(xml_header) - 1 +
54 sizeof("<context name=\"\" ></context>");
55 if (ctx->description)
56 len += strlen(ctx->description) +
57 sizeof(" description=\"\"") - 1;
58
Paul Cercueil9aab0192014-04-07 11:04:30 +020059 if (!ctx->nb_devices) {
60 str = malloc(len);
Paul Cercueildfeca0d2015-03-16 17:18:00 +010061 if (!str) {
62 errno = ENOMEM;
Paul Cercueil87350372015-03-16 13:24:37 +010063 return NULL;
Paul Cercueildfeca0d2015-03-16 17:18:00 +010064 }
Paul Cercueil87350372015-03-16 13:24:37 +010065
66 if (ctx->description)
67 snprintf(str, len, "%s<context name=\"%s\" "
68 "description=\"%s\" ></context>",
69 xml_header, ctx->name,
70 ctx->description);
71 else
Paul Cercueil9aab0192014-04-07 11:04:30 +020072 snprintf(str, len, "%s<context name=\"%s\" ></context>",
73 xml_header, ctx->name);
74 return str;
75 }
76
Paul Cercueil5822ab62014-04-04 13:29:17 +020077 devices_len = malloc(ctx->nb_devices * sizeof(*devices_len));
Paul Cercueildfeca0d2015-03-16 17:18:00 +010078 if (!devices_len) {
79 errno = ENOMEM;
Paul Cercueil5822ab62014-04-04 13:29:17 +020080 return NULL;
Paul Cercueildfeca0d2015-03-16 17:18:00 +010081 }
Paul Cercueil5822ab62014-04-04 13:29:17 +020082
83 devices = malloc(ctx->nb_devices * sizeof(*devices));
84 if (!devices)
85 goto err_free_devices_len;
86
Paul Cercueil42090d12014-02-24 12:32:23 +010087 for (i = 0; i < ctx->nb_devices; i++) {
88 char *xml = iio_device_get_xml(ctx->devices[i],
89 &devices_len[i]);
90 if (!xml)
91 goto err_free_devices;
92 devices[i] = xml;
93 len += devices_len[i];
94 }
95
96 str = malloc(len);
Paul Cercueildfeca0d2015-03-16 17:18:00 +010097 if (!str) {
98 errno = ENOMEM;
Paul Cercueil42090d12014-02-24 12:32:23 +010099 goto err_free_devices;
Paul Cercueildfeca0d2015-03-16 17:18:00 +0100100 }
Paul Cercueil42090d12014-02-24 12:32:23 +0100101
Paul Cercueil87350372015-03-16 13:24:37 +0100102 if (ctx->description)
103 snprintf(str, len, "%s<context name=\"%s\" "
104 "description=\"%s\" >",
105 xml_header, ctx->name, ctx->description);
106 else
107 snprintf(str, len, "%s<context name=\"%s\" >",
108 xml_header, ctx->name);
Paul Cercueil42090d12014-02-24 12:32:23 +0100109 ptr = strrchr(str, '\0');
110
111 for (i = 0; i < ctx->nb_devices; i++) {
112 strcpy(ptr, devices[i]);
113 ptr += devices_len[i];
114 free(devices[i]);
115 }
116
Paul Cercueil5822ab62014-04-04 13:29:17 +0200117 free(devices);
118 free(devices_len);
Paul Cercueil42090d12014-02-24 12:32:23 +0100119 strcpy(ptr, "</context>");
120 return str;
121
122err_free_devices:
123 while (i--)
124 free(devices[i]);
Paul Cercueil5822ab62014-04-04 13:29:17 +0200125 free(devices);
126err_free_devices_len:
127 free(devices_len);
Paul Cercueil42090d12014-02-24 12:32:23 +0100128 return NULL;
129}
130
Paul Cercueil4c6729d2014-04-04 17:24:41 +0200131const char * iio_context_get_xml(const struct iio_context *ctx)
132{
133 return ctx->xml;
134}
135
Paul Cercueil0b2ce712014-02-17 15:04:18 +0100136const char * iio_context_get_name(const struct iio_context *ctx)
137{
138 return ctx->name;
139}
140
Paul Cercueil3ac36c12015-01-08 14:44:00 +0100141const char * iio_context_get_description(const struct iio_context *ctx)
142{
143 if (ctx->description)
144 return ctx->description;
145 else
146 return "";
147}
148
Paul Cercueil0b2ce712014-02-17 15:04:18 +0100149void iio_context_destroy(struct iio_context *ctx)
150{
Paul Cercueil50363542014-02-18 16:04:28 +0100151 unsigned int i;
152 if (ctx->ops->shutdown)
153 ctx->ops->shutdown(ctx);
154
155 for (i = 0; i < ctx->nb_devices; i++)
156 free_device(ctx->devices[i]);
157 if (ctx->nb_devices)
158 free(ctx->devices);
Paul Cercueil4c6729d2014-04-04 17:24:41 +0200159 if (ctx->xml)
160 free(ctx->xml);
Paul Cercueil3ac36c12015-01-08 14:44:00 +0100161 if (ctx->description)
162 free(ctx->description);
Paul Cercueil0b2ce712014-02-17 15:04:18 +0100163 free(ctx);
164}
165
166unsigned int iio_context_get_devices_count(const struct iio_context *ctx)
167{
168 return ctx->nb_devices;
169}
170
171struct iio_device * iio_context_get_device(const struct iio_context *ctx,
172 unsigned int index)
173{
174 if (index >= ctx->nb_devices)
175 return NULL;
176 else
177 return ctx->devices[index];
178}
Paul Cercueilae88fde2014-03-12 11:47:10 +0100179
Paul Cercueil17512b02014-03-28 11:15:24 +0100180struct iio_device * iio_context_find_device(const struct iio_context *ctx,
181 const char *name)
182{
183 unsigned int i;
184 for (i = 0; i < ctx->nb_devices; i++) {
185 struct iio_device *dev = ctx->devices[i];
186 if (!strcmp(dev->id, name) ||
187 (dev->name && !strcmp(dev->name, name)))
188 return dev;
189 }
190 return NULL;
191}
192
Paul Cercueil1f7bc152014-03-14 13:48:43 +0100193static void reorder_channels(struct iio_device *dev)
194{
195 bool found;
196 unsigned int i;
197
198 /* Reorder channels by index */
199 do {
200 found = false;
201 for (i = 1; i < dev->nb_channels; i++) {
202 struct iio_channel **channels = dev->channels;
203 long ch1 = channels[i - 1]->index;
204 long ch2 = channels[i]->index;
205
206 if (ch2 >= 0 && ((ch1 > ch2) || ch1 < 0)) {
207 struct iio_channel *bak = channels[i];
208 channels[i] = channels[i - 1];
209 channels[i - 1] = bak;
210 found = true;
211 }
212 }
213 } while (found);
214}
215
Paul Cercueilc1ed8482014-06-11 16:29:43 +0200216void iio_context_init(struct iio_context *ctx)
Paul Cercueilae88fde2014-03-12 11:47:10 +0100217{
218 unsigned int i;
Paul Cercueila7e80022014-06-11 11:41:26 +0200219 for (i = 0; i < ctx->nb_devices; i++)
220 reorder_channels(ctx->devices[i]);
Paul Cercueilae88fde2014-03-12 11:47:10 +0100221}
Paul Cercueile45f8762014-05-02 11:19:26 +0200222
223int iio_context_get_version(const struct iio_context *ctx,
Paul Cercueil9de9e9d2014-05-20 13:18:19 +0200224 unsigned int *major, unsigned int *minor, char git_tag[8])
Paul Cercueile45f8762014-05-02 11:19:26 +0200225{
226 if (ctx->ops->get_version)
Paul Cercueil9de9e9d2014-05-20 13:18:19 +0200227 return ctx->ops->get_version(ctx, major, minor, git_tag);
Paul Cercueil53ed9432014-11-20 13:46:04 +0100228
229 iio_library_get_version(major, minor, git_tag);
Paul Cercueile45f8762014-05-02 11:19:26 +0200230 return 0;
231}
Paul Cercueil4ca73542014-06-10 16:23:29 +0200232
233int iio_context_set_timeout(struct iio_context *ctx, unsigned int timeout)
234{
235 if (ctx->ops->set_timeout)
236 return ctx->ops->set_timeout(ctx, timeout);
237 else
238 return -ENOSYS;
239}
Paul Cercueil63d5e7c2014-10-28 14:33:08 +0100240
241struct iio_context * iio_context_clone(const struct iio_context *ctx)
242{
Paul Cercueildfeca0d2015-03-16 17:18:00 +0100243 if (ctx->ops->clone) {
Paul Cercueil63d5e7c2014-10-28 14:33:08 +0100244 return ctx->ops->clone(ctx);
Paul Cercueildfeca0d2015-03-16 17:18:00 +0100245 } else {
246 errno = ENOSYS;
Paul Cercueil63d5e7c2014-10-28 14:33:08 +0100247 return NULL;
Paul Cercueildfeca0d2015-03-16 17:18:00 +0100248 }
Paul Cercueil63d5e7c2014-10-28 14:33:08 +0100249}
Paul Cercueil8f56ea72014-10-28 15:18:18 +0100250
251struct iio_context * iio_create_default_context(void)
252{
253#if NETWORK_BACKEND
254 char *hostname = getenv("IIOD_REMOTE");
255
256 if (hostname) {
257 /* If the environment variable is an empty string, we will
258 * discover the server using ZeroConf */
259 if (strlen(hostname) == 0)
260 hostname = NULL;
261
262 return iio_create_network_context(hostname);
263 }
264#endif
Paul Cercueil8f56ea72014-10-28 15:18:18 +0100265 return iio_create_local_context();
Paul Cercueil63e52182014-12-11 12:52:48 +0100266}
267
268struct iio_context * iio_create_local_context(void)
269{
270#if LOCAL_BACKEND
271 return local_create_context();
272#else
Paul Cercueildfeca0d2015-03-16 17:18:00 +0100273 errno = ENOSYS;
Paul Cercueil63e52182014-12-11 12:52:48 +0100274 return NULL;
275#endif
276}
277
278struct iio_context * iio_create_network_context(const char *hostname)
279{
280#if NETWORK_BACKEND
281 return network_create_context(hostname);
282#else
Paul Cercueildfeca0d2015-03-16 17:18:00 +0100283 errno = ENOSYS;
Paul Cercueil63e52182014-12-11 12:52:48 +0100284 return NULL;
285#endif
286}
287
288struct iio_context * iio_create_xml_context_mem(const char *xml, size_t len)
289{
290#if NETWORK_BACKEND
291 return xml_create_context_mem(xml, len);
292#else
Paul Cercueildfeca0d2015-03-16 17:18:00 +0100293 errno = ENOSYS;
Paul Cercueil63e52182014-12-11 12:52:48 +0100294 return NULL;
295#endif
296}
297
298struct iio_context * iio_create_xml_context(const char *xml_file)
299{
300#if NETWORK_BACKEND
301 return xml_create_context(xml_file);
Paul Cercueil8f56ea72014-10-28 15:18:18 +0100302#else
Paul Cercueildfeca0d2015-03-16 17:18:00 +0100303 errno = ENOSYS;
Paul Cercueil8f56ea72014-10-28 15:18:18 +0100304 return NULL;
305#endif
306}