blob: 0db4cffb4595ef114b5347ab12a9103c6f19d094 [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
Lars-Peter Clausen75baa4d2016-02-01 17:58:57 +0100206 if (ch1 == ch2 && ch1 >= 0) {
207 ch1 = channels[i - 1]->format.shift;
208 ch2 = channels[i]->format.shift;
209 }
210
Paul Cercueil1f7bc152014-03-14 13:48:43 +0100211 if (ch2 >= 0 && ((ch1 > ch2) || ch1 < 0)) {
212 struct iio_channel *bak = channels[i];
213 channels[i] = channels[i - 1];
214 channels[i - 1] = bak;
215 found = true;
216 }
217 }
218 } while (found);
219}
220
Paul Cercueilfd387472015-08-05 10:34:19 +0200221int iio_context_init(struct iio_context *ctx)
Paul Cercueilae88fde2014-03-12 11:47:10 +0100222{
223 unsigned int i;
Paul Cercueilfd387472015-08-05 10:34:19 +0200224
Paul Cercueila7e80022014-06-11 11:41:26 +0200225 for (i = 0; i < ctx->nb_devices; i++)
226 reorder_channels(ctx->devices[i]);
Paul Cercueilfd387472015-08-05 10:34:19 +0200227
228 if (!ctx->xml) {
229 ctx->xml = iio_context_create_xml(ctx);
230 if (!ctx->xml)
231 return -ENOMEM;
232 }
233
234 return 0;
Paul Cercueilae88fde2014-03-12 11:47:10 +0100235}
Paul Cercueile45f8762014-05-02 11:19:26 +0200236
237int iio_context_get_version(const struct iio_context *ctx,
Paul Cercueil9de9e9d2014-05-20 13:18:19 +0200238 unsigned int *major, unsigned int *minor, char git_tag[8])
Paul Cercueile45f8762014-05-02 11:19:26 +0200239{
240 if (ctx->ops->get_version)
Paul Cercueil9de9e9d2014-05-20 13:18:19 +0200241 return ctx->ops->get_version(ctx, major, minor, git_tag);
Paul Cercueil53ed9432014-11-20 13:46:04 +0100242
243 iio_library_get_version(major, minor, git_tag);
Paul Cercueile45f8762014-05-02 11:19:26 +0200244 return 0;
245}
Paul Cercueil4ca73542014-06-10 16:23:29 +0200246
247int iio_context_set_timeout(struct iio_context *ctx, unsigned int timeout)
248{
249 if (ctx->ops->set_timeout)
250 return ctx->ops->set_timeout(ctx, timeout);
251 else
252 return -ENOSYS;
253}
Paul Cercueil63d5e7c2014-10-28 14:33:08 +0100254
255struct iio_context * iio_context_clone(const struct iio_context *ctx)
256{
Paul Cercueildfeca0d2015-03-16 17:18:00 +0100257 if (ctx->ops->clone) {
Paul Cercueil63d5e7c2014-10-28 14:33:08 +0100258 return ctx->ops->clone(ctx);
Paul Cercueildfeca0d2015-03-16 17:18:00 +0100259 } else {
260 errno = ENOSYS;
Paul Cercueil63d5e7c2014-10-28 14:33:08 +0100261 return NULL;
Paul Cercueildfeca0d2015-03-16 17:18:00 +0100262 }
Paul Cercueil63d5e7c2014-10-28 14:33:08 +0100263}
Paul Cercueil8f56ea72014-10-28 15:18:18 +0100264
Lars-Peter Clausen60f1c9a2016-02-22 13:20:40 +0100265struct iio_context * iio_create_context_from_uri(const char *uri)
266{
267 if (strcmp(uri, "local:") == 0) /* No address part */
268 return iio_create_local_context();
269
270 if (strncmp(uri, "xml:", sizeof("xml:") - 1) == 0)
271 return iio_create_xml_context(uri + sizeof("xml:") - 1);
272
273 if (strncmp(uri, "ip:", sizeof("ip:") - 1) == 0)
274 return iio_create_network_context(uri+3);
275
276 if (strncmp(uri, "usb:", sizeof("usb:") - 1) == 0)
277#if USB_BACKEND
278 return usb_create_context_from_uri(uri);
279#else
280 return NULL;
281#endif
282
283 return NULL;
284}
285
Paul Cercueil8f56ea72014-10-28 15:18:18 +0100286struct iio_context * iio_create_default_context(void)
287{
Paul Cercueil8f56ea72014-10-28 15:18:18 +0100288 char *hostname = getenv("IIOD_REMOTE");
289
290 if (hostname) {
Lars-Peter Clausen60f1c9a2016-02-22 13:20:40 +0100291 struct iio_context *ctx;
292
293 ctx = iio_create_context_from_uri(hostname);
294 if (ctx)
295 return ctx;
296
Paul Cercueil3cce9652015-12-02 13:11:47 +0100297#if NETWORK_BACKEND
Paul Cercueil8f56ea72014-10-28 15:18:18 +0100298 /* If the environment variable is an empty string, we will
299 * discover the server using ZeroConf */
300 if (strlen(hostname) == 0)
301 hostname = NULL;
302
303 return iio_create_network_context(hostname);
Paul Cercueil8f56ea72014-10-28 15:18:18 +0100304#endif
Paul Cercueil3cce9652015-12-02 13:11:47 +0100305 }
306
Paul Cercueil8f56ea72014-10-28 15:18:18 +0100307 return iio_create_local_context();
Paul Cercueil63e52182014-12-11 12:52:48 +0100308}
309
310struct iio_context * iio_create_local_context(void)
311{
312#if LOCAL_BACKEND
313 return local_create_context();
314#else
Paul Cercueildfeca0d2015-03-16 17:18:00 +0100315 errno = ENOSYS;
Paul Cercueil63e52182014-12-11 12:52:48 +0100316 return NULL;
317#endif
318}
319
320struct iio_context * iio_create_network_context(const char *hostname)
321{
322#if NETWORK_BACKEND
323 return network_create_context(hostname);
324#else
Paul Cercueildfeca0d2015-03-16 17:18:00 +0100325 errno = ENOSYS;
Paul Cercueil63e52182014-12-11 12:52:48 +0100326 return NULL;
327#endif
328}
329
330struct iio_context * iio_create_xml_context_mem(const char *xml, size_t len)
331{
Paul Cercueil20e86dc2015-11-27 16:07:29 +0100332#if XML_BACKEND
Paul Cercueil63e52182014-12-11 12:52:48 +0100333 return xml_create_context_mem(xml, len);
334#else
Paul Cercueildfeca0d2015-03-16 17:18:00 +0100335 errno = ENOSYS;
Paul Cercueil63e52182014-12-11 12:52:48 +0100336 return NULL;
337#endif
338}
339
340struct iio_context * iio_create_xml_context(const char *xml_file)
341{
Paul Cercueil9edafd62016-04-11 11:10:10 +0200342#if XML_BACKEND
Paul Cercueil63e52182014-12-11 12:52:48 +0100343 return xml_create_context(xml_file);
Paul Cercueil8f56ea72014-10-28 15:18:18 +0100344#else
Paul Cercueildfeca0d2015-03-16 17:18:00 +0100345 errno = ENOSYS;
Paul Cercueil8f56ea72014-10-28 15:18:18 +0100346 return NULL;
347#endif
348}