blob: 7524cf5e08f3f619595d9693f0ee7b85e4448c88 [file] [log] [blame]
Paul Cercueilc7bad0f2014-03-03 17:06:48 +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 Cercueilc7bad0f2014-03-03 17:06:48 +010019#include "iio-private.h"
20
21#include <errno.h>
Paul Cercueile60c3ed2014-03-04 11:23:56 +010022#include <stdbool.h>
Paul Cercueilc7bad0f2014-03-03 17:06:48 +010023#include <string.h>
24#include <sys/types.h>
Paul Cercueilab114932014-05-19 13:03:17 +020025#include <time.h>
Paul Cercueil1fef1a52014-04-07 16:31:15 +020026
27#ifdef _WIN32
28#include <winsock2.h>
29#include <ws2tcpip.h>
30#define close(s) closesocket(s)
31
32/* winsock2.h defines ERROR, we don't want that */
33#undef ERROR
34
35#else /* _WIN32 */
36#include <netdb.h>
Paul Cercueil05e26262014-05-09 11:32:43 +020037#include <pthread.h>
Paul Cercueilc7bad0f2014-03-03 17:06:48 +010038#include <sys/socket.h>
39#include <unistd.h>
Paul Cercueil1fef1a52014-04-07 16:31:15 +020040#endif /* _WIN32 */
41
Paul Cercueilab114932014-05-19 13:03:17 +020042#ifdef HAVE_AVAHI
43#include <avahi-client/client.h>
44#include <avahi-common/error.h>
45#include <avahi-client/lookup.h>
46#include <avahi-common/simple-watch.h>
47#endif
48
Paul Cercueil1fef1a52014-04-07 16:31:15 +020049#include "debug.h"
Paul Cercueilc7bad0f2014-03-03 17:06:48 +010050
Paul Cercueil8a266f12014-06-10 16:06:31 +020051#define DEFAULT_TIMEOUT_MS 5000
52
Paul Cercueil2e38bbe2014-03-19 15:27:15 +010053#define _STRINGIFY(x) #x
54#define STRINGIFY(x) _STRINGIFY(x)
55
Paul Cercueilc7bad0f2014-03-03 17:06:48 +010056#define IIOD_PORT 30431
Paul Cercueil2e38bbe2014-03-19 15:27:15 +010057#define IIOD_PORT_STR STRINGIFY(IIOD_PORT)
Paul Cercueilc7bad0f2014-03-03 17:06:48 +010058
Paul Cercueil05e26262014-05-09 11:32:43 +020059#ifndef HAVE_PTHREAD
60#define HAVE_PTHREAD defined(_PTHREAD_H)
61#endif
62
Paul Cercueil8fd9c8f2014-03-03 17:21:31 +010063struct iio_context_pdata {
64 int fd;
Paul Cercueil05e26262014-05-09 11:32:43 +020065#if HAVE_PTHREAD
Paul Cercueil1494b862014-05-05 12:49:07 +020066 pthread_mutex_t lock;
Paul Cercueil05e26262014-05-09 11:32:43 +020067#endif
Paul Cercueil8fd9c8f2014-03-03 17:21:31 +010068};
69
Paul Cercueilab114932014-05-19 13:03:17 +020070#ifdef HAVE_AVAHI
71struct avahi_discovery_data {
72 AvahiSimplePoll *poll;
73 AvahiAddress *address;
74 uint16_t *port;
75 bool found, resolved;
76};
77
78static void __avahi_resolver_cb(AvahiServiceResolver *resolver,
79 __notused AvahiIfIndex iface, __notused AvahiProtocol proto,
80 __notused AvahiResolverEvent event, __notused const char *name,
81 __notused const char *type, __notused const char *domain,
82 __notused const char *host_name, const AvahiAddress *address,
83 uint16_t port, __notused AvahiStringList *txt,
84 __notused AvahiLookupResultFlags flags, void *d)
85{
86 struct avahi_discovery_data *ddata = (struct avahi_discovery_data *) d;
87
88 memcpy(ddata->address, address, sizeof(*address));
89 *ddata->port = port;
90 ddata->resolved = true;
91 avahi_service_resolver_free(resolver);
92}
93
94static void __avahi_browser_cb(AvahiServiceBrowser *browser,
95 AvahiIfIndex iface, AvahiProtocol proto,
96 AvahiBrowserEvent event, const char *name,
97 const char *type, const char *domain,
98 __notused AvahiLookupResultFlags flags, void *d)
99{
100 struct avahi_discovery_data *ddata = (struct avahi_discovery_data *) d;
101 struct AvahiClient *client = avahi_service_browser_get_client(browser);
102
103 switch (event) {
104 default:
105 case AVAHI_BROWSER_NEW:
106 ddata->found = !!avahi_service_resolver_new(client, iface,
107 proto, name, type, domain,
108 AVAHI_PROTO_UNSPEC, 0,
109 __avahi_resolver_cb, d);
110 break;
111 case AVAHI_BROWSER_ALL_FOR_NOW:
112 if (ddata->found) {
113 while (!ddata->resolved) {
114 struct timespec ts;
115 ts.tv_sec = 0;
116 ts.tv_nsec = 4000000;
117 nanosleep(&ts, NULL);
118 }
119 }
120 case AVAHI_BROWSER_FAILURE: /* fall-through */
121 avahi_simple_poll_quit(ddata->poll);
122 case AVAHI_BROWSER_CACHE_EXHAUSTED: /* fall-through */
123 break;
124 }
125}
126
127static int discover_host(AvahiAddress *addr, uint16_t *port)
128{
129 struct avahi_discovery_data ddata;
130 int ret = 0;
131 AvahiClient *client;
132 AvahiServiceBrowser *browser;
133 AvahiSimplePoll *poll = avahi_simple_poll_new();
134 if (!poll)
135 return -ENOMEM;
136
137 client = avahi_client_new(avahi_simple_poll_get(poll),
138 0, NULL, NULL, &ret);
139 if (!client) {
140 ERROR("Unable to start ZeroConf client :%s\n",
141 avahi_strerror(ret));
142 goto err_free_poll;
143 }
144
145 memset(&ddata, 0, sizeof(ddata));
146 ddata.poll = poll;
147 ddata.address = addr;
148 ddata.port = port;
149
150 browser = avahi_service_browser_new(client,
151 AVAHI_IF_UNSPEC, AVAHI_PROTO_UNSPEC,
152 "_iio._tcp", NULL, 0, __avahi_browser_cb, &ddata);
153 if (!browser) {
154 ret = avahi_client_errno(client);
155 ERROR("Unable to create ZeroConf browser: %s\n",
156 avahi_strerror(ret));
157 goto err_free_client;
158 }
159
160 DEBUG("Trying to discover host\n");
161 avahi_simple_poll_loop(poll);
162
163 if (!ddata.found)
164 ret = ENXIO;
165
166 avahi_service_browser_free(browser);
167err_free_client:
168 avahi_client_free(client);
169err_free_poll:
170 avahi_simple_poll_free(poll);
171 return -ret; /* we want a negative error code */
172}
173#endif /* HAVE_AVAHI */
174
Paul Cercueil05e26262014-05-09 11:32:43 +0200175static void network_lock(struct iio_context_pdata *pdata)
176{
177#if HAVE_PTHREAD
178 pthread_mutex_lock(&pdata->lock);
179#endif
180}
181
182static void network_unlock(struct iio_context_pdata *pdata)
183{
184#if HAVE_PTHREAD
185 pthread_mutex_unlock(&pdata->lock);
186#endif
187}
188
Paul Cercueilc7bad0f2014-03-03 17:06:48 +0100189static ssize_t write_all(const void *src, size_t len, int fd)
190{
Paul Cercueil6e7f79e2014-04-04 12:27:24 +0200191 uintptr_t ptr = (uintptr_t) src;
Paul Cercueilc7bad0f2014-03-03 17:06:48 +0100192 while (len) {
Paul Cercueil6e7f79e2014-04-04 12:27:24 +0200193 ssize_t ret = send(fd, (const void *) ptr, len, 0);
Paul Cercueilc7bad0f2014-03-03 17:06:48 +0100194 if (ret < 0)
195 return -errno;
196 ptr += ret;
197 len -= ret;
198 }
Paul Cercueil6e7f79e2014-04-04 12:27:24 +0200199 return ptr - (uintptr_t) src;
Paul Cercueilc7bad0f2014-03-03 17:06:48 +0100200}
201
202static ssize_t read_all(void *dst, size_t len, int fd)
203{
Paul Cercueil6e7f79e2014-04-04 12:27:24 +0200204 uintptr_t ptr = (uintptr_t) dst;
Paul Cercueilc7bad0f2014-03-03 17:06:48 +0100205 while (len) {
Paul Cercueil6e7f79e2014-04-04 12:27:24 +0200206 ssize_t ret = recv(fd, (void *) ptr, len, 0);
Paul Cercueilc7bad0f2014-03-03 17:06:48 +0100207 if (ret < 0)
208 return -errno;
209 ptr += ret;
210 len -= ret;
211 }
Paul Cercueil6e7f79e2014-04-04 12:27:24 +0200212 return ptr - (uintptr_t) dst;
Paul Cercueilc7bad0f2014-03-03 17:06:48 +0100213}
214
Paul Cercueile60c3ed2014-03-04 11:23:56 +0100215static int read_integer(int fd, long *val)
216{
217 unsigned int i;
218 char buf[1024], *ptr;
219 ssize_t ret;
220 bool found = false;
221
222 for (i = 0; i < sizeof(buf) - 1; i++) {
223 ret = read_all(buf + i, 1, fd);
224 if (ret < 0)
225 return (int) ret;
226
Paul Cercueil6691a3f2014-05-02 12:32:01 +0200227 /* Skip the eventual first few carriage returns.
228 * Also stop when a dot is found (for parsing floats) */
229 if (buf[i] != '\n' && buf[i] != '.')
Paul Cercueile60c3ed2014-03-04 11:23:56 +0100230 found = true;
231 else if (found)
232 break;
233 }
234
235 buf[i] = '\0';
236 ret = (ssize_t) strtol(buf, &ptr, 10);
237 if (ptr == buf)
238 return -EINVAL;
239 *val = (long) ret;
240 return 0;
241}
242
Paul Cercueilbb76bf92014-03-11 10:20:18 +0100243static ssize_t write_command(const char *cmd, int fd)
244{
245 ssize_t ret;
246
247 DEBUG("Writing command: %s\n", cmd);
248 ret = write_all(cmd, strlen(cmd), fd);
249 if (ret < 0) {
250 char buf[1024];
251 strerror_r(-ret, buf, sizeof(buf));
252 ERROR("Unable to send command: %s\n", buf);
253 }
254 return ret;
255}
256
257static long exec_command(const char *cmd, int fd)
258{
259 long resp;
260 ssize_t ret = write_command(cmd, fd);
261 if (ret < 0)
262 return (long) ret;
263
264 DEBUG("Reading response\n");
265 ret = read_integer(fd, &resp);
266 if (ret < 0) {
267 char buf[1024];
268 strerror_r(-ret, buf, sizeof(buf));
269 ERROR("Unable to read response: %s\n", buf);
270 return (long) ret;
271 }
272
Paul Cercueilc7fe2ea2014-03-28 11:38:45 +0100273#if LOG_LEVEL >= DEBUG_L
Paul Cercueilbb76bf92014-03-11 10:20:18 +0100274 if (resp < 0) {
275 char buf[1024];
276 strerror_r(-resp, buf, sizeof(buf));
Paul Cercueilc7fe2ea2014-03-28 11:38:45 +0100277 DEBUG("Server returned an error: %s\n", buf);
Paul Cercueilbb76bf92014-03-11 10:20:18 +0100278 }
Paul Cercueilc7fe2ea2014-03-28 11:38:45 +0100279#endif
280
Paul Cercueilbb76bf92014-03-11 10:20:18 +0100281 return resp;
282}
283
Paul Cercueil71694c72014-05-22 14:02:13 +0200284static int network_open(const struct iio_device *dev, size_t samples_count,
285 uint32_t *mask, size_t nb, bool cyclic)
Paul Cercueilba059762014-03-14 11:02:02 +0100286{
287 char buf[1024], *ptr;
288 unsigned int i;
Paul Cercueil44ae11c2014-03-17 09:56:29 +0100289 int ret;
Paul Cercueilba059762014-03-14 11:02:02 +0100290
Paul Cercueilff778232014-03-24 14:23:08 +0100291 if (nb != dev->words)
Paul Cercueilba059762014-03-14 11:02:02 +0100292 return -EINVAL;
293
Paul Cercueil3c407f82014-04-02 14:11:59 +0200294 snprintf(buf, sizeof(buf), "OPEN %s %lu ",
295 dev->id, (unsigned long) samples_count);
Paul Cercueilba059762014-03-14 11:02:02 +0100296 ptr = buf + strlen(buf);
297
298 for (i = nb; i > 0; i--) {
Paul Cercueil8c29e412014-04-07 09:46:45 +0200299 snprintf(ptr, (ptr - buf) + i * 8, "%08x", mask[i - 1]);
Paul Cercueilba059762014-03-14 11:02:02 +0100300 ptr += 8;
301 }
Paul Cercueil71694c72014-05-22 14:02:13 +0200302
303 strcpy(ptr, cyclic ? " CYCLIC\r\n" : "\r\n");
Paul Cercueilba059762014-03-14 11:02:02 +0100304
Paul Cercueil05e26262014-05-09 11:32:43 +0200305 network_lock(dev->ctx->pdata);
Paul Cercueil44ae11c2014-03-17 09:56:29 +0100306 ret = (int) exec_command(buf, dev->ctx->pdata->fd);
Paul Cercueil05e26262014-05-09 11:32:43 +0200307 network_unlock(dev->ctx->pdata);
Paul Cercueil1494b862014-05-05 12:49:07 +0200308
Paul Cercueil44ae11c2014-03-17 09:56:29 +0100309 if (ret < 0) {
Paul Cercueil44ae11c2014-03-17 09:56:29 +0100310 return ret;
311 } else {
Paul Cercueilff778232014-03-24 14:23:08 +0100312 memcpy(dev->mask, mask, nb * sizeof(*mask));
Paul Cercueil44ae11c2014-03-17 09:56:29 +0100313 return 0;
314 }
Paul Cercueilba059762014-03-14 11:02:02 +0100315}
316
317static int network_close(const struct iio_device *dev)
318{
Paul Cercueil1494b862014-05-05 12:49:07 +0200319 int ret;
Paul Cercueilba059762014-03-14 11:02:02 +0100320 char buf[1024];
321 snprintf(buf, sizeof(buf), "CLOSE %s\r\n", dev->id);
Paul Cercueil1494b862014-05-05 12:49:07 +0200322
Paul Cercueil05e26262014-05-09 11:32:43 +0200323 network_lock(dev->ctx->pdata);
Paul Cercueil1494b862014-05-05 12:49:07 +0200324 ret = (int) exec_command(buf, dev->ctx->pdata->fd);
Paul Cercueil05e26262014-05-09 11:32:43 +0200325 network_unlock(dev->ctx->pdata);
Paul Cercueil1494b862014-05-05 12:49:07 +0200326
327 return ret;
Paul Cercueilba059762014-03-14 11:02:02 +0100328}
329
Paul Cercueil45c575d2014-03-20 15:14:01 +0100330static ssize_t network_read(const struct iio_device *dev, void *dst, size_t len,
331 uint32_t *mask, size_t words)
Paul Cercueilf9286452014-03-18 14:32:17 +0100332{
Paul Cercueil6e7f79e2014-04-04 12:27:24 +0200333 uintptr_t ptr = (uintptr_t) dst;
Paul Cercueil05e26262014-05-09 11:32:43 +0200334 struct iio_context_pdata *pdata = dev->ctx->pdata;
335 int fd = pdata->fd;
Paul Cercueil45c575d2014-03-20 15:14:01 +0100336 ssize_t ret, read = 0;
Paul Cercueil9945bc82014-03-05 14:07:29 +0100337 char buf[1024];
Paul Cercueil45c575d2014-03-20 15:14:01 +0100338 bool read_mask = true;
Paul Cercueil9945bc82014-03-05 14:07:29 +0100339
Paul Cercueil45c575d2014-03-20 15:14:01 +0100340 if (!len || words != (dev->nb_channels + 31) / 32)
Paul Cercueil9945bc82014-03-05 14:07:29 +0100341 return -EINVAL;
342
Paul Cercueila78b6eb2014-03-17 17:28:07 +0100343 snprintf(buf, sizeof(buf), "READBUF %s %lu\r\n",
344 dev->id, (unsigned long) len);
Paul Cercueil1494b862014-05-05 12:49:07 +0200345
Paul Cercueil05e26262014-05-09 11:32:43 +0200346 network_lock(pdata);
Paul Cercueilbb76bf92014-03-11 10:20:18 +0100347 ret = write_command(buf, fd);
Paul Cercueil1494b862014-05-05 12:49:07 +0200348 if (ret < 0) {
Paul Cercueil05e26262014-05-09 11:32:43 +0200349 network_unlock(pdata);
Paul Cercueil9945bc82014-03-05 14:07:29 +0100350 return ret;
Paul Cercueil1494b862014-05-05 12:49:07 +0200351 }
Paul Cercueil9945bc82014-03-05 14:07:29 +0100352
353 do {
Paul Cercueil5cab3ae2014-03-14 11:23:56 +0100354 unsigned int i;
Paul Cercueil9945bc82014-03-05 14:07:29 +0100355 long read_len;
356
357 DEBUG("Reading READ response\n");
358 ret = read_integer(fd, &read_len);
359 if (ret < 0) {
360 strerror_r(-ret, buf, sizeof(buf));
361 ERROR("Unable to read response to READ: %s\n", buf);
Paul Cercueil05e26262014-05-09 11:32:43 +0200362 network_unlock(pdata);
Paul Cercueil6e7f79e2014-04-04 12:27:24 +0200363 return read ? read : ret;
Paul Cercueil9945bc82014-03-05 14:07:29 +0100364 }
365
366 if (read_len < 0) {
367 strerror_r(-read_len, buf, sizeof(buf));
368 ERROR("Server returned an error: %s\n", buf);
Paul Cercueil05e26262014-05-09 11:32:43 +0200369 network_unlock(pdata);
Paul Cercueil6e7f79e2014-04-04 12:27:24 +0200370 return read ? read : read_len;
Paul Cercueila78b6eb2014-03-17 17:28:07 +0100371 } else if (read_len == 0) {
372 break;
Paul Cercueil9945bc82014-03-05 14:07:29 +0100373 }
374
375 DEBUG("Bytes to read: %li\n", read_len);
376
Paul Cercueil43c1e6c2014-03-20 14:26:20 +0100377 if (read_mask) {
378 DEBUG("Reading mask\n");
379 buf[8] = '\0';
Paul Cercueil45c575d2014-03-20 15:14:01 +0100380 for (i = words; i > 0; i--) {
Paul Cercueil43c1e6c2014-03-20 14:26:20 +0100381 ret = read_all(buf, 8, fd);
382 if (ret < 0)
383 break;
384 sscanf(buf, "%08x", &mask[i - 1]);
385 DEBUG("mask[%i] = 0x%x\n", i - 1, mask[i - 1]);
Paul Cercueil43c1e6c2014-03-20 14:26:20 +0100386 }
387 read_mask = false;
Paul Cercueil5cab3ae2014-03-14 11:23:56 +0100388 }
389
390 if (ret > 0) {
391 char c;
392 ret = recv(fd, &c, 1, 0);
393 if (ret > 0 && c != '\n')
394 ret = -EIO;
395 }
396
397 if (ret < 0) {
398 strerror_r(-ret, buf, sizeof(buf));
399 ERROR("Unable to read mask: %s\n", buf);
Paul Cercueil05e26262014-05-09 11:32:43 +0200400 network_unlock(pdata);
Paul Cercueil6e7f79e2014-04-04 12:27:24 +0200401 return read ? read : ret;
Paul Cercueil5cab3ae2014-03-14 11:23:56 +0100402 }
403
Paul Cercueil6e7f79e2014-04-04 12:27:24 +0200404 ret = read_all((void *) ptr, read_len, fd);
Paul Cercueil9945bc82014-03-05 14:07:29 +0100405 if (ret < 0) {
406 strerror_r(-ret, buf, sizeof(buf));
407 ERROR("Unable to read response to READ: %s\n", buf);
Paul Cercueil05e26262014-05-09 11:32:43 +0200408 network_unlock(pdata);
Paul Cercueil6e7f79e2014-04-04 12:27:24 +0200409 return read ? read : ret;
Paul Cercueil9945bc82014-03-05 14:07:29 +0100410 }
411
Paul Cercueil6e7f79e2014-04-04 12:27:24 +0200412 ptr += ret;
Paul Cercueilf9286452014-03-18 14:32:17 +0100413 read += ret;
Paul Cercueil9945bc82014-03-05 14:07:29 +0100414 len -= read_len;
415 } while (len);
416
Paul Cercueil05e26262014-05-09 11:32:43 +0200417 network_unlock(pdata);
Paul Cercueil9945bc82014-03-05 14:07:29 +0100418 return read;
419}
420
Paul Cercueild93215d2014-05-19 16:36:06 +0200421static ssize_t do_write(struct iio_context_pdata *pdata, bool attr,
Paul Cercueilcecda352014-05-06 18:14:29 +0200422 const char *command, const void *src, size_t len)
Paul Cercueil2725f702014-05-02 11:02:16 +0200423{
Paul Cercueilcecda352014-05-06 18:14:29 +0200424 int fd = pdata->fd;
Paul Cercueil2725f702014-05-02 11:02:16 +0200425 ssize_t ret;
Paul Cercueil2725f702014-05-02 11:02:16 +0200426 long resp;
427
Paul Cercueil05e26262014-05-09 11:32:43 +0200428 network_lock(pdata);
Paul Cercueild93215d2014-05-19 16:36:06 +0200429 if (attr)
430 ret = (ssize_t) write_command(command, fd);
431 else
432 ret = (ssize_t) exec_command(command, fd);
Paul Cercueil2725f702014-05-02 11:02:16 +0200433 if (ret < 0)
Paul Cercueil1494b862014-05-05 12:49:07 +0200434 goto err_unlock;
Paul Cercueil2725f702014-05-02 11:02:16 +0200435
436 ret = write_all(src, len, fd);
437 if (ret < 0)
Paul Cercueil1494b862014-05-05 12:49:07 +0200438 goto err_unlock;
Paul Cercueil2725f702014-05-02 11:02:16 +0200439
440 ret = read_integer(fd, &resp);
Paul Cercueil05e26262014-05-09 11:32:43 +0200441 network_unlock(pdata);
Paul Cercueil1494b862014-05-05 12:49:07 +0200442
Paul Cercueil2725f702014-05-02 11:02:16 +0200443 if (ret < 0)
444 return ret;
445 return (ssize_t) resp;
Paul Cercueil1494b862014-05-05 12:49:07 +0200446
447err_unlock:
Paul Cercueil05e26262014-05-09 11:32:43 +0200448 network_unlock(pdata);
Paul Cercueil1494b862014-05-05 12:49:07 +0200449 return ret;
Paul Cercueil2725f702014-05-02 11:02:16 +0200450}
451
Paul Cercueilcecda352014-05-06 18:14:29 +0200452static ssize_t network_write(const struct iio_device *dev,
453 const void *src, size_t len)
454{
455 char buf[1024];
456 snprintf(buf, sizeof(buf), "WRITEBUF %s %lu\r\n",
457 dev->id, (unsigned long) len);
Paul Cercueild93215d2014-05-19 16:36:06 +0200458 return do_write(dev->ctx->pdata, false, buf, src, len);
Paul Cercueilcecda352014-05-06 18:14:29 +0200459}
460
Paul Cercueil1494b862014-05-05 12:49:07 +0200461static ssize_t network_read_attr_helper(const struct iio_device *dev,
Paul Cercueil0cc0e162014-05-07 12:51:22 +0200462 const struct iio_channel *chn, const char *attr, char *dst,
Paul Cercueil1494b862014-05-05 12:49:07 +0200463 size_t len, bool is_debug)
Paul Cercueil3e94a5b2014-03-04 13:00:41 +0100464{
Paul Cercueil3e94a5b2014-03-04 13:00:41 +0100465 long read_len;
466 ssize_t ret;
467 char buf[1024];
Paul Cercueil05e26262014-05-09 11:32:43 +0200468 struct iio_context_pdata *pdata = dev->ctx->pdata;
469 int fd = pdata->fd;
Paul Cercueil1494b862014-05-05 12:49:07 +0200470 const char *id = dev->id;
Paul Cercueil3e94a5b2014-03-04 13:00:41 +0100471
Paul Cercueil99cf3d42014-03-06 12:35:26 +0100472 if (chn)
Paul Cercueil0cc0e162014-05-07 12:51:22 +0200473 snprintf(buf, sizeof(buf), "READ %s %s %s %s\r\n", id,
474 chn->is_output ? "OUTPUT" : "INPUT",
Paul Cercueil2a3e43d2014-05-21 16:58:45 +0200475 chn->id, attr ? attr : "");
Paul Cercueilc6f03612014-04-14 16:41:31 +0200476 else if (is_debug)
Paul Cercueil2a3e43d2014-05-21 16:58:45 +0200477 snprintf(buf, sizeof(buf), "READ %s DEBUG %s\r\n",
478 id, attr ? attr : "");
Paul Cercueil99cf3d42014-03-06 12:35:26 +0100479 else
Paul Cercueil2a3e43d2014-05-21 16:58:45 +0200480 snprintf(buf, sizeof(buf), "READ %s %s\r\n",
481 id, attr ? attr : "");
Paul Cercueil1494b862014-05-05 12:49:07 +0200482
Paul Cercueil05e26262014-05-09 11:32:43 +0200483 network_lock(pdata);
Paul Cercueilbb76bf92014-03-11 10:20:18 +0100484 read_len = exec_command(buf, fd);
Paul Cercueil1494b862014-05-05 12:49:07 +0200485 if (read_len < 0) {
Paul Cercueil05e26262014-05-09 11:32:43 +0200486 network_unlock(pdata);
Paul Cercueilbb76bf92014-03-11 10:20:18 +0100487 return (ssize_t) read_len;
Paul Cercueil1494b862014-05-05 12:49:07 +0200488 }
Paul Cercueil3e94a5b2014-03-04 13:00:41 +0100489
Paul Cercueil6e7f79e2014-04-04 12:27:24 +0200490 if ((unsigned long) read_len > len) {
Paul Cercueil3e94a5b2014-03-04 13:00:41 +0100491 ERROR("Value returned by server is too large\n");
Paul Cercueil05e26262014-05-09 11:32:43 +0200492 network_unlock(pdata);
Paul Cercueil3e94a5b2014-03-04 13:00:41 +0100493 return -EIO;
494 }
495
496 ret = read_all(dst, read_len, fd);
Paul Cercueil05e26262014-05-09 11:32:43 +0200497 network_unlock(pdata);
Paul Cercueil1494b862014-05-05 12:49:07 +0200498
Paul Cercueil3e94a5b2014-03-04 13:00:41 +0100499 if (ret < 0) {
500 strerror_r(-ret, buf, sizeof(buf));
501 ERROR("Unable to read response to READ: %s\n", buf);
502 return ret;
503 }
504
Paul Cercueil7d95fd72014-05-22 14:26:44 +0200505 return read_len;
Paul Cercueil3e94a5b2014-03-04 13:00:41 +0100506}
507
Paul Cercueil1494b862014-05-05 12:49:07 +0200508static ssize_t network_write_attr_helper(const struct iio_device *dev,
Paul Cercueil0cc0e162014-05-07 12:51:22 +0200509 const struct iio_channel *chn, const char *attr,
510 const char *src, size_t len, bool is_debug)
Paul Cercueil3e94a5b2014-03-04 13:00:41 +0100511{
Paul Cercueil3e94a5b2014-03-04 13:00:41 +0100512 char buf[1024];
Paul Cercueil1494b862014-05-05 12:49:07 +0200513 const char *id = dev->id;
Paul Cercueil3e94a5b2014-03-04 13:00:41 +0100514
Paul Cercueil07897d32014-03-06 12:46:08 +0100515 if (chn)
Paul Cercueil0cc0e162014-05-07 12:51:22 +0200516 snprintf(buf, sizeof(buf), "WRITE %s %s %s %s %lu\r\n",
517 id, chn->is_output ? "OUTPUT" : "INPUT",
Paul Cercueil8747efe2014-05-22 11:12:12 +0200518 chn->id, attr ? attr : "", (unsigned long) len);
Paul Cercueilc6f03612014-04-14 16:41:31 +0200519 else if (is_debug)
Paul Cercueil8747efe2014-05-22 11:12:12 +0200520 snprintf(buf, sizeof(buf), "WRITE %s DEBUG %s %lu\r\n",
521 id, attr ? attr : "", (unsigned long) len);
Paul Cercueil07897d32014-03-06 12:46:08 +0100522 else
Paul Cercueilcecda352014-05-06 18:14:29 +0200523 snprintf(buf, sizeof(buf), "WRITE %s %s %lu\r\n",
Paul Cercueil8747efe2014-05-22 11:12:12 +0200524 id, attr ? attr : "", (unsigned long) len);
Paul Cercueild93215d2014-05-19 16:36:06 +0200525 return do_write(dev->ctx->pdata, true, buf, src, len);
Paul Cercueil3e94a5b2014-03-04 13:00:41 +0100526}
527
Paul Cercueil99cf3d42014-03-06 12:35:26 +0100528static ssize_t network_read_dev_attr(const struct iio_device *dev,
Paul Cercueil50c762a2014-04-14 15:55:43 +0200529 const char *attr, char *dst, size_t len, bool is_debug)
Paul Cercueil99cf3d42014-03-06 12:35:26 +0100530{
Paul Cercueil5b577762014-06-03 15:31:42 +0200531 if (attr && ((is_debug && !iio_device_find_debug_attr(dev, attr)) ||
532 (!is_debug && !iio_device_find_attr(dev, attr))))
533 return -ENOENT;
534
Paul Cercueil1494b862014-05-05 12:49:07 +0200535 return network_read_attr_helper(dev, NULL, attr, dst, len, is_debug);
Paul Cercueil99cf3d42014-03-06 12:35:26 +0100536}
537
Paul Cercueil07897d32014-03-06 12:46:08 +0100538static ssize_t network_write_dev_attr(const struct iio_device *dev,
Paul Cercueilcecda352014-05-06 18:14:29 +0200539 const char *attr, const char *src, size_t len, bool is_debug)
Paul Cercueil07897d32014-03-06 12:46:08 +0100540{
Paul Cercueil5b577762014-06-03 15:31:42 +0200541 if (attr && ((is_debug && !iio_device_find_debug_attr(dev, attr)) ||
542 (!is_debug && !iio_device_find_attr(dev, attr))))
543 return -ENOENT;
544
Paul Cercueilcecda352014-05-06 18:14:29 +0200545 return network_write_attr_helper(dev, NULL, attr, src, len, is_debug);
Paul Cercueil07897d32014-03-06 12:46:08 +0100546}
547
Paul Cercueil99cf3d42014-03-06 12:35:26 +0100548static ssize_t network_read_chn_attr(const struct iio_channel *chn,
549 const char *attr, char *dst, size_t len)
550{
Paul Cercueil5b577762014-06-03 15:31:42 +0200551 if (attr && !iio_channel_find_attr(chn, attr))
552 return -ENOENT;
553
Paul Cercueil0cc0e162014-05-07 12:51:22 +0200554 return network_read_attr_helper(chn->dev, chn, attr, dst, len, false);
Paul Cercueil99cf3d42014-03-06 12:35:26 +0100555}
556
Paul Cercueil07897d32014-03-06 12:46:08 +0100557static ssize_t network_write_chn_attr(const struct iio_channel *chn,
Paul Cercueilcecda352014-05-06 18:14:29 +0200558 const char *attr, const char *src, size_t len)
Paul Cercueil07897d32014-03-06 12:46:08 +0100559{
Paul Cercueil5b577762014-06-03 15:31:42 +0200560 if (attr && !iio_channel_find_attr(chn, attr))
561 return -ENOENT;
562
Paul Cercueil0cc0e162014-05-07 12:51:22 +0200563 return network_write_attr_helper(chn->dev, chn, attr, src, len, false);
Paul Cercueil07897d32014-03-06 12:46:08 +0100564}
565
Paul Cercueildcab40c2014-03-11 10:59:14 +0100566static int network_get_trigger(const struct iio_device *dev,
567 const struct iio_device **trigger)
568{
569 struct iio_context_pdata *pdata = dev->ctx->pdata;
570 unsigned int i;
571 char buf[1024];
572 ssize_t ret;
573 long resp;
574
575 snprintf(buf, sizeof(buf), "GETTRIG %s\r\n", dev->id);
Paul Cercueil1494b862014-05-05 12:49:07 +0200576
Paul Cercueil05e26262014-05-09 11:32:43 +0200577 network_lock(dev->ctx->pdata);
Paul Cercueildcab40c2014-03-11 10:59:14 +0100578 resp = exec_command(buf, pdata->fd);
579 if (resp < 0) {
Paul Cercueil05e26262014-05-09 11:32:43 +0200580 network_unlock(pdata);
Paul Cercueildcab40c2014-03-11 10:59:14 +0100581 return (int) resp;
582 } else if (resp == 0) {
583 *trigger = NULL;
Paul Cercueil05e26262014-05-09 11:32:43 +0200584 network_unlock(pdata);
Paul Cercueildcab40c2014-03-11 10:59:14 +0100585 return 0;
Paul Cercueil6e7f79e2014-04-04 12:27:24 +0200586 } else if ((unsigned long) resp > sizeof(buf)) {
Paul Cercueildcab40c2014-03-11 10:59:14 +0100587 ERROR("Value returned by server is too large\n");
Paul Cercueil05e26262014-05-09 11:32:43 +0200588 network_unlock(pdata);
Paul Cercueildcab40c2014-03-11 10:59:14 +0100589 return -EIO;
590 }
591
592 ret = read_all(buf, resp, pdata->fd);
Paul Cercueil05e26262014-05-09 11:32:43 +0200593 network_unlock(pdata);
Paul Cercueil1494b862014-05-05 12:49:07 +0200594
Paul Cercueildcab40c2014-03-11 10:59:14 +0100595 if (ret < 0) {
596 strerror_r(-ret, buf, sizeof(buf));
597 ERROR("Unable to read response to GETTRIG: %s\n", buf);
598 return ret;
599 }
600
601 for (i = 0; i < dev->ctx->nb_devices; i++) {
602 struct iio_device *cur = dev->ctx->devices[i];
603 if (iio_device_is_trigger(cur) &&
604 !strncmp(cur->name, buf, resp)) {
605 *trigger = cur;
606 return 0;
607 }
608 }
609
610 return -ENXIO;
611}
612
613static int network_set_trigger(const struct iio_device *dev,
614 const struct iio_device *trigger)
615{
Paul Cercueil1494b862014-05-05 12:49:07 +0200616 int ret;
Paul Cercueildcab40c2014-03-11 10:59:14 +0100617 char buf[1024];
618 if (trigger)
619 snprintf(buf, sizeof(buf), "SETTRIG %s %s\r\n",
620 dev->id, trigger->id);
621 else
622 snprintf(buf, sizeof(buf), "SETTRIG %s\r\n", dev->id);
Paul Cercueil1494b862014-05-05 12:49:07 +0200623
Paul Cercueil05e26262014-05-09 11:32:43 +0200624 network_lock(dev->ctx->pdata);
Paul Cercueil1494b862014-05-05 12:49:07 +0200625 ret = (int) exec_command(buf, dev->ctx->pdata->fd);
Paul Cercueil05e26262014-05-09 11:32:43 +0200626 network_unlock(dev->ctx->pdata);
Paul Cercueil1494b862014-05-05 12:49:07 +0200627 return ret;
Paul Cercueildcab40c2014-03-11 10:59:14 +0100628}
629
Paul Cercueil8fd9c8f2014-03-03 17:21:31 +0100630static void network_shutdown(struct iio_context *ctx)
631{
632 struct iio_context_pdata *pdata = ctx->pdata;
Paul Cercueil44ae11c2014-03-17 09:56:29 +0100633 unsigned int i;
Paul Cercueil8fd9c8f2014-03-03 17:21:31 +0100634
Paul Cercueil05e26262014-05-09 11:32:43 +0200635 network_lock(pdata);
Paul Cercueilbb76bf92014-03-11 10:20:18 +0100636 write_command("\r\nEXIT\r\n", pdata->fd);
Paul Cercueil8fd9c8f2014-03-03 17:21:31 +0100637 close(pdata->fd);
Paul Cercueil05e26262014-05-09 11:32:43 +0200638 network_unlock(pdata);
Paul Cercueil1494b862014-05-05 12:49:07 +0200639
Paul Cercueil05e26262014-05-09 11:32:43 +0200640#if HAVE_PTHREAD
Paul Cercueil1494b862014-05-05 12:49:07 +0200641 /* XXX(pcercuei): is this safe? */
642 pthread_mutex_destroy(&pdata->lock);
Paul Cercueil05e26262014-05-09 11:32:43 +0200643#endif
Paul Cercueil8fd9c8f2014-03-03 17:21:31 +0100644 free(pdata);
Paul Cercueil44ae11c2014-03-17 09:56:29 +0100645
646 for (i = 0; i < ctx->nb_devices; i++) {
647 struct iio_device *dev = ctx->devices[i];
648 if (dev->pdata)
649 free(dev->pdata);
650 }
Paul Cercueil8fd9c8f2014-03-03 17:21:31 +0100651}
652
Paul Cercueil6691a3f2014-05-02 12:32:01 +0200653static int network_get_version(const struct iio_context *ctx,
Paul Cercueil9de9e9d2014-05-20 13:18:19 +0200654 unsigned int *major, unsigned int *minor, char git_tag[8])
Paul Cercueil6691a3f2014-05-02 12:32:01 +0200655{
656 struct iio_context_pdata *pdata = ctx->pdata;
657 long maj, min;
658 int ret;
Paul Cercueil6691a3f2014-05-02 12:32:01 +0200659
Paul Cercueil05e26262014-05-09 11:32:43 +0200660 network_lock(pdata);
Paul Cercueil1494b862014-05-05 12:49:07 +0200661 ret = (int) write_command("VERSION\r\n", pdata->fd);
662 if (ret < 0)
663 goto err_unlock;
664
665 ret = read_integer(pdata->fd, &maj);
666 if (!ret)
667 ret = read_integer(pdata->fd, &min);
668 if (!ret) {
Paul Cercueil9de9e9d2014-05-20 13:18:19 +0200669 char tag[8];
670 tag[7] = '\0';
671
672 ret = read_all(tag, sizeof(tag) - 1, pdata->fd);
673 if (ret < 0)
674 goto err_unlock;
675
Paul Cercueild15d9952014-05-20 11:40:08 +0200676 if (major)
677 *major = (unsigned int) maj;
678 if (minor)
679 *minor = (unsigned int) min;
Paul Cercueil9de9e9d2014-05-20 13:18:19 +0200680 if (git_tag)
681 strncpy(git_tag, tag, 8);
Paul Cercueil1494b862014-05-05 12:49:07 +0200682 }
683
684err_unlock:
Paul Cercueil05e26262014-05-09 11:32:43 +0200685 network_unlock(pdata);
Paul Cercueil1494b862014-05-05 12:49:07 +0200686 return ret;
Paul Cercueil6691a3f2014-05-02 12:32:01 +0200687}
688
Paul Cercueil8a266f12014-06-10 16:06:31 +0200689static unsigned int calculate_remote_timeout(unsigned int timeout)
690{
691 /* XXX(pcercuei): We currently hardcode timeout / 2 for the backend used
692 * by the remote. Is there something better to do here? */
693 return timeout / 2;
694}
695
Paul Cercueilbca3dbc2014-06-11 12:00:21 +0200696static int set_socket_timeout(int fd, unsigned int timeout)
Paul Cercueil8a266f12014-06-10 16:06:31 +0200697{
Paul Cercueil8a266f12014-06-10 16:06:31 +0200698 if (setsockopt(fd, SOL_SOCKET, SO_SNDTIMEO,
699 &timeout, sizeof(timeout)) < 0 ||
700 setsockopt(fd, SOL_SOCKET, SO_RCVTIMEO,
Paul Cercueilbca3dbc2014-06-11 12:00:21 +0200701 &timeout, sizeof(timeout)) < 0)
702 return -errno;
703 else
704 return 0;
705}
706
707static int set_remote_timeout(struct iio_context *ctx, unsigned int timeout)
708{
709 char buf[1024];
710 int ret;
711
712 snprintf(buf, sizeof(buf), "TIMEOUT %u\r\n", timeout);
713 network_lock(ctx->pdata);
714 ret = (int) exec_command(buf, ctx->pdata->fd);
715 network_unlock(ctx->pdata);
716 return ret;
717}
718
719static int network_set_timeout(struct iio_context *ctx, unsigned int timeout)
720{
721 int ret = set_socket_timeout(ctx->pdata->fd, timeout);
722 if (!ret) {
723 timeout = calculate_remote_timeout(timeout);
724 ret = set_remote_timeout(ctx, timeout);
725 }
726 if (ret < 0) {
727 char buf[1024];
728 strerror_r(-ret, buf, sizeof(buf));
Paul Cercueil8a266f12014-06-10 16:06:31 +0200729 WARNING("Unable to set R/W timeout: %s\n", buf);
730 } else {
Paul Cercueil8a266f12014-06-10 16:06:31 +0200731 ctx->rw_timeout_ms = timeout;
732 }
733 return ret;
734}
735
Paul Cercueilc7bad0f2014-03-03 17:06:48 +0100736static struct iio_backend_ops network_ops = {
Paul Cercueilba059762014-03-14 11:02:02 +0100737 .open = network_open,
738 .close = network_close,
Paul Cercueil9945bc82014-03-05 14:07:29 +0100739 .read = network_read,
Paul Cercueil2725f702014-05-02 11:02:16 +0200740 .write = network_write,
Paul Cercueil3e94a5b2014-03-04 13:00:41 +0100741 .read_device_attr = network_read_dev_attr,
742 .write_device_attr = network_write_dev_attr,
Paul Cercueil99cf3d42014-03-06 12:35:26 +0100743 .read_channel_attr = network_read_chn_attr,
Paul Cercueil07897d32014-03-06 12:46:08 +0100744 .write_channel_attr = network_write_chn_attr,
Paul Cercueildcab40c2014-03-11 10:59:14 +0100745 .get_trigger = network_get_trigger,
746 .set_trigger = network_set_trigger,
Paul Cercueil8fd9c8f2014-03-03 17:21:31 +0100747 .shutdown = network_shutdown,
Paul Cercueil6691a3f2014-05-02 12:32:01 +0200748 .get_version = network_get_version,
Paul Cercueil8a266f12014-06-10 16:06:31 +0200749 .set_timeout = network_set_timeout,
Paul Cercueilc7bad0f2014-03-03 17:06:48 +0100750};
751
752static struct iio_context * get_context(int fd)
753{
754 struct iio_context *ctx;
Paul Cercueile60c3ed2014-03-04 11:23:56 +0100755 char *xml;
Paul Cercueilbb76bf92014-03-11 10:20:18 +0100756 long xml_len = exec_command("PRINT\r\n", fd);
757 if (xml_len < 0)
Paul Cercueilc7bad0f2014-03-03 17:06:48 +0100758 return NULL;
Paul Cercueile60c3ed2014-03-04 11:23:56 +0100759
760 DEBUG("Server returned a XML string of length %li\n", xml_len);
Paul Cercueilc7bad0f2014-03-03 17:06:48 +0100761 xml = malloc(xml_len);
762 if (!xml) {
763 ERROR("Unable to allocate data\n");
764 return NULL;
765 }
766
767 DEBUG("Reading XML string...\n");
768 read_all(xml, xml_len, fd);
769
770 DEBUG("Creating context from XML...\n");
771 ctx = iio_create_xml_context_mem(xml, xml_len);
772 free(xml);
773 return ctx;
774}
775
776struct iio_context * iio_create_network_context(const char *host)
777{
Paul Cercueil2e38bbe2014-03-19 15:27:15 +0100778 struct addrinfo hints, *res;
Paul Cercueilc7bad0f2014-03-03 17:06:48 +0100779 struct iio_context *ctx;
Paul Cercueil8fd9c8f2014-03-03 17:21:31 +0100780 struct iio_context_pdata *pdata;
Paul Cercueil44ae11c2014-03-17 09:56:29 +0100781 unsigned int i;
Paul Cercueil2e38bbe2014-03-19 15:27:15 +0100782 int fd, ret;
Paul Cercueil1fef1a52014-04-07 16:31:15 +0200783#ifdef _WIN32
784 WSADATA wsaData;
785
786 ret = WSAStartup(MAKEWORD(2, 0), &wsaData);
787 if (ret < 0) {
788 ERROR("WSAStartup failed with error %i\n", ret);
789 return NULL;
790 }
791#endif
Paul Cercueilc7bad0f2014-03-03 17:06:48 +0100792
Paul Cercueil2e38bbe2014-03-19 15:27:15 +0100793 memset(&hints, 0, sizeof(hints));
794 hints.ai_family = AF_UNSPEC;
795 hints.ai_socktype = SOCK_STREAM;
Paul Cercueilab114932014-05-19 13:03:17 +0200796
797#ifdef HAVE_AVAHI
798 if (!host) {
799 char addr_str[AVAHI_ADDRESS_STR_MAX];
800 char port_str[6];
801 AvahiAddress address;
Paul Cercueil0f729d32014-06-05 17:38:54 +0200802 uint16_t port = IIOD_PORT;
Paul Cercueilab114932014-05-19 13:03:17 +0200803
804 memset(&address, 0, sizeof(address));
805
806 ret = discover_host(&address, &port);
807 if (ret < 0) {
808 ERROR("Unable to find host: %s\n", strerror(-ret));
809 return NULL;
810 }
811
812 avahi_address_snprint(addr_str, sizeof(addr_str), &address);
813 snprintf(port_str, sizeof(port_str), "%hu", port);
814 ret = getaddrinfo(addr_str, port_str, &hints, &res);
815 } else
816#endif
817 {
818 ret = getaddrinfo(host, IIOD_PORT_STR, &hints, &res);
819 }
820
Paul Cercueil2e38bbe2014-03-19 15:27:15 +0100821 if (ret) {
Paul Cercueilab114932014-05-19 13:03:17 +0200822 ERROR("Unable to find host: %s\n", gai_strerror(ret));
Paul Cercueilc7bad0f2014-03-03 17:06:48 +0100823 return NULL;
Paul Cercueilc7bad0f2014-03-03 17:06:48 +0100824 }
825
Paul Cercueil2e38bbe2014-03-19 15:27:15 +0100826 fd = socket(res->ai_family, res->ai_socktype, 0);
Paul Cercueilc7bad0f2014-03-03 17:06:48 +0100827 if (fd < 0) {
828 ERROR("Unable to open socket\n");
829 return NULL;
830 }
831
Paul Cercueil2e38bbe2014-03-19 15:27:15 +0100832 if (connect(fd, res->ai_addr, res->ai_addrlen) < 0) {
Paul Cercueilc7bad0f2014-03-03 17:06:48 +0100833 ERROR("Unable to connect\n");
834 goto err_close_socket;
835 }
836
Paul Cercueilbca3dbc2014-06-11 12:00:21 +0200837 set_socket_timeout(fd, DEFAULT_TIMEOUT_MS);
838
Paul Cercueil8fd9c8f2014-03-03 17:21:31 +0100839 pdata = calloc(1, sizeof(*pdata));
840 if (!pdata) {
841 ERROR("Unable to allocate memory\n");
842 goto err_close_socket;
843 }
844
845 pdata->fd = fd;
846
Paul Cercueilc7bad0f2014-03-03 17:06:48 +0100847 DEBUG("Creating context...\n");
848 ctx = get_context(fd);
849 if (!ctx)
Paul Cercueil8fd9c8f2014-03-03 17:21:31 +0100850 goto err_free_pdata;
Paul Cercueilc7bad0f2014-03-03 17:06:48 +0100851
Paul Cercueil44ae11c2014-03-17 09:56:29 +0100852 for (i = 0; i < ctx->nb_devices; i++) {
853 struct iio_device *dev = ctx->devices[i];
Paul Cercueilff778232014-03-24 14:23:08 +0100854 uint32_t *mask = NULL;
855
856 dev->words = (dev->nb_channels + 31) / 32;
857 if (dev->words) {
858 mask = calloc(dev->words, sizeof(*mask));
859 if (!mask)
860 goto err_network_shutdown;
861 }
862
863 dev->mask = mask;
Paul Cercueil44ae11c2014-03-17 09:56:29 +0100864 }
865
Paul Cercueilff778232014-03-24 14:23:08 +0100866
Paul Cercueilc7bad0f2014-03-03 17:06:48 +0100867 /* Override the name and low-level functions of the XML context
868 * with those corresponding to the network context */
869 ctx->name = "network";
870 ctx->ops = &network_ops;
Paul Cercueil8fd9c8f2014-03-03 17:21:31 +0100871 ctx->pdata = pdata;
Paul Cercueilc7bad0f2014-03-03 17:06:48 +0100872
Paul Cercueil4c6729d2014-04-04 17:24:41 +0200873 ret = iio_context_init(ctx);
874 if (ret < 0) {
875 char buf[1024];
876 strerror_r(-ret, buf, sizeof(buf));
877 ERROR("Unable to initialize context: %s\n", buf);
Paul Cercueildfcd6b12014-04-08 14:45:36 +0200878 goto err_network_shutdown;
Paul Cercueil4c6729d2014-04-04 17:24:41 +0200879 }
880
Paul Cercueil05e26262014-05-09 11:32:43 +0200881#if HAVE_PTHREAD
Paul Cercueil1494b862014-05-05 12:49:07 +0200882 ret = pthread_mutex_init(&pdata->lock, NULL);
883 if (ret < 0) {
884 char buf[1024];
885 strerror_r(-ret, buf, sizeof(buf));
886 ERROR("Unable to initialize mutex: %s\n", buf);
887 goto err_network_shutdown;
888 }
Paul Cercueil05e26262014-05-09 11:32:43 +0200889#endif
Paul Cercueil1494b862014-05-05 12:49:07 +0200890
Paul Cercueilbca3dbc2014-06-11 12:00:21 +0200891 set_remote_timeout(ctx, calculate_remote_timeout(DEFAULT_TIMEOUT_MS));
Paul Cercueilc7bad0f2014-03-03 17:06:48 +0100892 return ctx;
893
Paul Cercueil44ae11c2014-03-17 09:56:29 +0100894err_network_shutdown:
895 network_shutdown(ctx);
896 iio_context_destroy(ctx);
Paul Cercueil8fd9c8f2014-03-03 17:21:31 +0100897err_free_pdata:
898 free(pdata);
Paul Cercueilc7bad0f2014-03-03 17:06:48 +0100899err_close_socket:
900 close(fd);
901 return NULL;
902}