blob: aa37a46f4fb10f1f05ed2b6a4b65c87a776b2be3 [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 Cercueil42090d12014-02-24 12:32:23 +010029"<!ELEMENT channel (attribute)*>"
30"<!ELEMENT attribute EMPTY>"
Paul Cercueild9d9f9f2014-04-15 10:08:17 +020031"<!ELEMENT debug-attribute EMPTY>"
Paul Cercueil42090d12014-02-24 12:32:23 +010032"<!ATTLIST context name CDATA #REQUIRED>"
33"<!ATTLIST device id CDATA #REQUIRED name CDATA #IMPLIED>"
Paul Cercueil85aaf482014-04-24 16:39:09 +020034"<!ATTLIST channel id CDATA #REQUIRED type (input|output) #REQUIRED scan_element (true|false) \"false\" name CDATA #IMPLIED>"
Paul Cercueil42090d12014-02-24 12:32:23 +010035"<!ATTLIST attribute name CDATA #REQUIRED>"
Paul Cercueild9d9f9f2014-04-15 10:08:17 +020036"<!ATTLIST debug-attribute name CDATA #REQUIRED>"
Paul Cercueil42090d12014-02-24 12:32:23 +010037"]>";
38
39/* Returns a string containing the XML representation of this context */
Paul Cercueil4c6729d2014-04-04 17:24:41 +020040static char * context_create_xml(const struct iio_context *ctx)
Paul Cercueil42090d12014-02-24 12:32:23 +010041{
Paul Cercueil9aab0192014-04-07 11:04:30 +020042 size_t len = strlen(ctx->name) + sizeof(xml_header) - 1 +
Paul Cercueil42090d12014-02-24 12:32:23 +010043 sizeof("<context name=\"\" ></context>");
Paul Cercueil5822ab62014-04-04 13:29:17 +020044 size_t *devices_len;
45 char *str, *ptr, **devices;
Paul Cercueil42090d12014-02-24 12:32:23 +010046 unsigned int i;
47
Paul Cercueil9aab0192014-04-07 11:04:30 +020048 if (!ctx->nb_devices) {
49 str = malloc(len);
50 if (str)
51 snprintf(str, len, "%s<context name=\"%s\" ></context>",
52 xml_header, ctx->name);
53 return str;
54 }
55
Paul Cercueil5822ab62014-04-04 13:29:17 +020056 devices_len = malloc(ctx->nb_devices * sizeof(*devices_len));
57 if (!devices_len)
58 return NULL;
59
60 devices = malloc(ctx->nb_devices * sizeof(*devices));
61 if (!devices)
62 goto err_free_devices_len;
63
Paul Cercueil42090d12014-02-24 12:32:23 +010064 for (i = 0; i < ctx->nb_devices; i++) {
65 char *xml = iio_device_get_xml(ctx->devices[i],
66 &devices_len[i]);
67 if (!xml)
68 goto err_free_devices;
69 devices[i] = xml;
70 len += devices_len[i];
71 }
72
73 str = malloc(len);
74 if (!str)
75 goto err_free_devices;
76
Paul Cercueil8c29e412014-04-07 09:46:45 +020077 snprintf(str, len, "%s<context name=\"%s\" >", xml_header, ctx->name);
Paul Cercueil42090d12014-02-24 12:32:23 +010078 ptr = strrchr(str, '\0');
79
80 for (i = 0; i < ctx->nb_devices; i++) {
81 strcpy(ptr, devices[i]);
82 ptr += devices_len[i];
83 free(devices[i]);
84 }
85
Paul Cercueil5822ab62014-04-04 13:29:17 +020086 free(devices);
87 free(devices_len);
Paul Cercueil42090d12014-02-24 12:32:23 +010088 strcpy(ptr, "</context>");
89 return str;
90
91err_free_devices:
92 while (i--)
93 free(devices[i]);
Paul Cercueil5822ab62014-04-04 13:29:17 +020094 free(devices);
95err_free_devices_len:
96 free(devices_len);
Paul Cercueil42090d12014-02-24 12:32:23 +010097 return NULL;
98}
99
Paul Cercueil4c6729d2014-04-04 17:24:41 +0200100const char * iio_context_get_xml(const struct iio_context *ctx)
101{
102 return ctx->xml;
103}
104
Paul Cercueil0b2ce712014-02-17 15:04:18 +0100105const char * iio_context_get_name(const struct iio_context *ctx)
106{
107 return ctx->name;
108}
109
110void iio_context_destroy(struct iio_context *ctx)
111{
Paul Cercueil50363542014-02-18 16:04:28 +0100112 unsigned int i;
113 if (ctx->ops->shutdown)
114 ctx->ops->shutdown(ctx);
115
116 for (i = 0; i < ctx->nb_devices; i++)
117 free_device(ctx->devices[i]);
118 if (ctx->nb_devices)
119 free(ctx->devices);
Paul Cercueil4c6729d2014-04-04 17:24:41 +0200120 if (ctx->xml)
121 free(ctx->xml);
Paul Cercueil0b2ce712014-02-17 15:04:18 +0100122 free(ctx);
123}
124
125unsigned int iio_context_get_devices_count(const struct iio_context *ctx)
126{
127 return ctx->nb_devices;
128}
129
130struct iio_device * iio_context_get_device(const struct iio_context *ctx,
131 unsigned int index)
132{
133 if (index >= ctx->nb_devices)
134 return NULL;
135 else
136 return ctx->devices[index];
137}
Paul Cercueilae88fde2014-03-12 11:47:10 +0100138
Paul Cercueil17512b02014-03-28 11:15:24 +0100139struct iio_device * iio_context_find_device(const struct iio_context *ctx,
140 const char *name)
141{
142 unsigned int i;
143 for (i = 0; i < ctx->nb_devices; i++) {
144 struct iio_device *dev = ctx->devices[i];
145 if (!strcmp(dev->id, name) ||
146 (dev->name && !strcmp(dev->name, name)))
147 return dev;
148 }
149 return NULL;
150}
151
Paul Cercueilae88fde2014-03-12 11:47:10 +0100152static void init_index(struct iio_channel *chn)
153{
154 char buf[1024];
Paul Cercueilcd6ce842014-03-14 13:21:06 +0100155 long ret = (long) iio_channel_attr_read(chn, "index", buf, sizeof(buf));
Paul Cercueilae88fde2014-03-12 11:47:10 +0100156 if (ret < 0)
157 chn->index = ret;
158 else
159 chn->index = strtol(buf, NULL, 0);
160}
161
Paul Cercueilcd6ce842014-03-14 13:21:06 +0100162static void init_data_format(struct iio_channel *chn)
163{
164 char buf[1024];
165 int ret = iio_channel_attr_read(chn, "type", buf, sizeof(buf));
166 if (ret < 0) {
167 chn->format.length = 0;
168 } else {
169 char endian, sign;
170 sscanf(buf, "%ce:%c%u/%u>>%u", &endian, &sign,
171 &chn->format.bits,
172 &chn->format.length,
173 &chn->format.shift);
174 chn->format.is_signed = sign == 's';
175 chn->format.is_be = endian == 'b';
176 }
177
178 ret = iio_channel_attr_read(chn, "scale", buf, sizeof(buf));
179 if (ret < 0) {
180 chn->format.with_scale = false;
181 } else {
182 chn->format.with_scale = true;
183 chn->format.scale = strtod(buf, NULL);
184 }
185}
186
Paul Cercueil1f7bc152014-03-14 13:48:43 +0100187static void reorder_channels(struct iio_device *dev)
188{
189 bool found;
190 unsigned int i;
191
192 /* Reorder channels by index */
193 do {
194 found = false;
195 for (i = 1; i < dev->nb_channels; i++) {
196 struct iio_channel **channels = dev->channels;
197 long ch1 = channels[i - 1]->index;
198 long ch2 = channels[i]->index;
199
200 if (ch2 >= 0 && ((ch1 > ch2) || ch1 < 0)) {
201 struct iio_channel *bak = channels[i];
202 channels[i] = channels[i - 1];
203 channels[i - 1] = bak;
204 found = true;
205 }
206 }
207 } while (found);
208}
209
Paul Cercueil4c6729d2014-04-04 17:24:41 +0200210int iio_context_init(struct iio_context *ctx)
Paul Cercueilae88fde2014-03-12 11:47:10 +0100211{
212 unsigned int i;
213 for (i = 0; i < ctx->nb_devices; i++) {
214 unsigned int j;
215 struct iio_device *dev = ctx->devices[i];
Paul Cercueilcd6ce842014-03-14 13:21:06 +0100216 for (j = 0; j < dev->nb_channels; j++) {
Paul Cercueilae88fde2014-03-12 11:47:10 +0100217 init_index(dev->channels[j]);
Paul Cercueilcd6ce842014-03-14 13:21:06 +0100218 init_data_format(dev->channels[j]);
219 }
Paul Cercueil1f7bc152014-03-14 13:48:43 +0100220
221 reorder_channels(dev);
Paul Cercueilae88fde2014-03-12 11:47:10 +0100222 }
Paul Cercueil4c6729d2014-04-04 17:24:41 +0200223
224 ctx->xml = context_create_xml(ctx);
225 return ctx->xml ? 0 : -ENOMEM;
Paul Cercueilae88fde2014-03-12 11:47:10 +0100226}
Paul Cercueile45f8762014-05-02 11:19:26 +0200227
228int iio_context_get_version(const struct iio_context *ctx,
229 unsigned int *major, unsigned int *minor)
230{
231 if (ctx->ops->get_version)
232 return ctx->ops->get_version(ctx, major, minor);
233 *major = LIBIIO_VERSION_MAJOR;
234 *minor = LIBIIO_VERSION_MINOR;
235 return 0;
236}