blob: a0cb5a7a7a470d38506cf8f794583740e72033ad [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>");
42 char *str, *ptr, *devices[ctx->nb_devices];
43 size_t devices_len[ctx->nb_devices];
44 unsigned int i;
45
46 for (i = 0; i < ctx->nb_devices; i++) {
47 char *xml = iio_device_get_xml(ctx->devices[i],
48 &devices_len[i]);
49 if (!xml)
50 goto err_free_devices;
51 devices[i] = xml;
52 len += devices_len[i];
53 }
54
55 str = malloc(len);
56 if (!str)
57 goto err_free_devices;
58
59 sprintf(str, "%s<context name=\"%s\" >", xml_header, ctx->name);
60 ptr = strrchr(str, '\0');
61
62 for (i = 0; i < ctx->nb_devices; i++) {
63 strcpy(ptr, devices[i]);
64 ptr += devices_len[i];
65 free(devices[i]);
66 }
67
68 strcpy(ptr, "</context>");
69 return str;
70
71err_free_devices:
72 while (i--)
73 free(devices[i]);
74 return NULL;
75}
76
Paul Cercueil0b2ce712014-02-17 15:04:18 +010077const char * iio_context_get_name(const struct iio_context *ctx)
78{
79 return ctx->name;
80}
81
82void iio_context_destroy(struct iio_context *ctx)
83{
Paul Cercueil50363542014-02-18 16:04:28 +010084 unsigned int i;
85 if (ctx->ops->shutdown)
86 ctx->ops->shutdown(ctx);
87
88 for (i = 0; i < ctx->nb_devices; i++)
89 free_device(ctx->devices[i]);
90 if (ctx->nb_devices)
91 free(ctx->devices);
Paul Cercueil0b2ce712014-02-17 15:04:18 +010092 free(ctx);
93}
94
95unsigned int iio_context_get_devices_count(const struct iio_context *ctx)
96{
97 return ctx->nb_devices;
98}
99
100struct iio_device * iio_context_get_device(const struct iio_context *ctx,
101 unsigned int index)
102{
103 if (index >= ctx->nb_devices)
104 return NULL;
105 else
106 return ctx->devices[index];
107}
Paul Cercueilae88fde2014-03-12 11:47:10 +0100108
109static void init_index(struct iio_channel *chn)
110{
111 char buf[1024];
Paul Cercueilcd6ce842014-03-14 13:21:06 +0100112 long ret = (long) iio_channel_attr_read(chn, "index", buf, sizeof(buf));
Paul Cercueilae88fde2014-03-12 11:47:10 +0100113 if (ret < 0)
114 chn->index = ret;
115 else
116 chn->index = strtol(buf, NULL, 0);
117}
118
Paul Cercueilcd6ce842014-03-14 13:21:06 +0100119static void init_data_format(struct iio_channel *chn)
120{
121 char buf[1024];
122 int ret = iio_channel_attr_read(chn, "type", buf, sizeof(buf));
123 if (ret < 0) {
124 chn->format.length = 0;
125 } else {
126 char endian, sign;
127 sscanf(buf, "%ce:%c%u/%u>>%u", &endian, &sign,
128 &chn->format.bits,
129 &chn->format.length,
130 &chn->format.shift);
131 chn->format.is_signed = sign == 's';
132 chn->format.is_be = endian == 'b';
133 }
134
135 ret = iio_channel_attr_read(chn, "scale", buf, sizeof(buf));
136 if (ret < 0) {
137 chn->format.with_scale = false;
138 } else {
139 chn->format.with_scale = true;
140 chn->format.scale = strtod(buf, NULL);
141 }
142}
143
Paul Cercueil1f7bc152014-03-14 13:48:43 +0100144static void reorder_channels(struct iio_device *dev)
145{
146 bool found;
147 unsigned int i;
148
149 /* Reorder channels by index */
150 do {
151 found = false;
152 for (i = 1; i < dev->nb_channels; i++) {
153 struct iio_channel **channels = dev->channels;
154 long ch1 = channels[i - 1]->index;
155 long ch2 = channels[i]->index;
156
157 if (ch2 >= 0 && ((ch1 > ch2) || ch1 < 0)) {
158 struct iio_channel *bak = channels[i];
159 channels[i] = channels[i - 1];
160 channels[i - 1] = bak;
161 found = true;
162 }
163 }
164 } while (found);
165}
166
Paul Cercueilcd6ce842014-03-14 13:21:06 +0100167void iio_context_init_channels(const struct iio_context *ctx)
Paul Cercueilae88fde2014-03-12 11:47:10 +0100168{
169 unsigned int i;
170 for (i = 0; i < ctx->nb_devices; i++) {
171 unsigned int j;
172 struct iio_device *dev = ctx->devices[i];
Paul Cercueilcd6ce842014-03-14 13:21:06 +0100173 for (j = 0; j < dev->nb_channels; j++) {
Paul Cercueilae88fde2014-03-12 11:47:10 +0100174 init_index(dev->channels[j]);
Paul Cercueilcd6ce842014-03-14 13:21:06 +0100175 init_data_format(dev->channels[j]);
176 }
Paul Cercueil1f7bc152014-03-14 13:48:43 +0100177
178 reorder_channels(dev);
Paul Cercueilae88fde2014-03-12 11:47:10 +0100179 }
180}