blob: d254f161de0a7a4f9030bbd910b3682d6dd1d5d3 [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 Cercueil6e7f79e2014-04-04 12:27:24 +0200236 ssize_t ret = send(fd, (const void *) ptr, 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 Cercueil6e7f79e2014-04-04 12:27:24 +0200246 return 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 Cercueil6e7f79e2014-04-04 12:27:24 +0200253 ssize_t ret = recv(fd, (void *) ptr, 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 Cercueil6e7f79e2014-04-04 12:27:24 +0200264 return 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
433 fd = socket(addrinfo->ai_family, addrinfo->ai_socktype, 0);
434 if (fd < 0) {
Paul Cercueilcc575532015-03-16 17:15:24 +0100435 ret = -errno;
436 return ret;
Paul Cercueil4970ac32015-02-24 10:59:00 +0100437 }
438
439 timeout.tv_sec = DEFAULT_TIMEOUT_MS / 1000;
440 timeout.tv_usec = (DEFAULT_TIMEOUT_MS % 1000) * 1000;
441
442#ifndef _WIN32
443 ret = do_connect(fd, addrinfo->ai_addr, addrinfo->ai_addrlen, &timeout);
444#else
445 ret = connect(fd, addrinfo->ai_addr, addrinfo->ai_addrlen);
446#endif
447 if (ret < 0) {
Paul Cercueilcc575532015-03-16 17:15:24 +0100448 ret = -errno;
Paul Cercueil4970ac32015-02-24 10:59:00 +0100449 close(fd);
450 return ret;
451 }
452
453 set_socket_timeout(fd, DEFAULT_TIMEOUT_MS);
454 setsockopt(fd, IPPROTO_TCP, TCP_NODELAY,
455 (const char *) &yes, sizeof(yes));
456 return fd;
457}
458
Paul Cercueil92f15c22015-04-20 11:36:51 +0200459static int network_open(const struct iio_device *dev,
460 size_t samples_count, bool cyclic)
Paul Cercueilba059762014-03-14 11:02:02 +0100461{
Paul Cercueil439e1a22015-02-24 13:50:51 +0100462 struct iio_context_pdata *pdata = dev->ctx->pdata;
Paul Cercueilba059762014-03-14 11:02:02 +0100463 char buf[1024], *ptr;
464 unsigned int i;
Paul Cercueil439e1a22015-02-24 13:50:51 +0100465 int ret, fd;
Paul Cercueilba059762014-03-14 11:02:02 +0100466
Paul Cercueil439e1a22015-02-24 13:50:51 +0100467 if (dev->pdata->fd >= 0)
468 return -EBUSY;
469
470 fd = create_socket(pdata->addrinfo);
471 if (fd < 0)
472 return fd;
Paul Cercueilba059762014-03-14 11:02:02 +0100473
Paul Cercueil3c407f82014-04-02 14:11:59 +0200474 snprintf(buf, sizeof(buf), "OPEN %s %lu ",
475 dev->id, (unsigned long) samples_count);
Paul Cercueilba059762014-03-14 11:02:02 +0100476 ptr = buf + strlen(buf);
477
Paul Cercueil92f15c22015-04-20 11:36:51 +0200478 for (i = dev->words; i > 0; i--) {
479 snprintf(ptr, (ptr - buf) + i * 8, "%08x", dev->mask[i - 1]);
Paul Cercueilba059762014-03-14 11:02:02 +0100480 ptr += 8;
481 }
Paul Cercueil71694c72014-05-22 14:02:13 +0200482
483 strcpy(ptr, cyclic ? " CYCLIC\r\n" : "\r\n");
Paul Cercueilba059762014-03-14 11:02:02 +0100484
Paul Cercueilc5b00752015-02-24 14:29:53 +0100485 network_lock_dev(dev->pdata);
Paul Cercueil439e1a22015-02-24 13:50:51 +0100486 ret = (int) exec_command(buf, fd);
Paul Cercueilc5b00752015-02-24 14:29:53 +0100487 network_unlock_dev(dev->pdata);
Paul Cercueil1494b862014-05-05 12:49:07 +0200488
Paul Cercueil44ae11c2014-03-17 09:56:29 +0100489 if (ret < 0) {
Paul Cercueil439e1a22015-02-24 13:50:51 +0100490 close(fd);
Paul Cercueil44ae11c2014-03-17 09:56:29 +0100491 return ret;
Paul Cercueil44ae11c2014-03-17 09:56:29 +0100492 }
Paul Cercueil439e1a22015-02-24 13:50:51 +0100493
Lars-Peter Clausen62bd5522015-03-27 16:06:52 +0100494 dev->pdata->is_tx = iio_device_is_tx(dev);
Paul Cercueil1d70d442015-03-04 15:00:37 +0100495 dev->pdata->is_cyclic = cyclic;
Paul Cercueil439e1a22015-02-24 13:50:51 +0100496 dev->pdata->fd = fd;
Paul Cercueil8f7f6c42015-02-24 15:00:35 +0100497 dev->pdata->wait_for_err_code = false;
Paul Cercueil439e1a22015-02-24 13:50:51 +0100498 return 0;
Paul Cercueilba059762014-03-14 11:02:02 +0100499}
500
Paul Cercueil8f7f6c42015-02-24 15:00:35 +0100501static ssize_t read_error_code(int fd)
502{
503 /*
504 * The server returns two integer codes.
505 * The first one is returned right after the WRITEBUF command is issued,
506 * and corresponds to the error code returned when the server attempted
507 * to open the device.
508 * If zero, a second error code is returned, that corresponds (if positive)
509 * to the number of bytes written.
510 *
511 * To speed up things, we delay error reporting. We just send out the
512 * data without reading the error code that the server gives us, because
513 * the answer will take too much time. If an error occured, it will be
514 * reported by the next call to iio_buffer_push().
515 */
516
517 unsigned int i;
518 long resp = 0;
519
520 for (i = 0; i < 2; i++) {
521 ssize_t ret = read_integer(fd, &resp);
522 if (ret < 0)
523 return ret;
524 if (resp < 0)
525 return (ssize_t) resp;
526 }
527
Paul Cercueil7d7e5d32015-03-05 10:51:41 +0100528 return (ssize_t) resp;
Paul Cercueil8f7f6c42015-02-24 15:00:35 +0100529}
530
Paul Cercueil3c0da372015-03-05 11:36:39 +0100531static ssize_t write_rwbuf_command(const struct iio_device *dev,
532 const char *cmd, bool do_exec)
533{
534 struct iio_device_pdata *pdata = dev->pdata;
535 int fd = pdata->fd;
536
537 if (pdata->wait_for_err_code) {
538 ssize_t ret = read_error_code(fd);
539
540 pdata->wait_for_err_code = false;
541 if (ret < 0)
542 return ret;
543 }
544
545 return do_exec ? exec_command(cmd, fd) : write_command(cmd, fd);
546}
547
Paul Cercueilba059762014-03-14 11:02:02 +0100548static int network_close(const struct iio_device *dev)
549{
Paul Cercueil439e1a22015-02-24 13:50:51 +0100550 struct iio_device_pdata *pdata = dev->pdata;
Paul Cercueil1494b862014-05-05 12:49:07 +0200551 int ret;
Paul Cercueilba059762014-03-14 11:02:02 +0100552 char buf[1024];
Paul Cercueil439e1a22015-02-24 13:50:51 +0100553
Paul Cercueila34596e2015-03-05 14:33:46 +0100554 if (pdata->fd >= 0) {
555 snprintf(buf, sizeof(buf), "CLOSE %s\r\n", dev->id);
Paul Cercueil1494b862014-05-05 12:49:07 +0200556
Paul Cercueila34596e2015-03-05 14:33:46 +0100557 network_lock_dev(pdata);
558 ret = (int) write_rwbuf_command(dev, buf, true);
Paul Cercueil1494b862014-05-05 12:49:07 +0200559
Paul Cercueila34596e2015-03-05 14:33:46 +0100560 write_command("\r\nEXIT\r\n", pdata->fd);
Paul Cercueilaa0db142015-03-04 16:25:24 +0100561
Paul Cercueila34596e2015-03-05 14:33:46 +0100562 close(pdata->fd);
563 pdata->fd = -1;
564 network_unlock_dev(pdata);
565 }
Paul Cercueile6e5a092015-03-04 16:33:26 +0100566
Paul Cercueil90189672015-03-16 11:41:53 +0100567#ifdef WITH_NETWORK_GET_BUFFER
Paul Cercueile6e5a092015-03-04 16:33:26 +0100568 if (pdata->memfd >= 0)
569 close(pdata->memfd);
570 pdata->memfd = -1;
571
572 if (pdata->mmap_addr) {
573 munmap(pdata->mmap_addr, pdata->mmap_len);
574 pdata->mmap_addr = NULL;
575 }
576#endif
Paul Cercueil1494b862014-05-05 12:49:07 +0200577 return ret;
Paul Cercueilba059762014-03-14 11:02:02 +0100578}
579
Paul Cercueil7d7e5d32015-03-05 10:51:41 +0100580static ssize_t network_read_mask(int fd, uint32_t *mask, size_t words)
581{
582 long read_len;
583 ssize_t ret;
584
585 ret = read_integer(fd, &read_len);
586 if (ret < 0)
587 return ret;
588
589 if (read_len > 0 && mask) {
590 unsigned int i;
591 char buf[9];
592
593 buf[8] = '\0';
594 DEBUG("Reading mask\n");
595
596 for (i = words; i > 0; i--) {
597 ret = read_all(buf, 8, fd);
598 if (ret < 0)
599 return ret;
600
601 sscanf(buf, "%08x", &mask[i - 1]);
602 DEBUG("mask[%i] = 0x%x\n", i - 1, mask[i - 1]);
603 }
604 }
605
606 if (read_len > 0) {
607 char c;
608 ssize_t nb = read_all(&c, 1, fd);
609 if (nb > 0 && c != '\n')
610 read_len = -EIO;
611 }
612
613 return (ssize_t) read_len;
614}
615
Paul Cercueil45c575d2014-03-20 15:14:01 +0100616static ssize_t network_read(const struct iio_device *dev, void *dst, size_t len,
617 uint32_t *mask, size_t words)
Paul Cercueilf9286452014-03-18 14:32:17 +0100618{
Paul Cercueil6e7f79e2014-04-04 12:27:24 +0200619 uintptr_t ptr = (uintptr_t) dst;
Paul Cercueilc5b00752015-02-24 14:29:53 +0100620 struct iio_device_pdata *pdata = dev->pdata;
621 int fd = pdata->fd;
Paul Cercueil45c575d2014-03-20 15:14:01 +0100622 ssize_t ret, read = 0;
Paul Cercueil9945bc82014-03-05 14:07:29 +0100623 char buf[1024];
624
Paul Cercueil45c575d2014-03-20 15:14:01 +0100625 if (!len || words != (dev->nb_channels + 31) / 32)
Paul Cercueil9945bc82014-03-05 14:07:29 +0100626 return -EINVAL;
627
Paul Cercueila78b6eb2014-03-17 17:28:07 +0100628 snprintf(buf, sizeof(buf), "READBUF %s %lu\r\n",
629 dev->id, (unsigned long) len);
Paul Cercueil1494b862014-05-05 12:49:07 +0200630
Paul Cercueilc5b00752015-02-24 14:29:53 +0100631 network_lock_dev(pdata);
Paul Cercueil3c0da372015-03-05 11:36:39 +0100632 ret = write_rwbuf_command(dev, buf, false);
Paul Cercueil1494b862014-05-05 12:49:07 +0200633 if (ret < 0) {
Paul Cercueilc5b00752015-02-24 14:29:53 +0100634 network_unlock_dev(pdata);
Paul Cercueil9945bc82014-03-05 14:07:29 +0100635 return ret;
Paul Cercueil1494b862014-05-05 12:49:07 +0200636 }
Paul Cercueil9945bc82014-03-05 14:07:29 +0100637
638 do {
Paul Cercueil7d7e5d32015-03-05 10:51:41 +0100639 ret = network_read_mask(fd, mask, words);
640 if (!ret)
Paul Cercueila78b6eb2014-03-17 17:28:07 +0100641 break;
Paul Cercueil5cab3ae2014-03-14 11:23:56 +0100642 if (ret < 0) {
643 strerror_r(-ret, buf, sizeof(buf));
644 ERROR("Unable to read mask: %s\n", buf);
Paul Cercueilc5b00752015-02-24 14:29:53 +0100645 network_unlock_dev(pdata);
Paul Cercueil6e7f79e2014-04-04 12:27:24 +0200646 return read ? read : ret;
Paul Cercueil5cab3ae2014-03-14 11:23:56 +0100647 }
648
Paul Cercueil7d7e5d32015-03-05 10:51:41 +0100649 mask = NULL; /* We read the mask only once */
650
651 ret = read_all((void *) ptr, ret, fd);
Paul Cercueil9945bc82014-03-05 14:07:29 +0100652 if (ret < 0) {
653 strerror_r(-ret, buf, sizeof(buf));
654 ERROR("Unable to read response to READ: %s\n", buf);
Paul Cercueilc5b00752015-02-24 14:29:53 +0100655 network_unlock_dev(pdata);
Paul Cercueil6e7f79e2014-04-04 12:27:24 +0200656 return read ? read : ret;
Paul Cercueil9945bc82014-03-05 14:07:29 +0100657 }
658
Paul Cercueil6e7f79e2014-04-04 12:27:24 +0200659 ptr += ret;
Paul Cercueilf9286452014-03-18 14:32:17 +0100660 read += ret;
Paul Cercueil7d7e5d32015-03-05 10:51:41 +0100661 len -= ret;
Paul Cercueil9945bc82014-03-05 14:07:29 +0100662 } while (len);
663
Paul Cercueilc5b00752015-02-24 14:29:53 +0100664 network_unlock_dev(pdata);
Paul Cercueil9945bc82014-03-05 14:07:29 +0100665 return read;
666}
667
Paul Cercueila62f84e2015-02-24 14:16:08 +0100668static ssize_t network_write(const struct iio_device *dev,
669 const void *src, size_t len)
Paul Cercueil2725f702014-05-02 11:02:16 +0200670{
Paul Cercueilc5b00752015-02-24 14:29:53 +0100671 struct iio_device_pdata *pdata = dev->pdata;
Paul Cercueil439e1a22015-02-24 13:50:51 +0100672 int fd;
Paul Cercueil2725f702014-05-02 11:02:16 +0200673 ssize_t ret;
Paul Cercueil2725f702014-05-02 11:02:16 +0200674 long resp;
Paul Cercueila62f84e2015-02-24 14:16:08 +0100675 char buf[1024];
676
677 snprintf(buf, sizeof(buf), "WRITEBUF %s %lu\r\n",
678 dev->id, (unsigned long) len);
Paul Cercueil2725f702014-05-02 11:02:16 +0200679
Paul Cercueilc5b00752015-02-24 14:29:53 +0100680 network_lock_dev(pdata);
681 fd = pdata->fd;
Paul Cercueil8f7f6c42015-02-24 15:00:35 +0100682
Paul Cercueil3c0da372015-03-05 11:36:39 +0100683 ret = write_rwbuf_command(dev, buf, pdata->is_cyclic);
Paul Cercueil2725f702014-05-02 11:02:16 +0200684 if (ret < 0)
Paul Cercueil1494b862014-05-05 12:49:07 +0200685 goto err_unlock;
Paul Cercueil2725f702014-05-02 11:02:16 +0200686
687 ret = write_all(src, len, fd);
688 if (ret < 0)
Paul Cercueil1494b862014-05-05 12:49:07 +0200689 goto err_unlock;
Paul Cercueil2725f702014-05-02 11:02:16 +0200690
Paul Cercueil1d70d442015-03-04 15:00:37 +0100691 if (pdata->is_cyclic) {
692 ret = read_integer(fd, &resp);
693 if (ret < 0)
694 goto err_unlock;
695 if (resp < 0) {
696 ret = (ssize_t) resp;
697 goto err_unlock;
698 }
699 } else {
700 pdata->wait_for_err_code = true;
701 }
Paul Cercueilc5b00752015-02-24 14:29:53 +0100702 network_unlock_dev(pdata);
Paul Cercueil1494b862014-05-05 12:49:07 +0200703
Paul Cercueil8f7f6c42015-02-24 15:00:35 +0100704 /* We assume that the whole buffer was submitted.
705 * The error code will be returned by the next call to this function. */
706 return (ssize_t) len;
Paul Cercueil1494b862014-05-05 12:49:07 +0200707
708err_unlock:
Paul Cercueilc5b00752015-02-24 14:29:53 +0100709 network_unlock_dev(pdata);
Paul Cercueil1494b862014-05-05 12:49:07 +0200710 return ret;
Paul Cercueil2725f702014-05-02 11:02:16 +0200711}
712
Paul Cercueil90189672015-03-16 11:41:53 +0100713#ifdef WITH_NETWORK_GET_BUFFER
Paul Cercueil7d7e5d32015-03-05 10:51:41 +0100714static ssize_t network_do_splice(int fd_out, int fd_in, size_t len)
Paul Cercueil09a43482015-03-04 15:50:27 +0100715{
716 int pipefd[2];
Paul Cercueil04065c22015-03-05 14:08:16 +0100717 ssize_t ret, read_len = len;
Paul Cercueil09a43482015-03-04 15:50:27 +0100718
719 ret = (ssize_t) pipe(pipefd);
720 if (ret < 0)
721 return -errno;
722
723 do {
Paul Cercueila107c6d2015-03-05 13:54:10 +0100724 /*
725 * SPLICE_F_NONBLOCK is just here to avoid a deadlock when
726 * splicing from a socket. As the socket is not in
727 * non-blocking mode, it should never return -EAGAIN.
728 * TODO(pcercuei): Find why it locks...
729 * */
730 ret = splice(fd_in, NULL, pipefd[1], NULL, len,
731 SPLICE_F_MOVE | SPLICE_F_NONBLOCK);
732 if (!ret)
733 ret = -EIO;
Paul Cercueil09a43482015-03-04 15:50:27 +0100734 if (ret < 0)
735 goto err_close_pipe;
736
Paul Cercueila107c6d2015-03-05 13:54:10 +0100737 ret = splice(pipefd[0], NULL, fd_out, NULL, ret,
738 SPLICE_F_MOVE | SPLICE_F_NONBLOCK);
739 if (!ret)
740 ret = -EIO;
Paul Cercueil09a43482015-03-04 15:50:27 +0100741 if (ret < 0)
742 goto err_close_pipe;
743
744 len -= ret;
745 } while (len);
746
747err_close_pipe:
748 close(pipefd[0]);
749 close(pipefd[1]);
Paul Cercueil04065c22015-03-05 14:08:16 +0100750 return ret < 0 ? ret : read_len;
Paul Cercueil09a43482015-03-04 15:50:27 +0100751}
752
753static ssize_t network_get_buffer(const struct iio_device *dev,
Paul Cercueil76ca8842015-03-05 11:16:16 +0100754 void **addr_ptr, size_t bytes_used,
755 uint32_t *mask, size_t words)
Paul Cercueil09a43482015-03-04 15:50:27 +0100756{
757 struct iio_device_pdata *pdata = dev->pdata;
Paul Cercueil04065c22015-03-05 14:08:16 +0100758 ssize_t ret, read = 0;
Paul Cercueilca9d3382015-05-04 14:30:09 +0200759 int memfd;
Paul Cercueil09a43482015-03-04 15:50:27 +0100760 bool tx;
Paul Cercueil09a43482015-03-04 15:50:27 +0100761
Paul Cercueil04065c22015-03-05 14:08:16 +0100762 if (pdata->is_cyclic)
Paul Cercueil09a43482015-03-04 15:50:27 +0100763 return -ENOSYS;
Paul Cercueilca9d3382015-05-04 14:30:09 +0200764
765 /* We check early that the temporary file can be created, so that we can
766 * return -ENOSYS in case it fails, which will indicate that the
767 * high-speed interface is not available.
768 *
769 * O_TMPFILE -> Linux 3.11.
770 * TODO: use memfd_create (Linux 3.17) */
771 memfd = open(P_tmpdir, O_RDWR | O_TMPFILE | O_EXCL, S_IRWXU);
772 if (memfd < 0)
773 return -ENOSYS;
774
775 if (!addr_ptr || words != (dev->nb_channels + 31) / 32) {
776 close(memfd);
Paul Cercueil09a43482015-03-04 15:50:27 +0100777 return -EINVAL;
Paul Cercueilca9d3382015-05-04 14:30:09 +0200778 }
Paul Cercueil09a43482015-03-04 15:50:27 +0100779
Paul Cercueile6e5a092015-03-04 16:33:26 +0100780 if (pdata->mmap_addr)
781 munmap(pdata->mmap_addr, pdata->mmap_len);
Paul Cercueil09a43482015-03-04 15:50:27 +0100782
Paul Cercueile6e5a092015-03-04 16:33:26 +0100783 if (pdata->mmap_addr && pdata->is_tx) {
Paul Cercueil09a43482015-03-04 15:50:27 +0100784 char buf[1024];
785 snprintf(buf, sizeof(buf), "WRITEBUF %s %lu\r\n",
786 dev->id, (unsigned long) pdata->mmap_len);
787
788 network_lock_dev(pdata);
789
Paul Cercueil3c0da372015-03-05 11:36:39 +0100790 ret = write_rwbuf_command(dev, buf, false);
Paul Cercueil09a43482015-03-04 15:50:27 +0100791 if (ret < 0)
Paul Cercueilca9d3382015-05-04 14:30:09 +0200792 goto err_close_memfd;
Paul Cercueil09a43482015-03-04 15:50:27 +0100793
794 ret = network_do_splice(pdata->fd,
795 pdata->memfd, pdata->mmap_len);
796 if (ret < 0)
Paul Cercueilca9d3382015-05-04 14:30:09 +0200797 goto err_close_memfd;
Paul Cercueil09a43482015-03-04 15:50:27 +0100798
799 pdata->wait_for_err_code = true;
800 network_unlock_dev(pdata);
801 }
802
803 if (pdata->memfd >= 0)
804 close(pdata->memfd);
805
806 if (bytes_used)
807 pdata->mmap_len = bytes_used;
808
Paul Cercueilca9d3382015-05-04 14:30:09 +0200809 pdata->memfd = memfd;
Paul Cercueil09a43482015-03-04 15:50:27 +0100810
Paul Cercueilef32d582015-03-05 11:18:35 +0100811 ret = (ssize_t) ftruncate(pdata->memfd, pdata->mmap_len);
812 if (ret < 0) {
813 ret = -errno;
814 ERROR("Unable to truncate temp file: %zi\n", -ret);
815 return ret;
816 }
Paul Cercueil09a43482015-03-04 15:50:27 +0100817
Paul Cercueil04065c22015-03-05 14:08:16 +0100818 if (!pdata->is_tx) {
819 char buf[1024];
820 size_t len = pdata->mmap_len;
821
822 snprintf(buf, sizeof(buf), "READBUF %s %lu\r\n",
823 dev->id, (unsigned long) len);
824
825 network_lock_dev(pdata);
826 ret = write_rwbuf_command(dev, buf, false);
827 if (ret < 0)
828 goto err_unlock;
829
830 do {
831 ret = network_read_mask(pdata->fd, mask, words);
832 if (!ret)
833 break;
834 if (ret < 0)
835 goto err_unlock;
836
837 mask = NULL; /* We read the mask only once */
838
839 ret = network_do_splice(pdata->memfd, pdata->fd, ret);
840 if (ret < 0)
841 goto err_unlock;
842
843 read += ret;
844 len -= ret;
845 } while (len);
846
847 network_unlock_dev(pdata);
848 }
Paul Cercueil09a43482015-03-04 15:50:27 +0100849
Paul Cercueile6e5a092015-03-04 16:33:26 +0100850 pdata->mmap_addr = mmap(NULL, pdata->mmap_len,
Paul Cercueil09a43482015-03-04 15:50:27 +0100851 PROT_READ | PROT_WRITE, MAP_SHARED, pdata->memfd, 0);
Paul Cercueile6e5a092015-03-04 16:33:26 +0100852 if (pdata->mmap_addr == MAP_FAILED) {
853 pdata->mmap_addr = NULL;
Paul Cercueil09a43482015-03-04 15:50:27 +0100854 ret = -errno;
Paul Cercueil7d7e5d32015-03-05 10:51:41 +0100855 ERROR("Unable to mmap: %zi\n", -ret);
Paul Cercueil09a43482015-03-04 15:50:27 +0100856 return ret;
857 }
858
Paul Cercueile6e5a092015-03-04 16:33:26 +0100859 *addr_ptr = pdata->mmap_addr;
Paul Cercueil04065c22015-03-05 14:08:16 +0100860 return read ? read : bytes_used;
Paul Cercueil09a43482015-03-04 15:50:27 +0100861
Paul Cercueilca9d3382015-05-04 14:30:09 +0200862err_close_memfd:
863 close(memfd);
Paul Cercueil09a43482015-03-04 15:50:27 +0100864err_unlock:
865 network_unlock_dev(pdata);
866 return ret;
867}
868#endif
869
Paul Cercueil1494b862014-05-05 12:49:07 +0200870static ssize_t network_read_attr_helper(const struct iio_device *dev,
Paul Cercueil0cc0e162014-05-07 12:51:22 +0200871 const struct iio_channel *chn, const char *attr, char *dst,
Paul Cercueil1494b862014-05-05 12:49:07 +0200872 size_t len, bool is_debug)
Paul Cercueil3e94a5b2014-03-04 13:00:41 +0100873{
Paul Cercueil3e94a5b2014-03-04 13:00:41 +0100874 long read_len;
875 ssize_t ret;
876 char buf[1024];
Paul Cercueil05e26262014-05-09 11:32:43 +0200877 struct iio_context_pdata *pdata = dev->ctx->pdata;
878 int fd = pdata->fd;
Paul Cercueil1494b862014-05-05 12:49:07 +0200879 const char *id = dev->id;
Paul Cercueil3e94a5b2014-03-04 13:00:41 +0100880
Paul Cercueil99cf3d42014-03-06 12:35:26 +0100881 if (chn)
Paul Cercueil0cc0e162014-05-07 12:51:22 +0200882 snprintf(buf, sizeof(buf), "READ %s %s %s %s\r\n", id,
883 chn->is_output ? "OUTPUT" : "INPUT",
Paul Cercueil2a3e43d2014-05-21 16:58:45 +0200884 chn->id, attr ? attr : "");
Paul Cercueilc6f03612014-04-14 16:41:31 +0200885 else if (is_debug)
Paul Cercueil2a3e43d2014-05-21 16:58:45 +0200886 snprintf(buf, sizeof(buf), "READ %s DEBUG %s\r\n",
887 id, attr ? attr : "");
Paul Cercueil99cf3d42014-03-06 12:35:26 +0100888 else
Paul Cercueil2a3e43d2014-05-21 16:58:45 +0200889 snprintf(buf, sizeof(buf), "READ %s %s\r\n",
890 id, attr ? attr : "");
Paul Cercueil1494b862014-05-05 12:49:07 +0200891
Paul Cercueil05e26262014-05-09 11:32:43 +0200892 network_lock(pdata);
Paul Cercueilbb76bf92014-03-11 10:20:18 +0100893 read_len = exec_command(buf, fd);
Paul Cercueil1494b862014-05-05 12:49:07 +0200894 if (read_len < 0) {
Paul Cercueil05e26262014-05-09 11:32:43 +0200895 network_unlock(pdata);
Paul Cercueilbb76bf92014-03-11 10:20:18 +0100896 return (ssize_t) read_len;
Paul Cercueil1494b862014-05-05 12:49:07 +0200897 }
Paul Cercueil3e94a5b2014-03-04 13:00:41 +0100898
Paul Cercueil6e7f79e2014-04-04 12:27:24 +0200899 if ((unsigned long) read_len > len) {
Paul Cercueil3e94a5b2014-03-04 13:00:41 +0100900 ERROR("Value returned by server is too large\n");
Paul Cercueil05e26262014-05-09 11:32:43 +0200901 network_unlock(pdata);
Paul Cercueil3e94a5b2014-03-04 13:00:41 +0100902 return -EIO;
903 }
904
905 ret = read_all(dst, read_len, fd);
Paul Cercueil05e26262014-05-09 11:32:43 +0200906 network_unlock(pdata);
Paul Cercueil1494b862014-05-05 12:49:07 +0200907
Paul Cercueil3e94a5b2014-03-04 13:00:41 +0100908 if (ret < 0) {
909 strerror_r(-ret, buf, sizeof(buf));
910 ERROR("Unable to read response to READ: %s\n", buf);
911 return ret;
912 }
913
Paul Cercueil7d95fd72014-05-22 14:26:44 +0200914 return read_len;
Paul Cercueil3e94a5b2014-03-04 13:00:41 +0100915}
916
Paul Cercueil1494b862014-05-05 12:49:07 +0200917static ssize_t network_write_attr_helper(const struct iio_device *dev,
Paul Cercueil0cc0e162014-05-07 12:51:22 +0200918 const struct iio_channel *chn, const char *attr,
919 const char *src, size_t len, bool is_debug)
Paul Cercueil3e94a5b2014-03-04 13:00:41 +0100920{
Paul Cercueila62f84e2015-02-24 14:16:08 +0100921 struct iio_context_pdata *pdata = dev->ctx->pdata;
922 int fd;
923 ssize_t ret;
924 long resp;
Paul Cercueil3e94a5b2014-03-04 13:00:41 +0100925 char buf[1024];
Paul Cercueil1494b862014-05-05 12:49:07 +0200926 const char *id = dev->id;
Paul Cercueil3e94a5b2014-03-04 13:00:41 +0100927
Paul Cercueil07897d32014-03-06 12:46:08 +0100928 if (chn)
Paul Cercueil0cc0e162014-05-07 12:51:22 +0200929 snprintf(buf, sizeof(buf), "WRITE %s %s %s %s %lu\r\n",
930 id, chn->is_output ? "OUTPUT" : "INPUT",
Paul Cercueil8747efe2014-05-22 11:12:12 +0200931 chn->id, attr ? attr : "", (unsigned long) len);
Paul Cercueilc6f03612014-04-14 16:41:31 +0200932 else if (is_debug)
Paul Cercueil8747efe2014-05-22 11:12:12 +0200933 snprintf(buf, sizeof(buf), "WRITE %s DEBUG %s %lu\r\n",
934 id, attr ? attr : "", (unsigned long) len);
Paul Cercueil07897d32014-03-06 12:46:08 +0100935 else
Paul Cercueilcecda352014-05-06 18:14:29 +0200936 snprintf(buf, sizeof(buf), "WRITE %s %s %lu\r\n",
Paul Cercueil8747efe2014-05-22 11:12:12 +0200937 id, attr ? attr : "", (unsigned long) len);
Paul Cercueila62f84e2015-02-24 14:16:08 +0100938
939 network_lock(pdata);
940 fd = pdata->fd;
941 ret = (ssize_t) write_command(buf, fd);
942 if (ret < 0)
943 goto err_unlock;
944
945 ret = write_all(src, len, fd);
946 if (ret < 0)
947 goto err_unlock;
948
949 ret = read_integer(fd, &resp);
950 network_unlock(pdata);
951
952 if (ret < 0)
953 return ret;
954 return (ssize_t) resp;
955
956err_unlock:
957 network_unlock(pdata);
958 return ret;
Paul Cercueil3e94a5b2014-03-04 13:00:41 +0100959}
960
Paul Cercueil99cf3d42014-03-06 12:35:26 +0100961static ssize_t network_read_dev_attr(const struct iio_device *dev,
Paul Cercueil50c762a2014-04-14 15:55:43 +0200962 const char *attr, char *dst, size_t len, bool is_debug)
Paul Cercueil99cf3d42014-03-06 12:35:26 +0100963{
Paul Cercueil5b577762014-06-03 15:31:42 +0200964 if (attr && ((is_debug && !iio_device_find_debug_attr(dev, attr)) ||
965 (!is_debug && !iio_device_find_attr(dev, attr))))
966 return -ENOENT;
967
Paul Cercueil1494b862014-05-05 12:49:07 +0200968 return network_read_attr_helper(dev, NULL, attr, dst, len, is_debug);
Paul Cercueil99cf3d42014-03-06 12:35:26 +0100969}
970
Paul Cercueil07897d32014-03-06 12:46:08 +0100971static ssize_t network_write_dev_attr(const struct iio_device *dev,
Paul Cercueilcecda352014-05-06 18:14:29 +0200972 const char *attr, const char *src, size_t len, bool is_debug)
Paul Cercueil07897d32014-03-06 12:46:08 +0100973{
Paul Cercueil5b577762014-06-03 15:31:42 +0200974 if (attr && ((is_debug && !iio_device_find_debug_attr(dev, attr)) ||
975 (!is_debug && !iio_device_find_attr(dev, attr))))
976 return -ENOENT;
977
Paul Cercueilcecda352014-05-06 18:14:29 +0200978 return network_write_attr_helper(dev, NULL, attr, src, len, is_debug);
Paul Cercueil07897d32014-03-06 12:46:08 +0100979}
980
Paul Cercueil99cf3d42014-03-06 12:35:26 +0100981static ssize_t network_read_chn_attr(const struct iio_channel *chn,
982 const char *attr, char *dst, size_t len)
983{
Paul Cercueil5b577762014-06-03 15:31:42 +0200984 if (attr && !iio_channel_find_attr(chn, attr))
985 return -ENOENT;
986
Paul Cercueil0cc0e162014-05-07 12:51:22 +0200987 return network_read_attr_helper(chn->dev, chn, attr, dst, len, false);
Paul Cercueil99cf3d42014-03-06 12:35:26 +0100988}
989
Paul Cercueil07897d32014-03-06 12:46:08 +0100990static ssize_t network_write_chn_attr(const struct iio_channel *chn,
Paul Cercueilcecda352014-05-06 18:14:29 +0200991 const char *attr, const char *src, size_t len)
Paul Cercueil07897d32014-03-06 12:46:08 +0100992{
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_write_attr_helper(chn->dev, chn, attr, src, len, false);
Paul Cercueil07897d32014-03-06 12:46:08 +0100997}
998
Paul Cercueildcab40c2014-03-11 10:59:14 +0100999static int network_get_trigger(const struct iio_device *dev,
1000 const struct iio_device **trigger)
1001{
1002 struct iio_context_pdata *pdata = dev->ctx->pdata;
1003 unsigned int i;
1004 char buf[1024];
1005 ssize_t ret;
1006 long resp;
1007
1008 snprintf(buf, sizeof(buf), "GETTRIG %s\r\n", dev->id);
Paul Cercueil1494b862014-05-05 12:49:07 +02001009
Paul Cercueil05e26262014-05-09 11:32:43 +02001010 network_lock(dev->ctx->pdata);
Paul Cercueildcab40c2014-03-11 10:59:14 +01001011 resp = exec_command(buf, pdata->fd);
1012 if (resp < 0) {
Paul Cercueil05e26262014-05-09 11:32:43 +02001013 network_unlock(pdata);
Paul Cercueildcab40c2014-03-11 10:59:14 +01001014 return (int) resp;
1015 } else if (resp == 0) {
1016 *trigger = NULL;
Paul Cercueil05e26262014-05-09 11:32:43 +02001017 network_unlock(pdata);
Paul Cercueildcab40c2014-03-11 10:59:14 +01001018 return 0;
Paul Cercueil6e7f79e2014-04-04 12:27:24 +02001019 } else if ((unsigned long) resp > sizeof(buf)) {
Paul Cercueildcab40c2014-03-11 10:59:14 +01001020 ERROR("Value returned by server is too large\n");
Paul Cercueil05e26262014-05-09 11:32:43 +02001021 network_unlock(pdata);
Paul Cercueildcab40c2014-03-11 10:59:14 +01001022 return -EIO;
1023 }
1024
1025 ret = read_all(buf, resp, pdata->fd);
Paul Cercueil05e26262014-05-09 11:32:43 +02001026 network_unlock(pdata);
Paul Cercueil1494b862014-05-05 12:49:07 +02001027
Paul Cercueildcab40c2014-03-11 10:59:14 +01001028 if (ret < 0) {
1029 strerror_r(-ret, buf, sizeof(buf));
1030 ERROR("Unable to read response to GETTRIG: %s\n", buf);
1031 return ret;
1032 }
1033
Lars-Peter Clausenb5cdc102014-08-21 14:45:52 +02001034 if (buf[0] == '\0') {
1035 *trigger = NULL;
1036 return 0;
1037 }
1038
Paul Cercueildcab40c2014-03-11 10:59:14 +01001039 for (i = 0; i < dev->ctx->nb_devices; i++) {
1040 struct iio_device *cur = dev->ctx->devices[i];
1041 if (iio_device_is_trigger(cur) &&
1042 !strncmp(cur->name, buf, resp)) {
1043 *trigger = cur;
1044 return 0;
1045 }
1046 }
1047
1048 return -ENXIO;
1049}
1050
1051static int network_set_trigger(const struct iio_device *dev,
1052 const struct iio_device *trigger)
1053{
Paul Cercueil1494b862014-05-05 12:49:07 +02001054 int ret;
Paul Cercueildcab40c2014-03-11 10:59:14 +01001055 char buf[1024];
1056 if (trigger)
1057 snprintf(buf, sizeof(buf), "SETTRIG %s %s\r\n",
1058 dev->id, trigger->id);
1059 else
1060 snprintf(buf, sizeof(buf), "SETTRIG %s\r\n", dev->id);
Paul Cercueil1494b862014-05-05 12:49:07 +02001061
Paul Cercueil05e26262014-05-09 11:32:43 +02001062 network_lock(dev->ctx->pdata);
Paul Cercueil1494b862014-05-05 12:49:07 +02001063 ret = (int) exec_command(buf, dev->ctx->pdata->fd);
Paul Cercueil05e26262014-05-09 11:32:43 +02001064 network_unlock(dev->ctx->pdata);
Paul Cercueil1494b862014-05-05 12:49:07 +02001065 return ret;
Paul Cercueildcab40c2014-03-11 10:59:14 +01001066}
1067
Paul Cercueil8fd9c8f2014-03-03 17:21:31 +01001068static void network_shutdown(struct iio_context *ctx)
1069{
1070 struct iio_context_pdata *pdata = ctx->pdata;
Paul Cercueil44ae11c2014-03-17 09:56:29 +01001071 unsigned int i;
Paul Cercueil8fd9c8f2014-03-03 17:21:31 +01001072
Paul Cercueil05e26262014-05-09 11:32:43 +02001073 network_lock(pdata);
Paul Cercueilbb76bf92014-03-11 10:20:18 +01001074 write_command("\r\nEXIT\r\n", pdata->fd);
Paul Cercueil8fd9c8f2014-03-03 17:21:31 +01001075 close(pdata->fd);
Paul Cercueil05e26262014-05-09 11:32:43 +02001076 network_unlock(pdata);
Paul Cercueil1494b862014-05-05 12:49:07 +02001077
Paul Cercueil439e1a22015-02-24 13:50:51 +01001078 for (i = 0; i < ctx->nb_devices; i++) {
1079 struct iio_device *dev = ctx->devices[i];
Paul Cercueilc5b00752015-02-24 14:29:53 +01001080 struct iio_device_pdata *dpdata = dev->pdata;
Paul Cercueil439e1a22015-02-24 13:50:51 +01001081
Paul Cercueilc5b00752015-02-24 14:29:53 +01001082 if (dpdata) {
Paul Cercueilaa0db142015-03-04 16:25:24 +01001083 network_close(dev);
Paul Cercueilc5b00752015-02-24 14:29:53 +01001084#if HAVE_PTHREAD
Paul Cercueilaa0db142015-03-04 16:25:24 +01001085 pthread_mutex_destroy(&dpdata->lock);
Paul Cercueilc5b00752015-02-24 14:29:53 +01001086#endif
Paul Cercueilc5b00752015-02-24 14:29:53 +01001087 free(dpdata);
Paul Cercueil439e1a22015-02-24 13:50:51 +01001088 }
1089 }
1090
Paul Cercueil05e26262014-05-09 11:32:43 +02001091#if HAVE_PTHREAD
Paul Cercueil1494b862014-05-05 12:49:07 +02001092 pthread_mutex_destroy(&pdata->lock);
Paul Cercueil05e26262014-05-09 11:32:43 +02001093#endif
Paul Cercueil2dd2c132015-02-24 10:41:01 +01001094 freeaddrinfo(pdata->addrinfo);
Paul Cercueil8fd9c8f2014-03-03 17:21:31 +01001095 free(pdata);
1096}
1097
Paul Cercueil6691a3f2014-05-02 12:32:01 +02001098static int network_get_version(const struct iio_context *ctx,
Paul Cercueil9de9e9d2014-05-20 13:18:19 +02001099 unsigned int *major, unsigned int *minor, char git_tag[8])
Paul Cercueil6691a3f2014-05-02 12:32:01 +02001100{
1101 struct iio_context_pdata *pdata = ctx->pdata;
1102 long maj, min;
1103 int ret;
Paul Cercueil6691a3f2014-05-02 12:32:01 +02001104
Paul Cercueil05e26262014-05-09 11:32:43 +02001105 network_lock(pdata);
Paul Cercueil1494b862014-05-05 12:49:07 +02001106 ret = (int) write_command("VERSION\r\n", pdata->fd);
1107 if (ret < 0)
1108 goto err_unlock;
1109
1110 ret = read_integer(pdata->fd, &maj);
1111 if (!ret)
1112 ret = read_integer(pdata->fd, &min);
1113 if (!ret) {
Paul Cercueil9de9e9d2014-05-20 13:18:19 +02001114 char tag[8];
1115 tag[7] = '\0';
1116
1117 ret = read_all(tag, sizeof(tag) - 1, pdata->fd);
1118 if (ret < 0)
1119 goto err_unlock;
1120
Paul Cercueild15d9952014-05-20 11:40:08 +02001121 if (major)
1122 *major = (unsigned int) maj;
1123 if (minor)
1124 *minor = (unsigned int) min;
Paul Cercueil9de9e9d2014-05-20 13:18:19 +02001125 if (git_tag)
1126 strncpy(git_tag, tag, 8);
Paul Cercueil1494b862014-05-05 12:49:07 +02001127 }
1128
Paul Cercueil8e8f8992014-06-12 16:58:12 +02001129 ret = 0;
Paul Cercueil1494b862014-05-05 12:49:07 +02001130err_unlock:
Paul Cercueil05e26262014-05-09 11:32:43 +02001131 network_unlock(pdata);
Paul Cercueil1494b862014-05-05 12:49:07 +02001132 return ret;
Paul Cercueil6691a3f2014-05-02 12:32:01 +02001133}
1134
Paul Cercueil8a266f12014-06-10 16:06:31 +02001135static unsigned int calculate_remote_timeout(unsigned int timeout)
1136{
1137 /* XXX(pcercuei): We currently hardcode timeout / 2 for the backend used
1138 * by the remote. Is there something better to do here? */
1139 return timeout / 2;
1140}
1141
Paul Cercueilbca3dbc2014-06-11 12:00:21 +02001142static int set_remote_timeout(struct iio_context *ctx, unsigned int timeout)
1143{
1144 char buf[1024];
1145 int ret;
1146
1147 snprintf(buf, sizeof(buf), "TIMEOUT %u\r\n", timeout);
1148 network_lock(ctx->pdata);
1149 ret = (int) exec_command(buf, ctx->pdata->fd);
1150 network_unlock(ctx->pdata);
1151 return ret;
1152}
1153
1154static int network_set_timeout(struct iio_context *ctx, unsigned int timeout)
1155{
1156 int ret = set_socket_timeout(ctx->pdata->fd, timeout);
1157 if (!ret) {
1158 timeout = calculate_remote_timeout(timeout);
1159 ret = set_remote_timeout(ctx, timeout);
1160 }
1161 if (ret < 0) {
1162 char buf[1024];
1163 strerror_r(-ret, buf, sizeof(buf));
Paul Cercueil8a266f12014-06-10 16:06:31 +02001164 WARNING("Unable to set R/W timeout: %s\n", buf);
1165 } else {
Paul Cercueil8a266f12014-06-10 16:06:31 +02001166 ctx->rw_timeout_ms = timeout;
1167 }
1168 return ret;
1169}
1170
Paul Cercueil12d41832014-10-28 14:35:53 +01001171static struct iio_context * network_clone(const struct iio_context *ctx)
1172{
Paul Cercueil7ef45ce2015-03-16 14:36:16 +01001173 if (ctx->description) {
1174 char *ptr = strchr(ctx->description, ' ');
1175 if (ptr) {
1176#ifdef HAVE_IPV6
1177 char buf[INET6_ADDRSTRLEN + IF_NAMESIZE + 2];
1178#else
1179 char buf[INET_ADDRSTRLEN + 1];
1180#endif
1181 strncpy(buf, ctx->description, sizeof(buf) - 1);
1182 buf[ptr - ctx->description] = '\0';
1183 return iio_create_network_context(buf);
1184 }
1185 }
1186
Paul Cercueild3d56ee2015-01-08 16:36:31 +01001187 return iio_create_network_context(ctx->description);
Paul Cercueil12d41832014-10-28 14:35:53 +01001188}
1189
Paul Cercueilc7bad0f2014-03-03 17:06:48 +01001190static struct iio_backend_ops network_ops = {
Paul Cercueil12d41832014-10-28 14:35:53 +01001191 .clone = network_clone,
Paul Cercueilba059762014-03-14 11:02:02 +01001192 .open = network_open,
1193 .close = network_close,
Paul Cercueil9945bc82014-03-05 14:07:29 +01001194 .read = network_read,
Paul Cercueil2725f702014-05-02 11:02:16 +02001195 .write = network_write,
Paul Cercueil90189672015-03-16 11:41:53 +01001196#ifdef WITH_NETWORK_GET_BUFFER
Paul Cercueil09a43482015-03-04 15:50:27 +01001197 .get_buffer = network_get_buffer,
1198#endif
Paul Cercueil3e94a5b2014-03-04 13:00:41 +01001199 .read_device_attr = network_read_dev_attr,
1200 .write_device_attr = network_write_dev_attr,
Paul Cercueil99cf3d42014-03-06 12:35:26 +01001201 .read_channel_attr = network_read_chn_attr,
Paul Cercueil07897d32014-03-06 12:46:08 +01001202 .write_channel_attr = network_write_chn_attr,
Paul Cercueildcab40c2014-03-11 10:59:14 +01001203 .get_trigger = network_get_trigger,
1204 .set_trigger = network_set_trigger,
Paul Cercueil8fd9c8f2014-03-03 17:21:31 +01001205 .shutdown = network_shutdown,
Paul Cercueil6691a3f2014-05-02 12:32:01 +02001206 .get_version = network_get_version,
Paul Cercueil8a266f12014-06-10 16:06:31 +02001207 .set_timeout = network_set_timeout,
Paul Cercueilc7bad0f2014-03-03 17:06:48 +01001208};
1209
1210static struct iio_context * get_context(int fd)
1211{
1212 struct iio_context *ctx;
Paul Cercueile60c3ed2014-03-04 11:23:56 +01001213 char *xml;
Paul Cercueilbb76bf92014-03-11 10:20:18 +01001214 long xml_len = exec_command("PRINT\r\n", fd);
Paul Cercueilcc575532015-03-16 17:15:24 +01001215 if (xml_len < 0) {
1216 errno = (int) -xml_len;
Paul Cercueilc7bad0f2014-03-03 17:06:48 +01001217 return NULL;
Paul Cercueilcc575532015-03-16 17:15:24 +01001218 }
Paul Cercueile60c3ed2014-03-04 11:23:56 +01001219
1220 DEBUG("Server returned a XML string of length %li\n", xml_len);
Paul Cercueilc7bad0f2014-03-03 17:06:48 +01001221 xml = malloc(xml_len);
1222 if (!xml) {
Paul Cercueilcc575532015-03-16 17:15:24 +01001223 errno = ENOMEM;
Paul Cercueilc7bad0f2014-03-03 17:06:48 +01001224 return NULL;
1225 }
1226
1227 DEBUG("Reading XML string...\n");
1228 read_all(xml, xml_len, fd);
1229
1230 DEBUG("Creating context from XML...\n");
1231 ctx = iio_create_xml_context_mem(xml, xml_len);
Paul Cercueilc1ed8482014-06-11 16:29:43 +02001232
1233 if (ctx)
1234 ctx->xml = xml;
1235 else
1236 free(xml);
Paul Cercueilc7bad0f2014-03-03 17:06:48 +01001237 return ctx;
1238}
1239
Paul Cercueil63e52182014-12-11 12:52:48 +01001240struct iio_context * network_create_context(const char *host)
Paul Cercueilc7bad0f2014-03-03 17:06:48 +01001241{
Paul Cercueil2e38bbe2014-03-19 15:27:15 +01001242 struct addrinfo hints, *res;
Paul Cercueilc7bad0f2014-03-03 17:06:48 +01001243 struct iio_context *ctx;
Paul Cercueil8fd9c8f2014-03-03 17:21:31 +01001244 struct iio_context_pdata *pdata;
Paul Cercueil06c479d2015-01-08 16:14:57 +01001245 unsigned int i, len;
Paul Cercueil4970ac32015-02-24 10:59:00 +01001246 int fd, ret;
Paul Cercueilb03c9ef2015-03-16 14:07:58 +01001247 char *description;
Paul Cercueil1fef1a52014-04-07 16:31:15 +02001248#ifdef _WIN32
1249 WSADATA wsaData;
1250
1251 ret = WSAStartup(MAKEWORD(2, 0), &wsaData);
1252 if (ret < 0) {
1253 ERROR("WSAStartup failed with error %i\n", ret);
Paul Cercueilcc575532015-03-16 17:15:24 +01001254 errno = -ret;
Paul Cercueil1fef1a52014-04-07 16:31:15 +02001255 return NULL;
1256 }
1257#endif
Paul Cercueilc7bad0f2014-03-03 17:06:48 +01001258
Paul Cercueil2e38bbe2014-03-19 15:27:15 +01001259 memset(&hints, 0, sizeof(hints));
1260 hints.ai_family = AF_UNSPEC;
1261 hints.ai_socktype = SOCK_STREAM;
Paul Cercueilab114932014-05-19 13:03:17 +02001262
1263#ifdef HAVE_AVAHI
1264 if (!host) {
1265 char addr_str[AVAHI_ADDRESS_STR_MAX];
1266 char port_str[6];
1267 AvahiAddress address;
Paul Cercueil0f729d32014-06-05 17:38:54 +02001268 uint16_t port = IIOD_PORT;
Paul Cercueilab114932014-05-19 13:03:17 +02001269
1270 memset(&address, 0, sizeof(address));
1271
1272 ret = discover_host(&address, &port);
1273 if (ret < 0) {
Paul Cercueilcc575532015-03-16 17:15:24 +01001274 DEBUG("Unable to find host: %s\n", strerror(-ret));
1275 errno = -ret;
Paul Cercueilab114932014-05-19 13:03:17 +02001276 return NULL;
1277 }
1278
1279 avahi_address_snprint(addr_str, sizeof(addr_str), &address);
1280 snprintf(port_str, sizeof(port_str), "%hu", port);
1281 ret = getaddrinfo(addr_str, port_str, &hints, &res);
1282 } else
1283#endif
1284 {
1285 ret = getaddrinfo(host, IIOD_PORT_STR, &hints, &res);
1286 }
1287
Paul Cercueil2e38bbe2014-03-19 15:27:15 +01001288 if (ret) {
Paul Cercueilab114932014-05-19 13:03:17 +02001289 ERROR("Unable to find host: %s\n", gai_strerror(ret));
Paul Cercueild9eb4cb2015-03-23 14:30:20 +01001290#ifndef _WIN32
Paul Cercueilcc575532015-03-16 17:15:24 +01001291 if (ret != EAI_SYSTEM)
1292 errno = ret;
Paul Cercueild9eb4cb2015-03-23 14:30:20 +01001293#endif
Paul Cercueilc7bad0f2014-03-03 17:06:48 +01001294 return NULL;
Paul Cercueilc7bad0f2014-03-03 17:06:48 +01001295 }
1296
Paul Cercueil4970ac32015-02-24 10:59:00 +01001297 fd = create_socket(res);
Paul Cercueilcc575532015-03-16 17:15:24 +01001298 if (fd < 0) {
1299 errno = fd;
Paul Cercueil2dd2c132015-02-24 10:41:01 +01001300 goto err_free_addrinfo;
Paul Cercueilcc575532015-03-16 17:15:24 +01001301 }
Paul Cercueilbca3dbc2014-06-11 12:00:21 +02001302
Paul Cercueil8fd9c8f2014-03-03 17:21:31 +01001303 pdata = calloc(1, sizeof(*pdata));
1304 if (!pdata) {
Paul Cercueilcc575532015-03-16 17:15:24 +01001305 errno = ENOMEM;
Paul Cercueil8fd9c8f2014-03-03 17:21:31 +01001306 goto err_close_socket;
1307 }
1308
1309 pdata->fd = fd;
Paul Cercueil2dd2c132015-02-24 10:41:01 +01001310 pdata->addrinfo = res;
Paul Cercueil8fd9c8f2014-03-03 17:21:31 +01001311
Paul Cercueilc7bad0f2014-03-03 17:06:48 +01001312 DEBUG("Creating context...\n");
1313 ctx = get_context(fd);
1314 if (!ctx)
Paul Cercueild3d56ee2015-01-08 16:36:31 +01001315 goto err_free_pdata;
Paul Cercueilc7bad0f2014-03-03 17:06:48 +01001316
Paul Cercueil2057fd32014-10-28 14:44:19 +01001317 /* Override the name and low-level functions of the XML context
1318 * with those corresponding to the network context */
1319 ctx->name = "network";
1320 ctx->ops = &network_ops;
1321 ctx->pdata = pdata;
1322
Paul Cercueil06c479d2015-01-08 16:14:57 +01001323#ifdef HAVE_IPV6
Paul Cercueiled15e492015-01-12 15:52:28 +01001324 len = INET6_ADDRSTRLEN + IF_NAMESIZE + 2;
Paul Cercueil06c479d2015-01-08 16:14:57 +01001325#else
1326 len = INET_ADDRSTRLEN + 1;
1327#endif
Paul Cercueilb03c9ef2015-03-16 14:07:58 +01001328
1329 description = malloc(len);
1330 if (!description) {
Paul Cercueilcc575532015-03-16 17:15:24 +01001331 ret = -ENOMEM;
Paul Cercueil06c479d2015-01-08 16:14:57 +01001332 goto err_network_shutdown;
1333 }
1334
Paul Cercueilb03c9ef2015-03-16 14:07:58 +01001335 description[0] = '\0';
Paul Cercueil06c479d2015-01-08 16:14:57 +01001336
1337#ifdef HAVE_IPV6
1338 if (res->ai_family == AF_INET6) {
1339 struct sockaddr_in6 *in = (struct sockaddr_in6 *) res->ai_addr;
Paul Cercueiled15e492015-01-12 15:52:28 +01001340 char *ptr;
Paul Cercueil06c479d2015-01-08 16:14:57 +01001341 inet_ntop(AF_INET6, &in->sin6_addr,
Paul Cercueilb03c9ef2015-03-16 14:07:58 +01001342 description, INET6_ADDRSTRLEN);
Paul Cercueiled15e492015-01-12 15:52:28 +01001343
Paul Cercueilb03c9ef2015-03-16 14:07:58 +01001344 ptr = if_indextoname(in->sin6_scope_id, description +
1345 strlen(description) + 1);
Paul Cercueiled15e492015-01-12 15:52:28 +01001346 if (!ptr) {
Paul Cercueilcc575532015-03-16 17:15:24 +01001347 ret = -errno;
Paul Cercueiled15e492015-01-12 15:52:28 +01001348 ERROR("Unable to lookup interface of IPv6 address\n");
Paul Cercueilb03c9ef2015-03-16 14:07:58 +01001349 goto err_free_description;
Paul Cercueiled15e492015-01-12 15:52:28 +01001350 }
1351
1352 *(ptr - 1) = '%';
Paul Cercueil06c479d2015-01-08 16:14:57 +01001353 }
1354#endif
1355 if (res->ai_family == AF_INET) {
1356 struct sockaddr_in *in = (struct sockaddr_in *) res->ai_addr;
Paul Cercueilb03c9ef2015-03-16 14:07:58 +01001357 inet_ntop(AF_INET, &in->sin_addr, description, INET_ADDRSTRLEN);
Paul Cercueil06c479d2015-01-08 16:14:57 +01001358 }
1359
Paul Cercueil44ae11c2014-03-17 09:56:29 +01001360 for (i = 0; i < ctx->nb_devices; i++) {
1361 struct iio_device *dev = ctx->devices[i];
Paul Cercueilff778232014-03-24 14:23:08 +01001362
Paul Cercueil439e1a22015-02-24 13:50:51 +01001363 dev->pdata = calloc(1, sizeof(*dev->pdata));
1364 if (!dev->pdata) {
Paul Cercueilcc575532015-03-16 17:15:24 +01001365 ret = -ENOMEM;
Paul Cercueilb03c9ef2015-03-16 14:07:58 +01001366 goto err_free_description;
Paul Cercueil439e1a22015-02-24 13:50:51 +01001367 }
1368
1369 dev->pdata->fd = -1;
Paul Cercueil90189672015-03-16 11:41:53 +01001370#ifdef WITH_NETWORK_GET_BUFFER
Paul Cercueil09a43482015-03-04 15:50:27 +01001371 dev->pdata->memfd = -1;
Paul Cercueile6e5a092015-03-04 16:33:26 +01001372#endif
Paul Cercueilc5b00752015-02-24 14:29:53 +01001373
1374#if HAVE_PTHREAD
1375 ret = pthread_mutex_init(&dev->pdata->lock, NULL);
Paul Cercueilcc575532015-03-16 17:15:24 +01001376 if (ret < 0)
Paul Cercueilb03c9ef2015-03-16 14:07:58 +01001377 goto err_free_description;
Paul Cercueilc5b00752015-02-24 14:29:53 +01001378#endif
Paul Cercueil44ae11c2014-03-17 09:56:29 +01001379 }
1380
Paul Cercueilc1ed8482014-06-11 16:29:43 +02001381 iio_context_init(ctx);
Paul Cercueil4c6729d2014-04-04 17:24:41 +02001382
Paul Cercueil05e26262014-05-09 11:32:43 +02001383#if HAVE_PTHREAD
Paul Cercueil1494b862014-05-05 12:49:07 +02001384 ret = pthread_mutex_init(&pdata->lock, NULL);
Paul Cercueilcc575532015-03-16 17:15:24 +01001385 if (ret < 0)
Paul Cercueilb03c9ef2015-03-16 14:07:58 +01001386 goto err_free_description;
Paul Cercueil05e26262014-05-09 11:32:43 +02001387#endif
Paul Cercueil1494b862014-05-05 12:49:07 +02001388
Paul Cercueilb03c9ef2015-03-16 14:07:58 +01001389 if (ctx->description) {
1390 size_t new_size = len + strlen(ctx->description) + 1;
1391 char *ptr, *new_description = realloc(description, new_size);
Paul Cercueilcc575532015-03-16 17:15:24 +01001392 if (!new_description) {
1393 ret = -ENOMEM;
Paul Cercueilb03c9ef2015-03-16 14:07:58 +01001394 goto err_free_description;
Paul Cercueilcc575532015-03-16 17:15:24 +01001395 }
Paul Cercueilb03c9ef2015-03-16 14:07:58 +01001396
1397 ptr = strrchr(new_description, '\0');
1398 snprintf(ptr, new_size - len, " %s", ctx->description);
1399 free(ctx->description);
1400
1401 ctx->description = new_description;
1402 } else {
1403 ctx->description = description;
1404 }
1405
Paul Cercueilbca3dbc2014-06-11 12:00:21 +02001406 set_remote_timeout(ctx, calculate_remote_timeout(DEFAULT_TIMEOUT_MS));
Paul Cercueilc7bad0f2014-03-03 17:06:48 +01001407 return ctx;
1408
Paul Cercueilb03c9ef2015-03-16 14:07:58 +01001409err_free_description:
1410 free(description);
Paul Cercueil44ae11c2014-03-17 09:56:29 +01001411err_network_shutdown:
Paul Cercueil44ae11c2014-03-17 09:56:29 +01001412 iio_context_destroy(ctx);
Paul Cercueilcc575532015-03-16 17:15:24 +01001413 errno = -ret;
Paul Cercueil2057fd32014-10-28 14:44:19 +01001414 return NULL;
Paul Cercueil8fd9c8f2014-03-03 17:21:31 +01001415err_free_pdata:
1416 free(pdata);
Paul Cercueilc7bad0f2014-03-03 17:06:48 +01001417err_close_socket:
1418 close(fd);
Paul Cercueil2dd2c132015-02-24 10:41:01 +01001419err_free_addrinfo:
1420 freeaddrinfo(res);
Paul Cercueilc7bad0f2014-03-03 17:06:48 +01001421 return NULL;
1422}