blob: 75751a8518dad09ab318c7950b7d532a15fcdc19 [file] [log] [blame]
Paul Cercueilc7bad0f2014-03-03 17:06:48 +01001/*
2 * libiio - Library for interfacing industrial I/O (IIO) devices
3 *
Paul Cercueil135b3612015-06-30 14:10:14 +02004 * Copyright (C) 2014-2015 Analog Devices, Inc.
Paul Cercueilc7bad0f2014-03-03 17:06:48 +01005 * 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
33#include <winsock2.h>
34#include <ws2tcpip.h>
35#define close(s) closesocket(s)
36
37/* winsock2.h defines ERROR, we don't want that */
38#undef ERROR
39
40#else /* _WIN32 */
Paul Cercueil06c479d2015-01-08 16:14:57 +010041#include <arpa/inet.h>
Paul Cercueil1fef1a52014-04-07 16:31:15 +020042#include <netdb.h>
Paul Cercueil0c3ce452015-02-05 16:37:42 +010043#include <netinet/in.h>
Paul Cercueil0b584e12015-01-28 11:47:03 +010044#include <netinet/tcp.h>
Paul Cercueiled15e492015-01-12 15:52:28 +010045#include <net/if.h>
Paul Cercueil09a43482015-03-04 15:50:27 +010046#include <sys/mman.h>
Paul Cercueil83628b32014-11-24 11:26:21 +010047#include <sys/select.h>
Paul Cercueilc7bad0f2014-03-03 17:06:48 +010048#include <sys/socket.h>
49#include <unistd.h>
Paul Cercueil1fef1a52014-04-07 16:31:15 +020050#endif /* _WIN32 */
51
Paul Cercueil257e6ca2014-12-09 17:32:47 +010052#if HAVE_PTHREAD
53#include <pthread.h>
54#endif
55
Paul Cercueilab114932014-05-19 13:03:17 +020056#ifdef HAVE_AVAHI
57#include <avahi-client/client.h>
58#include <avahi-common/error.h>
59#include <avahi-client/lookup.h>
60#include <avahi-common/simple-watch.h>
61#endif
62
Paul Cercueil1fef1a52014-04-07 16:31:15 +020063#include "debug.h"
Paul Cercueilc7bad0f2014-03-03 17:06:48 +010064
Paul Cercueil8a266f12014-06-10 16:06:31 +020065#define DEFAULT_TIMEOUT_MS 5000
66
Paul Cercueil2e38bbe2014-03-19 15:27:15 +010067#define _STRINGIFY(x) #x
68#define STRINGIFY(x) _STRINGIFY(x)
69
Paul Cercueilc7bad0f2014-03-03 17:06:48 +010070#define IIOD_PORT 30431
Paul Cercueil2e38bbe2014-03-19 15:27:15 +010071#define IIOD_PORT_STR STRINGIFY(IIOD_PORT)
Paul Cercueilc7bad0f2014-03-03 17:06:48 +010072
Paul Cercueil8fd9c8f2014-03-03 17:21:31 +010073struct iio_context_pdata {
74 int fd;
Paul Cercueil2dd2c132015-02-24 10:41:01 +010075 struct addrinfo *addrinfo;
Paul Cercueil05e26262014-05-09 11:32:43 +020076#if HAVE_PTHREAD
Paul Cercueil1494b862014-05-05 12:49:07 +020077 pthread_mutex_t lock;
Paul Cercueil05e26262014-05-09 11:32:43 +020078#endif
Paul Cercueil8fd9c8f2014-03-03 17:21:31 +010079};
80
Paul Cercueil439e1a22015-02-24 13:50:51 +010081struct iio_device_pdata {
82 int fd;
Paul Cercueil90189672015-03-16 11:41:53 +010083#ifdef WITH_NETWORK_GET_BUFFER
Paul Cercueil09a43482015-03-04 15:50:27 +010084 int memfd;
Paul Cercueile6e5a092015-03-04 16:33:26 +010085 void *mmap_addr;
Paul Cercueil09a43482015-03-04 15:50:27 +010086 size_t mmap_len;
Paul Cercueile6e5a092015-03-04 16:33:26 +010087#endif
Paul Cercueil09a43482015-03-04 15:50:27 +010088 bool wait_for_err_code, is_cyclic, is_tx;
Paul Cercueilc5b00752015-02-24 14:29:53 +010089#if HAVE_PTHREAD
90 pthread_mutex_t lock;
91#endif
Paul Cercueil439e1a22015-02-24 13:50:51 +010092};
93
Paul Cercueilab114932014-05-19 13:03:17 +020094#ifdef HAVE_AVAHI
95struct avahi_discovery_data {
96 AvahiSimplePoll *poll;
97 AvahiAddress *address;
98 uint16_t *port;
99 bool found, resolved;
100};
101
102static void __avahi_resolver_cb(AvahiServiceResolver *resolver,
103 __notused AvahiIfIndex iface, __notused AvahiProtocol proto,
104 __notused AvahiResolverEvent event, __notused const char *name,
105 __notused const char *type, __notused const char *domain,
106 __notused const char *host_name, const AvahiAddress *address,
107 uint16_t port, __notused AvahiStringList *txt,
108 __notused AvahiLookupResultFlags flags, void *d)
109{
110 struct avahi_discovery_data *ddata = (struct avahi_discovery_data *) d;
111
112 memcpy(ddata->address, address, sizeof(*address));
113 *ddata->port = port;
114 ddata->resolved = true;
115 avahi_service_resolver_free(resolver);
116}
117
118static void __avahi_browser_cb(AvahiServiceBrowser *browser,
119 AvahiIfIndex iface, AvahiProtocol proto,
120 AvahiBrowserEvent event, const char *name,
121 const char *type, const char *domain,
122 __notused AvahiLookupResultFlags flags, void *d)
123{
124 struct avahi_discovery_data *ddata = (struct avahi_discovery_data *) d;
125 struct AvahiClient *client = avahi_service_browser_get_client(browser);
126
127 switch (event) {
128 default:
129 case AVAHI_BROWSER_NEW:
130 ddata->found = !!avahi_service_resolver_new(client, iface,
131 proto, name, type, domain,
132 AVAHI_PROTO_UNSPEC, 0,
133 __avahi_resolver_cb, d);
134 break;
135 case AVAHI_BROWSER_ALL_FOR_NOW:
136 if (ddata->found) {
137 while (!ddata->resolved) {
138 struct timespec ts;
139 ts.tv_sec = 0;
140 ts.tv_nsec = 4000000;
141 nanosleep(&ts, NULL);
142 }
143 }
144 case AVAHI_BROWSER_FAILURE: /* fall-through */
145 avahi_simple_poll_quit(ddata->poll);
146 case AVAHI_BROWSER_CACHE_EXHAUSTED: /* fall-through */
147 break;
148 }
149}
150
151static int discover_host(AvahiAddress *addr, uint16_t *port)
152{
153 struct avahi_discovery_data ddata;
154 int ret = 0;
155 AvahiClient *client;
156 AvahiServiceBrowser *browser;
157 AvahiSimplePoll *poll = avahi_simple_poll_new();
158 if (!poll)
159 return -ENOMEM;
160
161 client = avahi_client_new(avahi_simple_poll_get(poll),
162 0, NULL, NULL, &ret);
163 if (!client) {
164 ERROR("Unable to start ZeroConf client :%s\n",
165 avahi_strerror(ret));
166 goto err_free_poll;
167 }
168
169 memset(&ddata, 0, sizeof(ddata));
170 ddata.poll = poll;
171 ddata.address = addr;
172 ddata.port = port;
173
174 browser = avahi_service_browser_new(client,
175 AVAHI_IF_UNSPEC, AVAHI_PROTO_UNSPEC,
176 "_iio._tcp", NULL, 0, __avahi_browser_cb, &ddata);
177 if (!browser) {
178 ret = avahi_client_errno(client);
179 ERROR("Unable to create ZeroConf browser: %s\n",
180 avahi_strerror(ret));
181 goto err_free_client;
182 }
183
184 DEBUG("Trying to discover host\n");
185 avahi_simple_poll_loop(poll);
186
187 if (!ddata.found)
188 ret = ENXIO;
189
190 avahi_service_browser_free(browser);
191err_free_client:
192 avahi_client_free(client);
193err_free_poll:
194 avahi_simple_poll_free(poll);
195 return -ret; /* we want a negative error code */
196}
197#endif /* HAVE_AVAHI */
198
Paul Cercueil05e26262014-05-09 11:32:43 +0200199static void network_lock(struct iio_context_pdata *pdata)
200{
201#if HAVE_PTHREAD
202 pthread_mutex_lock(&pdata->lock);
203#endif
204}
205
206static void network_unlock(struct iio_context_pdata *pdata)
207{
208#if HAVE_PTHREAD
209 pthread_mutex_unlock(&pdata->lock);
210#endif
211}
212
Paul Cercueilc5b00752015-02-24 14:29:53 +0100213static void network_lock_dev(struct iio_device_pdata *pdata)
214{
215#if HAVE_PTHREAD
216 pthread_mutex_lock(&pdata->lock);
217#endif
218}
219
220static void network_unlock_dev(struct iio_device_pdata *pdata)
221{
222#if HAVE_PTHREAD
223 pthread_mutex_unlock(&pdata->lock);
224#endif
225}
226
Paul Cercueilc7bad0f2014-03-03 17:06:48 +0100227static ssize_t write_all(const void *src, size_t len, int fd)
228{
Paul Cercueil6e7f79e2014-04-04 12:27:24 +0200229 uintptr_t ptr = (uintptr_t) src;
Paul Cercueilc7bad0f2014-03-03 17:06:48 +0100230 while (len) {
Paul Cercueil4012cff2015-05-11 10:47:40 +0200231 ssize_t ret = send(fd, (const void *) ptr, (int) len, 0);
Lars-Peter Clausencb7b8bf2014-12-05 16:08:52 +0100232 if (ret < 0) {
Paul Cercueil135b3612015-06-30 14:10:14 +0200233#ifdef _WIN32
234 int err = WSAGetLastError();
235#else
236 int err = errno;
237#endif
Paul Cercueil0a96c062015-07-02 11:16:33 +0200238 if (err == EINTR)
Lars-Peter Clausencb7b8bf2014-12-05 16:08:52 +0100239 continue;
Paul Cercueil135b3612015-06-30 14:10:14 +0200240 return (ssize_t) -err;
Lars-Peter Clausencb7b8bf2014-12-05 16:08:52 +0100241 }
Paul Cercueilc7bad0f2014-03-03 17:06:48 +0100242 ptr += ret;
243 len -= ret;
244 }
Paul Cercueil4012cff2015-05-11 10:47:40 +0200245 return (ssize_t)(ptr - (uintptr_t) src);
Paul Cercueilc7bad0f2014-03-03 17:06:48 +0100246}
247
248static ssize_t read_all(void *dst, size_t len, int fd)
249{
Paul Cercueil6e7f79e2014-04-04 12:27:24 +0200250 uintptr_t ptr = (uintptr_t) dst;
Paul Cercueilc7bad0f2014-03-03 17:06:48 +0100251 while (len) {
Paul Cercueil4012cff2015-05-11 10:47:40 +0200252 ssize_t ret = recv(fd, (void *) ptr, (int) len, 0);
Lars-Peter Clausencb7b8bf2014-12-05 16:08:52 +0100253 if (ret < 0) {
Paul Cercueil135b3612015-06-30 14:10:14 +0200254#ifdef _WIN32
255 int err = WSAGetLastError();
256#else
257 int err = errno;
258#endif
Paul Cercueil0a96c062015-07-02 11:16:33 +0200259 if (err == EINTR)
Lars-Peter Clausencb7b8bf2014-12-05 16:08:52 +0100260 continue;
Paul Cercueil135b3612015-06-30 14:10:14 +0200261 return (ssize_t) -err;
Lars-Peter Clausencb7b8bf2014-12-05 16:08:52 +0100262 }
Paul Cercueil43eb7e82014-11-13 12:46:59 +0100263 if (ret == 0)
264 return -EPIPE;
Paul Cercueilc7bad0f2014-03-03 17:06:48 +0100265 ptr += ret;
266 len -= ret;
267 }
Paul Cercueil4012cff2015-05-11 10:47:40 +0200268 return (ssize_t)(ptr - (uintptr_t) dst);
Paul Cercueilc7bad0f2014-03-03 17:06:48 +0100269}
270
Paul Cercueile60c3ed2014-03-04 11:23:56 +0100271static int read_integer(int fd, long *val)
272{
273 unsigned int i;
274 char buf[1024], *ptr;
275 ssize_t ret;
276 bool found = false;
277
278 for (i = 0; i < sizeof(buf) - 1; i++) {
279 ret = read_all(buf + i, 1, fd);
280 if (ret < 0)
281 return (int) ret;
282
Paul Cercueil6691a3f2014-05-02 12:32:01 +0200283 /* Skip the eventual first few carriage returns.
284 * Also stop when a dot is found (for parsing floats) */
285 if (buf[i] != '\n' && buf[i] != '.')
Paul Cercueile60c3ed2014-03-04 11:23:56 +0100286 found = true;
287 else if (found)
288 break;
289 }
290
291 buf[i] = '\0';
292 ret = (ssize_t) strtol(buf, &ptr, 10);
293 if (ptr == buf)
294 return -EINVAL;
295 *val = (long) ret;
296 return 0;
297}
298
Paul Cercueilbb76bf92014-03-11 10:20:18 +0100299static ssize_t write_command(const char *cmd, int fd)
300{
301 ssize_t ret;
302
303 DEBUG("Writing command: %s\n", cmd);
304 ret = write_all(cmd, strlen(cmd), fd);
305 if (ret < 0) {
306 char buf[1024];
Paul Cercueil53fc4852015-05-22 10:57:53 +0200307 iio_strerror(-ret, buf, sizeof(buf));
Paul Cercueilbb76bf92014-03-11 10:20:18 +0100308 ERROR("Unable to send command: %s\n", buf);
309 }
310 return ret;
311}
312
313static long exec_command(const char *cmd, int fd)
314{
315 long resp;
316 ssize_t ret = write_command(cmd, fd);
317 if (ret < 0)
318 return (long) ret;
319
320 DEBUG("Reading response\n");
321 ret = read_integer(fd, &resp);
322 if (ret < 0) {
323 char buf[1024];
Paul Cercueil53fc4852015-05-22 10:57:53 +0200324 iio_strerror(-ret, buf, sizeof(buf));
Paul Cercueilbb76bf92014-03-11 10:20:18 +0100325 ERROR("Unable to read response: %s\n", buf);
326 return (long) ret;
327 }
328
Paul Cercueilc7fe2ea2014-03-28 11:38:45 +0100329#if LOG_LEVEL >= DEBUG_L
Paul Cercueilbb76bf92014-03-11 10:20:18 +0100330 if (resp < 0) {
331 char buf[1024];
Paul Cercueil53fc4852015-05-22 10:57:53 +0200332 iio_strerror(-resp, buf, sizeof(buf));
Paul Cercueilc7fe2ea2014-03-28 11:38:45 +0100333 DEBUG("Server returned an error: %s\n", buf);
Paul Cercueilbb76bf92014-03-11 10:20:18 +0100334 }
Paul Cercueilc7fe2ea2014-03-28 11:38:45 +0100335#endif
336
Paul Cercueilbb76bf92014-03-11 10:20:18 +0100337 return resp;
338}
339
Paul Cercueil4970ac32015-02-24 10:59:00 +0100340#ifndef _WIN32
Paul Cercueil4970ac32015-02-24 10:59:00 +0100341/* The purpose of this function is to provide a version of connect()
342 * that does not ignore timeouts... */
343static int do_connect(int fd, const struct sockaddr *addr,
344 socklen_t addrlen, struct timeval *timeout)
345{
346 int ret, error;
347 socklen_t len;
348 fd_set set;
349
350 FD_ZERO(&set);
351 FD_SET(fd, &set);
352
353 ret = set_blocking_mode(fd, false);
354 if (ret < 0)
355 return ret;
356
357 ret = connect(fd, addr, addrlen);
358 if (ret < 0 && errno != EINPROGRESS) {
359 ret = -errno;
360 goto end;
361 }
362
363 ret = select(fd + 1, &set, &set, NULL, timeout);
364 if (ret < 0) {
365 ret = -errno;
366 goto end;
367 }
368 if (ret == 0) {
369 ret = -ETIMEDOUT;
370 goto end;
371 }
372
373 /* Verify that we don't have an error */
374 len = sizeof(error);
375 ret = getsockopt(fd, SOL_SOCKET, SO_ERROR, &error, &len);
376 if(ret < 0) {
377 ret = -errno;
378 goto end;
379 }
380 if (error) {
381 ret = -error;
382 goto end;
383 }
384
385end:
386 /* Restore blocking mode */
387 set_blocking_mode(fd, true);
388 return ret;
389}
390
391static int set_socket_timeout(int fd, unsigned int timeout)
392{
393 struct timeval tv;
394
395 tv.tv_sec = timeout / 1000;
396 tv.tv_usec = (timeout % 1000) * 1000;
397 if (setsockopt(fd, SOL_SOCKET, SO_SNDTIMEO, &tv, sizeof(tv)) < 0 ||
398 setsockopt(fd, SOL_SOCKET, SO_RCVTIMEO,
399 &tv, sizeof(tv)) < 0)
400 return -errno;
401 else
402 return 0;
403}
404#else
405static int set_socket_timeout(int fd, unsigned int timeout)
406{
407 if (setsockopt(fd, SOL_SOCKET, SO_SNDTIMEO,
408 (const char *) &timeout, sizeof(timeout)) < 0 ||
409 setsockopt(fd, SOL_SOCKET, SO_RCVTIMEO,
410 (const char *) &timeout, sizeof(timeout)) < 0)
Paul Cercueil135b3612015-06-30 14:10:14 +0200411 return -WSAGetLastError();
Paul Cercueil4970ac32015-02-24 10:59:00 +0100412 else
413 return 0;
414}
415#endif /* !_WIN32 */
416
417static int create_socket(const struct addrinfo *addrinfo)
418{
419 struct timeval timeout;
420 int ret, fd, yes = 1;
421
Paul Cercueil4012cff2015-05-11 10:47:40 +0200422#ifdef _WIN32
423 SOCKET s = socket(addrinfo->ai_family, addrinfo->ai_socktype, 0);
424 fd = (s == INVALID_SOCKET) ? -1 : (int) s;
Paul Cercueil135b3612015-06-30 14:10:14 +0200425 if (fd < 0)
426 return -WSAGetLastError();
Paul Cercueil4012cff2015-05-11 10:47:40 +0200427#else
Paul Cercueil4970ac32015-02-24 10:59:00 +0100428 fd = socket(addrinfo->ai_family, addrinfo->ai_socktype, 0);
Paul Cercueil135b3612015-06-30 14:10:14 +0200429 if (fd < 0)
430 return -errno;
Paul Cercueil4012cff2015-05-11 10:47:40 +0200431#endif
Paul Cercueil4970ac32015-02-24 10:59:00 +0100432
433 timeout.tv_sec = DEFAULT_TIMEOUT_MS / 1000;
434 timeout.tv_usec = (DEFAULT_TIMEOUT_MS % 1000) * 1000;
435
436#ifndef _WIN32
437 ret = do_connect(fd, addrinfo->ai_addr, addrinfo->ai_addrlen, &timeout);
Paul Cercueil135b3612015-06-30 14:10:14 +0200438 if (ret < 0)
439 ret = -errno;
Paul Cercueil4970ac32015-02-24 10:59:00 +0100440#else
Paul Cercueil4012cff2015-05-11 10:47:40 +0200441 ret = connect(fd, addrinfo->ai_addr, (int) addrinfo->ai_addrlen);
Paul Cercueil135b3612015-06-30 14:10:14 +0200442 if (ret == SOCKET_ERROR)
443 ret = -WSAGetLastError();
Paul Cercueil4970ac32015-02-24 10:59:00 +0100444#endif
445 if (ret < 0) {
Paul Cercueil4970ac32015-02-24 10:59:00 +0100446 close(fd);
447 return ret;
448 }
449
450 set_socket_timeout(fd, DEFAULT_TIMEOUT_MS);
451 setsockopt(fd, IPPROTO_TCP, TCP_NODELAY,
452 (const char *) &yes, sizeof(yes));
453 return fd;
454}
455
Paul Cercueil92f15c22015-04-20 11:36:51 +0200456static int network_open(const struct iio_device *dev,
457 size_t samples_count, bool cyclic)
Paul Cercueilba059762014-03-14 11:02:02 +0100458{
Paul Cercueil439e1a22015-02-24 13:50:51 +0100459 struct iio_context_pdata *pdata = dev->ctx->pdata;
Paul Cercueilba059762014-03-14 11:02:02 +0100460 char buf[1024], *ptr;
Paul Cercueil4012cff2015-05-11 10:47:40 +0200461 size_t i;
Paul Cercueil439e1a22015-02-24 13:50:51 +0100462 int ret, fd;
Paul Cercueilba059762014-03-14 11:02:02 +0100463
Paul Cercueil439e1a22015-02-24 13:50:51 +0100464 if (dev->pdata->fd >= 0)
465 return -EBUSY;
466
467 fd = create_socket(pdata->addrinfo);
468 if (fd < 0)
469 return fd;
Paul Cercueilba059762014-03-14 11:02:02 +0100470
Paul Cercueil3c407f82014-04-02 14:11:59 +0200471 snprintf(buf, sizeof(buf), "OPEN %s %lu ",
472 dev->id, (unsigned long) samples_count);
Paul Cercueilba059762014-03-14 11:02:02 +0100473 ptr = buf + strlen(buf);
474
Paul Cercueil92f15c22015-04-20 11:36:51 +0200475 for (i = dev->words; i > 0; i--) {
476 snprintf(ptr, (ptr - buf) + i * 8, "%08x", dev->mask[i - 1]);
Paul Cercueilba059762014-03-14 11:02:02 +0100477 ptr += 8;
478 }
Paul Cercueil71694c72014-05-22 14:02:13 +0200479
480 strcpy(ptr, cyclic ? " CYCLIC\r\n" : "\r\n");
Paul Cercueilba059762014-03-14 11:02:02 +0100481
Paul Cercueilc5b00752015-02-24 14:29:53 +0100482 network_lock_dev(dev->pdata);
Paul Cercueil439e1a22015-02-24 13:50:51 +0100483 ret = (int) exec_command(buf, fd);
Paul Cercueilc5b00752015-02-24 14:29:53 +0100484 network_unlock_dev(dev->pdata);
Paul Cercueil1494b862014-05-05 12:49:07 +0200485
Paul Cercueil44ae11c2014-03-17 09:56:29 +0100486 if (ret < 0) {
Paul Cercueil439e1a22015-02-24 13:50:51 +0100487 close(fd);
Paul Cercueil44ae11c2014-03-17 09:56:29 +0100488 return ret;
Paul Cercueil44ae11c2014-03-17 09:56:29 +0100489 }
Paul Cercueil439e1a22015-02-24 13:50:51 +0100490
Lars-Peter Clausen62bd5522015-03-27 16:06:52 +0100491 dev->pdata->is_tx = iio_device_is_tx(dev);
Paul Cercueil1d70d442015-03-04 15:00:37 +0100492 dev->pdata->is_cyclic = cyclic;
Paul Cercueil439e1a22015-02-24 13:50:51 +0100493 dev->pdata->fd = fd;
Paul Cercueil8f7f6c42015-02-24 15:00:35 +0100494 dev->pdata->wait_for_err_code = false;
Paul Cercueild957b982015-08-05 14:39:01 +0200495#ifdef WITH_NETWORK_GET_BUFFER
496 dev->pdata->mmap_len = samples_count * iio_device_get_sample_size(dev);
497#endif
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 Cercueild5d84612015-06-08 21:24:15 +0200551 int ret = -EBADF;
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) {
Paul Cercueil4012cff2015-05-11 10:47:40 +0200590 size_t i;
Paul Cercueil7d7e5d32015-03-05 10:51:41 +0100591 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) {
Paul Cercueil53fc4852015-05-22 10:57:53 +0200643 iio_strerror(-ret, buf, sizeof(buf));
Paul Cercueil5cab3ae2014-03-14 11:23:56 +0100644 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) {
Paul Cercueil53fc4852015-05-22 10:57:53 +0200653 iio_strerror(-ret, buf, sizeof(buf));
Paul Cercueil9945bc82014-03-05 14:07:29 +0100654 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",
Paul Cercueild957b982015-08-05 14:39:01 +0200786 dev->id, (unsigned long) bytes_used);
Paul Cercueil09a43482015-03-04 15:50:27 +0100787
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
Paul Cercueild957b982015-08-05 14:39:01 +0200794 ret = network_do_splice(pdata->fd, pdata->memfd, bytes_used);
Paul Cercueil09a43482015-03-04 15:50:27 +0100795 if (ret < 0)
Paul Cercueilca9d3382015-05-04 14:30:09 +0200796 goto err_close_memfd;
Paul Cercueil09a43482015-03-04 15:50:27 +0100797
798 pdata->wait_for_err_code = true;
799 network_unlock_dev(pdata);
800 }
801
802 if (pdata->memfd >= 0)
803 close(pdata->memfd);
804
Paul Cercueilca9d3382015-05-04 14:30:09 +0200805 pdata->memfd = memfd;
Paul Cercueil09a43482015-03-04 15:50:27 +0100806
Paul Cercueilef32d582015-03-05 11:18:35 +0100807 ret = (ssize_t) ftruncate(pdata->memfd, pdata->mmap_len);
808 if (ret < 0) {
809 ret = -errno;
810 ERROR("Unable to truncate temp file: %zi\n", -ret);
811 return ret;
812 }
Paul Cercueil09a43482015-03-04 15:50:27 +0100813
Paul Cercueil04065c22015-03-05 14:08:16 +0100814 if (!pdata->is_tx) {
815 char buf[1024];
816 size_t len = pdata->mmap_len;
817
818 snprintf(buf, sizeof(buf), "READBUF %s %lu\r\n",
819 dev->id, (unsigned long) len);
820
821 network_lock_dev(pdata);
822 ret = write_rwbuf_command(dev, buf, false);
823 if (ret < 0)
824 goto err_unlock;
825
826 do {
827 ret = network_read_mask(pdata->fd, mask, words);
828 if (!ret)
829 break;
830 if (ret < 0)
831 goto err_unlock;
832
833 mask = NULL; /* We read the mask only once */
834
835 ret = network_do_splice(pdata->memfd, pdata->fd, ret);
836 if (ret < 0)
837 goto err_unlock;
838
839 read += ret;
840 len -= ret;
841 } while (len);
842
843 network_unlock_dev(pdata);
844 }
Paul Cercueil09a43482015-03-04 15:50:27 +0100845
Paul Cercueile6e5a092015-03-04 16:33:26 +0100846 pdata->mmap_addr = mmap(NULL, pdata->mmap_len,
Paul Cercueil09a43482015-03-04 15:50:27 +0100847 PROT_READ | PROT_WRITE, MAP_SHARED, pdata->memfd, 0);
Paul Cercueile6e5a092015-03-04 16:33:26 +0100848 if (pdata->mmap_addr == MAP_FAILED) {
849 pdata->mmap_addr = NULL;
Paul Cercueil09a43482015-03-04 15:50:27 +0100850 ret = -errno;
Paul Cercueil7d7e5d32015-03-05 10:51:41 +0100851 ERROR("Unable to mmap: %zi\n", -ret);
Paul Cercueil09a43482015-03-04 15:50:27 +0100852 return ret;
853 }
854
Paul Cercueile6e5a092015-03-04 16:33:26 +0100855 *addr_ptr = pdata->mmap_addr;
Paul Cercueil04065c22015-03-05 14:08:16 +0100856 return read ? read : bytes_used;
Paul Cercueil09a43482015-03-04 15:50:27 +0100857
Paul Cercueilca9d3382015-05-04 14:30:09 +0200858err_close_memfd:
859 close(memfd);
Paul Cercueil09a43482015-03-04 15:50:27 +0100860err_unlock:
861 network_unlock_dev(pdata);
862 return ret;
863}
864#endif
865
Paul Cercueil1494b862014-05-05 12:49:07 +0200866static ssize_t network_read_attr_helper(const struct iio_device *dev,
Paul Cercueil0cc0e162014-05-07 12:51:22 +0200867 const struct iio_channel *chn, const char *attr, char *dst,
Paul Cercueil1494b862014-05-05 12:49:07 +0200868 size_t len, bool is_debug)
Paul Cercueil3e94a5b2014-03-04 13:00:41 +0100869{
Paul Cercueil3e94a5b2014-03-04 13:00:41 +0100870 long read_len;
871 ssize_t ret;
872 char buf[1024];
Paul Cercueil05e26262014-05-09 11:32:43 +0200873 struct iio_context_pdata *pdata = dev->ctx->pdata;
874 int fd = pdata->fd;
Paul Cercueil1494b862014-05-05 12:49:07 +0200875 const char *id = dev->id;
Paul Cercueil3e94a5b2014-03-04 13:00:41 +0100876
Paul Cercueil99cf3d42014-03-06 12:35:26 +0100877 if (chn)
Paul Cercueil0cc0e162014-05-07 12:51:22 +0200878 snprintf(buf, sizeof(buf), "READ %s %s %s %s\r\n", id,
879 chn->is_output ? "OUTPUT" : "INPUT",
Paul Cercueil2a3e43d2014-05-21 16:58:45 +0200880 chn->id, attr ? attr : "");
Paul Cercueilc6f03612014-04-14 16:41:31 +0200881 else if (is_debug)
Paul Cercueil2a3e43d2014-05-21 16:58:45 +0200882 snprintf(buf, sizeof(buf), "READ %s DEBUG %s\r\n",
883 id, attr ? attr : "");
Paul Cercueil99cf3d42014-03-06 12:35:26 +0100884 else
Paul Cercueil2a3e43d2014-05-21 16:58:45 +0200885 snprintf(buf, sizeof(buf), "READ %s %s\r\n",
886 id, attr ? attr : "");
Paul Cercueil1494b862014-05-05 12:49:07 +0200887
Paul Cercueil05e26262014-05-09 11:32:43 +0200888 network_lock(pdata);
Paul Cercueilbb76bf92014-03-11 10:20:18 +0100889 read_len = exec_command(buf, fd);
Paul Cercueil1494b862014-05-05 12:49:07 +0200890 if (read_len < 0) {
Paul Cercueil05e26262014-05-09 11:32:43 +0200891 network_unlock(pdata);
Paul Cercueilbb76bf92014-03-11 10:20:18 +0100892 return (ssize_t) read_len;
Paul Cercueil1494b862014-05-05 12:49:07 +0200893 }
Paul Cercueil3e94a5b2014-03-04 13:00:41 +0100894
Paul Cercueil6e7f79e2014-04-04 12:27:24 +0200895 if ((unsigned long) read_len > len) {
Paul Cercueil3e94a5b2014-03-04 13:00:41 +0100896 ERROR("Value returned by server is too large\n");
Paul Cercueil05e26262014-05-09 11:32:43 +0200897 network_unlock(pdata);
Paul Cercueil3e94a5b2014-03-04 13:00:41 +0100898 return -EIO;
899 }
900
901 ret = read_all(dst, read_len, fd);
Paul Cercueil05e26262014-05-09 11:32:43 +0200902 network_unlock(pdata);
Paul Cercueil1494b862014-05-05 12:49:07 +0200903
Paul Cercueil3e94a5b2014-03-04 13:00:41 +0100904 if (ret < 0) {
Paul Cercueil53fc4852015-05-22 10:57:53 +0200905 iio_strerror(-ret, buf, sizeof(buf));
Paul Cercueil3e94a5b2014-03-04 13:00:41 +0100906 ERROR("Unable to read response to READ: %s\n", buf);
907 return ret;
908 }
909
Paul Cercueil7d95fd72014-05-22 14:26:44 +0200910 return read_len;
Paul Cercueil3e94a5b2014-03-04 13:00:41 +0100911}
912
Paul Cercueil1494b862014-05-05 12:49:07 +0200913static ssize_t network_write_attr_helper(const struct iio_device *dev,
Paul Cercueil0cc0e162014-05-07 12:51:22 +0200914 const struct iio_channel *chn, const char *attr,
915 const char *src, size_t len, bool is_debug)
Paul Cercueil3e94a5b2014-03-04 13:00:41 +0100916{
Paul Cercueila62f84e2015-02-24 14:16:08 +0100917 struct iio_context_pdata *pdata = dev->ctx->pdata;
918 int fd;
919 ssize_t ret;
920 long resp;
Paul Cercueil3e94a5b2014-03-04 13:00:41 +0100921 char buf[1024];
Paul Cercueil1494b862014-05-05 12:49:07 +0200922 const char *id = dev->id;
Paul Cercueil3e94a5b2014-03-04 13:00:41 +0100923
Paul Cercueil07897d32014-03-06 12:46:08 +0100924 if (chn)
Paul Cercueil0cc0e162014-05-07 12:51:22 +0200925 snprintf(buf, sizeof(buf), "WRITE %s %s %s %s %lu\r\n",
926 id, chn->is_output ? "OUTPUT" : "INPUT",
Paul Cercueil8747efe2014-05-22 11:12:12 +0200927 chn->id, attr ? attr : "", (unsigned long) len);
Paul Cercueilc6f03612014-04-14 16:41:31 +0200928 else if (is_debug)
Paul Cercueil8747efe2014-05-22 11:12:12 +0200929 snprintf(buf, sizeof(buf), "WRITE %s DEBUG %s %lu\r\n",
930 id, attr ? attr : "", (unsigned long) len);
Paul Cercueil07897d32014-03-06 12:46:08 +0100931 else
Paul Cercueilcecda352014-05-06 18:14:29 +0200932 snprintf(buf, sizeof(buf), "WRITE %s %s %lu\r\n",
Paul Cercueil8747efe2014-05-22 11:12:12 +0200933 id, attr ? attr : "", (unsigned long) len);
Paul Cercueila62f84e2015-02-24 14:16:08 +0100934
935 network_lock(pdata);
936 fd = pdata->fd;
937 ret = (ssize_t) write_command(buf, fd);
938 if (ret < 0)
939 goto err_unlock;
940
941 ret = write_all(src, len, fd);
942 if (ret < 0)
943 goto err_unlock;
944
945 ret = read_integer(fd, &resp);
946 network_unlock(pdata);
947
948 if (ret < 0)
949 return ret;
950 return (ssize_t) resp;
951
952err_unlock:
953 network_unlock(pdata);
954 return ret;
Paul Cercueil3e94a5b2014-03-04 13:00:41 +0100955}
956
Paul Cercueil99cf3d42014-03-06 12:35:26 +0100957static ssize_t network_read_dev_attr(const struct iio_device *dev,
Paul Cercueil50c762a2014-04-14 15:55:43 +0200958 const char *attr, char *dst, size_t len, bool is_debug)
Paul Cercueil99cf3d42014-03-06 12:35:26 +0100959{
Paul Cercueil5b577762014-06-03 15:31:42 +0200960 if (attr && ((is_debug && !iio_device_find_debug_attr(dev, attr)) ||
961 (!is_debug && !iio_device_find_attr(dev, attr))))
962 return -ENOENT;
963
Paul Cercueil1494b862014-05-05 12:49:07 +0200964 return network_read_attr_helper(dev, NULL, attr, dst, len, is_debug);
Paul Cercueil99cf3d42014-03-06 12:35:26 +0100965}
966
Paul Cercueil07897d32014-03-06 12:46:08 +0100967static ssize_t network_write_dev_attr(const struct iio_device *dev,
Paul Cercueilcecda352014-05-06 18:14:29 +0200968 const char *attr, const char *src, size_t len, bool is_debug)
Paul Cercueil07897d32014-03-06 12:46:08 +0100969{
Paul Cercueil5b577762014-06-03 15:31:42 +0200970 if (attr && ((is_debug && !iio_device_find_debug_attr(dev, attr)) ||
971 (!is_debug && !iio_device_find_attr(dev, attr))))
972 return -ENOENT;
973
Paul Cercueilcecda352014-05-06 18:14:29 +0200974 return network_write_attr_helper(dev, NULL, attr, src, len, is_debug);
Paul Cercueil07897d32014-03-06 12:46:08 +0100975}
976
Paul Cercueil99cf3d42014-03-06 12:35:26 +0100977static ssize_t network_read_chn_attr(const struct iio_channel *chn,
978 const char *attr, char *dst, size_t len)
979{
Paul Cercueil5b577762014-06-03 15:31:42 +0200980 if (attr && !iio_channel_find_attr(chn, attr))
981 return -ENOENT;
982
Paul Cercueil0cc0e162014-05-07 12:51:22 +0200983 return network_read_attr_helper(chn->dev, chn, attr, dst, len, false);
Paul Cercueil99cf3d42014-03-06 12:35:26 +0100984}
985
Paul Cercueil07897d32014-03-06 12:46:08 +0100986static ssize_t network_write_chn_attr(const struct iio_channel *chn,
Paul Cercueilcecda352014-05-06 18:14:29 +0200987 const char *attr, const char *src, size_t len)
Paul Cercueil07897d32014-03-06 12:46:08 +0100988{
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_write_attr_helper(chn->dev, chn, attr, src, len, false);
Paul Cercueil07897d32014-03-06 12:46:08 +0100993}
994
Paul Cercueildcab40c2014-03-11 10:59:14 +0100995static int network_get_trigger(const struct iio_device *dev,
996 const struct iio_device **trigger)
997{
998 struct iio_context_pdata *pdata = dev->ctx->pdata;
999 unsigned int i;
1000 char buf[1024];
1001 ssize_t ret;
1002 long resp;
1003
1004 snprintf(buf, sizeof(buf), "GETTRIG %s\r\n", dev->id);
Paul Cercueil1494b862014-05-05 12:49:07 +02001005
Paul Cercueil05e26262014-05-09 11:32:43 +02001006 network_lock(dev->ctx->pdata);
Paul Cercueildcab40c2014-03-11 10:59:14 +01001007 resp = exec_command(buf, pdata->fd);
1008 if (resp < 0) {
Paul Cercueil05e26262014-05-09 11:32:43 +02001009 network_unlock(pdata);
Paul Cercueildcab40c2014-03-11 10:59:14 +01001010 return (int) resp;
1011 } else if (resp == 0) {
1012 *trigger = NULL;
Paul Cercueil05e26262014-05-09 11:32:43 +02001013 network_unlock(pdata);
Paul Cercueildcab40c2014-03-11 10:59:14 +01001014 return 0;
Paul Cercueil6e7f79e2014-04-04 12:27:24 +02001015 } else if ((unsigned long) resp > sizeof(buf)) {
Paul Cercueildcab40c2014-03-11 10:59:14 +01001016 ERROR("Value returned by server is too large\n");
Paul Cercueil05e26262014-05-09 11:32:43 +02001017 network_unlock(pdata);
Paul Cercueildcab40c2014-03-11 10:59:14 +01001018 return -EIO;
1019 }
1020
1021 ret = read_all(buf, resp, pdata->fd);
Paul Cercueil05e26262014-05-09 11:32:43 +02001022 network_unlock(pdata);
Paul Cercueil1494b862014-05-05 12:49:07 +02001023
Paul Cercueildcab40c2014-03-11 10:59:14 +01001024 if (ret < 0) {
Paul Cercueil53fc4852015-05-22 10:57:53 +02001025 iio_strerror(-ret, buf, sizeof(buf));
Paul Cercueildcab40c2014-03-11 10:59:14 +01001026 ERROR("Unable to read response to GETTRIG: %s\n", buf);
1027 return ret;
1028 }
1029
Lars-Peter Clausenb5cdc102014-08-21 14:45:52 +02001030 if (buf[0] == '\0') {
1031 *trigger = NULL;
1032 return 0;
1033 }
1034
Paul Cercueildcab40c2014-03-11 10:59:14 +01001035 for (i = 0; i < dev->ctx->nb_devices; i++) {
1036 struct iio_device *cur = dev->ctx->devices[i];
1037 if (iio_device_is_trigger(cur) &&
1038 !strncmp(cur->name, buf, resp)) {
1039 *trigger = cur;
1040 return 0;
1041 }
1042 }
1043
1044 return -ENXIO;
1045}
1046
1047static int network_set_trigger(const struct iio_device *dev,
1048 const struct iio_device *trigger)
1049{
Paul Cercueil1494b862014-05-05 12:49:07 +02001050 int ret;
Paul Cercueildcab40c2014-03-11 10:59:14 +01001051 char buf[1024];
1052 if (trigger)
1053 snprintf(buf, sizeof(buf), "SETTRIG %s %s\r\n",
1054 dev->id, trigger->id);
1055 else
1056 snprintf(buf, sizeof(buf), "SETTRIG %s\r\n", dev->id);
Paul Cercueil1494b862014-05-05 12:49:07 +02001057
Paul Cercueil05e26262014-05-09 11:32:43 +02001058 network_lock(dev->ctx->pdata);
Paul Cercueil1494b862014-05-05 12:49:07 +02001059 ret = (int) exec_command(buf, dev->ctx->pdata->fd);
Paul Cercueil05e26262014-05-09 11:32:43 +02001060 network_unlock(dev->ctx->pdata);
Paul Cercueil1494b862014-05-05 12:49:07 +02001061 return ret;
Paul Cercueildcab40c2014-03-11 10:59:14 +01001062}
1063
Paul Cercueil8fd9c8f2014-03-03 17:21:31 +01001064static void network_shutdown(struct iio_context *ctx)
1065{
1066 struct iio_context_pdata *pdata = ctx->pdata;
Paul Cercueil44ae11c2014-03-17 09:56:29 +01001067 unsigned int i;
Paul Cercueil8fd9c8f2014-03-03 17:21:31 +01001068
Paul Cercueil05e26262014-05-09 11:32:43 +02001069 network_lock(pdata);
Paul Cercueilbb76bf92014-03-11 10:20:18 +01001070 write_command("\r\nEXIT\r\n", pdata->fd);
Paul Cercueil8fd9c8f2014-03-03 17:21:31 +01001071 close(pdata->fd);
Paul Cercueil05e26262014-05-09 11:32:43 +02001072 network_unlock(pdata);
Paul Cercueil1494b862014-05-05 12:49:07 +02001073
Paul Cercueil439e1a22015-02-24 13:50:51 +01001074 for (i = 0; i < ctx->nb_devices; i++) {
1075 struct iio_device *dev = ctx->devices[i];
Paul Cercueilc5b00752015-02-24 14:29:53 +01001076 struct iio_device_pdata *dpdata = dev->pdata;
Paul Cercueil439e1a22015-02-24 13:50:51 +01001077
Paul Cercueilc5b00752015-02-24 14:29:53 +01001078 if (dpdata) {
Paul Cercueilaa0db142015-03-04 16:25:24 +01001079 network_close(dev);
Paul Cercueilc5b00752015-02-24 14:29:53 +01001080#if HAVE_PTHREAD
Paul Cercueilaa0db142015-03-04 16:25:24 +01001081 pthread_mutex_destroy(&dpdata->lock);
Paul Cercueilc5b00752015-02-24 14:29:53 +01001082#endif
Paul Cercueilc5b00752015-02-24 14:29:53 +01001083 free(dpdata);
Paul Cercueil439e1a22015-02-24 13:50:51 +01001084 }
1085 }
1086
Paul Cercueil05e26262014-05-09 11:32:43 +02001087#if HAVE_PTHREAD
Paul Cercueil1494b862014-05-05 12:49:07 +02001088 pthread_mutex_destroy(&pdata->lock);
Paul Cercueil05e26262014-05-09 11:32:43 +02001089#endif
Paul Cercueil2dd2c132015-02-24 10:41:01 +01001090 freeaddrinfo(pdata->addrinfo);
Paul Cercueil8fd9c8f2014-03-03 17:21:31 +01001091 free(pdata);
1092}
1093
Paul Cercueil6691a3f2014-05-02 12:32:01 +02001094static int network_get_version(const struct iio_context *ctx,
Paul Cercueil9de9e9d2014-05-20 13:18:19 +02001095 unsigned int *major, unsigned int *minor, char git_tag[8])
Paul Cercueil6691a3f2014-05-02 12:32:01 +02001096{
1097 struct iio_context_pdata *pdata = ctx->pdata;
1098 long maj, min;
1099 int ret;
Paul Cercueil6691a3f2014-05-02 12:32:01 +02001100
Paul Cercueil05e26262014-05-09 11:32:43 +02001101 network_lock(pdata);
Paul Cercueil1494b862014-05-05 12:49:07 +02001102 ret = (int) write_command("VERSION\r\n", pdata->fd);
1103 if (ret < 0)
1104 goto err_unlock;
1105
1106 ret = read_integer(pdata->fd, &maj);
1107 if (!ret)
1108 ret = read_integer(pdata->fd, &min);
1109 if (!ret) {
Paul Cercueil9de9e9d2014-05-20 13:18:19 +02001110 char tag[8];
1111 tag[7] = '\0';
1112
1113 ret = read_all(tag, sizeof(tag) - 1, pdata->fd);
1114 if (ret < 0)
1115 goto err_unlock;
1116
Paul Cercueild15d9952014-05-20 11:40:08 +02001117 if (major)
1118 *major = (unsigned int) maj;
1119 if (minor)
1120 *minor = (unsigned int) min;
Paul Cercueil9de9e9d2014-05-20 13:18:19 +02001121 if (git_tag)
1122 strncpy(git_tag, tag, 8);
Paul Cercueil1494b862014-05-05 12:49:07 +02001123 }
1124
Paul Cercueil8e8f8992014-06-12 16:58:12 +02001125 ret = 0;
Paul Cercueil1494b862014-05-05 12:49:07 +02001126err_unlock:
Paul Cercueil05e26262014-05-09 11:32:43 +02001127 network_unlock(pdata);
Paul Cercueil1494b862014-05-05 12:49:07 +02001128 return ret;
Paul Cercueil6691a3f2014-05-02 12:32:01 +02001129}
1130
Paul Cercueil8a266f12014-06-10 16:06:31 +02001131static unsigned int calculate_remote_timeout(unsigned int timeout)
1132{
1133 /* XXX(pcercuei): We currently hardcode timeout / 2 for the backend used
1134 * by the remote. Is there something better to do here? */
1135 return timeout / 2;
1136}
1137
Paul Cercueilbca3dbc2014-06-11 12:00:21 +02001138static int set_remote_timeout(struct iio_context *ctx, unsigned int timeout)
1139{
1140 char buf[1024];
1141 int ret;
1142
1143 snprintf(buf, sizeof(buf), "TIMEOUT %u\r\n", timeout);
1144 network_lock(ctx->pdata);
1145 ret = (int) exec_command(buf, ctx->pdata->fd);
1146 network_unlock(ctx->pdata);
1147 return ret;
1148}
1149
1150static int network_set_timeout(struct iio_context *ctx, unsigned int timeout)
1151{
1152 int ret = set_socket_timeout(ctx->pdata->fd, timeout);
1153 if (!ret) {
1154 timeout = calculate_remote_timeout(timeout);
1155 ret = set_remote_timeout(ctx, timeout);
1156 }
1157 if (ret < 0) {
1158 char buf[1024];
Paul Cercueil53fc4852015-05-22 10:57:53 +02001159 iio_strerror(-ret, buf, sizeof(buf));
Paul Cercueil8a266f12014-06-10 16:06:31 +02001160 WARNING("Unable to set R/W timeout: %s\n", buf);
1161 } else {
Paul Cercueil8a266f12014-06-10 16:06:31 +02001162 ctx->rw_timeout_ms = timeout;
1163 }
1164 return ret;
1165}
1166
Paul Cercueil61157f92015-11-19 17:48:22 +01001167static int network_set_kernel_buffers_count(const struct iio_device *dev,
1168 unsigned int nb_blocks)
1169{
1170 int ret;
1171 char buf[1024];
1172
1173 snprintf(buf, sizeof(buf), "SET %s BUFFERS_COUNT %u\r\n",
1174 dev->id, nb_blocks);
1175
1176 network_lock(dev->ctx->pdata);
1177 ret = (int) exec_command(buf, dev->ctx->pdata->fd);
1178 network_unlock(dev->ctx->pdata);
1179 return ret;
1180}
1181
Paul Cercueil12d41832014-10-28 14:35:53 +01001182static struct iio_context * network_clone(const struct iio_context *ctx)
1183{
Paul Cercueil7ef45ce2015-03-16 14:36:16 +01001184 if (ctx->description) {
1185 char *ptr = strchr(ctx->description, ' ');
1186 if (ptr) {
1187#ifdef HAVE_IPV6
1188 char buf[INET6_ADDRSTRLEN + IF_NAMESIZE + 2];
1189#else
1190 char buf[INET_ADDRSTRLEN + 1];
1191#endif
1192 strncpy(buf, ctx->description, sizeof(buf) - 1);
1193 buf[ptr - ctx->description] = '\0';
1194 return iio_create_network_context(buf);
1195 }
1196 }
1197
Paul Cercueild3d56ee2015-01-08 16:36:31 +01001198 return iio_create_network_context(ctx->description);
Paul Cercueil12d41832014-10-28 14:35:53 +01001199}
1200
Paul Cercueilc7bad0f2014-03-03 17:06:48 +01001201static struct iio_backend_ops network_ops = {
Paul Cercueil12d41832014-10-28 14:35:53 +01001202 .clone = network_clone,
Paul Cercueilba059762014-03-14 11:02:02 +01001203 .open = network_open,
1204 .close = network_close,
Paul Cercueil9945bc82014-03-05 14:07:29 +01001205 .read = network_read,
Paul Cercueil2725f702014-05-02 11:02:16 +02001206 .write = network_write,
Paul Cercueil90189672015-03-16 11:41:53 +01001207#ifdef WITH_NETWORK_GET_BUFFER
Paul Cercueil09a43482015-03-04 15:50:27 +01001208 .get_buffer = network_get_buffer,
1209#endif
Paul Cercueil3e94a5b2014-03-04 13:00:41 +01001210 .read_device_attr = network_read_dev_attr,
1211 .write_device_attr = network_write_dev_attr,
Paul Cercueil99cf3d42014-03-06 12:35:26 +01001212 .read_channel_attr = network_read_chn_attr,
Paul Cercueil07897d32014-03-06 12:46:08 +01001213 .write_channel_attr = network_write_chn_attr,
Paul Cercueildcab40c2014-03-11 10:59:14 +01001214 .get_trigger = network_get_trigger,
1215 .set_trigger = network_set_trigger,
Paul Cercueil8fd9c8f2014-03-03 17:21:31 +01001216 .shutdown = network_shutdown,
Paul Cercueil6691a3f2014-05-02 12:32:01 +02001217 .get_version = network_get_version,
Paul Cercueil8a266f12014-06-10 16:06:31 +02001218 .set_timeout = network_set_timeout,
Paul Cercueil61157f92015-11-19 17:48:22 +01001219 .set_kernel_buffers_count = network_set_kernel_buffers_count,
Paul Cercueilc7bad0f2014-03-03 17:06:48 +01001220};
1221
1222static struct iio_context * get_context(int fd)
1223{
1224 struct iio_context *ctx;
Paul Cercueile60c3ed2014-03-04 11:23:56 +01001225 char *xml;
Paul Cercueilbb76bf92014-03-11 10:20:18 +01001226 long xml_len = exec_command("PRINT\r\n", fd);
Paul Cercueilcc575532015-03-16 17:15:24 +01001227 if (xml_len < 0) {
1228 errno = (int) -xml_len;
Paul Cercueilc7bad0f2014-03-03 17:06:48 +01001229 return NULL;
Paul Cercueilcc575532015-03-16 17:15:24 +01001230 }
Paul Cercueile60c3ed2014-03-04 11:23:56 +01001231
1232 DEBUG("Server returned a XML string of length %li\n", xml_len);
Paul Cercueilc7bad0f2014-03-03 17:06:48 +01001233 xml = malloc(xml_len);
1234 if (!xml) {
Paul Cercueilcc575532015-03-16 17:15:24 +01001235 errno = ENOMEM;
Paul Cercueilc7bad0f2014-03-03 17:06:48 +01001236 return NULL;
1237 }
1238
1239 DEBUG("Reading XML string...\n");
1240 read_all(xml, xml_len, fd);
1241
1242 DEBUG("Creating context from XML...\n");
1243 ctx = iio_create_xml_context_mem(xml, xml_len);
Paul Cercueilfd387472015-08-05 10:34:19 +02001244 free(xml);
Paul Cercueilc7bad0f2014-03-03 17:06:48 +01001245 return ctx;
1246}
1247
Paul Cercueil63e52182014-12-11 12:52:48 +01001248struct iio_context * network_create_context(const char *host)
Paul Cercueilc7bad0f2014-03-03 17:06:48 +01001249{
Paul Cercueil2e38bbe2014-03-19 15:27:15 +01001250 struct addrinfo hints, *res;
Paul Cercueilc7bad0f2014-03-03 17:06:48 +01001251 struct iio_context *ctx;
Paul Cercueil8fd9c8f2014-03-03 17:21:31 +01001252 struct iio_context_pdata *pdata;
Paul Cercueil0e3c04d2015-05-13 17:37:11 +02001253 size_t i, len;
Paul Cercueil4970ac32015-02-24 10:59:00 +01001254 int fd, ret;
Paul Cercueilb03c9ef2015-03-16 14:07:58 +01001255 char *description;
Paul Cercueil1fef1a52014-04-07 16:31:15 +02001256#ifdef _WIN32
1257 WSADATA wsaData;
1258
1259 ret = WSAStartup(MAKEWORD(2, 0), &wsaData);
1260 if (ret < 0) {
1261 ERROR("WSAStartup failed with error %i\n", ret);
Paul Cercueilcc575532015-03-16 17:15:24 +01001262 errno = -ret;
Paul Cercueil1fef1a52014-04-07 16:31:15 +02001263 return NULL;
1264 }
1265#endif
Paul Cercueilc7bad0f2014-03-03 17:06:48 +01001266
Paul Cercueil2e38bbe2014-03-19 15:27:15 +01001267 memset(&hints, 0, sizeof(hints));
1268 hints.ai_family = AF_UNSPEC;
1269 hints.ai_socktype = SOCK_STREAM;
Paul Cercueilab114932014-05-19 13:03:17 +02001270
1271#ifdef HAVE_AVAHI
1272 if (!host) {
1273 char addr_str[AVAHI_ADDRESS_STR_MAX];
1274 char port_str[6];
1275 AvahiAddress address;
Paul Cercueil0f729d32014-06-05 17:38:54 +02001276 uint16_t port = IIOD_PORT;
Paul Cercueilab114932014-05-19 13:03:17 +02001277
1278 memset(&address, 0, sizeof(address));
1279
1280 ret = discover_host(&address, &port);
1281 if (ret < 0) {
Paul Cercueilcc575532015-03-16 17:15:24 +01001282 DEBUG("Unable to find host: %s\n", strerror(-ret));
1283 errno = -ret;
Paul Cercueilab114932014-05-19 13:03:17 +02001284 return NULL;
1285 }
1286
1287 avahi_address_snprint(addr_str, sizeof(addr_str), &address);
1288 snprintf(port_str, sizeof(port_str), "%hu", port);
1289 ret = getaddrinfo(addr_str, port_str, &hints, &res);
1290 } else
1291#endif
1292 {
1293 ret = getaddrinfo(host, IIOD_PORT_STR, &hints, &res);
1294 }
1295
Paul Cercueil2e38bbe2014-03-19 15:27:15 +01001296 if (ret) {
Paul Cercueilab114932014-05-19 13:03:17 +02001297 ERROR("Unable to find host: %s\n", gai_strerror(ret));
Paul Cercueild9eb4cb2015-03-23 14:30:20 +01001298#ifndef _WIN32
Paul Cercueilcc575532015-03-16 17:15:24 +01001299 if (ret != EAI_SYSTEM)
1300 errno = ret;
Paul Cercueild9eb4cb2015-03-23 14:30:20 +01001301#endif
Paul Cercueilc7bad0f2014-03-03 17:06:48 +01001302 return NULL;
Paul Cercueilc7bad0f2014-03-03 17:06:48 +01001303 }
1304
Paul Cercueil4970ac32015-02-24 10:59:00 +01001305 fd = create_socket(res);
Paul Cercueilcc575532015-03-16 17:15:24 +01001306 if (fd < 0) {
1307 errno = fd;
Paul Cercueil2dd2c132015-02-24 10:41:01 +01001308 goto err_free_addrinfo;
Paul Cercueilcc575532015-03-16 17:15:24 +01001309 }
Paul Cercueilbca3dbc2014-06-11 12:00:21 +02001310
Paul Cercueil8fd9c8f2014-03-03 17:21:31 +01001311 pdata = calloc(1, sizeof(*pdata));
1312 if (!pdata) {
Paul Cercueilcc575532015-03-16 17:15:24 +01001313 errno = ENOMEM;
Paul Cercueil8fd9c8f2014-03-03 17:21:31 +01001314 goto err_close_socket;
1315 }
1316
1317 pdata->fd = fd;
Paul Cercueil2dd2c132015-02-24 10:41:01 +01001318 pdata->addrinfo = res;
Paul Cercueil8fd9c8f2014-03-03 17:21:31 +01001319
Paul Cercueilc7bad0f2014-03-03 17:06:48 +01001320 DEBUG("Creating context...\n");
1321 ctx = get_context(fd);
1322 if (!ctx)
Paul Cercueild3d56ee2015-01-08 16:36:31 +01001323 goto err_free_pdata;
Paul Cercueilc7bad0f2014-03-03 17:06:48 +01001324
Paul Cercueil2057fd32014-10-28 14:44:19 +01001325 /* Override the name and low-level functions of the XML context
1326 * with those corresponding to the network context */
1327 ctx->name = "network";
1328 ctx->ops = &network_ops;
1329 ctx->pdata = pdata;
1330
Paul Cercueil06c479d2015-01-08 16:14:57 +01001331#ifdef HAVE_IPV6
Paul Cercueiled15e492015-01-12 15:52:28 +01001332 len = INET6_ADDRSTRLEN + IF_NAMESIZE + 2;
Paul Cercueil06c479d2015-01-08 16:14:57 +01001333#else
1334 len = INET_ADDRSTRLEN + 1;
1335#endif
Paul Cercueilb03c9ef2015-03-16 14:07:58 +01001336
1337 description = malloc(len);
1338 if (!description) {
Paul Cercueilcc575532015-03-16 17:15:24 +01001339 ret = -ENOMEM;
Paul Cercueil06c479d2015-01-08 16:14:57 +01001340 goto err_network_shutdown;
1341 }
1342
Paul Cercueilb03c9ef2015-03-16 14:07:58 +01001343 description[0] = '\0';
Paul Cercueil06c479d2015-01-08 16:14:57 +01001344
1345#ifdef HAVE_IPV6
1346 if (res->ai_family == AF_INET6) {
1347 struct sockaddr_in6 *in = (struct sockaddr_in6 *) res->ai_addr;
Paul Cercueiled15e492015-01-12 15:52:28 +01001348 char *ptr;
Paul Cercueil06c479d2015-01-08 16:14:57 +01001349 inet_ntop(AF_INET6, &in->sin6_addr,
Paul Cercueilb03c9ef2015-03-16 14:07:58 +01001350 description, INET6_ADDRSTRLEN);
Paul Cercueiled15e492015-01-12 15:52:28 +01001351
Paul Cercueilb03c9ef2015-03-16 14:07:58 +01001352 ptr = if_indextoname(in->sin6_scope_id, description +
1353 strlen(description) + 1);
Paul Cercueiled15e492015-01-12 15:52:28 +01001354 if (!ptr) {
Paul Cercueilcc575532015-03-16 17:15:24 +01001355 ret = -errno;
Paul Cercueiled15e492015-01-12 15:52:28 +01001356 ERROR("Unable to lookup interface of IPv6 address\n");
Paul Cercueilb03c9ef2015-03-16 14:07:58 +01001357 goto err_free_description;
Paul Cercueiled15e492015-01-12 15:52:28 +01001358 }
1359
1360 *(ptr - 1) = '%';
Paul Cercueil06c479d2015-01-08 16:14:57 +01001361 }
1362#endif
1363 if (res->ai_family == AF_INET) {
1364 struct sockaddr_in *in = (struct sockaddr_in *) res->ai_addr;
Paul Cercueile7a31692015-07-15 10:52:47 +02001365#if (!_WIN32 || _WIN32_WINNT >= 0x600)
Paul Cercueilb03c9ef2015-03-16 14:07:58 +01001366 inet_ntop(AF_INET, &in->sin_addr, description, INET_ADDRSTRLEN);
Paul Cercueile7a31692015-07-15 10:52:47 +02001367#else
1368 char *tmp = inet_ntoa(in->sin_addr);
1369 strncpy(description, tmp, len);
1370#endif
Paul Cercueil06c479d2015-01-08 16:14:57 +01001371 }
1372
Paul Cercueil44ae11c2014-03-17 09:56:29 +01001373 for (i = 0; i < ctx->nb_devices; i++) {
1374 struct iio_device *dev = ctx->devices[i];
Paul Cercueilff778232014-03-24 14:23:08 +01001375
Paul Cercueil439e1a22015-02-24 13:50:51 +01001376 dev->pdata = calloc(1, sizeof(*dev->pdata));
1377 if (!dev->pdata) {
Paul Cercueilcc575532015-03-16 17:15:24 +01001378 ret = -ENOMEM;
Paul Cercueilb03c9ef2015-03-16 14:07:58 +01001379 goto err_free_description;
Paul Cercueil439e1a22015-02-24 13:50:51 +01001380 }
1381
1382 dev->pdata->fd = -1;
Paul Cercueil90189672015-03-16 11:41:53 +01001383#ifdef WITH_NETWORK_GET_BUFFER
Paul Cercueil09a43482015-03-04 15:50:27 +01001384 dev->pdata->memfd = -1;
Paul Cercueile6e5a092015-03-04 16:33:26 +01001385#endif
Paul Cercueilc5b00752015-02-24 14:29:53 +01001386
1387#if HAVE_PTHREAD
1388 ret = pthread_mutex_init(&dev->pdata->lock, NULL);
Paul Cercueilcc575532015-03-16 17:15:24 +01001389 if (ret < 0)
Paul Cercueilb03c9ef2015-03-16 14:07:58 +01001390 goto err_free_description;
Paul Cercueilc5b00752015-02-24 14:29:53 +01001391#endif
Paul Cercueil44ae11c2014-03-17 09:56:29 +01001392 }
1393
Paul Cercueilfd387472015-08-05 10:34:19 +02001394 ret = iio_context_init(ctx);
1395 if (ret < 0)
1396 goto err_free_description;
Paul Cercueil4c6729d2014-04-04 17:24:41 +02001397
Paul Cercueil05e26262014-05-09 11:32:43 +02001398#if HAVE_PTHREAD
Paul Cercueil1494b862014-05-05 12:49:07 +02001399 ret = pthread_mutex_init(&pdata->lock, NULL);
Paul Cercueilcc575532015-03-16 17:15:24 +01001400 if (ret < 0)
Paul Cercueilb03c9ef2015-03-16 14:07:58 +01001401 goto err_free_description;
Paul Cercueil05e26262014-05-09 11:32:43 +02001402#endif
Paul Cercueil1494b862014-05-05 12:49:07 +02001403
Paul Cercueilb03c9ef2015-03-16 14:07:58 +01001404 if (ctx->description) {
Paul Cercueil0e3c04d2015-05-13 17:37:11 +02001405 size_t desc_len = strlen(description);
1406 size_t new_size = desc_len + strlen(ctx->description) + 2;
Paul Cercueilb03c9ef2015-03-16 14:07:58 +01001407 char *ptr, *new_description = realloc(description, new_size);
Paul Cercueilcc575532015-03-16 17:15:24 +01001408 if (!new_description) {
1409 ret = -ENOMEM;
Paul Cercueilb03c9ef2015-03-16 14:07:58 +01001410 goto err_free_description;
Paul Cercueilcc575532015-03-16 17:15:24 +01001411 }
Paul Cercueilb03c9ef2015-03-16 14:07:58 +01001412
1413 ptr = strrchr(new_description, '\0');
Paul Cercueil0e3c04d2015-05-13 17:37:11 +02001414 snprintf(ptr, new_size - desc_len, " %s", ctx->description);
Paul Cercueilb03c9ef2015-03-16 14:07:58 +01001415 free(ctx->description);
1416
1417 ctx->description = new_description;
1418 } else {
1419 ctx->description = description;
1420 }
1421
Paul Cercueilbca3dbc2014-06-11 12:00:21 +02001422 set_remote_timeout(ctx, calculate_remote_timeout(DEFAULT_TIMEOUT_MS));
Paul Cercueilc7bad0f2014-03-03 17:06:48 +01001423 return ctx;
1424
Paul Cercueilb03c9ef2015-03-16 14:07:58 +01001425err_free_description:
1426 free(description);
Paul Cercueil44ae11c2014-03-17 09:56:29 +01001427err_network_shutdown:
Paul Cercueil44ae11c2014-03-17 09:56:29 +01001428 iio_context_destroy(ctx);
Paul Cercueilcc575532015-03-16 17:15:24 +01001429 errno = -ret;
Paul Cercueil2057fd32014-10-28 14:44:19 +01001430 return NULL;
Paul Cercueil8fd9c8f2014-03-03 17:21:31 +01001431err_free_pdata:
1432 free(pdata);
Paul Cercueilc7bad0f2014-03-03 17:06:48 +01001433err_close_socket:
1434 close(fd);
Paul Cercueil2dd2c132015-02-24 10:41:01 +01001435err_free_addrinfo:
1436 freeaddrinfo(res);
Paul Cercueilc7bad0f2014-03-03 17:06:48 +01001437 return NULL;
1438}