blob: 46f4d562d72951975aca983cd8fe663c2ada5473 [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 Cercueil42090d12014-02-24 12:32:23 +010022#include <string.h>
23
24static const char xml_header[] = "<?xml version=\"1.0\" encoding=\"utf-8\"?>"
25"<!DOCTYPE context ["
26"<!ELEMENT context (device)*>"
27"<!ELEMENT device (channel | attribute)*>"
28"<!ELEMENT channel (attribute)*>"
29"<!ELEMENT attribute EMPTY>"
30"<!ATTLIST context name CDATA #REQUIRED>"
31"<!ATTLIST device id CDATA #REQUIRED name CDATA #IMPLIED>"
32"<!ATTLIST channel id CDATA #REQUIRED type CDATA #REQUIRED name CDATA #IMPLIED>"
33"<!ATTLIST attribute name CDATA #REQUIRED>"
34"]>";
35
36/* Returns a string containing the XML representation of this context */
37char * iio_context_get_xml(const struct iio_context *ctx)
38{
39 size_t len = strlen(ctx->name) +
40 sizeof(xml_header) - 1 +
41 sizeof("<context name=\"\" ></context>");
Paul Cercueil5822ab62014-04-04 13:29:17 +020042 size_t *devices_len;
43 char *str, *ptr, **devices;
Paul Cercueil42090d12014-02-24 12:32:23 +010044 unsigned int i;
45
Paul Cercueil5822ab62014-04-04 13:29:17 +020046 devices_len = malloc(ctx->nb_devices * sizeof(*devices_len));
47 if (!devices_len)
48 return NULL;
49
50 devices = malloc(ctx->nb_devices * sizeof(*devices));
51 if (!devices)
52 goto err_free_devices_len;
53
Paul Cercueil42090d12014-02-24 12:32:23 +010054 for (i = 0; i < ctx->nb_devices; i++) {
55 char *xml = iio_device_get_xml(ctx->devices[i],
56 &devices_len[i]);
57 if (!xml)
58 goto err_free_devices;
59 devices[i] = xml;
60 len += devices_len[i];
61 }
62
63 str = malloc(len);
64 if (!str)
65 goto err_free_devices;
66
67 sprintf(str, "%s<context name=\"%s\" >", xml_header, ctx->name);
68 ptr = strrchr(str, '\0');
69
70 for (i = 0; i < ctx->nb_devices; i++) {
71 strcpy(ptr, devices[i]);
72 ptr += devices_len[i];
73 free(devices[i]);
74 }
75
Paul Cercueil5822ab62014-04-04 13:29:17 +020076 free(devices);
77 free(devices_len);
Paul Cercueil42090d12014-02-24 12:32:23 +010078 strcpy(ptr, "</context>");
79 return str;
80
81err_free_devices:
82 while (i--)
83 free(devices[i]);
Paul Cercueil5822ab62014-04-04 13:29:17 +020084 free(devices);
85err_free_devices_len:
86 free(devices_len);
Paul Cercueil42090d12014-02-24 12:32:23 +010087 return NULL;
88}
89
Paul Cercueil0b2ce712014-02-17 15:04:18 +010090const char * iio_context_get_name(const struct iio_context *ctx)
91{
92 return ctx->name;
93}
94
95void iio_context_destroy(struct iio_context *ctx)
96{
Paul Cercueil50363542014-02-18 16:04:28 +010097 unsigned int i;
98 if (ctx->ops->shutdown)
99 ctx->ops->shutdown(ctx);
100
101 for (i = 0; i < ctx->nb_devices; i++)
102 free_device(ctx->devices[i]);
103 if (ctx->nb_devices)
104 free(ctx->devices);
Paul Cercueil0b2ce712014-02-17 15:04:18 +0100105 free(ctx);
106}
107
108unsigned int iio_context_get_devices_count(const struct iio_context *ctx)
109{
110 return ctx->nb_devices;
111}
112
113struct iio_device * iio_context_get_device(const struct iio_context *ctx,
114 unsigned int index)
115{
116 if (index >= ctx->nb_devices)
117 return NULL;
118 else
119 return ctx->devices[index];
120}
Paul Cercueilae88fde2014-03-12 11:47:10 +0100121
Paul Cercueil17512b02014-03-28 11:15:24 +0100122struct iio_device * iio_context_find_device(const struct iio_context *ctx,
123 const char *name)
124{
125 unsigned int i;
126 for (i = 0; i < ctx->nb_devices; i++) {
127 struct iio_device *dev = ctx->devices[i];
128 if (!strcmp(dev->id, name) ||
129 (dev->name && !strcmp(dev->name, name)))
130 return dev;
131 }
132 return NULL;
133}
134
Paul Cercueilae88fde2014-03-12 11:47:10 +0100135static void init_index(struct iio_channel *chn)
136{
137 char buf[1024];
Paul Cercueilcd6ce842014-03-14 13:21:06 +0100138 long ret = (long) iio_channel_attr_read(chn, "index", buf, sizeof(buf));
Paul Cercueilae88fde2014-03-12 11:47:10 +0100139 if (ret < 0)
140 chn->index = ret;
141 else
142 chn->index = strtol(buf, NULL, 0);
143}
144
Paul Cercueilcd6ce842014-03-14 13:21:06 +0100145static void init_data_format(struct iio_channel *chn)
146{
147 char buf[1024];
148 int ret = iio_channel_attr_read(chn, "type", buf, sizeof(buf));
149 if (ret < 0) {
150 chn->format.length = 0;
151 } else {
152 char endian, sign;
153 sscanf(buf, "%ce:%c%u/%u>>%u", &endian, &sign,
154 &chn->format.bits,
155 &chn->format.length,
156 &chn->format.shift);
157 chn->format.is_signed = sign == 's';
158 chn->format.is_be = endian == 'b';
159 }
160
161 ret = iio_channel_attr_read(chn, "scale", buf, sizeof(buf));
162 if (ret < 0) {
163 chn->format.with_scale = false;
164 } else {
165 chn->format.with_scale = true;
166 chn->format.scale = strtod(buf, NULL);
167 }
168}
169
Paul Cercueil1f7bc152014-03-14 13:48:43 +0100170static void reorder_channels(struct iio_device *dev)
171{
172 bool found;
173 unsigned int i;
174
175 /* Reorder channels by index */
176 do {
177 found = false;
178 for (i = 1; i < dev->nb_channels; i++) {
179 struct iio_channel **channels = dev->channels;
180 long ch1 = channels[i - 1]->index;
181 long ch2 = channels[i]->index;
182
183 if (ch2 >= 0 && ((ch1 > ch2) || ch1 < 0)) {
184 struct iio_channel *bak = channels[i];
185 channels[i] = channels[i - 1];
186 channels[i - 1] = bak;
187 found = true;
188 }
189 }
190 } while (found);
191}
192
Paul Cercueilcd6ce842014-03-14 13:21:06 +0100193void iio_context_init_channels(const struct iio_context *ctx)
Paul Cercueilae88fde2014-03-12 11:47:10 +0100194{
195 unsigned int i;
196 for (i = 0; i < ctx->nb_devices; i++) {
197 unsigned int j;
198 struct iio_device *dev = ctx->devices[i];
Paul Cercueilcd6ce842014-03-14 13:21:06 +0100199 for (j = 0; j < dev->nb_channels; j++) {
Paul Cercueilae88fde2014-03-12 11:47:10 +0100200 init_index(dev->channels[j]);
Paul Cercueilcd6ce842014-03-14 13:21:06 +0100201 init_data_format(dev->channels[j]);
202 }
Paul Cercueil1f7bc152014-03-14 13:48:43 +0100203
204 reorder_channels(dev);
Paul Cercueilae88fde2014-03-12 11:47:10 +0100205 }
206}