blob: d159e3b9714a1fbabbea725c9ce1a21b9135cd37 [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 Cercueila7d445b2014-11-11 16:00:15 +010026#include <fcntl.h>
Paul Cercueile60c3ed2014-03-04 11:23:56 +010027#include <stdbool.h>
Paul Cercueilc7bad0f2014-03-03 17:06:48 +010028#include <string.h>
29#include <sys/types.h>
Paul Cercueilab114932014-05-19 13:03:17 +020030#include <time.h>
Paul Cercueil1fef1a52014-04-07 16:31:15 +020031
32#ifdef _WIN32
Paul Cercueil06c479d2015-01-08 16:14:57 +010033/* Override the default version of Windows supported by MinGW.
34 * This is required to use the function inet_ntop. */
35#undef _WIN32_WINNT
36#define _WIN32_WINNT 0x0600
37
Paul Cercueil1fef1a52014-04-07 16:31:15 +020038#include <winsock2.h>
39#include <ws2tcpip.h>
40#define close(s) closesocket(s)
41
42/* winsock2.h defines ERROR, we don't want that */
43#undef ERROR
44
45#else /* _WIN32 */
Paul Cercueil06c479d2015-01-08 16:14:57 +010046#include <arpa/inet.h>
Paul Cercueil1fef1a52014-04-07 16:31:15 +020047#include <netdb.h>
Paul Cercueil0c3ce452015-02-05 16:37:42 +010048#include <netinet/in.h>
Paul Cercueil0b584e12015-01-28 11:47:03 +010049#include <netinet/tcp.h>
Paul Cercueiled15e492015-01-12 15:52:28 +010050#include <net/if.h>
Paul Cercueil09a43482015-03-04 15:50:27 +010051#include <sys/mman.h>
Paul Cercueil83628b32014-11-24 11:26:21 +010052#include <sys/select.h>
Paul Cercueilc7bad0f2014-03-03 17:06:48 +010053#include <sys/socket.h>
54#include <unistd.h>
Paul Cercueil1fef1a52014-04-07 16:31:15 +020055#endif /* _WIN32 */
56
Paul Cercueil257e6ca2014-12-09 17:32:47 +010057#if HAVE_PTHREAD
58#include <pthread.h>
59#endif
60
Paul Cercueilab114932014-05-19 13:03:17 +020061#ifdef HAVE_AVAHI
62#include <avahi-client/client.h>
63#include <avahi-common/error.h>
64#include <avahi-client/lookup.h>
65#include <avahi-common/simple-watch.h>
66#endif
67
Paul Cercueil1fef1a52014-04-07 16:31:15 +020068#include "debug.h"
Paul Cercueilc7bad0f2014-03-03 17:06:48 +010069
Paul Cercueil8a266f12014-06-10 16:06:31 +020070#define DEFAULT_TIMEOUT_MS 5000
71
Paul Cercueil2e38bbe2014-03-19 15:27:15 +010072#define _STRINGIFY(x) #x
73#define STRINGIFY(x) _STRINGIFY(x)
74
Paul Cercueilc7bad0f2014-03-03 17:06:48 +010075#define IIOD_PORT 30431
Paul Cercueil2e38bbe2014-03-19 15:27:15 +010076#define IIOD_PORT_STR STRINGIFY(IIOD_PORT)
Paul Cercueilc7bad0f2014-03-03 17:06:48 +010077
Paul Cercueil8fd9c8f2014-03-03 17:21:31 +010078struct iio_context_pdata {
79 int fd;
Paul Cercueil2dd2c132015-02-24 10:41:01 +010080 struct addrinfo *addrinfo;
Paul Cercueil05e26262014-05-09 11:32:43 +020081#if HAVE_PTHREAD
Paul Cercueil1494b862014-05-05 12:49:07 +020082 pthread_mutex_t lock;
Paul Cercueil05e26262014-05-09 11:32:43 +020083#endif
Paul Cercueil8fd9c8f2014-03-03 17:21:31 +010084};
85
Paul Cercueil439e1a22015-02-24 13:50:51 +010086struct iio_device_pdata {
87 int fd;
Paul Cercueil90189672015-03-16 11:41:53 +010088#ifdef WITH_NETWORK_GET_BUFFER
Paul Cercueil09a43482015-03-04 15:50:27 +010089 int memfd;
Paul Cercueile6e5a092015-03-04 16:33:26 +010090 void *mmap_addr;
Paul Cercueil09a43482015-03-04 15:50:27 +010091 size_t mmap_len;
Paul Cercueile6e5a092015-03-04 16:33:26 +010092#endif
Paul Cercueil09a43482015-03-04 15:50:27 +010093 bool wait_for_err_code, is_cyclic, is_tx;
Paul Cercueilc5b00752015-02-24 14:29:53 +010094#if HAVE_PTHREAD
95 pthread_mutex_t lock;
96#endif
Paul Cercueil439e1a22015-02-24 13:50:51 +010097};
98
Paul Cercueilab114932014-05-19 13:03:17 +020099#ifdef HAVE_AVAHI
100struct avahi_discovery_data {
101 AvahiSimplePoll *poll;
102 AvahiAddress *address;
103 uint16_t *port;
104 bool found, resolved;
105};
106
107static void __avahi_resolver_cb(AvahiServiceResolver *resolver,
108 __notused AvahiIfIndex iface, __notused AvahiProtocol proto,
109 __notused AvahiResolverEvent event, __notused const char *name,
110 __notused const char *type, __notused const char *domain,
111 __notused const char *host_name, const AvahiAddress *address,
112 uint16_t port, __notused AvahiStringList *txt,
113 __notused AvahiLookupResultFlags flags, void *d)
114{
115 struct avahi_discovery_data *ddata = (struct avahi_discovery_data *) d;
116
117 memcpy(ddata->address, address, sizeof(*address));
118 *ddata->port = port;
119 ddata->resolved = true;
120 avahi_service_resolver_free(resolver);
121}
122
123static void __avahi_browser_cb(AvahiServiceBrowser *browser,
124 AvahiIfIndex iface, AvahiProtocol proto,
125 AvahiBrowserEvent event, const char *name,
126 const char *type, const char *domain,
127 __notused AvahiLookupResultFlags flags, void *d)
128{
129 struct avahi_discovery_data *ddata = (struct avahi_discovery_data *) d;
130 struct AvahiClient *client = avahi_service_browser_get_client(browser);
131
132 switch (event) {
133 default:
134 case AVAHI_BROWSER_NEW:
135 ddata->found = !!avahi_service_resolver_new(client, iface,
136 proto, name, type, domain,
137 AVAHI_PROTO_UNSPEC, 0,
138 __avahi_resolver_cb, d);
139 break;
140 case AVAHI_BROWSER_ALL_FOR_NOW:
141 if (ddata->found) {
142 while (!ddata->resolved) {
143 struct timespec ts;
144 ts.tv_sec = 0;
145 ts.tv_nsec = 4000000;
146 nanosleep(&ts, NULL);
147 }
148 }
149 case AVAHI_BROWSER_FAILURE: /* fall-through */
150 avahi_simple_poll_quit(ddata->poll);
151 case AVAHI_BROWSER_CACHE_EXHAUSTED: /* fall-through */
152 break;
153 }
154}
155
156static int discover_host(AvahiAddress *addr, uint16_t *port)
157{
158 struct avahi_discovery_data ddata;
159 int ret = 0;
160 AvahiClient *client;
161 AvahiServiceBrowser *browser;
162 AvahiSimplePoll *poll = avahi_simple_poll_new();
163 if (!poll)
164 return -ENOMEM;
165
166 client = avahi_client_new(avahi_simple_poll_get(poll),
167 0, NULL, NULL, &ret);
168 if (!client) {
169 ERROR("Unable to start ZeroConf client :%s\n",
170 avahi_strerror(ret));
171 goto err_free_poll;
172 }
173
174 memset(&ddata, 0, sizeof(ddata));
175 ddata.poll = poll;
176 ddata.address = addr;
177 ddata.port = port;
178
179 browser = avahi_service_browser_new(client,
180 AVAHI_IF_UNSPEC, AVAHI_PROTO_UNSPEC,
181 "_iio._tcp", NULL, 0, __avahi_browser_cb, &ddata);
182 if (!browser) {
183 ret = avahi_client_errno(client);
184 ERROR("Unable to create ZeroConf browser: %s\n",
185 avahi_strerror(ret));
186 goto err_free_client;
187 }
188
189 DEBUG("Trying to discover host\n");
190 avahi_simple_poll_loop(poll);
191
192 if (!ddata.found)
193 ret = ENXIO;
194
195 avahi_service_browser_free(browser);
196err_free_client:
197 avahi_client_free(client);
198err_free_poll:
199 avahi_simple_poll_free(poll);
200 return -ret; /* we want a negative error code */
201}
202#endif /* HAVE_AVAHI */
203
Paul Cercueil05e26262014-05-09 11:32:43 +0200204static void network_lock(struct iio_context_pdata *pdata)
205{
206#if HAVE_PTHREAD
207 pthread_mutex_lock(&pdata->lock);
208#endif
209}
210
211static void network_unlock(struct iio_context_pdata *pdata)
212{
213#if HAVE_PTHREAD
214 pthread_mutex_unlock(&pdata->lock);
215#endif
216}
217
Paul Cercueilc5b00752015-02-24 14:29:53 +0100218static void network_lock_dev(struct iio_device_pdata *pdata)
219{
220#if HAVE_PTHREAD
221 pthread_mutex_lock(&pdata->lock);
222#endif
223}
224
225static void network_unlock_dev(struct iio_device_pdata *pdata)
226{
227#if HAVE_PTHREAD
228 pthread_mutex_unlock(&pdata->lock);
229#endif
230}
231
Paul Cercueilc7bad0f2014-03-03 17:06:48 +0100232static ssize_t write_all(const void *src, size_t len, int fd)
233{
Paul Cercueil6e7f79e2014-04-04 12:27:24 +0200234 uintptr_t ptr = (uintptr_t) src;
Paul Cercueilc7bad0f2014-03-03 17:06:48 +0100235 while (len) {
Paul Cercueil4012cff2015-05-11 10:47:40 +0200236 ssize_t ret = send(fd, (const void *) ptr, (int) len, 0);
Lars-Peter Clausencb7b8bf2014-12-05 16:08:52 +0100237 if (ret < 0) {
238 if (errno == EINTR) {
239 continue;
240 }
Paul Cercueilc7bad0f2014-03-03 17:06:48 +0100241 return -errno;
Lars-Peter Clausencb7b8bf2014-12-05 16:08:52 +0100242 }
Paul Cercueilc7bad0f2014-03-03 17:06:48 +0100243 ptr += ret;
244 len -= ret;
245 }
Paul Cercueil4012cff2015-05-11 10:47:40 +0200246 return (ssize_t)(ptr - (uintptr_t) src);
Paul Cercueilc7bad0f2014-03-03 17:06:48 +0100247}
248
249static ssize_t read_all(void *dst, size_t len, int fd)
250{
Paul Cercueil6e7f79e2014-04-04 12:27:24 +0200251 uintptr_t ptr = (uintptr_t) dst;
Paul Cercueilc7bad0f2014-03-03 17:06:48 +0100252 while (len) {
Paul Cercueil4012cff2015-05-11 10:47:40 +0200253 ssize_t ret = recv(fd, (void *) ptr, (int) len, 0);
Lars-Peter Clausencb7b8bf2014-12-05 16:08:52 +0100254 if (ret < 0) {
255 if (errno == EINTR)
256 continue;
Paul Cercueilc7bad0f2014-03-03 17:06:48 +0100257 return -errno;
Lars-Peter Clausencb7b8bf2014-12-05 16:08:52 +0100258 }
Paul Cercueil43eb7e82014-11-13 12:46:59 +0100259 if (ret == 0)
260 return -EPIPE;
Paul Cercueilc7bad0f2014-03-03 17:06:48 +0100261 ptr += ret;
262 len -= ret;
263 }
Paul Cercueil4012cff2015-05-11 10:47:40 +0200264 return (ssize_t)(ptr - (uintptr_t) dst);
Paul Cercueilc7bad0f2014-03-03 17:06:48 +0100265}
266
Paul Cercueile60c3ed2014-03-04 11:23:56 +0100267static int read_integer(int fd, long *val)
268{
269 unsigned int i;
270 char buf[1024], *ptr;
271 ssize_t ret;
272 bool found = false;
273
274 for (i = 0; i < sizeof(buf) - 1; i++) {
275 ret = read_all(buf + i, 1, fd);
276 if (ret < 0)
277 return (int) ret;
278
Paul Cercueil6691a3f2014-05-02 12:32:01 +0200279 /* Skip the eventual first few carriage returns.
280 * Also stop when a dot is found (for parsing floats) */
281 if (buf[i] != '\n' && buf[i] != '.')
Paul Cercueile60c3ed2014-03-04 11:23:56 +0100282 found = true;
283 else if (found)
284 break;
285 }
286
287 buf[i] = '\0';
288 ret = (ssize_t) strtol(buf, &ptr, 10);
289 if (ptr == buf)
290 return -EINVAL;
291 *val = (long) ret;
292 return 0;
293}
294
Paul Cercueilbb76bf92014-03-11 10:20:18 +0100295static ssize_t write_command(const char *cmd, int fd)
296{
297 ssize_t ret;
298
299 DEBUG("Writing command: %s\n", cmd);
300 ret = write_all(cmd, strlen(cmd), fd);
301 if (ret < 0) {
302 char buf[1024];
303 strerror_r(-ret, buf, sizeof(buf));
304 ERROR("Unable to send command: %s\n", buf);
305 }
306 return ret;
307}
308
309static long exec_command(const char *cmd, int fd)
310{
311 long resp;
312 ssize_t ret = write_command(cmd, fd);
313 if (ret < 0)
314 return (long) ret;
315
316 DEBUG("Reading response\n");
317 ret = read_integer(fd, &resp);
318 if (ret < 0) {
319 char buf[1024];
320 strerror_r(-ret, buf, sizeof(buf));
321 ERROR("Unable to read response: %s\n", buf);
322 return (long) ret;
323 }
324
Paul Cercueilc7fe2ea2014-03-28 11:38:45 +0100325#if LOG_LEVEL >= DEBUG_L
Paul Cercueilbb76bf92014-03-11 10:20:18 +0100326 if (resp < 0) {
327 char buf[1024];
328 strerror_r(-resp, buf, sizeof(buf));
Paul Cercueilc7fe2ea2014-03-28 11:38:45 +0100329 DEBUG("Server returned an error: %s\n", buf);
Paul Cercueilbb76bf92014-03-11 10:20:18 +0100330 }
Paul Cercueilc7fe2ea2014-03-28 11:38:45 +0100331#endif
332
Paul Cercueilbb76bf92014-03-11 10:20:18 +0100333 return resp;
334}
335
Paul Cercueil4970ac32015-02-24 10:59:00 +0100336#ifndef _WIN32
337static int set_blocking_mode(int fd, bool blocking)
338{
339 int ret = fcntl(fd, F_GETFL, 0);
340 if (ret < 0)
341 return -errno;
342
343 if (blocking)
344 ret &= ~O_NONBLOCK;
345 else
346 ret |= O_NONBLOCK;
347
348 ret = fcntl(fd, F_SETFL, ret);
349 return ret < 0 ? -errno : 0;
350}
351
352/* The purpose of this function is to provide a version of connect()
353 * that does not ignore timeouts... */
354static int do_connect(int fd, const struct sockaddr *addr,
355 socklen_t addrlen, struct timeval *timeout)
356{
357 int ret, error;
358 socklen_t len;
359 fd_set set;
360
361 FD_ZERO(&set);
362 FD_SET(fd, &set);
363
364 ret = set_blocking_mode(fd, false);
365 if (ret < 0)
366 return ret;
367
368 ret = connect(fd, addr, addrlen);
369 if (ret < 0 && errno != EINPROGRESS) {
370 ret = -errno;
371 goto end;
372 }
373
374 ret = select(fd + 1, &set, &set, NULL, timeout);
375 if (ret < 0) {
376 ret = -errno;
377 goto end;
378 }
379 if (ret == 0) {
380 ret = -ETIMEDOUT;
381 goto end;
382 }
383
384 /* Verify that we don't have an error */
385 len = sizeof(error);
386 ret = getsockopt(fd, SOL_SOCKET, SO_ERROR, &error, &len);
387 if(ret < 0) {
388 ret = -errno;
389 goto end;
390 }
391 if (error) {
392 ret = -error;
393 goto end;
394 }
395
396end:
397 /* Restore blocking mode */
398 set_blocking_mode(fd, true);
399 return ret;
400}
401
402static int set_socket_timeout(int fd, unsigned int timeout)
403{
404 struct timeval tv;
405
406 tv.tv_sec = timeout / 1000;
407 tv.tv_usec = (timeout % 1000) * 1000;
408 if (setsockopt(fd, SOL_SOCKET, SO_SNDTIMEO, &tv, sizeof(tv)) < 0 ||
409 setsockopt(fd, SOL_SOCKET, SO_RCVTIMEO,
410 &tv, sizeof(tv)) < 0)
411 return -errno;
412 else
413 return 0;
414}
415#else
416static int set_socket_timeout(int fd, unsigned int timeout)
417{
418 if (setsockopt(fd, SOL_SOCKET, SO_SNDTIMEO,
419 (const char *) &timeout, sizeof(timeout)) < 0 ||
420 setsockopt(fd, SOL_SOCKET, SO_RCVTIMEO,
421 (const char *) &timeout, sizeof(timeout)) < 0)
422 return -errno;
423 else
424 return 0;
425}
426#endif /* !_WIN32 */
427
428static int create_socket(const struct addrinfo *addrinfo)
429{
430 struct timeval timeout;
431 int ret, fd, yes = 1;
432
Paul Cercueil4012cff2015-05-11 10:47:40 +0200433#ifdef _WIN32
434 SOCKET s = socket(addrinfo->ai_family, addrinfo->ai_socktype, 0);
435 fd = (s == INVALID_SOCKET) ? -1 : (int) s;
436#else
Paul Cercueil4970ac32015-02-24 10:59:00 +0100437 fd = socket(addrinfo->ai_family, addrinfo->ai_socktype, 0);
Paul Cercueil4012cff2015-05-11 10:47:40 +0200438#endif
Paul Cercueil4970ac32015-02-24 10:59:00 +0100439 if (fd < 0) {
Paul Cercueilcc575532015-03-16 17:15:24 +0100440 ret = -errno;
441 return ret;
Paul Cercueil4970ac32015-02-24 10:59:00 +0100442 }
443
444 timeout.tv_sec = DEFAULT_TIMEOUT_MS / 1000;
445 timeout.tv_usec = (DEFAULT_TIMEOUT_MS % 1000) * 1000;
446
447#ifndef _WIN32
448 ret = do_connect(fd, addrinfo->ai_addr, addrinfo->ai_addrlen, &timeout);
449#else
Paul Cercueil4012cff2015-05-11 10:47:40 +0200450 ret = connect(fd, addrinfo->ai_addr, (int) addrinfo->ai_addrlen);
Paul Cercueil4970ac32015-02-24 10:59:00 +0100451#endif
452 if (ret < 0) {
Paul Cercueilcc575532015-03-16 17:15:24 +0100453 ret = -errno;
Paul Cercueil4970ac32015-02-24 10:59:00 +0100454 close(fd);
455 return ret;
456 }
457
458 set_socket_timeout(fd, DEFAULT_TIMEOUT_MS);
459 setsockopt(fd, IPPROTO_TCP, TCP_NODELAY,
460 (const char *) &yes, sizeof(yes));
461 return fd;
462}
463
Paul Cercueil92f15c22015-04-20 11:36:51 +0200464static int network_open(const struct iio_device *dev,
465 size_t samples_count, bool cyclic)
Paul Cercueilba059762014-03-14 11:02:02 +0100466{
Paul Cercueil439e1a22015-02-24 13:50:51 +0100467 struct iio_context_pdata *pdata = dev->ctx->pdata;
Paul Cercueilba059762014-03-14 11:02:02 +0100468 char buf[1024], *ptr;
Paul Cercueil4012cff2015-05-11 10:47:40 +0200469 size_t i;
Paul Cercueil439e1a22015-02-24 13:50:51 +0100470 int ret, fd;
Paul Cercueilba059762014-03-14 11:02:02 +0100471
Paul Cercueil439e1a22015-02-24 13:50:51 +0100472 if (dev->pdata->fd >= 0)
473 return -EBUSY;
474
475 fd = create_socket(pdata->addrinfo);
476 if (fd < 0)
477 return fd;
Paul Cercueilba059762014-03-14 11:02:02 +0100478
Paul Cercueil3c407f82014-04-02 14:11:59 +0200479 snprintf(buf, sizeof(buf), "OPEN %s %lu ",
480 dev->id, (unsigned long) samples_count);
Paul Cercueilba059762014-03-14 11:02:02 +0100481 ptr = buf + strlen(buf);
482
Paul Cercueil92f15c22015-04-20 11:36:51 +0200483 for (i = dev->words; i > 0; i--) {
484 snprintf(ptr, (ptr - buf) + i * 8, "%08x", dev->mask[i - 1]);
Paul Cercueilba059762014-03-14 11:02:02 +0100485 ptr += 8;
486 }
Paul Cercueil71694c72014-05-22 14:02:13 +0200487
488 strcpy(ptr, cyclic ? " CYCLIC\r\n" : "\r\n");
Paul Cercueilba059762014-03-14 11:02:02 +0100489
Paul Cercueilc5b00752015-02-24 14:29:53 +0100490 network_lock_dev(dev->pdata);
Paul Cercueil439e1a22015-02-24 13:50:51 +0100491 ret = (int) exec_command(buf, fd);
Paul Cercueilc5b00752015-02-24 14:29:53 +0100492 network_unlock_dev(dev->pdata);
Paul Cercueil1494b862014-05-05 12:49:07 +0200493
Paul Cercueil44ae11c2014-03-17 09:56:29 +0100494 if (ret < 0) {
Paul Cercueil439e1a22015-02-24 13:50:51 +0100495 close(fd);
Paul Cercueil44ae11c2014-03-17 09:56:29 +0100496 return ret;
Paul Cercueil44ae11c2014-03-17 09:56:29 +0100497 }
Paul Cercueil439e1a22015-02-24 13:50:51 +0100498
Lars-Peter Clausen62bd5522015-03-27 16:06:52 +0100499 dev->pdata->is_tx = iio_device_is_tx(dev);
Paul Cercueil1d70d442015-03-04 15:00:37 +0100500 dev->pdata->is_cyclic = cyclic;
Paul Cercueil439e1a22015-02-24 13:50:51 +0100501 dev->pdata->fd = fd;
Paul Cercueil8f7f6c42015-02-24 15:00:35 +0100502 dev->pdata->wait_for_err_code = false;
Paul Cercueil439e1a22015-02-24 13:50:51 +0100503 return 0;
Paul Cercueilba059762014-03-14 11:02:02 +0100504}
505
Paul Cercueil8f7f6c42015-02-24 15:00:35 +0100506static ssize_t read_error_code(int fd)
507{
508 /*
509 * The server returns two integer codes.
510 * The first one is returned right after the WRITEBUF command is issued,
511 * and corresponds to the error code returned when the server attempted
512 * to open the device.
513 * If zero, a second error code is returned, that corresponds (if positive)
514 * to the number of bytes written.
515 *
516 * To speed up things, we delay error reporting. We just send out the
517 * data without reading the error code that the server gives us, because
518 * the answer will take too much time. If an error occured, it will be
519 * reported by the next call to iio_buffer_push().
520 */
521
522 unsigned int i;
523 long resp = 0;
524
525 for (i = 0; i < 2; i++) {
526 ssize_t ret = read_integer(fd, &resp);
527 if (ret < 0)
528 return ret;
529 if (resp < 0)
530 return (ssize_t) resp;
531 }
532
Paul Cercueil7d7e5d32015-03-05 10:51:41 +0100533 return (ssize_t) resp;
Paul Cercueil8f7f6c42015-02-24 15:00:35 +0100534}
535
Paul Cercueil3c0da372015-03-05 11:36:39 +0100536static ssize_t write_rwbuf_command(const struct iio_device *dev,
537 const char *cmd, bool do_exec)
538{
539 struct iio_device_pdata *pdata = dev->pdata;
540 int fd = pdata->fd;
541
542 if (pdata->wait_for_err_code) {
543 ssize_t ret = read_error_code(fd);
544
545 pdata->wait_for_err_code = false;
546 if (ret < 0)
547 return ret;
548 }
549
550 return do_exec ? exec_command(cmd, fd) : write_command(cmd, fd);
551}
552
Paul Cercueilba059762014-03-14 11:02:02 +0100553static int network_close(const struct iio_device *dev)
554{
Paul Cercueil439e1a22015-02-24 13:50:51 +0100555 struct iio_device_pdata *pdata = dev->pdata;
Paul Cercueil1494b862014-05-05 12:49:07 +0200556 int ret;
Paul Cercueilba059762014-03-14 11:02:02 +0100557 char buf[1024];
Paul Cercueil439e1a22015-02-24 13:50:51 +0100558
Paul Cercueila34596e2015-03-05 14:33:46 +0100559 if (pdata->fd >= 0) {
560 snprintf(buf, sizeof(buf), "CLOSE %s\r\n", dev->id);
Paul Cercueil1494b862014-05-05 12:49:07 +0200561
Paul Cercueila34596e2015-03-05 14:33:46 +0100562 network_lock_dev(pdata);
563 ret = (int) write_rwbuf_command(dev, buf, true);
Paul Cercueil1494b862014-05-05 12:49:07 +0200564
Paul Cercueila34596e2015-03-05 14:33:46 +0100565 write_command("\r\nEXIT\r\n", pdata->fd);
Paul Cercueilaa0db142015-03-04 16:25:24 +0100566
Paul Cercueila34596e2015-03-05 14:33:46 +0100567 close(pdata->fd);
568 pdata->fd = -1;
569 network_unlock_dev(pdata);
570 }
Paul Cercueile6e5a092015-03-04 16:33:26 +0100571
Paul Cercueil90189672015-03-16 11:41:53 +0100572#ifdef WITH_NETWORK_GET_BUFFER
Paul Cercueile6e5a092015-03-04 16:33:26 +0100573 if (pdata->memfd >= 0)
574 close(pdata->memfd);
575 pdata->memfd = -1;
576
577 if (pdata->mmap_addr) {
578 munmap(pdata->mmap_addr, pdata->mmap_len);
579 pdata->mmap_addr = NULL;
580 }
581#endif
Paul Cercueil1494b862014-05-05 12:49:07 +0200582 return ret;
Paul Cercueilba059762014-03-14 11:02:02 +0100583}
584
Paul Cercueil7d7e5d32015-03-05 10:51:41 +0100585static ssize_t network_read_mask(int fd, uint32_t *mask, size_t words)
586{
587 long read_len;
588 ssize_t ret;
589
590 ret = read_integer(fd, &read_len);
591 if (ret < 0)
592 return ret;
593
594 if (read_len > 0 && mask) {
Paul Cercueil4012cff2015-05-11 10:47:40 +0200595 size_t i;
Paul Cercueil7d7e5d32015-03-05 10:51:41 +0100596 char buf[9];
597
598 buf[8] = '\0';
599 DEBUG("Reading mask\n");
600
601 for (i = words; i > 0; i--) {
602 ret = read_all(buf, 8, fd);
603 if (ret < 0)
604 return ret;
605
606 sscanf(buf, "%08x", &mask[i - 1]);
607 DEBUG("mask[%i] = 0x%x\n", i - 1, mask[i - 1]);
608 }
609 }
610
611 if (read_len > 0) {
612 char c;
613 ssize_t nb = read_all(&c, 1, fd);
614 if (nb > 0 && c != '\n')
615 read_len = -EIO;
616 }
617
618 return (ssize_t) read_len;
619}
620
Paul Cercueil45c575d2014-03-20 15:14:01 +0100621static ssize_t network_read(const struct iio_device *dev, void *dst, size_t len,
622 uint32_t *mask, size_t words)
Paul Cercueilf9286452014-03-18 14:32:17 +0100623{
Paul Cercueil6e7f79e2014-04-04 12:27:24 +0200624 uintptr_t ptr = (uintptr_t) dst;
Paul Cercueilc5b00752015-02-24 14:29:53 +0100625 struct iio_device_pdata *pdata = dev->pdata;
626 int fd = pdata->fd;
Paul Cercueil45c575d2014-03-20 15:14:01 +0100627 ssize_t ret, read = 0;
Paul Cercueil9945bc82014-03-05 14:07:29 +0100628 char buf[1024];
629
Paul Cercueil45c575d2014-03-20 15:14:01 +0100630 if (!len || words != (dev->nb_channels + 31) / 32)
Paul Cercueil9945bc82014-03-05 14:07:29 +0100631 return -EINVAL;
632
Paul Cercueila78b6eb2014-03-17 17:28:07 +0100633 snprintf(buf, sizeof(buf), "READBUF %s %lu\r\n",
634 dev->id, (unsigned long) len);
Paul Cercueil1494b862014-05-05 12:49:07 +0200635
Paul Cercueilc5b00752015-02-24 14:29:53 +0100636 network_lock_dev(pdata);
Paul Cercueil3c0da372015-03-05 11:36:39 +0100637 ret = write_rwbuf_command(dev, buf, false);
Paul Cercueil1494b862014-05-05 12:49:07 +0200638 if (ret < 0) {
Paul Cercueilc5b00752015-02-24 14:29:53 +0100639 network_unlock_dev(pdata);
Paul Cercueil9945bc82014-03-05 14:07:29 +0100640 return ret;
Paul Cercueil1494b862014-05-05 12:49:07 +0200641 }
Paul Cercueil9945bc82014-03-05 14:07:29 +0100642
643 do {
Paul Cercueil7d7e5d32015-03-05 10:51:41 +0100644 ret = network_read_mask(fd, mask, words);
645 if (!ret)
Paul Cercueila78b6eb2014-03-17 17:28:07 +0100646 break;
Paul Cercueil5cab3ae2014-03-14 11:23:56 +0100647 if (ret < 0) {
648 strerror_r(-ret, buf, sizeof(buf));
649 ERROR("Unable to read mask: %s\n", buf);
Paul Cercueilc5b00752015-02-24 14:29:53 +0100650 network_unlock_dev(pdata);
Paul Cercueil6e7f79e2014-04-04 12:27:24 +0200651 return read ? read : ret;
Paul Cercueil5cab3ae2014-03-14 11:23:56 +0100652 }
653
Paul Cercueil7d7e5d32015-03-05 10:51:41 +0100654 mask = NULL; /* We read the mask only once */
655
656 ret = read_all((void *) ptr, ret, fd);
Paul Cercueil9945bc82014-03-05 14:07:29 +0100657 if (ret < 0) {
658 strerror_r(-ret, buf, sizeof(buf));
659 ERROR("Unable to read response to READ: %s\n", buf);
Paul Cercueilc5b00752015-02-24 14:29:53 +0100660 network_unlock_dev(pdata);
Paul Cercueil6e7f79e2014-04-04 12:27:24 +0200661 return read ? read : ret;
Paul Cercueil9945bc82014-03-05 14:07:29 +0100662 }
663
Paul Cercueil6e7f79e2014-04-04 12:27:24 +0200664 ptr += ret;
Paul Cercueilf9286452014-03-18 14:32:17 +0100665 read += ret;
Paul Cercueil7d7e5d32015-03-05 10:51:41 +0100666 len -= ret;
Paul Cercueil9945bc82014-03-05 14:07:29 +0100667 } while (len);
668
Paul Cercueilc5b00752015-02-24 14:29:53 +0100669 network_unlock_dev(pdata);
Paul Cercueil9945bc82014-03-05 14:07:29 +0100670 return read;
671}
672
Paul Cercueila62f84e2015-02-24 14:16:08 +0100673static ssize_t network_write(const struct iio_device *dev,
674 const void *src, size_t len)
Paul Cercueil2725f702014-05-02 11:02:16 +0200675{
Paul Cercueilc5b00752015-02-24 14:29:53 +0100676 struct iio_device_pdata *pdata = dev->pdata;
Paul Cercueil439e1a22015-02-24 13:50:51 +0100677 int fd;
Paul Cercueil2725f702014-05-02 11:02:16 +0200678 ssize_t ret;
Paul Cercueil2725f702014-05-02 11:02:16 +0200679 long resp;
Paul Cercueila62f84e2015-02-24 14:16:08 +0100680 char buf[1024];
681
682 snprintf(buf, sizeof(buf), "WRITEBUF %s %lu\r\n",
683 dev->id, (unsigned long) len);
Paul Cercueil2725f702014-05-02 11:02:16 +0200684
Paul Cercueilc5b00752015-02-24 14:29:53 +0100685 network_lock_dev(pdata);
686 fd = pdata->fd;
Paul Cercueil8f7f6c42015-02-24 15:00:35 +0100687
Paul Cercueil3c0da372015-03-05 11:36:39 +0100688 ret = write_rwbuf_command(dev, buf, pdata->is_cyclic);
Paul Cercueil2725f702014-05-02 11:02:16 +0200689 if (ret < 0)
Paul Cercueil1494b862014-05-05 12:49:07 +0200690 goto err_unlock;
Paul Cercueil2725f702014-05-02 11:02:16 +0200691
692 ret = write_all(src, len, fd);
693 if (ret < 0)
Paul Cercueil1494b862014-05-05 12:49:07 +0200694 goto err_unlock;
Paul Cercueil2725f702014-05-02 11:02:16 +0200695
Paul Cercueil1d70d442015-03-04 15:00:37 +0100696 if (pdata->is_cyclic) {
697 ret = read_integer(fd, &resp);
698 if (ret < 0)
699 goto err_unlock;
700 if (resp < 0) {
701 ret = (ssize_t) resp;
702 goto err_unlock;
703 }
704 } else {
705 pdata->wait_for_err_code = true;
706 }
Paul Cercueilc5b00752015-02-24 14:29:53 +0100707 network_unlock_dev(pdata);
Paul Cercueil1494b862014-05-05 12:49:07 +0200708
Paul Cercueil8f7f6c42015-02-24 15:00:35 +0100709 /* We assume that the whole buffer was submitted.
710 * The error code will be returned by the next call to this function. */
711 return (ssize_t) len;
Paul Cercueil1494b862014-05-05 12:49:07 +0200712
713err_unlock:
Paul Cercueilc5b00752015-02-24 14:29:53 +0100714 network_unlock_dev(pdata);
Paul Cercueil1494b862014-05-05 12:49:07 +0200715 return ret;
Paul Cercueil2725f702014-05-02 11:02:16 +0200716}
717
Paul Cercueil90189672015-03-16 11:41:53 +0100718#ifdef WITH_NETWORK_GET_BUFFER
Paul Cercueil7d7e5d32015-03-05 10:51:41 +0100719static ssize_t network_do_splice(int fd_out, int fd_in, size_t len)
Paul Cercueil09a43482015-03-04 15:50:27 +0100720{
721 int pipefd[2];
Paul Cercueil04065c22015-03-05 14:08:16 +0100722 ssize_t ret, read_len = len;
Paul Cercueil09a43482015-03-04 15:50:27 +0100723
724 ret = (ssize_t) pipe(pipefd);
725 if (ret < 0)
726 return -errno;
727
728 do {
Paul Cercueila107c6d2015-03-05 13:54:10 +0100729 /*
730 * SPLICE_F_NONBLOCK is just here to avoid a deadlock when
731 * splicing from a socket. As the socket is not in
732 * non-blocking mode, it should never return -EAGAIN.
733 * TODO(pcercuei): Find why it locks...
734 * */
735 ret = splice(fd_in, NULL, pipefd[1], NULL, len,
736 SPLICE_F_MOVE | SPLICE_F_NONBLOCK);
737 if (!ret)
738 ret = -EIO;
Paul Cercueil09a43482015-03-04 15:50:27 +0100739 if (ret < 0)
740 goto err_close_pipe;
741
Paul Cercueila107c6d2015-03-05 13:54:10 +0100742 ret = splice(pipefd[0], NULL, fd_out, NULL, ret,
743 SPLICE_F_MOVE | SPLICE_F_NONBLOCK);
744 if (!ret)
745 ret = -EIO;
Paul Cercueil09a43482015-03-04 15:50:27 +0100746 if (ret < 0)
747 goto err_close_pipe;
748
749 len -= ret;
750 } while (len);
751
752err_close_pipe:
753 close(pipefd[0]);
754 close(pipefd[1]);
Paul Cercueil04065c22015-03-05 14:08:16 +0100755 return ret < 0 ? ret : read_len;
Paul Cercueil09a43482015-03-04 15:50:27 +0100756}
757
758static ssize_t network_get_buffer(const struct iio_device *dev,
Paul Cercueil76ca8842015-03-05 11:16:16 +0100759 void **addr_ptr, size_t bytes_used,
760 uint32_t *mask, size_t words)
Paul Cercueil09a43482015-03-04 15:50:27 +0100761{
762 struct iio_device_pdata *pdata = dev->pdata;
Paul Cercueil04065c22015-03-05 14:08:16 +0100763 ssize_t ret, read = 0;
Paul Cercueilca9d3382015-05-04 14:30:09 +0200764 int memfd;
Paul Cercueil09a43482015-03-04 15:50:27 +0100765 bool tx;
Paul Cercueil09a43482015-03-04 15:50:27 +0100766
Paul Cercueil04065c22015-03-05 14:08:16 +0100767 if (pdata->is_cyclic)
Paul Cercueil09a43482015-03-04 15:50:27 +0100768 return -ENOSYS;
Paul Cercueilca9d3382015-05-04 14:30:09 +0200769
770 /* We check early that the temporary file can be created, so that we can
771 * return -ENOSYS in case it fails, which will indicate that the
772 * high-speed interface is not available.
773 *
774 * O_TMPFILE -> Linux 3.11.
775 * TODO: use memfd_create (Linux 3.17) */
776 memfd = open(P_tmpdir, O_RDWR | O_TMPFILE | O_EXCL, S_IRWXU);
777 if (memfd < 0)
778 return -ENOSYS;
779
780 if (!addr_ptr || words != (dev->nb_channels + 31) / 32) {
781 close(memfd);
Paul Cercueil09a43482015-03-04 15:50:27 +0100782 return -EINVAL;
Paul Cercueilca9d3382015-05-04 14:30:09 +0200783 }
Paul Cercueil09a43482015-03-04 15:50:27 +0100784
Paul Cercueile6e5a092015-03-04 16:33:26 +0100785 if (pdata->mmap_addr)
786 munmap(pdata->mmap_addr, pdata->mmap_len);
Paul Cercueil09a43482015-03-04 15:50:27 +0100787
Paul Cercueile6e5a092015-03-04 16:33:26 +0100788 if (pdata->mmap_addr && pdata->is_tx) {
Paul Cercueil09a43482015-03-04 15:50:27 +0100789 char buf[1024];
790 snprintf(buf, sizeof(buf), "WRITEBUF %s %lu\r\n",
791 dev->id, (unsigned long) pdata->mmap_len);
792
793 network_lock_dev(pdata);
794
Paul Cercueil3c0da372015-03-05 11:36:39 +0100795 ret = write_rwbuf_command(dev, buf, false);
Paul Cercueil09a43482015-03-04 15:50:27 +0100796 if (ret < 0)
Paul Cercueilca9d3382015-05-04 14:30:09 +0200797 goto err_close_memfd;
Paul Cercueil09a43482015-03-04 15:50:27 +0100798
799 ret = network_do_splice(pdata->fd,
800 pdata->memfd, pdata->mmap_len);
801 if (ret < 0)
Paul Cercueilca9d3382015-05-04 14:30:09 +0200802 goto err_close_memfd;
Paul Cercueil09a43482015-03-04 15:50:27 +0100803
804 pdata->wait_for_err_code = true;
805 network_unlock_dev(pdata);
806 }
807
808 if (pdata->memfd >= 0)
809 close(pdata->memfd);
810
811 if (bytes_used)
812 pdata->mmap_len = bytes_used;
813
Paul Cercueilca9d3382015-05-04 14:30:09 +0200814 pdata->memfd = memfd;
Paul Cercueil09a43482015-03-04 15:50:27 +0100815
Paul Cercueilef32d582015-03-05 11:18:35 +0100816 ret = (ssize_t) ftruncate(pdata->memfd, pdata->mmap_len);
817 if (ret < 0) {
818 ret = -errno;
819 ERROR("Unable to truncate temp file: %zi\n", -ret);
820 return ret;
821 }
Paul Cercueil09a43482015-03-04 15:50:27 +0100822
Paul Cercueil04065c22015-03-05 14:08:16 +0100823 if (!pdata->is_tx) {
824 char buf[1024];
825 size_t len = pdata->mmap_len;
826
827 snprintf(buf, sizeof(buf), "READBUF %s %lu\r\n",
828 dev->id, (unsigned long) len);
829
830 network_lock_dev(pdata);
831 ret = write_rwbuf_command(dev, buf, false);
832 if (ret < 0)
833 goto err_unlock;
834
835 do {
836 ret = network_read_mask(pdata->fd, mask, words);
837 if (!ret)
838 break;
839 if (ret < 0)
840 goto err_unlock;
841
842 mask = NULL; /* We read the mask only once */
843
844 ret = network_do_splice(pdata->memfd, pdata->fd, ret);
845 if (ret < 0)
846 goto err_unlock;
847
848 read += ret;
849 len -= ret;
850 } while (len);
851
852 network_unlock_dev(pdata);
853 }
Paul Cercueil09a43482015-03-04 15:50:27 +0100854
Paul Cercueile6e5a092015-03-04 16:33:26 +0100855 pdata->mmap_addr = mmap(NULL, pdata->mmap_len,
Paul Cercueil09a43482015-03-04 15:50:27 +0100856 PROT_READ | PROT_WRITE, MAP_SHARED, pdata->memfd, 0);
Paul Cercueile6e5a092015-03-04 16:33:26 +0100857 if (pdata->mmap_addr == MAP_FAILED) {
858 pdata->mmap_addr = NULL;
Paul Cercueil09a43482015-03-04 15:50:27 +0100859 ret = -errno;
Paul Cercueil7d7e5d32015-03-05 10:51:41 +0100860 ERROR("Unable to mmap: %zi\n", -ret);
Paul Cercueil09a43482015-03-04 15:50:27 +0100861 return ret;
862 }
863
Paul Cercueile6e5a092015-03-04 16:33:26 +0100864 *addr_ptr = pdata->mmap_addr;
Paul Cercueil04065c22015-03-05 14:08:16 +0100865 return read ? read : bytes_used;
Paul Cercueil09a43482015-03-04 15:50:27 +0100866
Paul Cercueilca9d3382015-05-04 14:30:09 +0200867err_close_memfd:
868 close(memfd);
Paul Cercueil09a43482015-03-04 15:50:27 +0100869err_unlock:
870 network_unlock_dev(pdata);
871 return ret;
872}
873#endif
874
Paul Cercueil1494b862014-05-05 12:49:07 +0200875static ssize_t network_read_attr_helper(const struct iio_device *dev,
Paul Cercueil0cc0e162014-05-07 12:51:22 +0200876 const struct iio_channel *chn, const char *attr, char *dst,
Paul Cercueil1494b862014-05-05 12:49:07 +0200877 size_t len, bool is_debug)
Paul Cercueil3e94a5b2014-03-04 13:00:41 +0100878{
Paul Cercueil3e94a5b2014-03-04 13:00:41 +0100879 long read_len;
880 ssize_t ret;
881 char buf[1024];
Paul Cercueil05e26262014-05-09 11:32:43 +0200882 struct iio_context_pdata *pdata = dev->ctx->pdata;
883 int fd = pdata->fd;
Paul Cercueil1494b862014-05-05 12:49:07 +0200884 const char *id = dev->id;
Paul Cercueil3e94a5b2014-03-04 13:00:41 +0100885
Paul Cercueil99cf3d42014-03-06 12:35:26 +0100886 if (chn)
Paul Cercueil0cc0e162014-05-07 12:51:22 +0200887 snprintf(buf, sizeof(buf), "READ %s %s %s %s\r\n", id,
888 chn->is_output ? "OUTPUT" : "INPUT",
Paul Cercueil2a3e43d2014-05-21 16:58:45 +0200889 chn->id, attr ? attr : "");
Paul Cercueilc6f03612014-04-14 16:41:31 +0200890 else if (is_debug)
Paul Cercueil2a3e43d2014-05-21 16:58:45 +0200891 snprintf(buf, sizeof(buf), "READ %s DEBUG %s\r\n",
892 id, attr ? attr : "");
Paul Cercueil99cf3d42014-03-06 12:35:26 +0100893 else
Paul Cercueil2a3e43d2014-05-21 16:58:45 +0200894 snprintf(buf, sizeof(buf), "READ %s %s\r\n",
895 id, attr ? attr : "");
Paul Cercueil1494b862014-05-05 12:49:07 +0200896
Paul Cercueil05e26262014-05-09 11:32:43 +0200897 network_lock(pdata);
Paul Cercueilbb76bf92014-03-11 10:20:18 +0100898 read_len = exec_command(buf, fd);
Paul Cercueil1494b862014-05-05 12:49:07 +0200899 if (read_len < 0) {
Paul Cercueil05e26262014-05-09 11:32:43 +0200900 network_unlock(pdata);
Paul Cercueilbb76bf92014-03-11 10:20:18 +0100901 return (ssize_t) read_len;
Paul Cercueil1494b862014-05-05 12:49:07 +0200902 }
Paul Cercueil3e94a5b2014-03-04 13:00:41 +0100903
Paul Cercueil6e7f79e2014-04-04 12:27:24 +0200904 if ((unsigned long) read_len > len) {
Paul Cercueil3e94a5b2014-03-04 13:00:41 +0100905 ERROR("Value returned by server is too large\n");
Paul Cercueil05e26262014-05-09 11:32:43 +0200906 network_unlock(pdata);
Paul Cercueil3e94a5b2014-03-04 13:00:41 +0100907 return -EIO;
908 }
909
910 ret = read_all(dst, read_len, fd);
Paul Cercueil05e26262014-05-09 11:32:43 +0200911 network_unlock(pdata);
Paul Cercueil1494b862014-05-05 12:49:07 +0200912
Paul Cercueil3e94a5b2014-03-04 13:00:41 +0100913 if (ret < 0) {
914 strerror_r(-ret, buf, sizeof(buf));
915 ERROR("Unable to read response to READ: %s\n", buf);
916 return ret;
917 }
918
Paul Cercueil7d95fd72014-05-22 14:26:44 +0200919 return read_len;
Paul Cercueil3e94a5b2014-03-04 13:00:41 +0100920}
921
Paul Cercueil1494b862014-05-05 12:49:07 +0200922static ssize_t network_write_attr_helper(const struct iio_device *dev,
Paul Cercueil0cc0e162014-05-07 12:51:22 +0200923 const struct iio_channel *chn, const char *attr,
924 const char *src, size_t len, bool is_debug)
Paul Cercueil3e94a5b2014-03-04 13:00:41 +0100925{
Paul Cercueila62f84e2015-02-24 14:16:08 +0100926 struct iio_context_pdata *pdata = dev->ctx->pdata;
927 int fd;
928 ssize_t ret;
929 long resp;
Paul Cercueil3e94a5b2014-03-04 13:00:41 +0100930 char buf[1024];
Paul Cercueil1494b862014-05-05 12:49:07 +0200931 const char *id = dev->id;
Paul Cercueil3e94a5b2014-03-04 13:00:41 +0100932
Paul Cercueil07897d32014-03-06 12:46:08 +0100933 if (chn)
Paul Cercueil0cc0e162014-05-07 12:51:22 +0200934 snprintf(buf, sizeof(buf), "WRITE %s %s %s %s %lu\r\n",
935 id, chn->is_output ? "OUTPUT" : "INPUT",
Paul Cercueil8747efe2014-05-22 11:12:12 +0200936 chn->id, attr ? attr : "", (unsigned long) len);
Paul Cercueilc6f03612014-04-14 16:41:31 +0200937 else if (is_debug)
Paul Cercueil8747efe2014-05-22 11:12:12 +0200938 snprintf(buf, sizeof(buf), "WRITE %s DEBUG %s %lu\r\n",
939 id, attr ? attr : "", (unsigned long) len);
Paul Cercueil07897d32014-03-06 12:46:08 +0100940 else
Paul Cercueilcecda352014-05-06 18:14:29 +0200941 snprintf(buf, sizeof(buf), "WRITE %s %s %lu\r\n",
Paul Cercueil8747efe2014-05-22 11:12:12 +0200942 id, attr ? attr : "", (unsigned long) len);
Paul Cercueila62f84e2015-02-24 14:16:08 +0100943
944 network_lock(pdata);
945 fd = pdata->fd;
946 ret = (ssize_t) write_command(buf, fd);
947 if (ret < 0)
948 goto err_unlock;
949
950 ret = write_all(src, len, fd);
951 if (ret < 0)
952 goto err_unlock;
953
954 ret = read_integer(fd, &resp);
955 network_unlock(pdata);
956
957 if (ret < 0)
958 return ret;
959 return (ssize_t) resp;
960
961err_unlock:
962 network_unlock(pdata);
963 return ret;
Paul Cercueil3e94a5b2014-03-04 13:00:41 +0100964}
965
Paul Cercueil99cf3d42014-03-06 12:35:26 +0100966static ssize_t network_read_dev_attr(const struct iio_device *dev,
Paul Cercueil50c762a2014-04-14 15:55:43 +0200967 const char *attr, char *dst, size_t len, bool is_debug)
Paul Cercueil99cf3d42014-03-06 12:35:26 +0100968{
Paul Cercueil5b577762014-06-03 15:31:42 +0200969 if (attr && ((is_debug && !iio_device_find_debug_attr(dev, attr)) ||
970 (!is_debug && !iio_device_find_attr(dev, attr))))
971 return -ENOENT;
972
Paul Cercueil1494b862014-05-05 12:49:07 +0200973 return network_read_attr_helper(dev, NULL, attr, dst, len, is_debug);
Paul Cercueil99cf3d42014-03-06 12:35:26 +0100974}
975
Paul Cercueil07897d32014-03-06 12:46:08 +0100976static ssize_t network_write_dev_attr(const struct iio_device *dev,
Paul Cercueilcecda352014-05-06 18:14:29 +0200977 const char *attr, const char *src, size_t len, bool is_debug)
Paul Cercueil07897d32014-03-06 12:46:08 +0100978{
Paul Cercueil5b577762014-06-03 15:31:42 +0200979 if (attr && ((is_debug && !iio_device_find_debug_attr(dev, attr)) ||
980 (!is_debug && !iio_device_find_attr(dev, attr))))
981 return -ENOENT;
982
Paul Cercueilcecda352014-05-06 18:14:29 +0200983 return network_write_attr_helper(dev, NULL, attr, src, len, is_debug);
Paul Cercueil07897d32014-03-06 12:46:08 +0100984}
985
Paul Cercueil99cf3d42014-03-06 12:35:26 +0100986static ssize_t network_read_chn_attr(const struct iio_channel *chn,
987 const char *attr, char *dst, size_t len)
988{
Paul Cercueil5b577762014-06-03 15:31:42 +0200989 if (attr && !iio_channel_find_attr(chn, attr))
990 return -ENOENT;
991
Paul Cercueil0cc0e162014-05-07 12:51:22 +0200992 return network_read_attr_helper(chn->dev, chn, attr, dst, len, false);
Paul Cercueil99cf3d42014-03-06 12:35:26 +0100993}
994
Paul Cercueil07897d32014-03-06 12:46:08 +0100995static ssize_t network_write_chn_attr(const struct iio_channel *chn,
Paul Cercueilcecda352014-05-06 18:14:29 +0200996 const char *attr, const char *src, size_t len)
Paul Cercueil07897d32014-03-06 12:46:08 +0100997{
Paul Cercueil5b577762014-06-03 15:31:42 +0200998 if (attr && !iio_channel_find_attr(chn, attr))
999 return -ENOENT;
1000
Paul Cercueil0cc0e162014-05-07 12:51:22 +02001001 return network_write_attr_helper(chn->dev, chn, attr, src, len, false);
Paul Cercueil07897d32014-03-06 12:46:08 +01001002}
1003
Paul Cercueildcab40c2014-03-11 10:59:14 +01001004static int network_get_trigger(const struct iio_device *dev,
1005 const struct iio_device **trigger)
1006{
1007 struct iio_context_pdata *pdata = dev->ctx->pdata;
1008 unsigned int i;
1009 char buf[1024];
1010 ssize_t ret;
1011 long resp;
1012
1013 snprintf(buf, sizeof(buf), "GETTRIG %s\r\n", dev->id);
Paul Cercueil1494b862014-05-05 12:49:07 +02001014
Paul Cercueil05e26262014-05-09 11:32:43 +02001015 network_lock(dev->ctx->pdata);
Paul Cercueildcab40c2014-03-11 10:59:14 +01001016 resp = exec_command(buf, pdata->fd);
1017 if (resp < 0) {
Paul Cercueil05e26262014-05-09 11:32:43 +02001018 network_unlock(pdata);
Paul Cercueildcab40c2014-03-11 10:59:14 +01001019 return (int) resp;
1020 } else if (resp == 0) {
1021 *trigger = NULL;
Paul Cercueil05e26262014-05-09 11:32:43 +02001022 network_unlock(pdata);
Paul Cercueildcab40c2014-03-11 10:59:14 +01001023 return 0;
Paul Cercueil6e7f79e2014-04-04 12:27:24 +02001024 } else if ((unsigned long) resp > sizeof(buf)) {
Paul Cercueildcab40c2014-03-11 10:59:14 +01001025 ERROR("Value returned by server is too large\n");
Paul Cercueil05e26262014-05-09 11:32:43 +02001026 network_unlock(pdata);
Paul Cercueildcab40c2014-03-11 10:59:14 +01001027 return -EIO;
1028 }
1029
1030 ret = read_all(buf, resp, pdata->fd);
Paul Cercueil05e26262014-05-09 11:32:43 +02001031 network_unlock(pdata);
Paul Cercueil1494b862014-05-05 12:49:07 +02001032
Paul Cercueildcab40c2014-03-11 10:59:14 +01001033 if (ret < 0) {
1034 strerror_r(-ret, buf, sizeof(buf));
1035 ERROR("Unable to read response to GETTRIG: %s\n", buf);
1036 return ret;
1037 }
1038
Lars-Peter Clausenb5cdc102014-08-21 14:45:52 +02001039 if (buf[0] == '\0') {
1040 *trigger = NULL;
1041 return 0;
1042 }
1043
Paul Cercueildcab40c2014-03-11 10:59:14 +01001044 for (i = 0; i < dev->ctx->nb_devices; i++) {
1045 struct iio_device *cur = dev->ctx->devices[i];
1046 if (iio_device_is_trigger(cur) &&
1047 !strncmp(cur->name, buf, resp)) {
1048 *trigger = cur;
1049 return 0;
1050 }
1051 }
1052
1053 return -ENXIO;
1054}
1055
1056static int network_set_trigger(const struct iio_device *dev,
1057 const struct iio_device *trigger)
1058{
Paul Cercueil1494b862014-05-05 12:49:07 +02001059 int ret;
Paul Cercueildcab40c2014-03-11 10:59:14 +01001060 char buf[1024];
1061 if (trigger)
1062 snprintf(buf, sizeof(buf), "SETTRIG %s %s\r\n",
1063 dev->id, trigger->id);
1064 else
1065 snprintf(buf, sizeof(buf), "SETTRIG %s\r\n", dev->id);
Paul Cercueil1494b862014-05-05 12:49:07 +02001066
Paul Cercueil05e26262014-05-09 11:32:43 +02001067 network_lock(dev->ctx->pdata);
Paul Cercueil1494b862014-05-05 12:49:07 +02001068 ret = (int) exec_command(buf, dev->ctx->pdata->fd);
Paul Cercueil05e26262014-05-09 11:32:43 +02001069 network_unlock(dev->ctx->pdata);
Paul Cercueil1494b862014-05-05 12:49:07 +02001070 return ret;
Paul Cercueildcab40c2014-03-11 10:59:14 +01001071}
1072
Paul Cercueil8fd9c8f2014-03-03 17:21:31 +01001073static void network_shutdown(struct iio_context *ctx)
1074{
1075 struct iio_context_pdata *pdata = ctx->pdata;
Paul Cercueil44ae11c2014-03-17 09:56:29 +01001076 unsigned int i;
Paul Cercueil8fd9c8f2014-03-03 17:21:31 +01001077
Paul Cercueil05e26262014-05-09 11:32:43 +02001078 network_lock(pdata);
Paul Cercueilbb76bf92014-03-11 10:20:18 +01001079 write_command("\r\nEXIT\r\n", pdata->fd);
Paul Cercueil8fd9c8f2014-03-03 17:21:31 +01001080 close(pdata->fd);
Paul Cercueil05e26262014-05-09 11:32:43 +02001081 network_unlock(pdata);
Paul Cercueil1494b862014-05-05 12:49:07 +02001082
Paul Cercueil439e1a22015-02-24 13:50:51 +01001083 for (i = 0; i < ctx->nb_devices; i++) {
1084 struct iio_device *dev = ctx->devices[i];
Paul Cercueilc5b00752015-02-24 14:29:53 +01001085 struct iio_device_pdata *dpdata = dev->pdata;
Paul Cercueil439e1a22015-02-24 13:50:51 +01001086
Paul Cercueilc5b00752015-02-24 14:29:53 +01001087 if (dpdata) {
Paul Cercueilaa0db142015-03-04 16:25:24 +01001088 network_close(dev);
Paul Cercueilc5b00752015-02-24 14:29:53 +01001089#if HAVE_PTHREAD
Paul Cercueilaa0db142015-03-04 16:25:24 +01001090 pthread_mutex_destroy(&dpdata->lock);
Paul Cercueilc5b00752015-02-24 14:29:53 +01001091#endif
Paul Cercueilc5b00752015-02-24 14:29:53 +01001092 free(dpdata);
Paul Cercueil439e1a22015-02-24 13:50:51 +01001093 }
1094 }
1095
Paul Cercueil05e26262014-05-09 11:32:43 +02001096#if HAVE_PTHREAD
Paul Cercueil1494b862014-05-05 12:49:07 +02001097 pthread_mutex_destroy(&pdata->lock);
Paul Cercueil05e26262014-05-09 11:32:43 +02001098#endif
Paul Cercueil2dd2c132015-02-24 10:41:01 +01001099 freeaddrinfo(pdata->addrinfo);
Paul Cercueil8fd9c8f2014-03-03 17:21:31 +01001100 free(pdata);
1101}
1102
Paul Cercueil6691a3f2014-05-02 12:32:01 +02001103static int network_get_version(const struct iio_context *ctx,
Paul Cercueil9de9e9d2014-05-20 13:18:19 +02001104 unsigned int *major, unsigned int *minor, char git_tag[8])
Paul Cercueil6691a3f2014-05-02 12:32:01 +02001105{
1106 struct iio_context_pdata *pdata = ctx->pdata;
1107 long maj, min;
1108 int ret;
Paul Cercueil6691a3f2014-05-02 12:32:01 +02001109
Paul Cercueil05e26262014-05-09 11:32:43 +02001110 network_lock(pdata);
Paul Cercueil1494b862014-05-05 12:49:07 +02001111 ret = (int) write_command("VERSION\r\n", pdata->fd);
1112 if (ret < 0)
1113 goto err_unlock;
1114
1115 ret = read_integer(pdata->fd, &maj);
1116 if (!ret)
1117 ret = read_integer(pdata->fd, &min);
1118 if (!ret) {
Paul Cercueil9de9e9d2014-05-20 13:18:19 +02001119 char tag[8];
1120 tag[7] = '\0';
1121
1122 ret = read_all(tag, sizeof(tag) - 1, pdata->fd);
1123 if (ret < 0)
1124 goto err_unlock;
1125
Paul Cercueild15d9952014-05-20 11:40:08 +02001126 if (major)
1127 *major = (unsigned int) maj;
1128 if (minor)
1129 *minor = (unsigned int) min;
Paul Cercueil9de9e9d2014-05-20 13:18:19 +02001130 if (git_tag)
1131 strncpy(git_tag, tag, 8);
Paul Cercueil1494b862014-05-05 12:49:07 +02001132 }
1133
Paul Cercueil8e8f8992014-06-12 16:58:12 +02001134 ret = 0;
Paul Cercueil1494b862014-05-05 12:49:07 +02001135err_unlock:
Paul Cercueil05e26262014-05-09 11:32:43 +02001136 network_unlock(pdata);
Paul Cercueil1494b862014-05-05 12:49:07 +02001137 return ret;
Paul Cercueil6691a3f2014-05-02 12:32:01 +02001138}
1139
Paul Cercueil8a266f12014-06-10 16:06:31 +02001140static unsigned int calculate_remote_timeout(unsigned int timeout)
1141{
1142 /* XXX(pcercuei): We currently hardcode timeout / 2 for the backend used
1143 * by the remote. Is there something better to do here? */
1144 return timeout / 2;
1145}
1146
Paul Cercueilbca3dbc2014-06-11 12:00:21 +02001147static int set_remote_timeout(struct iio_context *ctx, unsigned int timeout)
1148{
1149 char buf[1024];
1150 int ret;
1151
1152 snprintf(buf, sizeof(buf), "TIMEOUT %u\r\n", timeout);
1153 network_lock(ctx->pdata);
1154 ret = (int) exec_command(buf, ctx->pdata->fd);
1155 network_unlock(ctx->pdata);
1156 return ret;
1157}
1158
1159static int network_set_timeout(struct iio_context *ctx, unsigned int timeout)
1160{
1161 int ret = set_socket_timeout(ctx->pdata->fd, timeout);
1162 if (!ret) {
1163 timeout = calculate_remote_timeout(timeout);
1164 ret = set_remote_timeout(ctx, timeout);
1165 }
1166 if (ret < 0) {
1167 char buf[1024];
1168 strerror_r(-ret, buf, sizeof(buf));
Paul Cercueil8a266f12014-06-10 16:06:31 +02001169 WARNING("Unable to set R/W timeout: %s\n", buf);
1170 } else {
Paul Cercueil8a266f12014-06-10 16:06:31 +02001171 ctx->rw_timeout_ms = timeout;
1172 }
1173 return ret;
1174}
1175
Paul Cercueil12d41832014-10-28 14:35:53 +01001176static struct iio_context * network_clone(const struct iio_context *ctx)
1177{
Paul Cercueil7ef45ce2015-03-16 14:36:16 +01001178 if (ctx->description) {
1179 char *ptr = strchr(ctx->description, ' ');
1180 if (ptr) {
1181#ifdef HAVE_IPV6
1182 char buf[INET6_ADDRSTRLEN + IF_NAMESIZE + 2];
1183#else
1184 char buf[INET_ADDRSTRLEN + 1];
1185#endif
1186 strncpy(buf, ctx->description, sizeof(buf) - 1);
1187 buf[ptr - ctx->description] = '\0';
1188 return iio_create_network_context(buf);
1189 }
1190 }
1191
Paul Cercueild3d56ee2015-01-08 16:36:31 +01001192 return iio_create_network_context(ctx->description);
Paul Cercueil12d41832014-10-28 14:35:53 +01001193}
1194
Paul Cercueilc7bad0f2014-03-03 17:06:48 +01001195static struct iio_backend_ops network_ops = {
Paul Cercueil12d41832014-10-28 14:35:53 +01001196 .clone = network_clone,
Paul Cercueilba059762014-03-14 11:02:02 +01001197 .open = network_open,
1198 .close = network_close,
Paul Cercueil9945bc82014-03-05 14:07:29 +01001199 .read = network_read,
Paul Cercueil2725f702014-05-02 11:02:16 +02001200 .write = network_write,
Paul Cercueil90189672015-03-16 11:41:53 +01001201#ifdef WITH_NETWORK_GET_BUFFER
Paul Cercueil09a43482015-03-04 15:50:27 +01001202 .get_buffer = network_get_buffer,
1203#endif
Paul Cercueil3e94a5b2014-03-04 13:00:41 +01001204 .read_device_attr = network_read_dev_attr,
1205 .write_device_attr = network_write_dev_attr,
Paul Cercueil99cf3d42014-03-06 12:35:26 +01001206 .read_channel_attr = network_read_chn_attr,
Paul Cercueil07897d32014-03-06 12:46:08 +01001207 .write_channel_attr = network_write_chn_attr,
Paul Cercueildcab40c2014-03-11 10:59:14 +01001208 .get_trigger = network_get_trigger,
1209 .set_trigger = network_set_trigger,
Paul Cercueil8fd9c8f2014-03-03 17:21:31 +01001210 .shutdown = network_shutdown,
Paul Cercueil6691a3f2014-05-02 12:32:01 +02001211 .get_version = network_get_version,
Paul Cercueil8a266f12014-06-10 16:06:31 +02001212 .set_timeout = network_set_timeout,
Paul Cercueilc7bad0f2014-03-03 17:06:48 +01001213};
1214
1215static struct iio_context * get_context(int fd)
1216{
1217 struct iio_context *ctx;
Paul Cercueile60c3ed2014-03-04 11:23:56 +01001218 char *xml;
Paul Cercueilbb76bf92014-03-11 10:20:18 +01001219 long xml_len = exec_command("PRINT\r\n", fd);
Paul Cercueilcc575532015-03-16 17:15:24 +01001220 if (xml_len < 0) {
1221 errno = (int) -xml_len;
Paul Cercueilc7bad0f2014-03-03 17:06:48 +01001222 return NULL;
Paul Cercueilcc575532015-03-16 17:15:24 +01001223 }
Paul Cercueile60c3ed2014-03-04 11:23:56 +01001224
1225 DEBUG("Server returned a XML string of length %li\n", xml_len);
Paul Cercueilc7bad0f2014-03-03 17:06:48 +01001226 xml = malloc(xml_len);
1227 if (!xml) {
Paul Cercueilcc575532015-03-16 17:15:24 +01001228 errno = ENOMEM;
Paul Cercueilc7bad0f2014-03-03 17:06:48 +01001229 return NULL;
1230 }
1231
1232 DEBUG("Reading XML string...\n");
1233 read_all(xml, xml_len, fd);
1234
1235 DEBUG("Creating context from XML...\n");
1236 ctx = iio_create_xml_context_mem(xml, xml_len);
Paul Cercueilc1ed8482014-06-11 16:29:43 +02001237
1238 if (ctx)
1239 ctx->xml = xml;
1240 else
1241 free(xml);
Paul Cercueilc7bad0f2014-03-03 17:06:48 +01001242 return ctx;
1243}
1244
Paul Cercueil63e52182014-12-11 12:52:48 +01001245struct iio_context * network_create_context(const char *host)
Paul Cercueilc7bad0f2014-03-03 17:06:48 +01001246{
Paul Cercueil2e38bbe2014-03-19 15:27:15 +01001247 struct addrinfo hints, *res;
Paul Cercueilc7bad0f2014-03-03 17:06:48 +01001248 struct iio_context *ctx;
Paul Cercueil8fd9c8f2014-03-03 17:21:31 +01001249 struct iio_context_pdata *pdata;
Paul Cercueil06c479d2015-01-08 16:14:57 +01001250 unsigned int i, len;
Paul Cercueil4970ac32015-02-24 10:59:00 +01001251 int fd, ret;
Paul Cercueilb03c9ef2015-03-16 14:07:58 +01001252 char *description;
Paul Cercueil1fef1a52014-04-07 16:31:15 +02001253#ifdef _WIN32
1254 WSADATA wsaData;
1255
1256 ret = WSAStartup(MAKEWORD(2, 0), &wsaData);
1257 if (ret < 0) {
1258 ERROR("WSAStartup failed with error %i\n", ret);
Paul Cercueilcc575532015-03-16 17:15:24 +01001259 errno = -ret;
Paul Cercueil1fef1a52014-04-07 16:31:15 +02001260 return NULL;
1261 }
1262#endif
Paul Cercueilc7bad0f2014-03-03 17:06:48 +01001263
Paul Cercueil2e38bbe2014-03-19 15:27:15 +01001264 memset(&hints, 0, sizeof(hints));
1265 hints.ai_family = AF_UNSPEC;
1266 hints.ai_socktype = SOCK_STREAM;
Paul Cercueilab114932014-05-19 13:03:17 +02001267
1268#ifdef HAVE_AVAHI
1269 if (!host) {
1270 char addr_str[AVAHI_ADDRESS_STR_MAX];
1271 char port_str[6];
1272 AvahiAddress address;
Paul Cercueil0f729d32014-06-05 17:38:54 +02001273 uint16_t port = IIOD_PORT;
Paul Cercueilab114932014-05-19 13:03:17 +02001274
1275 memset(&address, 0, sizeof(address));
1276
1277 ret = discover_host(&address, &port);
1278 if (ret < 0) {
Paul Cercueilcc575532015-03-16 17:15:24 +01001279 DEBUG("Unable to find host: %s\n", strerror(-ret));
1280 errno = -ret;
Paul Cercueilab114932014-05-19 13:03:17 +02001281 return NULL;
1282 }
1283
1284 avahi_address_snprint(addr_str, sizeof(addr_str), &address);
1285 snprintf(port_str, sizeof(port_str), "%hu", port);
1286 ret = getaddrinfo(addr_str, port_str, &hints, &res);
1287 } else
1288#endif
1289 {
1290 ret = getaddrinfo(host, IIOD_PORT_STR, &hints, &res);
1291 }
1292
Paul Cercueil2e38bbe2014-03-19 15:27:15 +01001293 if (ret) {
Paul Cercueilab114932014-05-19 13:03:17 +02001294 ERROR("Unable to find host: %s\n", gai_strerror(ret));
Paul Cercueild9eb4cb2015-03-23 14:30:20 +01001295#ifndef _WIN32
Paul Cercueilcc575532015-03-16 17:15:24 +01001296 if (ret != EAI_SYSTEM)
1297 errno = ret;
Paul Cercueild9eb4cb2015-03-23 14:30:20 +01001298#endif
Paul Cercueilc7bad0f2014-03-03 17:06:48 +01001299 return NULL;
Paul Cercueilc7bad0f2014-03-03 17:06:48 +01001300 }
1301
Paul Cercueil4970ac32015-02-24 10:59:00 +01001302 fd = create_socket(res);
Paul Cercueilcc575532015-03-16 17:15:24 +01001303 if (fd < 0) {
1304 errno = fd;
Paul Cercueil2dd2c132015-02-24 10:41:01 +01001305 goto err_free_addrinfo;
Paul Cercueilcc575532015-03-16 17:15:24 +01001306 }
Paul Cercueilbca3dbc2014-06-11 12:00:21 +02001307
Paul Cercueil8fd9c8f2014-03-03 17:21:31 +01001308 pdata = calloc(1, sizeof(*pdata));
1309 if (!pdata) {
Paul Cercueilcc575532015-03-16 17:15:24 +01001310 errno = ENOMEM;
Paul Cercueil8fd9c8f2014-03-03 17:21:31 +01001311 goto err_close_socket;
1312 }
1313
1314 pdata->fd = fd;
Paul Cercueil2dd2c132015-02-24 10:41:01 +01001315 pdata->addrinfo = res;
Paul Cercueil8fd9c8f2014-03-03 17:21:31 +01001316
Paul Cercueilc7bad0f2014-03-03 17:06:48 +01001317 DEBUG("Creating context...\n");
1318 ctx = get_context(fd);
1319 if (!ctx)
Paul Cercueild3d56ee2015-01-08 16:36:31 +01001320 goto err_free_pdata;
Paul Cercueilc7bad0f2014-03-03 17:06:48 +01001321
Paul Cercueil2057fd32014-10-28 14:44:19 +01001322 /* Override the name and low-level functions of the XML context
1323 * with those corresponding to the network context */
1324 ctx->name = "network";
1325 ctx->ops = &network_ops;
1326 ctx->pdata = pdata;
1327
Paul Cercueil06c479d2015-01-08 16:14:57 +01001328#ifdef HAVE_IPV6
Paul Cercueiled15e492015-01-12 15:52:28 +01001329 len = INET6_ADDRSTRLEN + IF_NAMESIZE + 2;
Paul Cercueil06c479d2015-01-08 16:14:57 +01001330#else
1331 len = INET_ADDRSTRLEN + 1;
1332#endif
Paul Cercueilb03c9ef2015-03-16 14:07:58 +01001333
1334 description = malloc(len);
1335 if (!description) {
Paul Cercueilcc575532015-03-16 17:15:24 +01001336 ret = -ENOMEM;
Paul Cercueil06c479d2015-01-08 16:14:57 +01001337 goto err_network_shutdown;
1338 }
1339
Paul Cercueilb03c9ef2015-03-16 14:07:58 +01001340 description[0] = '\0';
Paul Cercueil06c479d2015-01-08 16:14:57 +01001341
1342#ifdef HAVE_IPV6
1343 if (res->ai_family == AF_INET6) {
1344 struct sockaddr_in6 *in = (struct sockaddr_in6 *) res->ai_addr;
Paul Cercueiled15e492015-01-12 15:52:28 +01001345 char *ptr;
Paul Cercueil06c479d2015-01-08 16:14:57 +01001346 inet_ntop(AF_INET6, &in->sin6_addr,
Paul Cercueilb03c9ef2015-03-16 14:07:58 +01001347 description, INET6_ADDRSTRLEN);
Paul Cercueiled15e492015-01-12 15:52:28 +01001348
Paul Cercueilb03c9ef2015-03-16 14:07:58 +01001349 ptr = if_indextoname(in->sin6_scope_id, description +
1350 strlen(description) + 1);
Paul Cercueiled15e492015-01-12 15:52:28 +01001351 if (!ptr) {
Paul Cercueilcc575532015-03-16 17:15:24 +01001352 ret = -errno;
Paul Cercueiled15e492015-01-12 15:52:28 +01001353 ERROR("Unable to lookup interface of IPv6 address\n");
Paul Cercueilb03c9ef2015-03-16 14:07:58 +01001354 goto err_free_description;
Paul Cercueiled15e492015-01-12 15:52:28 +01001355 }
1356
1357 *(ptr - 1) = '%';
Paul Cercueil06c479d2015-01-08 16:14:57 +01001358 }
1359#endif
1360 if (res->ai_family == AF_INET) {
1361 struct sockaddr_in *in = (struct sockaddr_in *) res->ai_addr;
Paul Cercueilb03c9ef2015-03-16 14:07:58 +01001362 inet_ntop(AF_INET, &in->sin_addr, description, INET_ADDRSTRLEN);
Paul Cercueil06c479d2015-01-08 16:14:57 +01001363 }
1364
Paul Cercueil44ae11c2014-03-17 09:56:29 +01001365 for (i = 0; i < ctx->nb_devices; i++) {
1366 struct iio_device *dev = ctx->devices[i];
Paul Cercueilff778232014-03-24 14:23:08 +01001367
Paul Cercueil439e1a22015-02-24 13:50:51 +01001368 dev->pdata = calloc(1, sizeof(*dev->pdata));
1369 if (!dev->pdata) {
Paul Cercueilcc575532015-03-16 17:15:24 +01001370 ret = -ENOMEM;
Paul Cercueilb03c9ef2015-03-16 14:07:58 +01001371 goto err_free_description;
Paul Cercueil439e1a22015-02-24 13:50:51 +01001372 }
1373
1374 dev->pdata->fd = -1;
Paul Cercueil90189672015-03-16 11:41:53 +01001375#ifdef WITH_NETWORK_GET_BUFFER
Paul Cercueil09a43482015-03-04 15:50:27 +01001376 dev->pdata->memfd = -1;
Paul Cercueile6e5a092015-03-04 16:33:26 +01001377#endif
Paul Cercueilc5b00752015-02-24 14:29:53 +01001378
1379#if HAVE_PTHREAD
1380 ret = pthread_mutex_init(&dev->pdata->lock, NULL);
Paul Cercueilcc575532015-03-16 17:15:24 +01001381 if (ret < 0)
Paul Cercueilb03c9ef2015-03-16 14:07:58 +01001382 goto err_free_description;
Paul Cercueilc5b00752015-02-24 14:29:53 +01001383#endif
Paul Cercueil44ae11c2014-03-17 09:56:29 +01001384 }
1385
Paul Cercueilc1ed8482014-06-11 16:29:43 +02001386 iio_context_init(ctx);
Paul Cercueil4c6729d2014-04-04 17:24:41 +02001387
Paul Cercueil05e26262014-05-09 11:32:43 +02001388#if HAVE_PTHREAD
Paul Cercueil1494b862014-05-05 12:49:07 +02001389 ret = pthread_mutex_init(&pdata->lock, NULL);
Paul Cercueilcc575532015-03-16 17:15:24 +01001390 if (ret < 0)
Paul Cercueilb03c9ef2015-03-16 14:07:58 +01001391 goto err_free_description;
Paul Cercueil05e26262014-05-09 11:32:43 +02001392#endif
Paul Cercueil1494b862014-05-05 12:49:07 +02001393
Paul Cercueilb03c9ef2015-03-16 14:07:58 +01001394 if (ctx->description) {
1395 size_t new_size = len + strlen(ctx->description) + 1;
1396 char *ptr, *new_description = realloc(description, new_size);
Paul Cercueilcc575532015-03-16 17:15:24 +01001397 if (!new_description) {
1398 ret = -ENOMEM;
Paul Cercueilb03c9ef2015-03-16 14:07:58 +01001399 goto err_free_description;
Paul Cercueilcc575532015-03-16 17:15:24 +01001400 }
Paul Cercueilb03c9ef2015-03-16 14:07:58 +01001401
1402 ptr = strrchr(new_description, '\0');
1403 snprintf(ptr, new_size - len, " %s", ctx->description);
1404 free(ctx->description);
1405
1406 ctx->description = new_description;
1407 } else {
1408 ctx->description = description;
1409 }
1410
Paul Cercueilbca3dbc2014-06-11 12:00:21 +02001411 set_remote_timeout(ctx, calculate_remote_timeout(DEFAULT_TIMEOUT_MS));
Paul Cercueilc7bad0f2014-03-03 17:06:48 +01001412 return ctx;
1413
Paul Cercueilb03c9ef2015-03-16 14:07:58 +01001414err_free_description:
1415 free(description);
Paul Cercueil44ae11c2014-03-17 09:56:29 +01001416err_network_shutdown:
Paul Cercueil44ae11c2014-03-17 09:56:29 +01001417 iio_context_destroy(ctx);
Paul Cercueilcc575532015-03-16 17:15:24 +01001418 errno = -ret;
Paul Cercueil2057fd32014-10-28 14:44:19 +01001419 return NULL;
Paul Cercueil8fd9c8f2014-03-03 17:21:31 +01001420err_free_pdata:
1421 free(pdata);
Paul Cercueilc7bad0f2014-03-03 17:06:48 +01001422err_close_socket:
1423 close(fd);
Paul Cercueil2dd2c132015-02-24 10:41:01 +01001424err_free_addrinfo:
1425 freeaddrinfo(res);
Paul Cercueilc7bad0f2014-03-03 17:06:48 +01001426 return NULL;
1427}