blob: 45d8c01c92cacda13b7dbb0081daaf7a371203c2 [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 Cercueil09a43482015-03-04 15:50:27 +010019#ifdef __linux__
20#define _GNU_SOURCE 1 /* Required for splice() */
21#endif
22
Paul Cercueilc7bad0f2014-03-03 17:06:48 +010023#include "iio-private.h"
24
Paul Cercueil9aabe892014-09-02 12:33:46 +020025#ifndef HAVE_PTHREAD
26#define HAVE_PTHREAD 1
27#endif
28
Paul Cercueilc7bad0f2014-03-03 17:06:48 +010029#include <errno.h>
Paul Cercueila7d445b2014-11-11 16:00:15 +010030#include <fcntl.h>
Paul Cercueile60c3ed2014-03-04 11:23:56 +010031#include <stdbool.h>
Paul Cercueilc7bad0f2014-03-03 17:06:48 +010032#include <string.h>
33#include <sys/types.h>
Paul Cercueilab114932014-05-19 13:03:17 +020034#include <time.h>
Paul Cercueil1fef1a52014-04-07 16:31:15 +020035
36#ifdef _WIN32
Paul Cercueil06c479d2015-01-08 16:14:57 +010037/* Override the default version of Windows supported by MinGW.
38 * This is required to use the function inet_ntop. */
39#undef _WIN32_WINNT
40#define _WIN32_WINNT 0x0600
41
Paul Cercueil1fef1a52014-04-07 16:31:15 +020042#include <winsock2.h>
43#include <ws2tcpip.h>
44#define close(s) closesocket(s)
45
46/* winsock2.h defines ERROR, we don't want that */
47#undef ERROR
48
49#else /* _WIN32 */
Paul Cercueil06c479d2015-01-08 16:14:57 +010050#include <arpa/inet.h>
Paul Cercueil1fef1a52014-04-07 16:31:15 +020051#include <netdb.h>
Paul Cercueil0c3ce452015-02-05 16:37:42 +010052#include <netinet/in.h>
Paul Cercueil0b584e12015-01-28 11:47:03 +010053#include <netinet/tcp.h>
Paul Cercueiled15e492015-01-12 15:52:28 +010054#include <net/if.h>
Paul Cercueil09a43482015-03-04 15:50:27 +010055#include <sys/mman.h>
Paul Cercueil83628b32014-11-24 11:26:21 +010056#include <sys/select.h>
Paul Cercueilc7bad0f2014-03-03 17:06:48 +010057#include <sys/socket.h>
58#include <unistd.h>
Paul Cercueil1fef1a52014-04-07 16:31:15 +020059#endif /* _WIN32 */
60
Paul Cercueil257e6ca2014-12-09 17:32:47 +010061#if HAVE_PTHREAD
62#include <pthread.h>
63#endif
64
Paul Cercueilab114932014-05-19 13:03:17 +020065#ifdef HAVE_AVAHI
66#include <avahi-client/client.h>
67#include <avahi-common/error.h>
68#include <avahi-client/lookup.h>
69#include <avahi-common/simple-watch.h>
70#endif
71
Paul Cercueil1fef1a52014-04-07 16:31:15 +020072#include "debug.h"
Paul Cercueilc7bad0f2014-03-03 17:06:48 +010073
Paul Cercueil8a266f12014-06-10 16:06:31 +020074#define DEFAULT_TIMEOUT_MS 5000
75
Paul Cercueil2e38bbe2014-03-19 15:27:15 +010076#define _STRINGIFY(x) #x
77#define STRINGIFY(x) _STRINGIFY(x)
78
Paul Cercueilc7bad0f2014-03-03 17:06:48 +010079#define IIOD_PORT 30431
Paul Cercueil2e38bbe2014-03-19 15:27:15 +010080#define IIOD_PORT_STR STRINGIFY(IIOD_PORT)
Paul Cercueilc7bad0f2014-03-03 17:06:48 +010081
Paul Cercueil8fd9c8f2014-03-03 17:21:31 +010082struct iio_context_pdata {
83 int fd;
Paul Cercueil2dd2c132015-02-24 10:41:01 +010084 struct addrinfo *addrinfo;
Paul Cercueil05e26262014-05-09 11:32:43 +020085#if HAVE_PTHREAD
Paul Cercueil1494b862014-05-05 12:49:07 +020086 pthread_mutex_t lock;
Paul Cercueil05e26262014-05-09 11:32:43 +020087#endif
Paul Cercueil8fd9c8f2014-03-03 17:21:31 +010088};
89
Paul Cercueil439e1a22015-02-24 13:50:51 +010090struct iio_device_pdata {
91 int fd;
Paul Cercueile6e5a092015-03-04 16:33:26 +010092#ifdef __linux__
Paul Cercueil09a43482015-03-04 15:50:27 +010093 int memfd;
Paul Cercueile6e5a092015-03-04 16:33:26 +010094 void *mmap_addr;
Paul Cercueil09a43482015-03-04 15:50:27 +010095 size_t mmap_len;
Paul Cercueile6e5a092015-03-04 16:33:26 +010096#endif
Paul Cercueil09a43482015-03-04 15:50:27 +010097 bool wait_for_err_code, is_cyclic, is_tx;
Paul Cercueilc5b00752015-02-24 14:29:53 +010098#if HAVE_PTHREAD
99 pthread_mutex_t lock;
100#endif
Paul Cercueil439e1a22015-02-24 13:50:51 +0100101};
102
Paul Cercueilab114932014-05-19 13:03:17 +0200103#ifdef HAVE_AVAHI
104struct avahi_discovery_data {
105 AvahiSimplePoll *poll;
106 AvahiAddress *address;
107 uint16_t *port;
108 bool found, resolved;
109};
110
111static void __avahi_resolver_cb(AvahiServiceResolver *resolver,
112 __notused AvahiIfIndex iface, __notused AvahiProtocol proto,
113 __notused AvahiResolverEvent event, __notused const char *name,
114 __notused const char *type, __notused const char *domain,
115 __notused const char *host_name, const AvahiAddress *address,
116 uint16_t port, __notused AvahiStringList *txt,
117 __notused AvahiLookupResultFlags flags, void *d)
118{
119 struct avahi_discovery_data *ddata = (struct avahi_discovery_data *) d;
120
121 memcpy(ddata->address, address, sizeof(*address));
122 *ddata->port = port;
123 ddata->resolved = true;
124 avahi_service_resolver_free(resolver);
125}
126
127static void __avahi_browser_cb(AvahiServiceBrowser *browser,
128 AvahiIfIndex iface, AvahiProtocol proto,
129 AvahiBrowserEvent event, const char *name,
130 const char *type, const char *domain,
131 __notused AvahiLookupResultFlags flags, void *d)
132{
133 struct avahi_discovery_data *ddata = (struct avahi_discovery_data *) d;
134 struct AvahiClient *client = avahi_service_browser_get_client(browser);
135
136 switch (event) {
137 default:
138 case AVAHI_BROWSER_NEW:
139 ddata->found = !!avahi_service_resolver_new(client, iface,
140 proto, name, type, domain,
141 AVAHI_PROTO_UNSPEC, 0,
142 __avahi_resolver_cb, d);
143 break;
144 case AVAHI_BROWSER_ALL_FOR_NOW:
145 if (ddata->found) {
146 while (!ddata->resolved) {
147 struct timespec ts;
148 ts.tv_sec = 0;
149 ts.tv_nsec = 4000000;
150 nanosleep(&ts, NULL);
151 }
152 }
153 case AVAHI_BROWSER_FAILURE: /* fall-through */
154 avahi_simple_poll_quit(ddata->poll);
155 case AVAHI_BROWSER_CACHE_EXHAUSTED: /* fall-through */
156 break;
157 }
158}
159
160static int discover_host(AvahiAddress *addr, uint16_t *port)
161{
162 struct avahi_discovery_data ddata;
163 int ret = 0;
164 AvahiClient *client;
165 AvahiServiceBrowser *browser;
166 AvahiSimplePoll *poll = avahi_simple_poll_new();
167 if (!poll)
168 return -ENOMEM;
169
170 client = avahi_client_new(avahi_simple_poll_get(poll),
171 0, NULL, NULL, &ret);
172 if (!client) {
173 ERROR("Unable to start ZeroConf client :%s\n",
174 avahi_strerror(ret));
175 goto err_free_poll;
176 }
177
178 memset(&ddata, 0, sizeof(ddata));
179 ddata.poll = poll;
180 ddata.address = addr;
181 ddata.port = port;
182
183 browser = avahi_service_browser_new(client,
184 AVAHI_IF_UNSPEC, AVAHI_PROTO_UNSPEC,
185 "_iio._tcp", NULL, 0, __avahi_browser_cb, &ddata);
186 if (!browser) {
187 ret = avahi_client_errno(client);
188 ERROR("Unable to create ZeroConf browser: %s\n",
189 avahi_strerror(ret));
190 goto err_free_client;
191 }
192
193 DEBUG("Trying to discover host\n");
194 avahi_simple_poll_loop(poll);
195
196 if (!ddata.found)
197 ret = ENXIO;
198
199 avahi_service_browser_free(browser);
200err_free_client:
201 avahi_client_free(client);
202err_free_poll:
203 avahi_simple_poll_free(poll);
204 return -ret; /* we want a negative error code */
205}
206#endif /* HAVE_AVAHI */
207
Paul Cercueil05e26262014-05-09 11:32:43 +0200208static void network_lock(struct iio_context_pdata *pdata)
209{
210#if HAVE_PTHREAD
211 pthread_mutex_lock(&pdata->lock);
212#endif
213}
214
215static void network_unlock(struct iio_context_pdata *pdata)
216{
217#if HAVE_PTHREAD
218 pthread_mutex_unlock(&pdata->lock);
219#endif
220}
221
Paul Cercueilc5b00752015-02-24 14:29:53 +0100222static void network_lock_dev(struct iio_device_pdata *pdata)
223{
224#if HAVE_PTHREAD
225 pthread_mutex_lock(&pdata->lock);
226#endif
227}
228
229static void network_unlock_dev(struct iio_device_pdata *pdata)
230{
231#if HAVE_PTHREAD
232 pthread_mutex_unlock(&pdata->lock);
233#endif
234}
235
Paul Cercueilc7bad0f2014-03-03 17:06:48 +0100236static ssize_t write_all(const void *src, size_t len, int fd)
237{
Paul Cercueil6e7f79e2014-04-04 12:27:24 +0200238 uintptr_t ptr = (uintptr_t) src;
Paul Cercueilc7bad0f2014-03-03 17:06:48 +0100239 while (len) {
Paul Cercueil6e7f79e2014-04-04 12:27:24 +0200240 ssize_t ret = send(fd, (const void *) ptr, len, 0);
Lars-Peter Clausencb7b8bf2014-12-05 16:08:52 +0100241 if (ret < 0) {
242 if (errno == EINTR) {
243 continue;
244 }
Paul Cercueilc7bad0f2014-03-03 17:06:48 +0100245 return -errno;
Lars-Peter Clausencb7b8bf2014-12-05 16:08:52 +0100246 }
Paul Cercueilc7bad0f2014-03-03 17:06:48 +0100247 ptr += ret;
248 len -= ret;
249 }
Paul Cercueil6e7f79e2014-04-04 12:27:24 +0200250 return ptr - (uintptr_t) src;
Paul Cercueilc7bad0f2014-03-03 17:06:48 +0100251}
252
253static ssize_t read_all(void *dst, size_t len, int fd)
254{
Paul Cercueil6e7f79e2014-04-04 12:27:24 +0200255 uintptr_t ptr = (uintptr_t) dst;
Paul Cercueilc7bad0f2014-03-03 17:06:48 +0100256 while (len) {
Paul Cercueil6e7f79e2014-04-04 12:27:24 +0200257 ssize_t ret = recv(fd, (void *) ptr, len, 0);
Lars-Peter Clausencb7b8bf2014-12-05 16:08:52 +0100258 if (ret < 0) {
259 if (errno == EINTR)
260 continue;
Paul Cercueilc7bad0f2014-03-03 17:06:48 +0100261 return -errno;
Lars-Peter Clausencb7b8bf2014-12-05 16:08:52 +0100262 }
Paul Cercueil43eb7e82014-11-13 12:46:59 +0100263 if (ret == 0)
264 return -EPIPE;
Paul Cercueilc7bad0f2014-03-03 17:06:48 +0100265 ptr += ret;
266 len -= ret;
267 }
Paul Cercueil6e7f79e2014-04-04 12:27:24 +0200268 return ptr - (uintptr_t) dst;
Paul Cercueilc7bad0f2014-03-03 17:06:48 +0100269}
270
Paul Cercueile60c3ed2014-03-04 11:23:56 +0100271static int read_integer(int fd, long *val)
272{
273 unsigned int i;
274 char buf[1024], *ptr;
275 ssize_t ret;
276 bool found = false;
277
278 for (i = 0; i < sizeof(buf) - 1; i++) {
279 ret = read_all(buf + i, 1, fd);
280 if (ret < 0)
281 return (int) ret;
282
Paul Cercueil6691a3f2014-05-02 12:32:01 +0200283 /* Skip the eventual first few carriage returns.
284 * Also stop when a dot is found (for parsing floats) */
285 if (buf[i] != '\n' && buf[i] != '.')
Paul Cercueile60c3ed2014-03-04 11:23:56 +0100286 found = true;
287 else if (found)
288 break;
289 }
290
291 buf[i] = '\0';
292 ret = (ssize_t) strtol(buf, &ptr, 10);
293 if (ptr == buf)
294 return -EINVAL;
295 *val = (long) ret;
296 return 0;
297}
298
Paul Cercueilbb76bf92014-03-11 10:20:18 +0100299static ssize_t write_command(const char *cmd, int fd)
300{
301 ssize_t ret;
302
303 DEBUG("Writing command: %s\n", cmd);
304 ret = write_all(cmd, strlen(cmd), fd);
305 if (ret < 0) {
306 char buf[1024];
307 strerror_r(-ret, buf, sizeof(buf));
308 ERROR("Unable to send command: %s\n", buf);
309 }
310 return ret;
311}
312
313static long exec_command(const char *cmd, int fd)
314{
315 long resp;
316 ssize_t ret = write_command(cmd, fd);
317 if (ret < 0)
318 return (long) ret;
319
320 DEBUG("Reading response\n");
321 ret = read_integer(fd, &resp);
322 if (ret < 0) {
323 char buf[1024];
324 strerror_r(-ret, buf, sizeof(buf));
325 ERROR("Unable to read response: %s\n", buf);
326 return (long) ret;
327 }
328
Paul Cercueilc7fe2ea2014-03-28 11:38:45 +0100329#if LOG_LEVEL >= DEBUG_L
Paul Cercueilbb76bf92014-03-11 10:20:18 +0100330 if (resp < 0) {
331 char buf[1024];
332 strerror_r(-resp, buf, sizeof(buf));
Paul Cercueilc7fe2ea2014-03-28 11:38:45 +0100333 DEBUG("Server returned an error: %s\n", buf);
Paul Cercueilbb76bf92014-03-11 10:20:18 +0100334 }
Paul Cercueilc7fe2ea2014-03-28 11:38:45 +0100335#endif
336
Paul Cercueilbb76bf92014-03-11 10:20:18 +0100337 return resp;
338}
339
Paul Cercueil4970ac32015-02-24 10:59:00 +0100340#ifndef _WIN32
341static int set_blocking_mode(int fd, bool blocking)
342{
343 int ret = fcntl(fd, F_GETFL, 0);
344 if (ret < 0)
345 return -errno;
346
347 if (blocking)
348 ret &= ~O_NONBLOCK;
349 else
350 ret |= O_NONBLOCK;
351
352 ret = fcntl(fd, F_SETFL, ret);
353 return ret < 0 ? -errno : 0;
354}
355
356/* The purpose of this function is to provide a version of connect()
357 * that does not ignore timeouts... */
358static int do_connect(int fd, const struct sockaddr *addr,
359 socklen_t addrlen, struct timeval *timeout)
360{
361 int ret, error;
362 socklen_t len;
363 fd_set set;
364
365 FD_ZERO(&set);
366 FD_SET(fd, &set);
367
368 ret = set_blocking_mode(fd, false);
369 if (ret < 0)
370 return ret;
371
372 ret = connect(fd, addr, addrlen);
373 if (ret < 0 && errno != EINPROGRESS) {
374 ret = -errno;
375 goto end;
376 }
377
378 ret = select(fd + 1, &set, &set, NULL, timeout);
379 if (ret < 0) {
380 ret = -errno;
381 goto end;
382 }
383 if (ret == 0) {
384 ret = -ETIMEDOUT;
385 goto end;
386 }
387
388 /* Verify that we don't have an error */
389 len = sizeof(error);
390 ret = getsockopt(fd, SOL_SOCKET, SO_ERROR, &error, &len);
391 if(ret < 0) {
392 ret = -errno;
393 goto end;
394 }
395 if (error) {
396 ret = -error;
397 goto end;
398 }
399
400end:
401 /* Restore blocking mode */
402 set_blocking_mode(fd, true);
403 return ret;
404}
405
406static int set_socket_timeout(int fd, unsigned int timeout)
407{
408 struct timeval tv;
409
410 tv.tv_sec = timeout / 1000;
411 tv.tv_usec = (timeout % 1000) * 1000;
412 if (setsockopt(fd, SOL_SOCKET, SO_SNDTIMEO, &tv, sizeof(tv)) < 0 ||
413 setsockopt(fd, SOL_SOCKET, SO_RCVTIMEO,
414 &tv, sizeof(tv)) < 0)
415 return -errno;
416 else
417 return 0;
418}
419#else
420static int set_socket_timeout(int fd, unsigned int timeout)
421{
422 if (setsockopt(fd, SOL_SOCKET, SO_SNDTIMEO,
423 (const char *) &timeout, sizeof(timeout)) < 0 ||
424 setsockopt(fd, SOL_SOCKET, SO_RCVTIMEO,
425 (const char *) &timeout, sizeof(timeout)) < 0)
426 return -errno;
427 else
428 return 0;
429}
430#endif /* !_WIN32 */
431
432static int create_socket(const struct addrinfo *addrinfo)
433{
434 struct timeval timeout;
435 int ret, fd, yes = 1;
436
437 fd = socket(addrinfo->ai_family, addrinfo->ai_socktype, 0);
438 if (fd < 0) {
439 ERROR("Unable to open socket\n");
440 return fd;
441 }
442
443 timeout.tv_sec = DEFAULT_TIMEOUT_MS / 1000;
444 timeout.tv_usec = (DEFAULT_TIMEOUT_MS % 1000) * 1000;
445
446#ifndef _WIN32
447 ret = do_connect(fd, addrinfo->ai_addr, addrinfo->ai_addrlen, &timeout);
448#else
449 ret = connect(fd, addrinfo->ai_addr, addrinfo->ai_addrlen);
450#endif
451 if (ret < 0) {
452 ERROR("Unable to connect\n");
453 close(fd);
454 return ret;
455 }
456
457 set_socket_timeout(fd, DEFAULT_TIMEOUT_MS);
458 setsockopt(fd, IPPROTO_TCP, TCP_NODELAY,
459 (const char *) &yes, sizeof(yes));
460 return fd;
461}
462
Paul Cercueil09a43482015-03-04 15:50:27 +0100463static bool is_tx(const struct iio_device *dev)
464{
465 unsigned int i;
466
467 for (i = 0; i < dev->nb_channels; i++) {
468 struct iio_channel *ch = dev->channels[i];
469 if (iio_channel_is_output(ch) && iio_channel_is_enabled(ch))
470 return true;
471 }
472
473 return false;
474}
475
Paul Cercueil71694c72014-05-22 14:02:13 +0200476static int network_open(const struct iio_device *dev, size_t samples_count,
477 uint32_t *mask, size_t nb, bool cyclic)
Paul Cercueilba059762014-03-14 11:02:02 +0100478{
Paul Cercueil439e1a22015-02-24 13:50:51 +0100479 struct iio_context_pdata *pdata = dev->ctx->pdata;
Paul Cercueilba059762014-03-14 11:02:02 +0100480 char buf[1024], *ptr;
481 unsigned int i;
Paul Cercueil439e1a22015-02-24 13:50:51 +0100482 int ret, fd;
Paul Cercueilba059762014-03-14 11:02:02 +0100483
Paul Cercueilff778232014-03-24 14:23:08 +0100484 if (nb != dev->words)
Paul Cercueilba059762014-03-14 11:02:02 +0100485 return -EINVAL;
Paul Cercueil439e1a22015-02-24 13:50:51 +0100486 if (dev->pdata->fd >= 0)
487 return -EBUSY;
488
489 fd = create_socket(pdata->addrinfo);
490 if (fd < 0)
491 return fd;
Paul Cercueilba059762014-03-14 11:02:02 +0100492
Paul Cercueil3c407f82014-04-02 14:11:59 +0200493 snprintf(buf, sizeof(buf), "OPEN %s %lu ",
494 dev->id, (unsigned long) samples_count);
Paul Cercueilba059762014-03-14 11:02:02 +0100495 ptr = buf + strlen(buf);
496
497 for (i = nb; i > 0; i--) {
Paul Cercueil8c29e412014-04-07 09:46:45 +0200498 snprintf(ptr, (ptr - buf) + i * 8, "%08x", mask[i - 1]);
Paul Cercueilba059762014-03-14 11:02:02 +0100499 ptr += 8;
500 }
Paul Cercueil71694c72014-05-22 14:02:13 +0200501
502 strcpy(ptr, cyclic ? " CYCLIC\r\n" : "\r\n");
Paul Cercueilba059762014-03-14 11:02:02 +0100503
Paul Cercueilc5b00752015-02-24 14:29:53 +0100504 network_lock_dev(dev->pdata);
Paul Cercueil439e1a22015-02-24 13:50:51 +0100505 ret = (int) exec_command(buf, fd);
Paul Cercueilc5b00752015-02-24 14:29:53 +0100506 network_unlock_dev(dev->pdata);
Paul Cercueil1494b862014-05-05 12:49:07 +0200507
Paul Cercueil44ae11c2014-03-17 09:56:29 +0100508 if (ret < 0) {
Paul Cercueil439e1a22015-02-24 13:50:51 +0100509 close(fd);
Paul Cercueil44ae11c2014-03-17 09:56:29 +0100510 return ret;
Paul Cercueil44ae11c2014-03-17 09:56:29 +0100511 }
Paul Cercueil439e1a22015-02-24 13:50:51 +0100512
Paul Cercueil09a43482015-03-04 15:50:27 +0100513 dev->pdata->is_tx = is_tx(dev);
Paul Cercueil1d70d442015-03-04 15:00:37 +0100514 dev->pdata->is_cyclic = cyclic;
Paul Cercueil439e1a22015-02-24 13:50:51 +0100515 dev->pdata->fd = fd;
Paul Cercueil8f7f6c42015-02-24 15:00:35 +0100516 dev->pdata->wait_for_err_code = false;
Paul Cercueil439e1a22015-02-24 13:50:51 +0100517 memcpy(dev->mask, mask, nb * sizeof(*mask));
518 return 0;
Paul Cercueilba059762014-03-14 11:02:02 +0100519}
520
Paul Cercueil8f7f6c42015-02-24 15:00:35 +0100521static ssize_t read_error_code(int fd)
522{
523 /*
524 * The server returns two integer codes.
525 * The first one is returned right after the WRITEBUF command is issued,
526 * and corresponds to the error code returned when the server attempted
527 * to open the device.
528 * If zero, a second error code is returned, that corresponds (if positive)
529 * to the number of bytes written.
530 *
531 * To speed up things, we delay error reporting. We just send out the
532 * data without reading the error code that the server gives us, because
533 * the answer will take too much time. If an error occured, it will be
534 * reported by the next call to iio_buffer_push().
535 */
536
537 unsigned int i;
538 long resp = 0;
539
540 for (i = 0; i < 2; i++) {
541 ssize_t ret = read_integer(fd, &resp);
542 if (ret < 0)
543 return ret;
544 if (resp < 0)
545 return (ssize_t) resp;
546 }
547
Paul Cercueil7d7e5d32015-03-05 10:51:41 +0100548 return (ssize_t) resp;
Paul Cercueil8f7f6c42015-02-24 15:00:35 +0100549}
550
Paul Cercueil3c0da372015-03-05 11:36:39 +0100551static ssize_t write_rwbuf_command(const struct iio_device *dev,
552 const char *cmd, bool do_exec)
553{
554 struct iio_device_pdata *pdata = dev->pdata;
555 int fd = pdata->fd;
556
557 if (pdata->wait_for_err_code) {
558 ssize_t ret = read_error_code(fd);
559
560 pdata->wait_for_err_code = false;
561 if (ret < 0)
562 return ret;
563 }
564
565 return do_exec ? exec_command(cmd, fd) : write_command(cmd, fd);
566}
567
Paul Cercueilba059762014-03-14 11:02:02 +0100568static int network_close(const struct iio_device *dev)
569{
Paul Cercueil439e1a22015-02-24 13:50:51 +0100570 struct iio_device_pdata *pdata = dev->pdata;
Paul Cercueil1494b862014-05-05 12:49:07 +0200571 int ret;
Paul Cercueilba059762014-03-14 11:02:02 +0100572 char buf[1024];
Paul Cercueil439e1a22015-02-24 13:50:51 +0100573
Paul Cercueilba059762014-03-14 11:02:02 +0100574 snprintf(buf, sizeof(buf), "CLOSE %s\r\n", dev->id);
Paul Cercueil1494b862014-05-05 12:49:07 +0200575
Paul Cercueilc5b00752015-02-24 14:29:53 +0100576 network_lock_dev(pdata);
Paul Cercueil3c0da372015-03-05 11:36:39 +0100577 ret = (int) write_rwbuf_command(dev, buf, true);
Paul Cercueil1494b862014-05-05 12:49:07 +0200578
Paul Cercueilaa0db142015-03-04 16:25:24 +0100579 write_command("\r\nEXIT\r\n", pdata->fd);
580
Paul Cercueil439e1a22015-02-24 13:50:51 +0100581 close(pdata->fd);
582 pdata->fd = -1;
Paul Cercueilc5b00752015-02-24 14:29:53 +0100583 network_unlock_dev(pdata);
Paul Cercueile6e5a092015-03-04 16:33:26 +0100584
585#ifdef __linux__
586 if (pdata->memfd >= 0)
587 close(pdata->memfd);
588 pdata->memfd = -1;
589
590 if (pdata->mmap_addr) {
591 munmap(pdata->mmap_addr, pdata->mmap_len);
592 pdata->mmap_addr = NULL;
593 }
594#endif
Paul Cercueil1494b862014-05-05 12:49:07 +0200595 return ret;
Paul Cercueilba059762014-03-14 11:02:02 +0100596}
597
Paul Cercueil7d7e5d32015-03-05 10:51:41 +0100598static ssize_t network_read_mask(int fd, uint32_t *mask, size_t words)
599{
600 long read_len;
601 ssize_t ret;
602
603 ret = read_integer(fd, &read_len);
604 if (ret < 0)
605 return ret;
606
607 if (read_len > 0 && mask) {
608 unsigned int i;
609 char buf[9];
610
611 buf[8] = '\0';
612 DEBUG("Reading mask\n");
613
614 for (i = words; i > 0; i--) {
615 ret = read_all(buf, 8, fd);
616 if (ret < 0)
617 return ret;
618
619 sscanf(buf, "%08x", &mask[i - 1]);
620 DEBUG("mask[%i] = 0x%x\n", i - 1, mask[i - 1]);
621 }
622 }
623
624 if (read_len > 0) {
625 char c;
626 ssize_t nb = read_all(&c, 1, fd);
627 if (nb > 0 && c != '\n')
628 read_len = -EIO;
629 }
630
631 return (ssize_t) read_len;
632}
633
Paul Cercueil45c575d2014-03-20 15:14:01 +0100634static ssize_t network_read(const struct iio_device *dev, void *dst, size_t len,
635 uint32_t *mask, size_t words)
Paul Cercueilf9286452014-03-18 14:32:17 +0100636{
Paul Cercueil6e7f79e2014-04-04 12:27:24 +0200637 uintptr_t ptr = (uintptr_t) dst;
Paul Cercueilc5b00752015-02-24 14:29:53 +0100638 struct iio_device_pdata *pdata = dev->pdata;
639 int fd = pdata->fd;
Paul Cercueil45c575d2014-03-20 15:14:01 +0100640 ssize_t ret, read = 0;
Paul Cercueil9945bc82014-03-05 14:07:29 +0100641 char buf[1024];
642
Paul Cercueil45c575d2014-03-20 15:14:01 +0100643 if (!len || words != (dev->nb_channels + 31) / 32)
Paul Cercueil9945bc82014-03-05 14:07:29 +0100644 return -EINVAL;
645
Paul Cercueila78b6eb2014-03-17 17:28:07 +0100646 snprintf(buf, sizeof(buf), "READBUF %s %lu\r\n",
647 dev->id, (unsigned long) len);
Paul Cercueil1494b862014-05-05 12:49:07 +0200648
Paul Cercueilc5b00752015-02-24 14:29:53 +0100649 network_lock_dev(pdata);
Paul Cercueil3c0da372015-03-05 11:36:39 +0100650 ret = write_rwbuf_command(dev, buf, false);
Paul Cercueil1494b862014-05-05 12:49:07 +0200651 if (ret < 0) {
Paul Cercueilc5b00752015-02-24 14:29:53 +0100652 network_unlock_dev(pdata);
Paul Cercueil9945bc82014-03-05 14:07:29 +0100653 return ret;
Paul Cercueil1494b862014-05-05 12:49:07 +0200654 }
Paul Cercueil9945bc82014-03-05 14:07:29 +0100655
656 do {
Paul Cercueil7d7e5d32015-03-05 10:51:41 +0100657 ret = network_read_mask(fd, mask, words);
658 if (!ret)
Paul Cercueila78b6eb2014-03-17 17:28:07 +0100659 break;
Paul Cercueil5cab3ae2014-03-14 11:23:56 +0100660 if (ret < 0) {
661 strerror_r(-ret, buf, sizeof(buf));
662 ERROR("Unable to read mask: %s\n", buf);
Paul Cercueilc5b00752015-02-24 14:29:53 +0100663 network_unlock_dev(pdata);
Paul Cercueil6e7f79e2014-04-04 12:27:24 +0200664 return read ? read : ret;
Paul Cercueil5cab3ae2014-03-14 11:23:56 +0100665 }
666
Paul Cercueil7d7e5d32015-03-05 10:51:41 +0100667 mask = NULL; /* We read the mask only once */
668
669 ret = read_all((void *) ptr, ret, fd);
Paul Cercueil9945bc82014-03-05 14:07:29 +0100670 if (ret < 0) {
671 strerror_r(-ret, buf, sizeof(buf));
672 ERROR("Unable to read response to READ: %s\n", buf);
Paul Cercueilc5b00752015-02-24 14:29:53 +0100673 network_unlock_dev(pdata);
Paul Cercueil6e7f79e2014-04-04 12:27:24 +0200674 return read ? read : ret;
Paul Cercueil9945bc82014-03-05 14:07:29 +0100675 }
676
Paul Cercueil6e7f79e2014-04-04 12:27:24 +0200677 ptr += ret;
Paul Cercueilf9286452014-03-18 14:32:17 +0100678 read += ret;
Paul Cercueil7d7e5d32015-03-05 10:51:41 +0100679 len -= ret;
Paul Cercueil9945bc82014-03-05 14:07:29 +0100680 } while (len);
681
Paul Cercueilc5b00752015-02-24 14:29:53 +0100682 network_unlock_dev(pdata);
Paul Cercueil9945bc82014-03-05 14:07:29 +0100683 return read;
684}
685
Paul Cercueila62f84e2015-02-24 14:16:08 +0100686static ssize_t network_write(const struct iio_device *dev,
687 const void *src, size_t len)
Paul Cercueil2725f702014-05-02 11:02:16 +0200688{
Paul Cercueilc5b00752015-02-24 14:29:53 +0100689 struct iio_device_pdata *pdata = dev->pdata;
Paul Cercueil439e1a22015-02-24 13:50:51 +0100690 int fd;
Paul Cercueil2725f702014-05-02 11:02:16 +0200691 ssize_t ret;
Paul Cercueil2725f702014-05-02 11:02:16 +0200692 long resp;
Paul Cercueila62f84e2015-02-24 14:16:08 +0100693 char buf[1024];
694
695 snprintf(buf, sizeof(buf), "WRITEBUF %s %lu\r\n",
696 dev->id, (unsigned long) len);
Paul Cercueil2725f702014-05-02 11:02:16 +0200697
Paul Cercueilc5b00752015-02-24 14:29:53 +0100698 network_lock_dev(pdata);
699 fd = pdata->fd;
Paul Cercueil8f7f6c42015-02-24 15:00:35 +0100700
Paul Cercueil3c0da372015-03-05 11:36:39 +0100701 ret = write_rwbuf_command(dev, buf, pdata->is_cyclic);
Paul Cercueil2725f702014-05-02 11:02:16 +0200702 if (ret < 0)
Paul Cercueil1494b862014-05-05 12:49:07 +0200703 goto err_unlock;
Paul Cercueil2725f702014-05-02 11:02:16 +0200704
705 ret = write_all(src, len, fd);
706 if (ret < 0)
Paul Cercueil1494b862014-05-05 12:49:07 +0200707 goto err_unlock;
Paul Cercueil2725f702014-05-02 11:02:16 +0200708
Paul Cercueil1d70d442015-03-04 15:00:37 +0100709 if (pdata->is_cyclic) {
710 ret = read_integer(fd, &resp);
711 if (ret < 0)
712 goto err_unlock;
713 if (resp < 0) {
714 ret = (ssize_t) resp;
715 goto err_unlock;
716 }
717 } else {
718 pdata->wait_for_err_code = true;
719 }
Paul Cercueilc5b00752015-02-24 14:29:53 +0100720 network_unlock_dev(pdata);
Paul Cercueil1494b862014-05-05 12:49:07 +0200721
Paul Cercueil8f7f6c42015-02-24 15:00:35 +0100722 /* We assume that the whole buffer was submitted.
723 * The error code will be returned by the next call to this function. */
724 return (ssize_t) len;
Paul Cercueil1494b862014-05-05 12:49:07 +0200725
726err_unlock:
Paul Cercueilc5b00752015-02-24 14:29:53 +0100727 network_unlock_dev(pdata);
Paul Cercueil1494b862014-05-05 12:49:07 +0200728 return ret;
Paul Cercueil2725f702014-05-02 11:02:16 +0200729}
730
Paul Cercueil09a43482015-03-04 15:50:27 +0100731#ifdef __linux__
Paul Cercueil7d7e5d32015-03-05 10:51:41 +0100732static ssize_t network_do_splice(int fd_out, int fd_in, size_t len)
Paul Cercueil09a43482015-03-04 15:50:27 +0100733{
734 int pipefd[2];
Paul Cercueil04065c22015-03-05 14:08:16 +0100735 ssize_t ret, read_len = len;
Paul Cercueil09a43482015-03-04 15:50:27 +0100736
737 ret = (ssize_t) pipe(pipefd);
738 if (ret < 0)
739 return -errno;
740
741 do {
Paul Cercueila107c6d2015-03-05 13:54:10 +0100742 /*
743 * SPLICE_F_NONBLOCK is just here to avoid a deadlock when
744 * splicing from a socket. As the socket is not in
745 * non-blocking mode, it should never return -EAGAIN.
746 * TODO(pcercuei): Find why it locks...
747 * */
748 ret = splice(fd_in, NULL, pipefd[1], NULL, len,
749 SPLICE_F_MOVE | SPLICE_F_NONBLOCK);
750 if (!ret)
751 ret = -EIO;
Paul Cercueil09a43482015-03-04 15:50:27 +0100752 if (ret < 0)
753 goto err_close_pipe;
754
Paul Cercueila107c6d2015-03-05 13:54:10 +0100755 ret = splice(pipefd[0], NULL, fd_out, NULL, ret,
756 SPLICE_F_MOVE | SPLICE_F_NONBLOCK);
757 if (!ret)
758 ret = -EIO;
Paul Cercueil09a43482015-03-04 15:50:27 +0100759 if (ret < 0)
760 goto err_close_pipe;
761
762 len -= ret;
763 } while (len);
764
765err_close_pipe:
766 close(pipefd[0]);
767 close(pipefd[1]);
Paul Cercueil04065c22015-03-05 14:08:16 +0100768 return ret < 0 ? ret : read_len;
Paul Cercueil09a43482015-03-04 15:50:27 +0100769}
770
771static ssize_t network_get_buffer(const struct iio_device *dev,
Paul Cercueil76ca8842015-03-05 11:16:16 +0100772 void **addr_ptr, size_t bytes_used,
773 uint32_t *mask, size_t words)
Paul Cercueil09a43482015-03-04 15:50:27 +0100774{
775 struct iio_device_pdata *pdata = dev->pdata;
Paul Cercueil04065c22015-03-05 14:08:16 +0100776 ssize_t ret, read = 0;
Paul Cercueil09a43482015-03-04 15:50:27 +0100777 bool tx;
Paul Cercueil09a43482015-03-04 15:50:27 +0100778
Paul Cercueil04065c22015-03-05 14:08:16 +0100779 if (pdata->is_cyclic)
Paul Cercueil09a43482015-03-04 15:50:27 +0100780 return -ENOSYS;
Paul Cercueil76ca8842015-03-05 11:16:16 +0100781 if (!addr_ptr || words != (dev->nb_channels + 31) / 32)
Paul Cercueil09a43482015-03-04 15:50:27 +0100782 return -EINVAL;
783
Paul Cercueile6e5a092015-03-04 16:33:26 +0100784 if (pdata->mmap_addr)
785 munmap(pdata->mmap_addr, pdata->mmap_len);
Paul Cercueil09a43482015-03-04 15:50:27 +0100786
Paul Cercueile6e5a092015-03-04 16:33:26 +0100787 if (pdata->mmap_addr && pdata->is_tx) {
Paul Cercueil09a43482015-03-04 15:50:27 +0100788 char buf[1024];
789 snprintf(buf, sizeof(buf), "WRITEBUF %s %lu\r\n",
790 dev->id, (unsigned long) pdata->mmap_len);
791
792 network_lock_dev(pdata);
793
Paul Cercueil3c0da372015-03-05 11:36:39 +0100794 ret = write_rwbuf_command(dev, buf, false);
Paul Cercueil09a43482015-03-04 15:50:27 +0100795 if (ret < 0)
796 goto err_unlock;
797
798 ret = network_do_splice(pdata->fd,
799 pdata->memfd, pdata->mmap_len);
800 if (ret < 0)
801 goto err_unlock;
802
803 pdata->wait_for_err_code = true;
804 network_unlock_dev(pdata);
805 }
806
807 if (pdata->memfd >= 0)
808 close(pdata->memfd);
809
810 if (bytes_used)
811 pdata->mmap_len = bytes_used;
812
813 /* O_TMPFILE -> Linux 3.11.
814 * TODO: use memfd_create (Linux 3.17) */
815 pdata->memfd = open(P_tmpdir, O_RDWR | O_TMPFILE | O_EXCL, S_IRWXU);
816 if (pdata->memfd < 0) {
817 ret = -errno;
Paul Cercueil7d7e5d32015-03-05 10:51:41 +0100818 ERROR("Unable to create temp file: %zi\n", -ret);
Paul Cercueil09a43482015-03-04 15:50:27 +0100819 return ret;
820 }
821
Paul Cercueilef32d582015-03-05 11:18:35 +0100822 ret = (ssize_t) ftruncate(pdata->memfd, pdata->mmap_len);
823 if (ret < 0) {
824 ret = -errno;
825 ERROR("Unable to truncate temp file: %zi\n", -ret);
826 return ret;
827 }
Paul Cercueil09a43482015-03-04 15:50:27 +0100828
Paul Cercueil04065c22015-03-05 14:08:16 +0100829 if (!pdata->is_tx) {
830 char buf[1024];
831 size_t len = pdata->mmap_len;
832
833 snprintf(buf, sizeof(buf), "READBUF %s %lu\r\n",
834 dev->id, (unsigned long) len);
835
836 network_lock_dev(pdata);
837 ret = write_rwbuf_command(dev, buf, false);
838 if (ret < 0)
839 goto err_unlock;
840
841 do {
842 ret = network_read_mask(pdata->fd, mask, words);
843 if (!ret)
844 break;
845 if (ret < 0)
846 goto err_unlock;
847
848 mask = NULL; /* We read the mask only once */
849
850 ret = network_do_splice(pdata->memfd, pdata->fd, ret);
851 if (ret < 0)
852 goto err_unlock;
853
854 read += ret;
855 len -= ret;
856 } while (len);
857
858 network_unlock_dev(pdata);
859 }
Paul Cercueil09a43482015-03-04 15:50:27 +0100860
Paul Cercueile6e5a092015-03-04 16:33:26 +0100861 pdata->mmap_addr = mmap(NULL, pdata->mmap_len,
Paul Cercueil09a43482015-03-04 15:50:27 +0100862 PROT_READ | PROT_WRITE, MAP_SHARED, pdata->memfd, 0);
Paul Cercueile6e5a092015-03-04 16:33:26 +0100863 if (pdata->mmap_addr == MAP_FAILED) {
864 pdata->mmap_addr = NULL;
Paul Cercueil09a43482015-03-04 15:50:27 +0100865 ret = -errno;
Paul Cercueil7d7e5d32015-03-05 10:51:41 +0100866 ERROR("Unable to mmap: %zi\n", -ret);
Paul Cercueil09a43482015-03-04 15:50:27 +0100867 return ret;
868 }
869
Paul Cercueile6e5a092015-03-04 16:33:26 +0100870 *addr_ptr = pdata->mmap_addr;
Paul Cercueil04065c22015-03-05 14:08:16 +0100871 return read ? read : bytes_used;
Paul Cercueil09a43482015-03-04 15:50:27 +0100872
873err_unlock:
874 network_unlock_dev(pdata);
875 return ret;
876}
877#endif
878
Paul Cercueil1494b862014-05-05 12:49:07 +0200879static ssize_t network_read_attr_helper(const struct iio_device *dev,
Paul Cercueil0cc0e162014-05-07 12:51:22 +0200880 const struct iio_channel *chn, const char *attr, char *dst,
Paul Cercueil1494b862014-05-05 12:49:07 +0200881 size_t len, bool is_debug)
Paul Cercueil3e94a5b2014-03-04 13:00:41 +0100882{
Paul Cercueil3e94a5b2014-03-04 13:00:41 +0100883 long read_len;
884 ssize_t ret;
885 char buf[1024];
Paul Cercueil05e26262014-05-09 11:32:43 +0200886 struct iio_context_pdata *pdata = dev->ctx->pdata;
887 int fd = pdata->fd;
Paul Cercueil1494b862014-05-05 12:49:07 +0200888 const char *id = dev->id;
Paul Cercueil3e94a5b2014-03-04 13:00:41 +0100889
Paul Cercueil99cf3d42014-03-06 12:35:26 +0100890 if (chn)
Paul Cercueil0cc0e162014-05-07 12:51:22 +0200891 snprintf(buf, sizeof(buf), "READ %s %s %s %s\r\n", id,
892 chn->is_output ? "OUTPUT" : "INPUT",
Paul Cercueil2a3e43d2014-05-21 16:58:45 +0200893 chn->id, attr ? attr : "");
Paul Cercueilc6f03612014-04-14 16:41:31 +0200894 else if (is_debug)
Paul Cercueil2a3e43d2014-05-21 16:58:45 +0200895 snprintf(buf, sizeof(buf), "READ %s DEBUG %s\r\n",
896 id, attr ? attr : "");
Paul Cercueil99cf3d42014-03-06 12:35:26 +0100897 else
Paul Cercueil2a3e43d2014-05-21 16:58:45 +0200898 snprintf(buf, sizeof(buf), "READ %s %s\r\n",
899 id, attr ? attr : "");
Paul Cercueil1494b862014-05-05 12:49:07 +0200900
Paul Cercueil05e26262014-05-09 11:32:43 +0200901 network_lock(pdata);
Paul Cercueilbb76bf92014-03-11 10:20:18 +0100902 read_len = exec_command(buf, fd);
Paul Cercueil1494b862014-05-05 12:49:07 +0200903 if (read_len < 0) {
Paul Cercueil05e26262014-05-09 11:32:43 +0200904 network_unlock(pdata);
Paul Cercueilbb76bf92014-03-11 10:20:18 +0100905 return (ssize_t) read_len;
Paul Cercueil1494b862014-05-05 12:49:07 +0200906 }
Paul Cercueil3e94a5b2014-03-04 13:00:41 +0100907
Paul Cercueil6e7f79e2014-04-04 12:27:24 +0200908 if ((unsigned long) read_len > len) {
Paul Cercueil3e94a5b2014-03-04 13:00:41 +0100909 ERROR("Value returned by server is too large\n");
Paul Cercueil05e26262014-05-09 11:32:43 +0200910 network_unlock(pdata);
Paul Cercueil3e94a5b2014-03-04 13:00:41 +0100911 return -EIO;
912 }
913
914 ret = read_all(dst, read_len, fd);
Paul Cercueil05e26262014-05-09 11:32:43 +0200915 network_unlock(pdata);
Paul Cercueil1494b862014-05-05 12:49:07 +0200916
Paul Cercueil3e94a5b2014-03-04 13:00:41 +0100917 if (ret < 0) {
918 strerror_r(-ret, buf, sizeof(buf));
919 ERROR("Unable to read response to READ: %s\n", buf);
920 return ret;
921 }
922
Paul Cercueil7d95fd72014-05-22 14:26:44 +0200923 return read_len;
Paul Cercueil3e94a5b2014-03-04 13:00:41 +0100924}
925
Paul Cercueil1494b862014-05-05 12:49:07 +0200926static ssize_t network_write_attr_helper(const struct iio_device *dev,
Paul Cercueil0cc0e162014-05-07 12:51:22 +0200927 const struct iio_channel *chn, const char *attr,
928 const char *src, size_t len, bool is_debug)
Paul Cercueil3e94a5b2014-03-04 13:00:41 +0100929{
Paul Cercueila62f84e2015-02-24 14:16:08 +0100930 struct iio_context_pdata *pdata = dev->ctx->pdata;
931 int fd;
932 ssize_t ret;
933 long resp;
Paul Cercueil3e94a5b2014-03-04 13:00:41 +0100934 char buf[1024];
Paul Cercueil1494b862014-05-05 12:49:07 +0200935 const char *id = dev->id;
Paul Cercueil3e94a5b2014-03-04 13:00:41 +0100936
Paul Cercueil07897d32014-03-06 12:46:08 +0100937 if (chn)
Paul Cercueil0cc0e162014-05-07 12:51:22 +0200938 snprintf(buf, sizeof(buf), "WRITE %s %s %s %s %lu\r\n",
939 id, chn->is_output ? "OUTPUT" : "INPUT",
Paul Cercueil8747efe2014-05-22 11:12:12 +0200940 chn->id, attr ? attr : "", (unsigned long) len);
Paul Cercueilc6f03612014-04-14 16:41:31 +0200941 else if (is_debug)
Paul Cercueil8747efe2014-05-22 11:12:12 +0200942 snprintf(buf, sizeof(buf), "WRITE %s DEBUG %s %lu\r\n",
943 id, attr ? attr : "", (unsigned long) len);
Paul Cercueil07897d32014-03-06 12:46:08 +0100944 else
Paul Cercueilcecda352014-05-06 18:14:29 +0200945 snprintf(buf, sizeof(buf), "WRITE %s %s %lu\r\n",
Paul Cercueil8747efe2014-05-22 11:12:12 +0200946 id, attr ? attr : "", (unsigned long) len);
Paul Cercueila62f84e2015-02-24 14:16:08 +0100947
948 network_lock(pdata);
949 fd = pdata->fd;
950 ret = (ssize_t) write_command(buf, fd);
951 if (ret < 0)
952 goto err_unlock;
953
954 ret = write_all(src, len, fd);
955 if (ret < 0)
956 goto err_unlock;
957
958 ret = read_integer(fd, &resp);
959 network_unlock(pdata);
960
961 if (ret < 0)
962 return ret;
963 return (ssize_t) resp;
964
965err_unlock:
966 network_unlock(pdata);
967 return ret;
Paul Cercueil3e94a5b2014-03-04 13:00:41 +0100968}
969
Paul Cercueil99cf3d42014-03-06 12:35:26 +0100970static ssize_t network_read_dev_attr(const struct iio_device *dev,
Paul Cercueil50c762a2014-04-14 15:55:43 +0200971 const char *attr, char *dst, size_t len, bool is_debug)
Paul Cercueil99cf3d42014-03-06 12:35:26 +0100972{
Paul Cercueil5b577762014-06-03 15:31:42 +0200973 if (attr && ((is_debug && !iio_device_find_debug_attr(dev, attr)) ||
974 (!is_debug && !iio_device_find_attr(dev, attr))))
975 return -ENOENT;
976
Paul Cercueil1494b862014-05-05 12:49:07 +0200977 return network_read_attr_helper(dev, NULL, attr, dst, len, is_debug);
Paul Cercueil99cf3d42014-03-06 12:35:26 +0100978}
979
Paul Cercueil07897d32014-03-06 12:46:08 +0100980static ssize_t network_write_dev_attr(const struct iio_device *dev,
Paul Cercueilcecda352014-05-06 18:14:29 +0200981 const char *attr, const char *src, size_t len, bool is_debug)
Paul Cercueil07897d32014-03-06 12:46:08 +0100982{
Paul Cercueil5b577762014-06-03 15:31:42 +0200983 if (attr && ((is_debug && !iio_device_find_debug_attr(dev, attr)) ||
984 (!is_debug && !iio_device_find_attr(dev, attr))))
985 return -ENOENT;
986
Paul Cercueilcecda352014-05-06 18:14:29 +0200987 return network_write_attr_helper(dev, NULL, attr, src, len, is_debug);
Paul Cercueil07897d32014-03-06 12:46:08 +0100988}
989
Paul Cercueil99cf3d42014-03-06 12:35:26 +0100990static ssize_t network_read_chn_attr(const struct iio_channel *chn,
991 const char *attr, char *dst, size_t len)
992{
Paul Cercueil5b577762014-06-03 15:31:42 +0200993 if (attr && !iio_channel_find_attr(chn, attr))
994 return -ENOENT;
995
Paul Cercueil0cc0e162014-05-07 12:51:22 +0200996 return network_read_attr_helper(chn->dev, chn, attr, dst, len, false);
Paul Cercueil99cf3d42014-03-06 12:35:26 +0100997}
998
Paul Cercueil07897d32014-03-06 12:46:08 +0100999static ssize_t network_write_chn_attr(const struct iio_channel *chn,
Paul Cercueilcecda352014-05-06 18:14:29 +02001000 const char *attr, const char *src, size_t len)
Paul Cercueil07897d32014-03-06 12:46:08 +01001001{
Paul Cercueil5b577762014-06-03 15:31:42 +02001002 if (attr && !iio_channel_find_attr(chn, attr))
1003 return -ENOENT;
1004
Paul Cercueil0cc0e162014-05-07 12:51:22 +02001005 return network_write_attr_helper(chn->dev, chn, attr, src, len, false);
Paul Cercueil07897d32014-03-06 12:46:08 +01001006}
1007
Paul Cercueildcab40c2014-03-11 10:59:14 +01001008static int network_get_trigger(const struct iio_device *dev,
1009 const struct iio_device **trigger)
1010{
1011 struct iio_context_pdata *pdata = dev->ctx->pdata;
1012 unsigned int i;
1013 char buf[1024];
1014 ssize_t ret;
1015 long resp;
1016
1017 snprintf(buf, sizeof(buf), "GETTRIG %s\r\n", dev->id);
Paul Cercueil1494b862014-05-05 12:49:07 +02001018
Paul Cercueil05e26262014-05-09 11:32:43 +02001019 network_lock(dev->ctx->pdata);
Paul Cercueildcab40c2014-03-11 10:59:14 +01001020 resp = exec_command(buf, pdata->fd);
1021 if (resp < 0) {
Paul Cercueil05e26262014-05-09 11:32:43 +02001022 network_unlock(pdata);
Paul Cercueildcab40c2014-03-11 10:59:14 +01001023 return (int) resp;
1024 } else if (resp == 0) {
1025 *trigger = NULL;
Paul Cercueil05e26262014-05-09 11:32:43 +02001026 network_unlock(pdata);
Paul Cercueildcab40c2014-03-11 10:59:14 +01001027 return 0;
Paul Cercueil6e7f79e2014-04-04 12:27:24 +02001028 } else if ((unsigned long) resp > sizeof(buf)) {
Paul Cercueildcab40c2014-03-11 10:59:14 +01001029 ERROR("Value returned by server is too large\n");
Paul Cercueil05e26262014-05-09 11:32:43 +02001030 network_unlock(pdata);
Paul Cercueildcab40c2014-03-11 10:59:14 +01001031 return -EIO;
1032 }
1033
1034 ret = read_all(buf, resp, pdata->fd);
Paul Cercueil05e26262014-05-09 11:32:43 +02001035 network_unlock(pdata);
Paul Cercueil1494b862014-05-05 12:49:07 +02001036
Paul Cercueildcab40c2014-03-11 10:59:14 +01001037 if (ret < 0) {
1038 strerror_r(-ret, buf, sizeof(buf));
1039 ERROR("Unable to read response to GETTRIG: %s\n", buf);
1040 return ret;
1041 }
1042
Lars-Peter Clausenb5cdc102014-08-21 14:45:52 +02001043 if (buf[0] == '\0') {
1044 *trigger = NULL;
1045 return 0;
1046 }
1047
Paul Cercueildcab40c2014-03-11 10:59:14 +01001048 for (i = 0; i < dev->ctx->nb_devices; i++) {
1049 struct iio_device *cur = dev->ctx->devices[i];
1050 if (iio_device_is_trigger(cur) &&
1051 !strncmp(cur->name, buf, resp)) {
1052 *trigger = cur;
1053 return 0;
1054 }
1055 }
1056
1057 return -ENXIO;
1058}
1059
1060static int network_set_trigger(const struct iio_device *dev,
1061 const struct iio_device *trigger)
1062{
Paul Cercueil1494b862014-05-05 12:49:07 +02001063 int ret;
Paul Cercueildcab40c2014-03-11 10:59:14 +01001064 char buf[1024];
1065 if (trigger)
1066 snprintf(buf, sizeof(buf), "SETTRIG %s %s\r\n",
1067 dev->id, trigger->id);
1068 else
1069 snprintf(buf, sizeof(buf), "SETTRIG %s\r\n", dev->id);
Paul Cercueil1494b862014-05-05 12:49:07 +02001070
Paul Cercueil05e26262014-05-09 11:32:43 +02001071 network_lock(dev->ctx->pdata);
Paul Cercueil1494b862014-05-05 12:49:07 +02001072 ret = (int) exec_command(buf, dev->ctx->pdata->fd);
Paul Cercueil05e26262014-05-09 11:32:43 +02001073 network_unlock(dev->ctx->pdata);
Paul Cercueil1494b862014-05-05 12:49:07 +02001074 return ret;
Paul Cercueildcab40c2014-03-11 10:59:14 +01001075}
1076
Paul Cercueil8fd9c8f2014-03-03 17:21:31 +01001077static void network_shutdown(struct iio_context *ctx)
1078{
1079 struct iio_context_pdata *pdata = ctx->pdata;
Paul Cercueil44ae11c2014-03-17 09:56:29 +01001080 unsigned int i;
Paul Cercueil8fd9c8f2014-03-03 17:21:31 +01001081
Paul Cercueil05e26262014-05-09 11:32:43 +02001082 network_lock(pdata);
Paul Cercueilbb76bf92014-03-11 10:20:18 +01001083 write_command("\r\nEXIT\r\n", pdata->fd);
Paul Cercueil8fd9c8f2014-03-03 17:21:31 +01001084 close(pdata->fd);
Paul Cercueil05e26262014-05-09 11:32:43 +02001085 network_unlock(pdata);
Paul Cercueil1494b862014-05-05 12:49:07 +02001086
Paul Cercueil439e1a22015-02-24 13:50:51 +01001087 for (i = 0; i < ctx->nb_devices; i++) {
1088 struct iio_device *dev = ctx->devices[i];
Paul Cercueilc5b00752015-02-24 14:29:53 +01001089 struct iio_device_pdata *dpdata = dev->pdata;
Paul Cercueil439e1a22015-02-24 13:50:51 +01001090
Paul Cercueilc5b00752015-02-24 14:29:53 +01001091 if (dpdata) {
Paul Cercueilaa0db142015-03-04 16:25:24 +01001092 network_close(dev);
Paul Cercueilc5b00752015-02-24 14:29:53 +01001093#if HAVE_PTHREAD
Paul Cercueilaa0db142015-03-04 16:25:24 +01001094 pthread_mutex_destroy(&dpdata->lock);
Paul Cercueilc5b00752015-02-24 14:29:53 +01001095#endif
Paul Cercueilc5b00752015-02-24 14:29:53 +01001096 free(dpdata);
Paul Cercueil439e1a22015-02-24 13:50:51 +01001097 }
1098 }
1099
Paul Cercueil05e26262014-05-09 11:32:43 +02001100#if HAVE_PTHREAD
Paul Cercueil1494b862014-05-05 12:49:07 +02001101 pthread_mutex_destroy(&pdata->lock);
Paul Cercueil05e26262014-05-09 11:32:43 +02001102#endif
Paul Cercueil2dd2c132015-02-24 10:41:01 +01001103 freeaddrinfo(pdata->addrinfo);
Paul Cercueil8fd9c8f2014-03-03 17:21:31 +01001104 free(pdata);
1105}
1106
Paul Cercueil6691a3f2014-05-02 12:32:01 +02001107static int network_get_version(const struct iio_context *ctx,
Paul Cercueil9de9e9d2014-05-20 13:18:19 +02001108 unsigned int *major, unsigned int *minor, char git_tag[8])
Paul Cercueil6691a3f2014-05-02 12:32:01 +02001109{
1110 struct iio_context_pdata *pdata = ctx->pdata;
1111 long maj, min;
1112 int ret;
Paul Cercueil6691a3f2014-05-02 12:32:01 +02001113
Paul Cercueil05e26262014-05-09 11:32:43 +02001114 network_lock(pdata);
Paul Cercueil1494b862014-05-05 12:49:07 +02001115 ret = (int) write_command("VERSION\r\n", pdata->fd);
1116 if (ret < 0)
1117 goto err_unlock;
1118
1119 ret = read_integer(pdata->fd, &maj);
1120 if (!ret)
1121 ret = read_integer(pdata->fd, &min);
1122 if (!ret) {
Paul Cercueil9de9e9d2014-05-20 13:18:19 +02001123 char tag[8];
1124 tag[7] = '\0';
1125
1126 ret = read_all(tag, sizeof(tag) - 1, pdata->fd);
1127 if (ret < 0)
1128 goto err_unlock;
1129
Paul Cercueild15d9952014-05-20 11:40:08 +02001130 if (major)
1131 *major = (unsigned int) maj;
1132 if (minor)
1133 *minor = (unsigned int) min;
Paul Cercueil9de9e9d2014-05-20 13:18:19 +02001134 if (git_tag)
1135 strncpy(git_tag, tag, 8);
Paul Cercueil1494b862014-05-05 12:49:07 +02001136 }
1137
Paul Cercueil8e8f8992014-06-12 16:58:12 +02001138 ret = 0;
Paul Cercueil1494b862014-05-05 12:49:07 +02001139err_unlock:
Paul Cercueil05e26262014-05-09 11:32:43 +02001140 network_unlock(pdata);
Paul Cercueil1494b862014-05-05 12:49:07 +02001141 return ret;
Paul Cercueil6691a3f2014-05-02 12:32:01 +02001142}
1143
Paul Cercueil8a266f12014-06-10 16:06:31 +02001144static unsigned int calculate_remote_timeout(unsigned int timeout)
1145{
1146 /* XXX(pcercuei): We currently hardcode timeout / 2 for the backend used
1147 * by the remote. Is there something better to do here? */
1148 return timeout / 2;
1149}
1150
Paul Cercueilbca3dbc2014-06-11 12:00:21 +02001151static int set_remote_timeout(struct iio_context *ctx, unsigned int timeout)
1152{
1153 char buf[1024];
1154 int ret;
1155
1156 snprintf(buf, sizeof(buf), "TIMEOUT %u\r\n", timeout);
1157 network_lock(ctx->pdata);
1158 ret = (int) exec_command(buf, ctx->pdata->fd);
1159 network_unlock(ctx->pdata);
1160 return ret;
1161}
1162
1163static int network_set_timeout(struct iio_context *ctx, unsigned int timeout)
1164{
1165 int ret = set_socket_timeout(ctx->pdata->fd, timeout);
1166 if (!ret) {
1167 timeout = calculate_remote_timeout(timeout);
1168 ret = set_remote_timeout(ctx, timeout);
1169 }
1170 if (ret < 0) {
1171 char buf[1024];
1172 strerror_r(-ret, buf, sizeof(buf));
Paul Cercueil8a266f12014-06-10 16:06:31 +02001173 WARNING("Unable to set R/W timeout: %s\n", buf);
1174 } else {
Paul Cercueil8a266f12014-06-10 16:06:31 +02001175 ctx->rw_timeout_ms = timeout;
1176 }
1177 return ret;
1178}
1179
Paul Cercueil12d41832014-10-28 14:35:53 +01001180static struct iio_context * network_clone(const struct iio_context *ctx)
1181{
Paul Cercueild3d56ee2015-01-08 16:36:31 +01001182 return iio_create_network_context(ctx->description);
Paul Cercueil12d41832014-10-28 14:35:53 +01001183}
1184
Paul Cercueilc7bad0f2014-03-03 17:06:48 +01001185static struct iio_backend_ops network_ops = {
Paul Cercueil12d41832014-10-28 14:35:53 +01001186 .clone = network_clone,
Paul Cercueilba059762014-03-14 11:02:02 +01001187 .open = network_open,
1188 .close = network_close,
Paul Cercueil9945bc82014-03-05 14:07:29 +01001189 .read = network_read,
Paul Cercueil2725f702014-05-02 11:02:16 +02001190 .write = network_write,
Paul Cercueil09a43482015-03-04 15:50:27 +01001191#ifdef __linux__
1192 .get_buffer = network_get_buffer,
1193#endif
Paul Cercueil3e94a5b2014-03-04 13:00:41 +01001194 .read_device_attr = network_read_dev_attr,
1195 .write_device_attr = network_write_dev_attr,
Paul Cercueil99cf3d42014-03-06 12:35:26 +01001196 .read_channel_attr = network_read_chn_attr,
Paul Cercueil07897d32014-03-06 12:46:08 +01001197 .write_channel_attr = network_write_chn_attr,
Paul Cercueildcab40c2014-03-11 10:59:14 +01001198 .get_trigger = network_get_trigger,
1199 .set_trigger = network_set_trigger,
Paul Cercueil8fd9c8f2014-03-03 17:21:31 +01001200 .shutdown = network_shutdown,
Paul Cercueil6691a3f2014-05-02 12:32:01 +02001201 .get_version = network_get_version,
Paul Cercueil8a266f12014-06-10 16:06:31 +02001202 .set_timeout = network_set_timeout,
Paul Cercueilc7bad0f2014-03-03 17:06:48 +01001203};
1204
1205static struct iio_context * get_context(int fd)
1206{
1207 struct iio_context *ctx;
Paul Cercueile60c3ed2014-03-04 11:23:56 +01001208 char *xml;
Paul Cercueilbb76bf92014-03-11 10:20:18 +01001209 long xml_len = exec_command("PRINT\r\n", fd);
1210 if (xml_len < 0)
Paul Cercueilc7bad0f2014-03-03 17:06:48 +01001211 return NULL;
Paul Cercueile60c3ed2014-03-04 11:23:56 +01001212
1213 DEBUG("Server returned a XML string of length %li\n", xml_len);
Paul Cercueilc7bad0f2014-03-03 17:06:48 +01001214 xml = malloc(xml_len);
1215 if (!xml) {
1216 ERROR("Unable to allocate data\n");
1217 return NULL;
1218 }
1219
1220 DEBUG("Reading XML string...\n");
1221 read_all(xml, xml_len, fd);
1222
1223 DEBUG("Creating context from XML...\n");
1224 ctx = iio_create_xml_context_mem(xml, xml_len);
Paul Cercueilc1ed8482014-06-11 16:29:43 +02001225
1226 if (ctx)
1227 ctx->xml = xml;
1228 else
1229 free(xml);
Paul Cercueilc7bad0f2014-03-03 17:06:48 +01001230 return ctx;
1231}
1232
Paul Cercueil63e52182014-12-11 12:52:48 +01001233struct iio_context * network_create_context(const char *host)
Paul Cercueilc7bad0f2014-03-03 17:06:48 +01001234{
Paul Cercueil2e38bbe2014-03-19 15:27:15 +01001235 struct addrinfo hints, *res;
Paul Cercueilc7bad0f2014-03-03 17:06:48 +01001236 struct iio_context *ctx;
Paul Cercueil8fd9c8f2014-03-03 17:21:31 +01001237 struct iio_context_pdata *pdata;
Paul Cercueil06c479d2015-01-08 16:14:57 +01001238 unsigned int i, len;
Paul Cercueil4970ac32015-02-24 10:59:00 +01001239 int fd, ret;
Paul Cercueil1fef1a52014-04-07 16:31:15 +02001240#ifdef _WIN32
1241 WSADATA wsaData;
1242
1243 ret = WSAStartup(MAKEWORD(2, 0), &wsaData);
1244 if (ret < 0) {
1245 ERROR("WSAStartup failed with error %i\n", ret);
1246 return NULL;
1247 }
1248#endif
Paul Cercueilc7bad0f2014-03-03 17:06:48 +01001249
Paul Cercueil2e38bbe2014-03-19 15:27:15 +01001250 memset(&hints, 0, sizeof(hints));
1251 hints.ai_family = AF_UNSPEC;
1252 hints.ai_socktype = SOCK_STREAM;
Paul Cercueilab114932014-05-19 13:03:17 +02001253
1254#ifdef HAVE_AVAHI
1255 if (!host) {
1256 char addr_str[AVAHI_ADDRESS_STR_MAX];
1257 char port_str[6];
1258 AvahiAddress address;
Paul Cercueil0f729d32014-06-05 17:38:54 +02001259 uint16_t port = IIOD_PORT;
Paul Cercueilab114932014-05-19 13:03:17 +02001260
1261 memset(&address, 0, sizeof(address));
1262
1263 ret = discover_host(&address, &port);
1264 if (ret < 0) {
1265 ERROR("Unable to find host: %s\n", strerror(-ret));
1266 return NULL;
1267 }
1268
1269 avahi_address_snprint(addr_str, sizeof(addr_str), &address);
1270 snprintf(port_str, sizeof(port_str), "%hu", port);
1271 ret = getaddrinfo(addr_str, port_str, &hints, &res);
1272 } else
1273#endif
1274 {
1275 ret = getaddrinfo(host, IIOD_PORT_STR, &hints, &res);
1276 }
1277
Paul Cercueil2e38bbe2014-03-19 15:27:15 +01001278 if (ret) {
Paul Cercueilab114932014-05-19 13:03:17 +02001279 ERROR("Unable to find host: %s\n", gai_strerror(ret));
Paul Cercueilc7bad0f2014-03-03 17:06:48 +01001280 return NULL;
Paul Cercueilc7bad0f2014-03-03 17:06:48 +01001281 }
1282
Paul Cercueil4970ac32015-02-24 10:59:00 +01001283 fd = create_socket(res);
1284 if (fd < 0)
Paul Cercueil2dd2c132015-02-24 10:41:01 +01001285 goto err_free_addrinfo;
Paul Cercueilbca3dbc2014-06-11 12:00:21 +02001286
Paul Cercueil8fd9c8f2014-03-03 17:21:31 +01001287 pdata = calloc(1, sizeof(*pdata));
1288 if (!pdata) {
1289 ERROR("Unable to allocate memory\n");
1290 goto err_close_socket;
1291 }
1292
1293 pdata->fd = fd;
Paul Cercueil2dd2c132015-02-24 10:41:01 +01001294 pdata->addrinfo = res;
Paul Cercueil8fd9c8f2014-03-03 17:21:31 +01001295
Paul Cercueilc7bad0f2014-03-03 17:06:48 +01001296 DEBUG("Creating context...\n");
1297 ctx = get_context(fd);
1298 if (!ctx)
Paul Cercueild3d56ee2015-01-08 16:36:31 +01001299 goto err_free_pdata;
Paul Cercueilc7bad0f2014-03-03 17:06:48 +01001300
Paul Cercueil2057fd32014-10-28 14:44:19 +01001301 /* Override the name and low-level functions of the XML context
1302 * with those corresponding to the network context */
1303 ctx->name = "network";
1304 ctx->ops = &network_ops;
1305 ctx->pdata = pdata;
1306
Paul Cercueil06c479d2015-01-08 16:14:57 +01001307#ifdef HAVE_IPV6
Paul Cercueiled15e492015-01-12 15:52:28 +01001308 len = INET6_ADDRSTRLEN + IF_NAMESIZE + 2;
Paul Cercueil06c479d2015-01-08 16:14:57 +01001309#else
1310 len = INET_ADDRSTRLEN + 1;
1311#endif
1312 ctx->description = malloc(len);
1313 if (!ctx->description) {
1314 ERROR("Unable to allocate memory\n");
1315 goto err_network_shutdown;
1316 }
1317
1318 ctx->description[0] = '\0';
1319
1320#ifdef HAVE_IPV6
1321 if (res->ai_family == AF_INET6) {
1322 struct sockaddr_in6 *in = (struct sockaddr_in6 *) res->ai_addr;
Paul Cercueiled15e492015-01-12 15:52:28 +01001323 char *ptr;
Paul Cercueil06c479d2015-01-08 16:14:57 +01001324 inet_ntop(AF_INET6, &in->sin6_addr,
1325 ctx->description, INET6_ADDRSTRLEN);
Paul Cercueiled15e492015-01-12 15:52:28 +01001326
1327 ptr = if_indextoname(in->sin6_scope_id, ctx->description +
1328 strlen(ctx->description) + 1);
1329 if (!ptr) {
1330 ERROR("Unable to lookup interface of IPv6 address\n");
1331 goto err_network_shutdown;
1332 }
1333
1334 *(ptr - 1) = '%';
Paul Cercueil06c479d2015-01-08 16:14:57 +01001335 }
1336#endif
1337 if (res->ai_family == AF_INET) {
1338 struct sockaddr_in *in = (struct sockaddr_in *) res->ai_addr;
1339 inet_ntop(AF_INET, &in->sin_addr,
1340 ctx->description, INET_ADDRSTRLEN);
1341 }
1342
Paul Cercueil44ae11c2014-03-17 09:56:29 +01001343 for (i = 0; i < ctx->nb_devices; i++) {
1344 struct iio_device *dev = ctx->devices[i];
Paul Cercueilff778232014-03-24 14:23:08 +01001345
1346 dev->words = (dev->nb_channels + 31) / 32;
1347 if (dev->words) {
Paul Cercueil439e1a22015-02-24 13:50:51 +01001348 dev->mask = calloc(dev->words, sizeof(*dev->mask));
1349 if (!dev->mask) {
Paul Cercueil2057fd32014-10-28 14:44:19 +01001350 ERROR("Unable to allocate memory\n");
Paul Cercueilff778232014-03-24 14:23:08 +01001351 goto err_network_shutdown;
Paul Cercueil2057fd32014-10-28 14:44:19 +01001352 }
Paul Cercueilff778232014-03-24 14:23:08 +01001353 }
1354
Paul Cercueil439e1a22015-02-24 13:50:51 +01001355 dev->pdata = calloc(1, sizeof(*dev->pdata));
1356 if (!dev->pdata) {
1357 ERROR("Unable to allocate memory\n");
1358 goto err_network_shutdown;
1359 }
1360
1361 dev->pdata->fd = -1;
Paul Cercueile6e5a092015-03-04 16:33:26 +01001362#ifdef __linux__
Paul Cercueil09a43482015-03-04 15:50:27 +01001363 dev->pdata->memfd = -1;
Paul Cercueile6e5a092015-03-04 16:33:26 +01001364#endif
Paul Cercueilc5b00752015-02-24 14:29:53 +01001365
1366#if HAVE_PTHREAD
1367 ret = pthread_mutex_init(&dev->pdata->lock, NULL);
1368 if (ret < 0) {
1369 char buf[1024];
1370 strerror_r(-ret, buf, sizeof(buf));
1371 ERROR("Unable to initialize mutex: %s\n", buf);
1372 goto err_network_shutdown;
1373 }
1374#endif
Paul Cercueil44ae11c2014-03-17 09:56:29 +01001375 }
1376
Paul Cercueilc1ed8482014-06-11 16:29:43 +02001377 iio_context_init(ctx);
Paul Cercueil4c6729d2014-04-04 17:24:41 +02001378
Paul Cercueil05e26262014-05-09 11:32:43 +02001379#if HAVE_PTHREAD
Paul Cercueil1494b862014-05-05 12:49:07 +02001380 ret = pthread_mutex_init(&pdata->lock, NULL);
1381 if (ret < 0) {
1382 char buf[1024];
1383 strerror_r(-ret, buf, sizeof(buf));
1384 ERROR("Unable to initialize mutex: %s\n", buf);
1385 goto err_network_shutdown;
1386 }
Paul Cercueil05e26262014-05-09 11:32:43 +02001387#endif
Paul Cercueil1494b862014-05-05 12:49:07 +02001388
Paul Cercueilbca3dbc2014-06-11 12:00:21 +02001389 set_remote_timeout(ctx, calculate_remote_timeout(DEFAULT_TIMEOUT_MS));
Paul Cercueilc7bad0f2014-03-03 17:06:48 +01001390 return ctx;
1391
Paul Cercueil44ae11c2014-03-17 09:56:29 +01001392err_network_shutdown:
Paul Cercueil44ae11c2014-03-17 09:56:29 +01001393 iio_context_destroy(ctx);
Paul Cercueil2057fd32014-10-28 14:44:19 +01001394 return NULL;
Paul Cercueil8fd9c8f2014-03-03 17:21:31 +01001395err_free_pdata:
1396 free(pdata);
Paul Cercueilc7bad0f2014-03-03 17:06:48 +01001397err_close_socket:
1398 close(fd);
Paul Cercueil2dd2c132015-02-24 10:41:01 +01001399err_free_addrinfo:
1400 freeaddrinfo(res);
Paul Cercueilc7bad0f2014-03-03 17:06:48 +01001401 return NULL;
1402}