blob: 75b82f84b34624fe9cd2ee36ba7c8200c85a7145 [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
Paul Cercueil9aabe892014-09-02 12:33:46 +020021#ifndef HAVE_PTHREAD
22#define HAVE_PTHREAD 1
23#endif
24
Paul Cercueilc7bad0f2014-03-03 17:06:48 +010025#include <errno.h>
Paul Cercueile60c3ed2014-03-04 11:23:56 +010026#include <stdbool.h>
Paul Cercueilc7bad0f2014-03-03 17:06:48 +010027#include <string.h>
28#include <sys/types.h>
Paul Cercueilab114932014-05-19 13:03:17 +020029#include <time.h>
Paul Cercueil1fef1a52014-04-07 16:31:15 +020030
31#ifdef _WIN32
32#include <winsock2.h>
33#include <ws2tcpip.h>
34#define close(s) closesocket(s)
35
36/* winsock2.h defines ERROR, we don't want that */
37#undef ERROR
38
39#else /* _WIN32 */
40#include <netdb.h>
Paul Cercueil9aabe892014-09-02 12:33:46 +020041#if HAVE_PTHREAD
Paul Cercueil05e26262014-05-09 11:32:43 +020042#include <pthread.h>
Paul Cercueil9aabe892014-09-02 12:33:46 +020043#endif
Paul Cercueilc7bad0f2014-03-03 17:06:48 +010044#include <sys/socket.h>
45#include <unistd.h>
Paul Cercueil1fef1a52014-04-07 16:31:15 +020046#endif /* _WIN32 */
47
Paul Cercueilab114932014-05-19 13:03:17 +020048#ifdef HAVE_AVAHI
49#include <avahi-client/client.h>
50#include <avahi-common/error.h>
51#include <avahi-client/lookup.h>
52#include <avahi-common/simple-watch.h>
53#endif
54
Paul Cercueil1fef1a52014-04-07 16:31:15 +020055#include "debug.h"
Paul Cercueilc7bad0f2014-03-03 17:06:48 +010056
Paul Cercueil8a266f12014-06-10 16:06:31 +020057#define DEFAULT_TIMEOUT_MS 5000
58
Paul Cercueil2e38bbe2014-03-19 15:27:15 +010059#define _STRINGIFY(x) #x
60#define STRINGIFY(x) _STRINGIFY(x)
61
Paul Cercueilc7bad0f2014-03-03 17:06:48 +010062#define IIOD_PORT 30431
Paul Cercueil2e38bbe2014-03-19 15:27:15 +010063#define IIOD_PORT_STR STRINGIFY(IIOD_PORT)
Paul Cercueilc7bad0f2014-03-03 17:06:48 +010064
Paul Cercueil8fd9c8f2014-03-03 17:21:31 +010065struct iio_context_pdata {
66 int fd;
Paul Cercueil12d41832014-10-28 14:35:53 +010067 char *host;
Paul Cercueil05e26262014-05-09 11:32:43 +020068#if HAVE_PTHREAD
Paul Cercueil1494b862014-05-05 12:49:07 +020069 pthread_mutex_t lock;
Paul Cercueil05e26262014-05-09 11:32:43 +020070#endif
Paul Cercueil8fd9c8f2014-03-03 17:21:31 +010071};
72
Paul Cercueilab114932014-05-19 13:03:17 +020073#ifdef HAVE_AVAHI
74struct avahi_discovery_data {
75 AvahiSimplePoll *poll;
76 AvahiAddress *address;
77 uint16_t *port;
78 bool found, resolved;
79};
80
81static void __avahi_resolver_cb(AvahiServiceResolver *resolver,
82 __notused AvahiIfIndex iface, __notused AvahiProtocol proto,
83 __notused AvahiResolverEvent event, __notused const char *name,
84 __notused const char *type, __notused const char *domain,
85 __notused const char *host_name, const AvahiAddress *address,
86 uint16_t port, __notused AvahiStringList *txt,
87 __notused AvahiLookupResultFlags flags, void *d)
88{
89 struct avahi_discovery_data *ddata = (struct avahi_discovery_data *) d;
90
91 memcpy(ddata->address, address, sizeof(*address));
92 *ddata->port = port;
93 ddata->resolved = true;
94 avahi_service_resolver_free(resolver);
95}
96
97static void __avahi_browser_cb(AvahiServiceBrowser *browser,
98 AvahiIfIndex iface, AvahiProtocol proto,
99 AvahiBrowserEvent event, const char *name,
100 const char *type, const char *domain,
101 __notused AvahiLookupResultFlags flags, void *d)
102{
103 struct avahi_discovery_data *ddata = (struct avahi_discovery_data *) d;
104 struct AvahiClient *client = avahi_service_browser_get_client(browser);
105
106 switch (event) {
107 default:
108 case AVAHI_BROWSER_NEW:
109 ddata->found = !!avahi_service_resolver_new(client, iface,
110 proto, name, type, domain,
111 AVAHI_PROTO_UNSPEC, 0,
112 __avahi_resolver_cb, d);
113 break;
114 case AVAHI_BROWSER_ALL_FOR_NOW:
115 if (ddata->found) {
116 while (!ddata->resolved) {
117 struct timespec ts;
118 ts.tv_sec = 0;
119 ts.tv_nsec = 4000000;
120 nanosleep(&ts, NULL);
121 }
122 }
123 case AVAHI_BROWSER_FAILURE: /* fall-through */
124 avahi_simple_poll_quit(ddata->poll);
125 case AVAHI_BROWSER_CACHE_EXHAUSTED: /* fall-through */
126 break;
127 }
128}
129
130static int discover_host(AvahiAddress *addr, uint16_t *port)
131{
132 struct avahi_discovery_data ddata;
133 int ret = 0;
134 AvahiClient *client;
135 AvahiServiceBrowser *browser;
136 AvahiSimplePoll *poll = avahi_simple_poll_new();
137 if (!poll)
138 return -ENOMEM;
139
140 client = avahi_client_new(avahi_simple_poll_get(poll),
141 0, NULL, NULL, &ret);
142 if (!client) {
143 ERROR("Unable to start ZeroConf client :%s\n",
144 avahi_strerror(ret));
145 goto err_free_poll;
146 }
147
148 memset(&ddata, 0, sizeof(ddata));
149 ddata.poll = poll;
150 ddata.address = addr;
151 ddata.port = port;
152
153 browser = avahi_service_browser_new(client,
154 AVAHI_IF_UNSPEC, AVAHI_PROTO_UNSPEC,
155 "_iio._tcp", NULL, 0, __avahi_browser_cb, &ddata);
156 if (!browser) {
157 ret = avahi_client_errno(client);
158 ERROR("Unable to create ZeroConf browser: %s\n",
159 avahi_strerror(ret));
160 goto err_free_client;
161 }
162
163 DEBUG("Trying to discover host\n");
164 avahi_simple_poll_loop(poll);
165
166 if (!ddata.found)
167 ret = ENXIO;
168
169 avahi_service_browser_free(browser);
170err_free_client:
171 avahi_client_free(client);
172err_free_poll:
173 avahi_simple_poll_free(poll);
174 return -ret; /* we want a negative error code */
175}
176#endif /* HAVE_AVAHI */
177
Paul Cercueil05e26262014-05-09 11:32:43 +0200178static void network_lock(struct iio_context_pdata *pdata)
179{
180#if HAVE_PTHREAD
181 pthread_mutex_lock(&pdata->lock);
182#endif
183}
184
185static void network_unlock(struct iio_context_pdata *pdata)
186{
187#if HAVE_PTHREAD
188 pthread_mutex_unlock(&pdata->lock);
189#endif
190}
191
Paul Cercueilc7bad0f2014-03-03 17:06:48 +0100192static ssize_t write_all(const void *src, size_t len, int fd)
193{
Paul Cercueil6e7f79e2014-04-04 12:27:24 +0200194 uintptr_t ptr = (uintptr_t) src;
Paul Cercueilc7bad0f2014-03-03 17:06:48 +0100195 while (len) {
Paul Cercueil6e7f79e2014-04-04 12:27:24 +0200196 ssize_t ret = send(fd, (const void *) ptr, len, 0);
Paul Cercueilc7bad0f2014-03-03 17:06:48 +0100197 if (ret < 0)
198 return -errno;
199 ptr += ret;
200 len -= ret;
201 }
Paul Cercueil6e7f79e2014-04-04 12:27:24 +0200202 return ptr - (uintptr_t) src;
Paul Cercueilc7bad0f2014-03-03 17:06:48 +0100203}
204
205static ssize_t read_all(void *dst, size_t len, int fd)
206{
Paul Cercueil6e7f79e2014-04-04 12:27:24 +0200207 uintptr_t ptr = (uintptr_t) dst;
Paul Cercueilc7bad0f2014-03-03 17:06:48 +0100208 while (len) {
Paul Cercueil6e7f79e2014-04-04 12:27:24 +0200209 ssize_t ret = recv(fd, (void *) ptr, len, 0);
Paul Cercueilc7bad0f2014-03-03 17:06:48 +0100210 if (ret < 0)
211 return -errno;
212 ptr += ret;
213 len -= ret;
214 }
Paul Cercueil6e7f79e2014-04-04 12:27:24 +0200215 return ptr - (uintptr_t) dst;
Paul Cercueilc7bad0f2014-03-03 17:06:48 +0100216}
217
Paul Cercueile60c3ed2014-03-04 11:23:56 +0100218static int read_integer(int fd, long *val)
219{
220 unsigned int i;
221 char buf[1024], *ptr;
222 ssize_t ret;
223 bool found = false;
224
225 for (i = 0; i < sizeof(buf) - 1; i++) {
226 ret = read_all(buf + i, 1, fd);
227 if (ret < 0)
228 return (int) ret;
229
Paul Cercueil6691a3f2014-05-02 12:32:01 +0200230 /* Skip the eventual first few carriage returns.
231 * Also stop when a dot is found (for parsing floats) */
232 if (buf[i] != '\n' && buf[i] != '.')
Paul Cercueile60c3ed2014-03-04 11:23:56 +0100233 found = true;
234 else if (found)
235 break;
236 }
237
238 buf[i] = '\0';
239 ret = (ssize_t) strtol(buf, &ptr, 10);
240 if (ptr == buf)
241 return -EINVAL;
242 *val = (long) ret;
243 return 0;
244}
245
Paul Cercueilbb76bf92014-03-11 10:20:18 +0100246static ssize_t write_command(const char *cmd, int fd)
247{
248 ssize_t ret;
249
250 DEBUG("Writing command: %s\n", cmd);
251 ret = write_all(cmd, strlen(cmd), fd);
252 if (ret < 0) {
253 char buf[1024];
254 strerror_r(-ret, buf, sizeof(buf));
255 ERROR("Unable to send command: %s\n", buf);
256 }
257 return ret;
258}
259
260static long exec_command(const char *cmd, int fd)
261{
262 long resp;
263 ssize_t ret = write_command(cmd, fd);
264 if (ret < 0)
265 return (long) ret;
266
267 DEBUG("Reading response\n");
268 ret = read_integer(fd, &resp);
269 if (ret < 0) {
270 char buf[1024];
271 strerror_r(-ret, buf, sizeof(buf));
272 ERROR("Unable to read response: %s\n", buf);
273 return (long) ret;
274 }
275
Paul Cercueilc7fe2ea2014-03-28 11:38:45 +0100276#if LOG_LEVEL >= DEBUG_L
Paul Cercueilbb76bf92014-03-11 10:20:18 +0100277 if (resp < 0) {
278 char buf[1024];
279 strerror_r(-resp, buf, sizeof(buf));
Paul Cercueilc7fe2ea2014-03-28 11:38:45 +0100280 DEBUG("Server returned an error: %s\n", buf);
Paul Cercueilbb76bf92014-03-11 10:20:18 +0100281 }
Paul Cercueilc7fe2ea2014-03-28 11:38:45 +0100282#endif
283
Paul Cercueilbb76bf92014-03-11 10:20:18 +0100284 return resp;
285}
286
Paul Cercueil71694c72014-05-22 14:02:13 +0200287static int network_open(const struct iio_device *dev, size_t samples_count,
288 uint32_t *mask, size_t nb, bool cyclic)
Paul Cercueilba059762014-03-14 11:02:02 +0100289{
290 char buf[1024], *ptr;
291 unsigned int i;
Paul Cercueil44ae11c2014-03-17 09:56:29 +0100292 int ret;
Paul Cercueilba059762014-03-14 11:02:02 +0100293
Paul Cercueilff778232014-03-24 14:23:08 +0100294 if (nb != dev->words)
Paul Cercueilba059762014-03-14 11:02:02 +0100295 return -EINVAL;
296
Paul Cercueil3c407f82014-04-02 14:11:59 +0200297 snprintf(buf, sizeof(buf), "OPEN %s %lu ",
298 dev->id, (unsigned long) samples_count);
Paul Cercueilba059762014-03-14 11:02:02 +0100299 ptr = buf + strlen(buf);
300
301 for (i = nb; i > 0; i--) {
Paul Cercueil8c29e412014-04-07 09:46:45 +0200302 snprintf(ptr, (ptr - buf) + i * 8, "%08x", mask[i - 1]);
Paul Cercueilba059762014-03-14 11:02:02 +0100303 ptr += 8;
304 }
Paul Cercueil71694c72014-05-22 14:02:13 +0200305
306 strcpy(ptr, cyclic ? " CYCLIC\r\n" : "\r\n");
Paul Cercueilba059762014-03-14 11:02:02 +0100307
Paul Cercueil05e26262014-05-09 11:32:43 +0200308 network_lock(dev->ctx->pdata);
Paul Cercueil44ae11c2014-03-17 09:56:29 +0100309 ret = (int) exec_command(buf, dev->ctx->pdata->fd);
Paul Cercueil05e26262014-05-09 11:32:43 +0200310 network_unlock(dev->ctx->pdata);
Paul Cercueil1494b862014-05-05 12:49:07 +0200311
Paul Cercueil44ae11c2014-03-17 09:56:29 +0100312 if (ret < 0) {
Paul Cercueil44ae11c2014-03-17 09:56:29 +0100313 return ret;
314 } else {
Paul Cercueilff778232014-03-24 14:23:08 +0100315 memcpy(dev->mask, mask, nb * sizeof(*mask));
Paul Cercueil44ae11c2014-03-17 09:56:29 +0100316 return 0;
317 }
Paul Cercueilba059762014-03-14 11:02:02 +0100318}
319
320static int network_close(const struct iio_device *dev)
321{
Paul Cercueil1494b862014-05-05 12:49:07 +0200322 int ret;
Paul Cercueilba059762014-03-14 11:02:02 +0100323 char buf[1024];
324 snprintf(buf, sizeof(buf), "CLOSE %s\r\n", dev->id);
Paul Cercueil1494b862014-05-05 12:49:07 +0200325
Paul Cercueil05e26262014-05-09 11:32:43 +0200326 network_lock(dev->ctx->pdata);
Paul Cercueil1494b862014-05-05 12:49:07 +0200327 ret = (int) exec_command(buf, dev->ctx->pdata->fd);
Paul Cercueil05e26262014-05-09 11:32:43 +0200328 network_unlock(dev->ctx->pdata);
Paul Cercueil1494b862014-05-05 12:49:07 +0200329
330 return ret;
Paul Cercueilba059762014-03-14 11:02:02 +0100331}
332
Paul Cercueil45c575d2014-03-20 15:14:01 +0100333static ssize_t network_read(const struct iio_device *dev, void *dst, size_t len,
334 uint32_t *mask, size_t words)
Paul Cercueilf9286452014-03-18 14:32:17 +0100335{
Paul Cercueil6e7f79e2014-04-04 12:27:24 +0200336 uintptr_t ptr = (uintptr_t) dst;
Paul Cercueil05e26262014-05-09 11:32:43 +0200337 struct iio_context_pdata *pdata = dev->ctx->pdata;
338 int fd = pdata->fd;
Paul Cercueil45c575d2014-03-20 15:14:01 +0100339 ssize_t ret, read = 0;
Paul Cercueil9945bc82014-03-05 14:07:29 +0100340 char buf[1024];
Paul Cercueil45c575d2014-03-20 15:14:01 +0100341 bool read_mask = true;
Paul Cercueil9945bc82014-03-05 14:07:29 +0100342
Paul Cercueil45c575d2014-03-20 15:14:01 +0100343 if (!len || words != (dev->nb_channels + 31) / 32)
Paul Cercueil9945bc82014-03-05 14:07:29 +0100344 return -EINVAL;
345
Paul Cercueila78b6eb2014-03-17 17:28:07 +0100346 snprintf(buf, sizeof(buf), "READBUF %s %lu\r\n",
347 dev->id, (unsigned long) len);
Paul Cercueil1494b862014-05-05 12:49:07 +0200348
Paul Cercueil05e26262014-05-09 11:32:43 +0200349 network_lock(pdata);
Paul Cercueilbb76bf92014-03-11 10:20:18 +0100350 ret = write_command(buf, fd);
Paul Cercueil1494b862014-05-05 12:49:07 +0200351 if (ret < 0) {
Paul Cercueil05e26262014-05-09 11:32:43 +0200352 network_unlock(pdata);
Paul Cercueil9945bc82014-03-05 14:07:29 +0100353 return ret;
Paul Cercueil1494b862014-05-05 12:49:07 +0200354 }
Paul Cercueil9945bc82014-03-05 14:07:29 +0100355
356 do {
Paul Cercueil5cab3ae2014-03-14 11:23:56 +0100357 unsigned int i;
Paul Cercueil9945bc82014-03-05 14:07:29 +0100358 long read_len;
359
360 DEBUG("Reading READ response\n");
361 ret = read_integer(fd, &read_len);
362 if (ret < 0) {
363 strerror_r(-ret, buf, sizeof(buf));
364 ERROR("Unable to read response to READ: %s\n", buf);
Paul Cercueil05e26262014-05-09 11:32:43 +0200365 network_unlock(pdata);
Paul Cercueil6e7f79e2014-04-04 12:27:24 +0200366 return read ? read : ret;
Paul Cercueil9945bc82014-03-05 14:07:29 +0100367 }
368
369 if (read_len < 0) {
370 strerror_r(-read_len, buf, sizeof(buf));
371 ERROR("Server returned an error: %s\n", buf);
Paul Cercueil05e26262014-05-09 11:32:43 +0200372 network_unlock(pdata);
Paul Cercueil6e7f79e2014-04-04 12:27:24 +0200373 return read ? read : read_len;
Paul Cercueila78b6eb2014-03-17 17:28:07 +0100374 } else if (read_len == 0) {
375 break;
Paul Cercueil9945bc82014-03-05 14:07:29 +0100376 }
377
378 DEBUG("Bytes to read: %li\n", read_len);
379
Paul Cercueil43c1e6c2014-03-20 14:26:20 +0100380 if (read_mask) {
381 DEBUG("Reading mask\n");
382 buf[8] = '\0';
Paul Cercueil45c575d2014-03-20 15:14:01 +0100383 for (i = words; i > 0; i--) {
Paul Cercueil43c1e6c2014-03-20 14:26:20 +0100384 ret = read_all(buf, 8, fd);
385 if (ret < 0)
386 break;
387 sscanf(buf, "%08x", &mask[i - 1]);
388 DEBUG("mask[%i] = 0x%x\n", i - 1, mask[i - 1]);
Paul Cercueil43c1e6c2014-03-20 14:26:20 +0100389 }
390 read_mask = false;
Paul Cercueil5cab3ae2014-03-14 11:23:56 +0100391 }
392
393 if (ret > 0) {
394 char c;
395 ret = recv(fd, &c, 1, 0);
396 if (ret > 0 && c != '\n')
397 ret = -EIO;
398 }
399
400 if (ret < 0) {
401 strerror_r(-ret, buf, sizeof(buf));
402 ERROR("Unable to read mask: %s\n", buf);
Paul Cercueil05e26262014-05-09 11:32:43 +0200403 network_unlock(pdata);
Paul Cercueil6e7f79e2014-04-04 12:27:24 +0200404 return read ? read : ret;
Paul Cercueil5cab3ae2014-03-14 11:23:56 +0100405 }
406
Paul Cercueil6e7f79e2014-04-04 12:27:24 +0200407 ret = read_all((void *) ptr, read_len, fd);
Paul Cercueil9945bc82014-03-05 14:07:29 +0100408 if (ret < 0) {
409 strerror_r(-ret, buf, sizeof(buf));
410 ERROR("Unable to read response to READ: %s\n", buf);
Paul Cercueil05e26262014-05-09 11:32:43 +0200411 network_unlock(pdata);
Paul Cercueil6e7f79e2014-04-04 12:27:24 +0200412 return read ? read : ret;
Paul Cercueil9945bc82014-03-05 14:07:29 +0100413 }
414
Paul Cercueil6e7f79e2014-04-04 12:27:24 +0200415 ptr += ret;
Paul Cercueilf9286452014-03-18 14:32:17 +0100416 read += ret;
Paul Cercueil9945bc82014-03-05 14:07:29 +0100417 len -= read_len;
418 } while (len);
419
Paul Cercueil05e26262014-05-09 11:32:43 +0200420 network_unlock(pdata);
Paul Cercueil9945bc82014-03-05 14:07:29 +0100421 return read;
422}
423
Paul Cercueild93215d2014-05-19 16:36:06 +0200424static ssize_t do_write(struct iio_context_pdata *pdata, bool attr,
Paul Cercueilcecda352014-05-06 18:14:29 +0200425 const char *command, const void *src, size_t len)
Paul Cercueil2725f702014-05-02 11:02:16 +0200426{
Paul Cercueilcecda352014-05-06 18:14:29 +0200427 int fd = pdata->fd;
Paul Cercueil2725f702014-05-02 11:02:16 +0200428 ssize_t ret;
Paul Cercueil2725f702014-05-02 11:02:16 +0200429 long resp;
430
Paul Cercueil05e26262014-05-09 11:32:43 +0200431 network_lock(pdata);
Paul Cercueild93215d2014-05-19 16:36:06 +0200432 if (attr)
433 ret = (ssize_t) write_command(command, fd);
434 else
435 ret = (ssize_t) exec_command(command, fd);
Paul Cercueil2725f702014-05-02 11:02:16 +0200436 if (ret < 0)
Paul Cercueil1494b862014-05-05 12:49:07 +0200437 goto err_unlock;
Paul Cercueil2725f702014-05-02 11:02:16 +0200438
439 ret = write_all(src, len, fd);
440 if (ret < 0)
Paul Cercueil1494b862014-05-05 12:49:07 +0200441 goto err_unlock;
Paul Cercueil2725f702014-05-02 11:02:16 +0200442
443 ret = read_integer(fd, &resp);
Paul Cercueil05e26262014-05-09 11:32:43 +0200444 network_unlock(pdata);
Paul Cercueil1494b862014-05-05 12:49:07 +0200445
Paul Cercueil2725f702014-05-02 11:02:16 +0200446 if (ret < 0)
447 return ret;
448 return (ssize_t) resp;
Paul Cercueil1494b862014-05-05 12:49:07 +0200449
450err_unlock:
Paul Cercueil05e26262014-05-09 11:32:43 +0200451 network_unlock(pdata);
Paul Cercueil1494b862014-05-05 12:49:07 +0200452 return ret;
Paul Cercueil2725f702014-05-02 11:02:16 +0200453}
454
Paul Cercueilcecda352014-05-06 18:14:29 +0200455static ssize_t network_write(const struct iio_device *dev,
456 const void *src, size_t len)
457{
458 char buf[1024];
459 snprintf(buf, sizeof(buf), "WRITEBUF %s %lu\r\n",
460 dev->id, (unsigned long) len);
Paul Cercueild93215d2014-05-19 16:36:06 +0200461 return do_write(dev->ctx->pdata, false, buf, src, len);
Paul Cercueilcecda352014-05-06 18:14:29 +0200462}
463
Paul Cercueil1494b862014-05-05 12:49:07 +0200464static ssize_t network_read_attr_helper(const struct iio_device *dev,
Paul Cercueil0cc0e162014-05-07 12:51:22 +0200465 const struct iio_channel *chn, const char *attr, char *dst,
Paul Cercueil1494b862014-05-05 12:49:07 +0200466 size_t len, bool is_debug)
Paul Cercueil3e94a5b2014-03-04 13:00:41 +0100467{
Paul Cercueil3e94a5b2014-03-04 13:00:41 +0100468 long read_len;
469 ssize_t ret;
470 char buf[1024];
Paul Cercueil05e26262014-05-09 11:32:43 +0200471 struct iio_context_pdata *pdata = dev->ctx->pdata;
472 int fd = pdata->fd;
Paul Cercueil1494b862014-05-05 12:49:07 +0200473 const char *id = dev->id;
Paul Cercueil3e94a5b2014-03-04 13:00:41 +0100474
Paul Cercueil99cf3d42014-03-06 12:35:26 +0100475 if (chn)
Paul Cercueil0cc0e162014-05-07 12:51:22 +0200476 snprintf(buf, sizeof(buf), "READ %s %s %s %s\r\n", id,
477 chn->is_output ? "OUTPUT" : "INPUT",
Paul Cercueil2a3e43d2014-05-21 16:58:45 +0200478 chn->id, attr ? attr : "");
Paul Cercueilc6f03612014-04-14 16:41:31 +0200479 else if (is_debug)
Paul Cercueil2a3e43d2014-05-21 16:58:45 +0200480 snprintf(buf, sizeof(buf), "READ %s DEBUG %s\r\n",
481 id, attr ? attr : "");
Paul Cercueil99cf3d42014-03-06 12:35:26 +0100482 else
Paul Cercueil2a3e43d2014-05-21 16:58:45 +0200483 snprintf(buf, sizeof(buf), "READ %s %s\r\n",
484 id, attr ? attr : "");
Paul Cercueil1494b862014-05-05 12:49:07 +0200485
Paul Cercueil05e26262014-05-09 11:32:43 +0200486 network_lock(pdata);
Paul Cercueilbb76bf92014-03-11 10:20:18 +0100487 read_len = exec_command(buf, fd);
Paul Cercueil1494b862014-05-05 12:49:07 +0200488 if (read_len < 0) {
Paul Cercueil05e26262014-05-09 11:32:43 +0200489 network_unlock(pdata);
Paul Cercueilbb76bf92014-03-11 10:20:18 +0100490 return (ssize_t) read_len;
Paul Cercueil1494b862014-05-05 12:49:07 +0200491 }
Paul Cercueil3e94a5b2014-03-04 13:00:41 +0100492
Paul Cercueil6e7f79e2014-04-04 12:27:24 +0200493 if ((unsigned long) read_len > len) {
Paul Cercueil3e94a5b2014-03-04 13:00:41 +0100494 ERROR("Value returned by server is too large\n");
Paul Cercueil05e26262014-05-09 11:32:43 +0200495 network_unlock(pdata);
Paul Cercueil3e94a5b2014-03-04 13:00:41 +0100496 return -EIO;
497 }
498
499 ret = read_all(dst, read_len, fd);
Paul Cercueil05e26262014-05-09 11:32:43 +0200500 network_unlock(pdata);
Paul Cercueil1494b862014-05-05 12:49:07 +0200501
Paul Cercueil3e94a5b2014-03-04 13:00:41 +0100502 if (ret < 0) {
503 strerror_r(-ret, buf, sizeof(buf));
504 ERROR("Unable to read response to READ: %s\n", buf);
505 return ret;
506 }
507
Paul Cercueil7d95fd72014-05-22 14:26:44 +0200508 return read_len;
Paul Cercueil3e94a5b2014-03-04 13:00:41 +0100509}
510
Paul Cercueil1494b862014-05-05 12:49:07 +0200511static ssize_t network_write_attr_helper(const struct iio_device *dev,
Paul Cercueil0cc0e162014-05-07 12:51:22 +0200512 const struct iio_channel *chn, const char *attr,
513 const char *src, size_t len, bool is_debug)
Paul Cercueil3e94a5b2014-03-04 13:00:41 +0100514{
Paul Cercueil3e94a5b2014-03-04 13:00:41 +0100515 char buf[1024];
Paul Cercueil1494b862014-05-05 12:49:07 +0200516 const char *id = dev->id;
Paul Cercueil3e94a5b2014-03-04 13:00:41 +0100517
Paul Cercueil07897d32014-03-06 12:46:08 +0100518 if (chn)
Paul Cercueil0cc0e162014-05-07 12:51:22 +0200519 snprintf(buf, sizeof(buf), "WRITE %s %s %s %s %lu\r\n",
520 id, chn->is_output ? "OUTPUT" : "INPUT",
Paul Cercueil8747efe2014-05-22 11:12:12 +0200521 chn->id, attr ? attr : "", (unsigned long) len);
Paul Cercueilc6f03612014-04-14 16:41:31 +0200522 else if (is_debug)
Paul Cercueil8747efe2014-05-22 11:12:12 +0200523 snprintf(buf, sizeof(buf), "WRITE %s DEBUG %s %lu\r\n",
524 id, attr ? attr : "", (unsigned long) len);
Paul Cercueil07897d32014-03-06 12:46:08 +0100525 else
Paul Cercueilcecda352014-05-06 18:14:29 +0200526 snprintf(buf, sizeof(buf), "WRITE %s %s %lu\r\n",
Paul Cercueil8747efe2014-05-22 11:12:12 +0200527 id, attr ? attr : "", (unsigned long) len);
Paul Cercueild93215d2014-05-19 16:36:06 +0200528 return do_write(dev->ctx->pdata, true, buf, src, len);
Paul Cercueil3e94a5b2014-03-04 13:00:41 +0100529}
530
Paul Cercueil99cf3d42014-03-06 12:35:26 +0100531static ssize_t network_read_dev_attr(const struct iio_device *dev,
Paul Cercueil50c762a2014-04-14 15:55:43 +0200532 const char *attr, char *dst, size_t len, bool is_debug)
Paul Cercueil99cf3d42014-03-06 12:35:26 +0100533{
Paul Cercueil5b577762014-06-03 15:31:42 +0200534 if (attr && ((is_debug && !iio_device_find_debug_attr(dev, attr)) ||
535 (!is_debug && !iio_device_find_attr(dev, attr))))
536 return -ENOENT;
537
Paul Cercueil1494b862014-05-05 12:49:07 +0200538 return network_read_attr_helper(dev, NULL, attr, dst, len, is_debug);
Paul Cercueil99cf3d42014-03-06 12:35:26 +0100539}
540
Paul Cercueil07897d32014-03-06 12:46:08 +0100541static ssize_t network_write_dev_attr(const struct iio_device *dev,
Paul Cercueilcecda352014-05-06 18:14:29 +0200542 const char *attr, const char *src, size_t len, bool is_debug)
Paul Cercueil07897d32014-03-06 12:46:08 +0100543{
Paul Cercueil5b577762014-06-03 15:31:42 +0200544 if (attr && ((is_debug && !iio_device_find_debug_attr(dev, attr)) ||
545 (!is_debug && !iio_device_find_attr(dev, attr))))
546 return -ENOENT;
547
Paul Cercueilcecda352014-05-06 18:14:29 +0200548 return network_write_attr_helper(dev, NULL, attr, src, len, is_debug);
Paul Cercueil07897d32014-03-06 12:46:08 +0100549}
550
Paul Cercueil99cf3d42014-03-06 12:35:26 +0100551static ssize_t network_read_chn_attr(const struct iio_channel *chn,
552 const char *attr, char *dst, size_t len)
553{
Paul Cercueil5b577762014-06-03 15:31:42 +0200554 if (attr && !iio_channel_find_attr(chn, attr))
555 return -ENOENT;
556
Paul Cercueil0cc0e162014-05-07 12:51:22 +0200557 return network_read_attr_helper(chn->dev, chn, attr, dst, len, false);
Paul Cercueil99cf3d42014-03-06 12:35:26 +0100558}
559
Paul Cercueil07897d32014-03-06 12:46:08 +0100560static ssize_t network_write_chn_attr(const struct iio_channel *chn,
Paul Cercueilcecda352014-05-06 18:14:29 +0200561 const char *attr, const char *src, size_t len)
Paul Cercueil07897d32014-03-06 12:46:08 +0100562{
Paul Cercueil5b577762014-06-03 15:31:42 +0200563 if (attr && !iio_channel_find_attr(chn, attr))
564 return -ENOENT;
565
Paul Cercueil0cc0e162014-05-07 12:51:22 +0200566 return network_write_attr_helper(chn->dev, chn, attr, src, len, false);
Paul Cercueil07897d32014-03-06 12:46:08 +0100567}
568
Paul Cercueildcab40c2014-03-11 10:59:14 +0100569static int network_get_trigger(const struct iio_device *dev,
570 const struct iio_device **trigger)
571{
572 struct iio_context_pdata *pdata = dev->ctx->pdata;
573 unsigned int i;
574 char buf[1024];
575 ssize_t ret;
576 long resp;
577
578 snprintf(buf, sizeof(buf), "GETTRIG %s\r\n", dev->id);
Paul Cercueil1494b862014-05-05 12:49:07 +0200579
Paul Cercueil05e26262014-05-09 11:32:43 +0200580 network_lock(dev->ctx->pdata);
Paul Cercueildcab40c2014-03-11 10:59:14 +0100581 resp = exec_command(buf, pdata->fd);
582 if (resp < 0) {
Paul Cercueil05e26262014-05-09 11:32:43 +0200583 network_unlock(pdata);
Paul Cercueildcab40c2014-03-11 10:59:14 +0100584 return (int) resp;
585 } else if (resp == 0) {
586 *trigger = NULL;
Paul Cercueil05e26262014-05-09 11:32:43 +0200587 network_unlock(pdata);
Paul Cercueildcab40c2014-03-11 10:59:14 +0100588 return 0;
Paul Cercueil6e7f79e2014-04-04 12:27:24 +0200589 } else if ((unsigned long) resp > sizeof(buf)) {
Paul Cercueildcab40c2014-03-11 10:59:14 +0100590 ERROR("Value returned by server is too large\n");
Paul Cercueil05e26262014-05-09 11:32:43 +0200591 network_unlock(pdata);
Paul Cercueildcab40c2014-03-11 10:59:14 +0100592 return -EIO;
593 }
594
595 ret = read_all(buf, resp, pdata->fd);
Paul Cercueil05e26262014-05-09 11:32:43 +0200596 network_unlock(pdata);
Paul Cercueil1494b862014-05-05 12:49:07 +0200597
Paul Cercueildcab40c2014-03-11 10:59:14 +0100598 if (ret < 0) {
599 strerror_r(-ret, buf, sizeof(buf));
600 ERROR("Unable to read response to GETTRIG: %s\n", buf);
601 return ret;
602 }
603
Lars-Peter Clausenb5cdc102014-08-21 14:45:52 +0200604 if (buf[0] == '\0') {
605 *trigger = NULL;
606 return 0;
607 }
608
Paul Cercueildcab40c2014-03-11 10:59:14 +0100609 for (i = 0; i < dev->ctx->nb_devices; i++) {
610 struct iio_device *cur = dev->ctx->devices[i];
611 if (iio_device_is_trigger(cur) &&
612 !strncmp(cur->name, buf, resp)) {
613 *trigger = cur;
614 return 0;
615 }
616 }
617
618 return -ENXIO;
619}
620
621static int network_set_trigger(const struct iio_device *dev,
622 const struct iio_device *trigger)
623{
Paul Cercueil1494b862014-05-05 12:49:07 +0200624 int ret;
Paul Cercueildcab40c2014-03-11 10:59:14 +0100625 char buf[1024];
626 if (trigger)
627 snprintf(buf, sizeof(buf), "SETTRIG %s %s\r\n",
628 dev->id, trigger->id);
629 else
630 snprintf(buf, sizeof(buf), "SETTRIG %s\r\n", dev->id);
Paul Cercueil1494b862014-05-05 12:49:07 +0200631
Paul Cercueil05e26262014-05-09 11:32:43 +0200632 network_lock(dev->ctx->pdata);
Paul Cercueil1494b862014-05-05 12:49:07 +0200633 ret = (int) exec_command(buf, dev->ctx->pdata->fd);
Paul Cercueil05e26262014-05-09 11:32:43 +0200634 network_unlock(dev->ctx->pdata);
Paul Cercueil1494b862014-05-05 12:49:07 +0200635 return ret;
Paul Cercueildcab40c2014-03-11 10:59:14 +0100636}
637
Paul Cercueil8fd9c8f2014-03-03 17:21:31 +0100638static void network_shutdown(struct iio_context *ctx)
639{
640 struct iio_context_pdata *pdata = ctx->pdata;
Paul Cercueil44ae11c2014-03-17 09:56:29 +0100641 unsigned int i;
Paul Cercueil8fd9c8f2014-03-03 17:21:31 +0100642
Paul Cercueil05e26262014-05-09 11:32:43 +0200643 network_lock(pdata);
Paul Cercueilbb76bf92014-03-11 10:20:18 +0100644 write_command("\r\nEXIT\r\n", pdata->fd);
Paul Cercueil8fd9c8f2014-03-03 17:21:31 +0100645 close(pdata->fd);
Paul Cercueil05e26262014-05-09 11:32:43 +0200646 network_unlock(pdata);
Paul Cercueil1494b862014-05-05 12:49:07 +0200647
Paul Cercueil05e26262014-05-09 11:32:43 +0200648#if HAVE_PTHREAD
Paul Cercueil1494b862014-05-05 12:49:07 +0200649 /* XXX(pcercuei): is this safe? */
650 pthread_mutex_destroy(&pdata->lock);
Paul Cercueil05e26262014-05-09 11:32:43 +0200651#endif
Paul Cercueil12d41832014-10-28 14:35:53 +0100652 if (pdata->host)
653 free(pdata->host);
Paul Cercueil8fd9c8f2014-03-03 17:21:31 +0100654 free(pdata);
Paul Cercueil44ae11c2014-03-17 09:56:29 +0100655
656 for (i = 0; i < ctx->nb_devices; i++) {
657 struct iio_device *dev = ctx->devices[i];
658 if (dev->pdata)
659 free(dev->pdata);
660 }
Paul Cercueil8fd9c8f2014-03-03 17:21:31 +0100661}
662
Paul Cercueil6691a3f2014-05-02 12:32:01 +0200663static int network_get_version(const struct iio_context *ctx,
Paul Cercueil9de9e9d2014-05-20 13:18:19 +0200664 unsigned int *major, unsigned int *minor, char git_tag[8])
Paul Cercueil6691a3f2014-05-02 12:32:01 +0200665{
666 struct iio_context_pdata *pdata = ctx->pdata;
667 long maj, min;
668 int ret;
Paul Cercueil6691a3f2014-05-02 12:32:01 +0200669
Paul Cercueil05e26262014-05-09 11:32:43 +0200670 network_lock(pdata);
Paul Cercueil1494b862014-05-05 12:49:07 +0200671 ret = (int) write_command("VERSION\r\n", pdata->fd);
672 if (ret < 0)
673 goto err_unlock;
674
675 ret = read_integer(pdata->fd, &maj);
676 if (!ret)
677 ret = read_integer(pdata->fd, &min);
678 if (!ret) {
Paul Cercueil9de9e9d2014-05-20 13:18:19 +0200679 char tag[8];
680 tag[7] = '\0';
681
682 ret = read_all(tag, sizeof(tag) - 1, pdata->fd);
683 if (ret < 0)
684 goto err_unlock;
685
Paul Cercueild15d9952014-05-20 11:40:08 +0200686 if (major)
687 *major = (unsigned int) maj;
688 if (minor)
689 *minor = (unsigned int) min;
Paul Cercueil9de9e9d2014-05-20 13:18:19 +0200690 if (git_tag)
691 strncpy(git_tag, tag, 8);
Paul Cercueil1494b862014-05-05 12:49:07 +0200692 }
693
Paul Cercueil8e8f8992014-06-12 16:58:12 +0200694 ret = 0;
Paul Cercueil1494b862014-05-05 12:49:07 +0200695err_unlock:
Paul Cercueil05e26262014-05-09 11:32:43 +0200696 network_unlock(pdata);
Paul Cercueil1494b862014-05-05 12:49:07 +0200697 return ret;
Paul Cercueil6691a3f2014-05-02 12:32:01 +0200698}
699
Paul Cercueil8a266f12014-06-10 16:06:31 +0200700static unsigned int calculate_remote_timeout(unsigned int timeout)
701{
702 /* XXX(pcercuei): We currently hardcode timeout / 2 for the backend used
703 * by the remote. Is there something better to do here? */
704 return timeout / 2;
705}
706
Paul Cercueilbca3dbc2014-06-11 12:00:21 +0200707static int set_socket_timeout(int fd, unsigned int timeout)
Paul Cercueil8a266f12014-06-10 16:06:31 +0200708{
Paul Cercueil8a266f12014-06-10 16:06:31 +0200709 if (setsockopt(fd, SOL_SOCKET, SO_SNDTIMEO,
710 &timeout, sizeof(timeout)) < 0 ||
711 setsockopt(fd, SOL_SOCKET, SO_RCVTIMEO,
Paul Cercueilbca3dbc2014-06-11 12:00:21 +0200712 &timeout, sizeof(timeout)) < 0)
713 return -errno;
714 else
715 return 0;
716}
717
718static int set_remote_timeout(struct iio_context *ctx, unsigned int timeout)
719{
720 char buf[1024];
721 int ret;
722
723 snprintf(buf, sizeof(buf), "TIMEOUT %u\r\n", timeout);
724 network_lock(ctx->pdata);
725 ret = (int) exec_command(buf, ctx->pdata->fd);
726 network_unlock(ctx->pdata);
727 return ret;
728}
729
730static int network_set_timeout(struct iio_context *ctx, unsigned int timeout)
731{
732 int ret = set_socket_timeout(ctx->pdata->fd, timeout);
733 if (!ret) {
734 timeout = calculate_remote_timeout(timeout);
735 ret = set_remote_timeout(ctx, timeout);
736 }
737 if (ret < 0) {
738 char buf[1024];
739 strerror_r(-ret, buf, sizeof(buf));
Paul Cercueil8a266f12014-06-10 16:06:31 +0200740 WARNING("Unable to set R/W timeout: %s\n", buf);
741 } else {
Paul Cercueil8a266f12014-06-10 16:06:31 +0200742 ctx->rw_timeout_ms = timeout;
743 }
744 return ret;
745}
746
Paul Cercueil12d41832014-10-28 14:35:53 +0100747static struct iio_context * network_clone(const struct iio_context *ctx)
748{
749 return iio_create_network_context(ctx->pdata->host);
750}
751
Paul Cercueilc7bad0f2014-03-03 17:06:48 +0100752static struct iio_backend_ops network_ops = {
Paul Cercueil12d41832014-10-28 14:35:53 +0100753 .clone = network_clone,
Paul Cercueilba059762014-03-14 11:02:02 +0100754 .open = network_open,
755 .close = network_close,
Paul Cercueil9945bc82014-03-05 14:07:29 +0100756 .read = network_read,
Paul Cercueil2725f702014-05-02 11:02:16 +0200757 .write = network_write,
Paul Cercueil3e94a5b2014-03-04 13:00:41 +0100758 .read_device_attr = network_read_dev_attr,
759 .write_device_attr = network_write_dev_attr,
Paul Cercueil99cf3d42014-03-06 12:35:26 +0100760 .read_channel_attr = network_read_chn_attr,
Paul Cercueil07897d32014-03-06 12:46:08 +0100761 .write_channel_attr = network_write_chn_attr,
Paul Cercueildcab40c2014-03-11 10:59:14 +0100762 .get_trigger = network_get_trigger,
763 .set_trigger = network_set_trigger,
Paul Cercueil8fd9c8f2014-03-03 17:21:31 +0100764 .shutdown = network_shutdown,
Paul Cercueil6691a3f2014-05-02 12:32:01 +0200765 .get_version = network_get_version,
Paul Cercueil8a266f12014-06-10 16:06:31 +0200766 .set_timeout = network_set_timeout,
Paul Cercueilc7bad0f2014-03-03 17:06:48 +0100767};
768
769static struct iio_context * get_context(int fd)
770{
771 struct iio_context *ctx;
Paul Cercueile60c3ed2014-03-04 11:23:56 +0100772 char *xml;
Paul Cercueilbb76bf92014-03-11 10:20:18 +0100773 long xml_len = exec_command("PRINT\r\n", fd);
774 if (xml_len < 0)
Paul Cercueilc7bad0f2014-03-03 17:06:48 +0100775 return NULL;
Paul Cercueile60c3ed2014-03-04 11:23:56 +0100776
777 DEBUG("Server returned a XML string of length %li\n", xml_len);
Paul Cercueilc7bad0f2014-03-03 17:06:48 +0100778 xml = malloc(xml_len);
779 if (!xml) {
780 ERROR("Unable to allocate data\n");
781 return NULL;
782 }
783
784 DEBUG("Reading XML string...\n");
785 read_all(xml, xml_len, fd);
786
787 DEBUG("Creating context from XML...\n");
788 ctx = iio_create_xml_context_mem(xml, xml_len);
Paul Cercueilc1ed8482014-06-11 16:29:43 +0200789
790 if (ctx)
791 ctx->xml = xml;
792 else
793 free(xml);
Paul Cercueilc7bad0f2014-03-03 17:06:48 +0100794 return ctx;
795}
796
797struct iio_context * iio_create_network_context(const char *host)
798{
Paul Cercueil2e38bbe2014-03-19 15:27:15 +0100799 struct addrinfo hints, *res;
Paul Cercueilc7bad0f2014-03-03 17:06:48 +0100800 struct iio_context *ctx;
Paul Cercueil8fd9c8f2014-03-03 17:21:31 +0100801 struct iio_context_pdata *pdata;
Paul Cercueil44ae11c2014-03-17 09:56:29 +0100802 unsigned int i;
Paul Cercueil2e38bbe2014-03-19 15:27:15 +0100803 int fd, ret;
Paul Cercueil1fef1a52014-04-07 16:31:15 +0200804#ifdef _WIN32
805 WSADATA wsaData;
806
807 ret = WSAStartup(MAKEWORD(2, 0), &wsaData);
808 if (ret < 0) {
809 ERROR("WSAStartup failed with error %i\n", ret);
810 return NULL;
811 }
812#endif
Paul Cercueilc7bad0f2014-03-03 17:06:48 +0100813
Paul Cercueil2e38bbe2014-03-19 15:27:15 +0100814 memset(&hints, 0, sizeof(hints));
815 hints.ai_family = AF_UNSPEC;
816 hints.ai_socktype = SOCK_STREAM;
Paul Cercueilab114932014-05-19 13:03:17 +0200817
818#ifdef HAVE_AVAHI
819 if (!host) {
820 char addr_str[AVAHI_ADDRESS_STR_MAX];
821 char port_str[6];
822 AvahiAddress address;
Paul Cercueil0f729d32014-06-05 17:38:54 +0200823 uint16_t port = IIOD_PORT;
Paul Cercueilab114932014-05-19 13:03:17 +0200824
825 memset(&address, 0, sizeof(address));
826
827 ret = discover_host(&address, &port);
828 if (ret < 0) {
829 ERROR("Unable to find host: %s\n", strerror(-ret));
830 return NULL;
831 }
832
833 avahi_address_snprint(addr_str, sizeof(addr_str), &address);
834 snprintf(port_str, sizeof(port_str), "%hu", port);
835 ret = getaddrinfo(addr_str, port_str, &hints, &res);
836 } else
837#endif
838 {
839 ret = getaddrinfo(host, IIOD_PORT_STR, &hints, &res);
840 }
841
Paul Cercueil2e38bbe2014-03-19 15:27:15 +0100842 if (ret) {
Paul Cercueilab114932014-05-19 13:03:17 +0200843 ERROR("Unable to find host: %s\n", gai_strerror(ret));
Paul Cercueilc7bad0f2014-03-03 17:06:48 +0100844 return NULL;
Paul Cercueilc7bad0f2014-03-03 17:06:48 +0100845 }
846
Paul Cercueil2e38bbe2014-03-19 15:27:15 +0100847 fd = socket(res->ai_family, res->ai_socktype, 0);
Paul Cercueilc7bad0f2014-03-03 17:06:48 +0100848 if (fd < 0) {
849 ERROR("Unable to open socket\n");
850 return NULL;
851 }
852
Paul Cercueil2e38bbe2014-03-19 15:27:15 +0100853 if (connect(fd, res->ai_addr, res->ai_addrlen) < 0) {
Paul Cercueilc7bad0f2014-03-03 17:06:48 +0100854 ERROR("Unable to connect\n");
855 goto err_close_socket;
856 }
857
Paul Cercueilbca3dbc2014-06-11 12:00:21 +0200858 set_socket_timeout(fd, DEFAULT_TIMEOUT_MS);
859
Paul Cercueil8fd9c8f2014-03-03 17:21:31 +0100860 pdata = calloc(1, sizeof(*pdata));
861 if (!pdata) {
862 ERROR("Unable to allocate memory\n");
863 goto err_close_socket;
864 }
865
Paul Cercueil12d41832014-10-28 14:35:53 +0100866 if (host) {
867 pdata->host = strdup(host);
868 if (!pdata->host) {
869 ERROR("Unable to allocate memory\n");
870 goto err_free_pdata;
871 }
872 }
873
Paul Cercueil8fd9c8f2014-03-03 17:21:31 +0100874 pdata->fd = fd;
875
Paul Cercueilc7bad0f2014-03-03 17:06:48 +0100876 DEBUG("Creating context...\n");
877 ctx = get_context(fd);
878 if (!ctx)
Paul Cercueil12d41832014-10-28 14:35:53 +0100879 goto err_free_pdata_host;
Paul Cercueilc7bad0f2014-03-03 17:06:48 +0100880
Paul Cercueil44ae11c2014-03-17 09:56:29 +0100881 for (i = 0; i < ctx->nb_devices; i++) {
882 struct iio_device *dev = ctx->devices[i];
Paul Cercueilff778232014-03-24 14:23:08 +0100883 uint32_t *mask = NULL;
884
885 dev->words = (dev->nb_channels + 31) / 32;
886 if (dev->words) {
887 mask = calloc(dev->words, sizeof(*mask));
888 if (!mask)
889 goto err_network_shutdown;
890 }
891
892 dev->mask = mask;
Paul Cercueil44ae11c2014-03-17 09:56:29 +0100893 }
894
Paul Cercueilff778232014-03-24 14:23:08 +0100895
Paul Cercueilc7bad0f2014-03-03 17:06:48 +0100896 /* Override the name and low-level functions of the XML context
897 * with those corresponding to the network context */
898 ctx->name = "network";
899 ctx->ops = &network_ops;
Paul Cercueil8fd9c8f2014-03-03 17:21:31 +0100900 ctx->pdata = pdata;
Paul Cercueilc7bad0f2014-03-03 17:06:48 +0100901
Paul Cercueilc1ed8482014-06-11 16:29:43 +0200902 iio_context_init(ctx);
Paul Cercueil4c6729d2014-04-04 17:24:41 +0200903
Paul Cercueil05e26262014-05-09 11:32:43 +0200904#if HAVE_PTHREAD
Paul Cercueil1494b862014-05-05 12:49:07 +0200905 ret = pthread_mutex_init(&pdata->lock, NULL);
906 if (ret < 0) {
907 char buf[1024];
908 strerror_r(-ret, buf, sizeof(buf));
909 ERROR("Unable to initialize mutex: %s\n", buf);
910 goto err_network_shutdown;
911 }
Paul Cercueil05e26262014-05-09 11:32:43 +0200912#endif
Paul Cercueil1494b862014-05-05 12:49:07 +0200913
Paul Cercueilbca3dbc2014-06-11 12:00:21 +0200914 set_remote_timeout(ctx, calculate_remote_timeout(DEFAULT_TIMEOUT_MS));
Paul Cercueilc7bad0f2014-03-03 17:06:48 +0100915 return ctx;
916
Paul Cercueil44ae11c2014-03-17 09:56:29 +0100917err_network_shutdown:
918 network_shutdown(ctx);
919 iio_context_destroy(ctx);
Paul Cercueil12d41832014-10-28 14:35:53 +0100920err_free_pdata_host:
921 if (pdata->host)
922 free(pdata->host);
Paul Cercueil8fd9c8f2014-03-03 17:21:31 +0100923err_free_pdata:
924 free(pdata);
Paul Cercueilc7bad0f2014-03-03 17:06:48 +0100925err_close_socket:
926 close(fd);
927 return NULL;
928}