blob: 31e17c779bbf663ea9d004383e5924c31c24ffc4 [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 Cercueil2814ed12016-08-25 17:08:18 +020020#include "iio-config.h"
Paul Cercueil0b2ce712014-02-17 15:04:18 +010021#include "iio-private.h"
22
Paul Cercueil4c6729d2014-04-04 17:24:41 +020023#include <errno.h>
Paul Cercueil42090d12014-02-24 12:32:23 +010024#include <string.h>
25
Paul Cercueil8f56ea72014-10-28 15:18:18 +010026#ifdef _WIN32
27#define LOCAL_BACKEND 0
28#define NETWORK_BACKEND 1
29#endif
30
Paul Cercueil42090d12014-02-24 12:32:23 +010031static const char xml_header[] = "<?xml version=\"1.0\" encoding=\"utf-8\"?>"
32"<!DOCTYPE context ["
33"<!ELEMENT context (device)*>"
Paul Cercueild9d9f9f2014-04-15 10:08:17 +020034"<!ELEMENT device (channel | attribute | debug-attribute)*>"
Paul Cercueila7e80022014-06-11 11:41:26 +020035"<!ELEMENT channel (scan-element?, attribute*)>"
Paul Cercueil42090d12014-02-24 12:32:23 +010036"<!ELEMENT attribute EMPTY>"
Paul Cercueila7e80022014-06-11 11:41:26 +020037"<!ELEMENT scan-element EMPTY>"
Paul Cercueild9d9f9f2014-04-15 10:08:17 +020038"<!ELEMENT debug-attribute EMPTY>"
Paul Cercueil87350372015-03-16 13:24:37 +010039"<!ATTLIST context name CDATA #REQUIRED description CDATA #IMPLIED>"
Paul Cercueil42090d12014-02-24 12:32:23 +010040"<!ATTLIST device id CDATA #REQUIRED name CDATA #IMPLIED>"
Paul Cercueila7e80022014-06-11 11:41:26 +020041"<!ATTLIST channel id CDATA #REQUIRED type (input|output) #REQUIRED name CDATA #IMPLIED>"
42"<!ATTLIST scan-element index CDATA #REQUIRED format CDATA #REQUIRED scale CDATA #IMPLIED>"
Paul Cercueil42d12352014-05-05 16:11:58 +020043"<!ATTLIST attribute name CDATA #REQUIRED filename CDATA #IMPLIED>"
Paul Cercueild9d9f9f2014-04-15 10:08:17 +020044"<!ATTLIST debug-attribute name CDATA #REQUIRED>"
Paul Cercueil42090d12014-02-24 12:32:23 +010045"]>";
46
47/* Returns a string containing the XML representation of this context */
Paul Cercueilc1ed8482014-06-11 16:29:43 +020048char * iio_context_create_xml(const struct iio_context *ctx)
Paul Cercueil42090d12014-02-24 12:32:23 +010049{
Paul Cercueil87350372015-03-16 13:24:37 +010050 size_t len, *devices_len;
Paul Cercueil5822ab62014-04-04 13:29:17 +020051 char *str, *ptr, **devices;
Paul Cercueil42090d12014-02-24 12:32:23 +010052 unsigned int i;
53
Paul Cercueil87350372015-03-16 13:24:37 +010054 len = strlen(ctx->name) + sizeof(xml_header) - 1 +
55 sizeof("<context name=\"\" ></context>");
56 if (ctx->description)
57 len += strlen(ctx->description) +
58 sizeof(" description=\"\"") - 1;
59
Paul Cercueil9aab0192014-04-07 11:04:30 +020060 if (!ctx->nb_devices) {
61 str = malloc(len);
Paul Cercueildfeca0d2015-03-16 17:18:00 +010062 if (!str) {
63 errno = ENOMEM;
Paul Cercueil87350372015-03-16 13:24:37 +010064 return NULL;
Paul Cercueildfeca0d2015-03-16 17:18:00 +010065 }
Paul Cercueil87350372015-03-16 13:24:37 +010066
67 if (ctx->description)
68 snprintf(str, len, "%s<context name=\"%s\" "
69 "description=\"%s\" ></context>",
70 xml_header, ctx->name,
71 ctx->description);
72 else
Paul Cercueil9aab0192014-04-07 11:04:30 +020073 snprintf(str, len, "%s<context name=\"%s\" ></context>",
74 xml_header, ctx->name);
75 return str;
76 }
77
Paul Cercueil5822ab62014-04-04 13:29:17 +020078 devices_len = malloc(ctx->nb_devices * sizeof(*devices_len));
Paul Cercueildfeca0d2015-03-16 17:18:00 +010079 if (!devices_len) {
80 errno = ENOMEM;
Paul Cercueil5822ab62014-04-04 13:29:17 +020081 return NULL;
Paul Cercueildfeca0d2015-03-16 17:18:00 +010082 }
Paul Cercueil5822ab62014-04-04 13:29:17 +020083
84 devices = malloc(ctx->nb_devices * sizeof(*devices));
85 if (!devices)
86 goto err_free_devices_len;
87
Paul Cercueil42090d12014-02-24 12:32:23 +010088 for (i = 0; i < ctx->nb_devices; i++) {
89 char *xml = iio_device_get_xml(ctx->devices[i],
90 &devices_len[i]);
91 if (!xml)
92 goto err_free_devices;
93 devices[i] = xml;
94 len += devices_len[i];
95 }
96
97 str = malloc(len);
Paul Cercueildfeca0d2015-03-16 17:18:00 +010098 if (!str) {
99 errno = ENOMEM;
Paul Cercueil42090d12014-02-24 12:32:23 +0100100 goto err_free_devices;
Paul Cercueildfeca0d2015-03-16 17:18:00 +0100101 }
Paul Cercueil42090d12014-02-24 12:32:23 +0100102
Paul Cercueil87350372015-03-16 13:24:37 +0100103 if (ctx->description)
104 snprintf(str, len, "%s<context name=\"%s\" "
105 "description=\"%s\" >",
106 xml_header, ctx->name, ctx->description);
107 else
108 snprintf(str, len, "%s<context name=\"%s\" >",
109 xml_header, ctx->name);
Paul Cercueil42090d12014-02-24 12:32:23 +0100110 ptr = strrchr(str, '\0');
111
112 for (i = 0; i < ctx->nb_devices; i++) {
113 strcpy(ptr, devices[i]);
114 ptr += devices_len[i];
115 free(devices[i]);
116 }
117
Paul Cercueil5822ab62014-04-04 13:29:17 +0200118 free(devices);
119 free(devices_len);
Paul Cercueil42090d12014-02-24 12:32:23 +0100120 strcpy(ptr, "</context>");
121 return str;
122
123err_free_devices:
124 while (i--)
125 free(devices[i]);
Paul Cercueil5822ab62014-04-04 13:29:17 +0200126 free(devices);
127err_free_devices_len:
128 free(devices_len);
Paul Cercueil42090d12014-02-24 12:32:23 +0100129 return NULL;
130}
131
Paul Cercueil4c6729d2014-04-04 17:24:41 +0200132const char * iio_context_get_xml(const struct iio_context *ctx)
133{
134 return ctx->xml;
135}
136
Paul Cercueil0b2ce712014-02-17 15:04:18 +0100137const char * iio_context_get_name(const struct iio_context *ctx)
138{
139 return ctx->name;
140}
141
Paul Cercueil3ac36c12015-01-08 14:44:00 +0100142const char * iio_context_get_description(const struct iio_context *ctx)
143{
144 if (ctx->description)
145 return ctx->description;
146 else
147 return "";
148}
149
Paul Cercueil0b2ce712014-02-17 15:04:18 +0100150void iio_context_destroy(struct iio_context *ctx)
151{
Paul Cercueil50363542014-02-18 16:04:28 +0100152 unsigned int i;
153 if (ctx->ops->shutdown)
154 ctx->ops->shutdown(ctx);
155
156 for (i = 0; i < ctx->nb_devices; i++)
157 free_device(ctx->devices[i]);
158 if (ctx->nb_devices)
159 free(ctx->devices);
Paul Cercueil4c6729d2014-04-04 17:24:41 +0200160 if (ctx->xml)
161 free(ctx->xml);
Paul Cercueil3ac36c12015-01-08 14:44:00 +0100162 if (ctx->description)
163 free(ctx->description);
Paul Cercueil0b2ce712014-02-17 15:04:18 +0100164 free(ctx);
165}
166
167unsigned int iio_context_get_devices_count(const struct iio_context *ctx)
168{
169 return ctx->nb_devices;
170}
171
172struct iio_device * iio_context_get_device(const struct iio_context *ctx,
173 unsigned int index)
174{
175 if (index >= ctx->nb_devices)
176 return NULL;
177 else
178 return ctx->devices[index];
179}
Paul Cercueilae88fde2014-03-12 11:47:10 +0100180
Paul Cercueil17512b02014-03-28 11:15:24 +0100181struct iio_device * iio_context_find_device(const struct iio_context *ctx,
182 const char *name)
183{
184 unsigned int i;
185 for (i = 0; i < ctx->nb_devices; i++) {
186 struct iio_device *dev = ctx->devices[i];
187 if (!strcmp(dev->id, name) ||
188 (dev->name && !strcmp(dev->name, name)))
189 return dev;
190 }
191 return NULL;
192}
193
Paul Cercueil1f7bc152014-03-14 13:48:43 +0100194static void reorder_channels(struct iio_device *dev)
195{
196 bool found;
197 unsigned int i;
198
199 /* Reorder channels by index */
200 do {
201 found = false;
202 for (i = 1; i < dev->nb_channels; i++) {
203 struct iio_channel **channels = dev->channels;
204 long ch1 = channels[i - 1]->index;
205 long ch2 = channels[i]->index;
206
Lars-Peter Clausen75baa4d2016-02-01 17:58:57 +0100207 if (ch1 == ch2 && ch1 >= 0) {
208 ch1 = channels[i - 1]->format.shift;
209 ch2 = channels[i]->format.shift;
210 }
211
Paul Cercueil1f7bc152014-03-14 13:48:43 +0100212 if (ch2 >= 0 && ((ch1 > ch2) || ch1 < 0)) {
213 struct iio_channel *bak = channels[i];
214 channels[i] = channels[i - 1];
215 channels[i - 1] = bak;
216 found = true;
217 }
218 }
219 } while (found);
220}
221
Paul Cercueilfd387472015-08-05 10:34:19 +0200222int iio_context_init(struct iio_context *ctx)
Paul Cercueilae88fde2014-03-12 11:47:10 +0100223{
224 unsigned int i;
Paul Cercueilfd387472015-08-05 10:34:19 +0200225
Paul Cercueila7e80022014-06-11 11:41:26 +0200226 for (i = 0; i < ctx->nb_devices; i++)
227 reorder_channels(ctx->devices[i]);
Paul Cercueilfd387472015-08-05 10:34:19 +0200228
229 if (!ctx->xml) {
230 ctx->xml = iio_context_create_xml(ctx);
231 if (!ctx->xml)
232 return -ENOMEM;
233 }
234
235 return 0;
Paul Cercueilae88fde2014-03-12 11:47:10 +0100236}
Paul Cercueile45f8762014-05-02 11:19:26 +0200237
238int iio_context_get_version(const struct iio_context *ctx,
Paul Cercueil9de9e9d2014-05-20 13:18:19 +0200239 unsigned int *major, unsigned int *minor, char git_tag[8])
Paul Cercueile45f8762014-05-02 11:19:26 +0200240{
241 if (ctx->ops->get_version)
Paul Cercueil9de9e9d2014-05-20 13:18:19 +0200242 return ctx->ops->get_version(ctx, major, minor, git_tag);
Paul Cercueil53ed9432014-11-20 13:46:04 +0100243
244 iio_library_get_version(major, minor, git_tag);
Paul Cercueile45f8762014-05-02 11:19:26 +0200245 return 0;
246}
Paul Cercueil4ca73542014-06-10 16:23:29 +0200247
248int iio_context_set_timeout(struct iio_context *ctx, unsigned int timeout)
249{
250 if (ctx->ops->set_timeout)
251 return ctx->ops->set_timeout(ctx, timeout);
252 else
253 return -ENOSYS;
254}
Paul Cercueil63d5e7c2014-10-28 14:33:08 +0100255
256struct iio_context * iio_context_clone(const struct iio_context *ctx)
257{
Paul Cercueildfeca0d2015-03-16 17:18:00 +0100258 if (ctx->ops->clone) {
Paul Cercueil63d5e7c2014-10-28 14:33:08 +0100259 return ctx->ops->clone(ctx);
Paul Cercueildfeca0d2015-03-16 17:18:00 +0100260 } else {
261 errno = ENOSYS;
Paul Cercueil63d5e7c2014-10-28 14:33:08 +0100262 return NULL;
Paul Cercueildfeca0d2015-03-16 17:18:00 +0100263 }
Paul Cercueil63d5e7c2014-10-28 14:33:08 +0100264}
Paul Cercueil8f56ea72014-10-28 15:18:18 +0100265
Lars-Peter Clausen60f1c9a2016-02-22 13:20:40 +0100266struct iio_context * iio_create_context_from_uri(const char *uri)
267{
Paul Cercueil2814ed12016-08-25 17:08:18 +0200268#ifdef WITH_LOCAL_BACKEND
Lars-Peter Clausen60f1c9a2016-02-22 13:20:40 +0100269 if (strcmp(uri, "local:") == 0) /* No address part */
270 return iio_create_local_context();
Paul Cercueilc399f512016-04-26 17:55:27 +0200271#endif
Lars-Peter Clausen60f1c9a2016-02-22 13:20:40 +0100272
Paul Cercueil2814ed12016-08-25 17:08:18 +0200273#ifdef WITH_XML_BACKEND
Lars-Peter Clausen60f1c9a2016-02-22 13:20:40 +0100274 if (strncmp(uri, "xml:", sizeof("xml:") - 1) == 0)
275 return iio_create_xml_context(uri + sizeof("xml:") - 1);
Paul Cercueilc399f512016-04-26 17:55:27 +0200276#endif
Lars-Peter Clausen60f1c9a2016-02-22 13:20:40 +0100277
Paul Cercueil2814ed12016-08-25 17:08:18 +0200278#ifdef WITH_NETWORK_BACKEND
Lars-Peter Clausen60f1c9a2016-02-22 13:20:40 +0100279 if (strncmp(uri, "ip:", sizeof("ip:") - 1) == 0)
280 return iio_create_network_context(uri+3);
Paul Cercueilc399f512016-04-26 17:55:27 +0200281#endif
Lars-Peter Clausen60f1c9a2016-02-22 13:20:40 +0100282
Paul Cercueil2814ed12016-08-25 17:08:18 +0200283#ifdef WITH_USB_BACKEND
Paul Cercueilc399f512016-04-26 17:55:27 +0200284 if (strncmp(uri, "usb:", sizeof("usb:") - 1) == 0)
Lars-Peter Clausen60f1c9a2016-02-22 13:20:40 +0100285 return usb_create_context_from_uri(uri);
Lars-Peter Clausen60f1c9a2016-02-22 13:20:40 +0100286#endif
287
Paul Cercueil2814ed12016-08-25 17:08:18 +0200288#ifdef WITH_SERIAL_BACKEND
Paul Cercueilbcb04522016-03-22 17:03:29 +0100289 if (strncmp(uri, "serial:", sizeof("serial:") - 1) == 0)
290 return serial_create_context_from_uri(uri);
291#endif
292
Paul Cercueil10416462016-04-26 16:09:06 +0200293 errno = ENOSYS;
Lars-Peter Clausen60f1c9a2016-02-22 13:20:40 +0100294 return NULL;
295}
296
Paul Cercueil8f56ea72014-10-28 15:18:18 +0100297struct iio_context * iio_create_default_context(void)
298{
Paul Cercueil8f56ea72014-10-28 15:18:18 +0100299 char *hostname = getenv("IIOD_REMOTE");
300
301 if (hostname) {
Lars-Peter Clausen60f1c9a2016-02-22 13:20:40 +0100302 struct iio_context *ctx;
303
304 ctx = iio_create_context_from_uri(hostname);
305 if (ctx)
306 return ctx;
307
Paul Cercueil2814ed12016-08-25 17:08:18 +0200308#ifdef WITH_NETWORK_BACKEND
Paul Cercueil8f56ea72014-10-28 15:18:18 +0100309 /* If the environment variable is an empty string, we will
310 * discover the server using ZeroConf */
311 if (strlen(hostname) == 0)
312 hostname = NULL;
313
314 return iio_create_network_context(hostname);
Paul Cercueil8f56ea72014-10-28 15:18:18 +0100315#endif
Paul Cercueil3cce9652015-12-02 13:11:47 +0100316 }
317
Paul Cercueil8f56ea72014-10-28 15:18:18 +0100318 return iio_create_local_context();
Paul Cercueil63e52182014-12-11 12:52:48 +0100319}
320
321struct iio_context * iio_create_local_context(void)
322{
Paul Cercueil2814ed12016-08-25 17:08:18 +0200323#ifdef WITH_LOCAL_BACKEND
Paul Cercueil63e52182014-12-11 12:52:48 +0100324 return local_create_context();
325#else
Paul Cercueildfeca0d2015-03-16 17:18:00 +0100326 errno = ENOSYS;
Paul Cercueil63e52182014-12-11 12:52:48 +0100327 return NULL;
328#endif
329}
330
331struct iio_context * iio_create_network_context(const char *hostname)
332{
Paul Cercueil2814ed12016-08-25 17:08:18 +0200333#ifdef WITH_NETWORK_BACKEND
Paul Cercueil63e52182014-12-11 12:52:48 +0100334 return network_create_context(hostname);
335#else
Paul Cercueildfeca0d2015-03-16 17:18:00 +0100336 errno = ENOSYS;
Paul Cercueil63e52182014-12-11 12:52:48 +0100337 return NULL;
338#endif
339}
340
341struct iio_context * iio_create_xml_context_mem(const char *xml, size_t len)
342{
Paul Cercueil2814ed12016-08-25 17:08:18 +0200343#ifdef WITH_XML_BACKEND
Paul Cercueil63e52182014-12-11 12:52:48 +0100344 return xml_create_context_mem(xml, len);
345#else
Paul Cercueildfeca0d2015-03-16 17:18:00 +0100346 errno = ENOSYS;
Paul Cercueil63e52182014-12-11 12:52:48 +0100347 return NULL;
348#endif
349}
350
351struct iio_context * iio_create_xml_context(const char *xml_file)
352{
Paul Cercueil2814ed12016-08-25 17:08:18 +0200353#ifdef WITH_XML_BACKEND
Paul Cercueil63e52182014-12-11 12:52:48 +0100354 return xml_create_context(xml_file);
Paul Cercueil8f56ea72014-10-28 15:18:18 +0100355#else
Paul Cercueildfeca0d2015-03-16 17:18:00 +0100356 errno = ENOSYS;
Paul Cercueil8f56ea72014-10-28 15:18:18 +0100357 return NULL;
358#endif
359}