blob: 555a79ac04ce948d63402b367a50982e4f868ff8 [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
Paul Cercueil17512b02014-03-28 11:15:24 +0100109struct iio_device * iio_context_find_device(const struct iio_context *ctx,
110 const char *name)
111{
112 unsigned int i;
113 for (i = 0; i < ctx->nb_devices; i++) {
114 struct iio_device *dev = ctx->devices[i];
115 if (!strcmp(dev->id, name) ||
116 (dev->name && !strcmp(dev->name, name)))
117 return dev;
118 }
119 return NULL;
120}
121
Paul Cercueilae88fde2014-03-12 11:47:10 +0100122static void init_index(struct iio_channel *chn)
123{
124 char buf[1024];
Paul Cercueilcd6ce842014-03-14 13:21:06 +0100125 long ret = (long) iio_channel_attr_read(chn, "index", buf, sizeof(buf));
Paul Cercueilae88fde2014-03-12 11:47:10 +0100126 if (ret < 0)
127 chn->index = ret;
128 else
129 chn->index = strtol(buf, NULL, 0);
130}
131
Paul Cercueilcd6ce842014-03-14 13:21:06 +0100132static void init_data_format(struct iio_channel *chn)
133{
134 char buf[1024];
135 int ret = iio_channel_attr_read(chn, "type", buf, sizeof(buf));
136 if (ret < 0) {
137 chn->format.length = 0;
138 } else {
139 char endian, sign;
140 sscanf(buf, "%ce:%c%u/%u>>%u", &endian, &sign,
141 &chn->format.bits,
142 &chn->format.length,
143 &chn->format.shift);
144 chn->format.is_signed = sign == 's';
145 chn->format.is_be = endian == 'b';
146 }
147
148 ret = iio_channel_attr_read(chn, "scale", buf, sizeof(buf));
149 if (ret < 0) {
150 chn->format.with_scale = false;
151 } else {
152 chn->format.with_scale = true;
153 chn->format.scale = strtod(buf, NULL);
154 }
155}
156
Paul Cercueil1f7bc152014-03-14 13:48:43 +0100157static void reorder_channels(struct iio_device *dev)
158{
159 bool found;
160 unsigned int i;
161
162 /* Reorder channels by index */
163 do {
164 found = false;
165 for (i = 1; i < dev->nb_channels; i++) {
166 struct iio_channel **channels = dev->channels;
167 long ch1 = channels[i - 1]->index;
168 long ch2 = channels[i]->index;
169
170 if (ch2 >= 0 && ((ch1 > ch2) || ch1 < 0)) {
171 struct iio_channel *bak = channels[i];
172 channels[i] = channels[i - 1];
173 channels[i - 1] = bak;
174 found = true;
175 }
176 }
177 } while (found);
178}
179
Paul Cercueilcd6ce842014-03-14 13:21:06 +0100180void iio_context_init_channels(const struct iio_context *ctx)
Paul Cercueilae88fde2014-03-12 11:47:10 +0100181{
182 unsigned int i;
183 for (i = 0; i < ctx->nb_devices; i++) {
184 unsigned int j;
185 struct iio_device *dev = ctx->devices[i];
Paul Cercueilcd6ce842014-03-14 13:21:06 +0100186 for (j = 0; j < dev->nb_channels; j++) {
Paul Cercueilae88fde2014-03-12 11:47:10 +0100187 init_index(dev->channels[j]);
Paul Cercueilcd6ce842014-03-14 13:21:06 +0100188 init_data_format(dev->channels[j]);
189 }
Paul Cercueil1f7bc152014-03-14 13:48:43 +0100190
191 reorder_channels(dev);
Paul Cercueilae88fde2014-03-12 11:47:10 +0100192 }
193}