blob: 423634f4886fe861648d8ef05743518441379415 [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"
Paul Cercueil388dcd62015-11-27 15:15:48 +010020#include "iio-lock.h"
Paul Cercueil9aabe892014-09-02 12:33:46 +020021
Paul Cercueilc7bad0f2014-03-03 17:06:48 +010022#include <errno.h>
Paul Cercueila7d445b2014-11-11 16:00:15 +010023#include <fcntl.h>
Paul Cercueile60c3ed2014-03-04 11:23:56 +010024#include <stdbool.h>
Paul Cercueilc7bad0f2014-03-03 17:06:48 +010025#include <string.h>
26#include <sys/types.h>
Paul Cercueilab114932014-05-19 13:03:17 +020027#include <time.h>
Paul Cercueil1fef1a52014-04-07 16:31:15 +020028
29#ifdef _WIN32
30#include <winsock2.h>
31#include <ws2tcpip.h>
32#define close(s) closesocket(s)
33
34/* winsock2.h defines ERROR, we don't want that */
35#undef ERROR
36
37#else /* _WIN32 */
Paul Cercueil06c479d2015-01-08 16:14:57 +010038#include <arpa/inet.h>
Paul Cercueil1fef1a52014-04-07 16:31:15 +020039#include <netdb.h>
Paul Cercueil0c3ce452015-02-05 16:37:42 +010040#include <netinet/in.h>
Paul Cercueil0b584e12015-01-28 11:47:03 +010041#include <netinet/tcp.h>
Paul Cercueiled15e492015-01-12 15:52:28 +010042#include <net/if.h>
Paul Cercueil09a43482015-03-04 15:50:27 +010043#include <sys/mman.h>
Paul Cercueil83628b32014-11-24 11:26:21 +010044#include <sys/select.h>
Paul Cercueilc7bad0f2014-03-03 17:06:48 +010045#include <sys/socket.h>
46#include <unistd.h>
Paul Cercueil1fef1a52014-04-07 16:31:15 +020047#endif /* _WIN32 */
48
Paul Cercueilab114932014-05-19 13:03:17 +020049#ifdef HAVE_AVAHI
50#include <avahi-client/client.h>
51#include <avahi-common/error.h>
52#include <avahi-client/lookup.h>
53#include <avahi-common/simple-watch.h>
54#endif
55
Paul Cercueil1fef1a52014-04-07 16:31:15 +020056#include "debug.h"
Paul Cercueilc7bad0f2014-03-03 17:06:48 +010057
Paul Cercueil8a266f12014-06-10 16:06:31 +020058#define DEFAULT_TIMEOUT_MS 5000
59
Paul Cercueil2e38bbe2014-03-19 15:27:15 +010060#define _STRINGIFY(x) #x
61#define STRINGIFY(x) _STRINGIFY(x)
62
Paul Cercueilc7bad0f2014-03-03 17:06:48 +010063#define IIOD_PORT 30431
Paul Cercueil2e38bbe2014-03-19 15:27:15 +010064#define IIOD_PORT_STR STRINGIFY(IIOD_PORT)
Paul Cercueilc7bad0f2014-03-03 17:06:48 +010065
Paul Cercueil8fd9c8f2014-03-03 17:21:31 +010066struct iio_context_pdata {
67 int fd;
Paul Cercueil2dd2c132015-02-24 10:41:01 +010068 struct addrinfo *addrinfo;
Paul Cercueil388dcd62015-11-27 15:15:48 +010069 struct iio_mutex *lock;
Paul Cercueil8fd9c8f2014-03-03 17:21:31 +010070};
71
Paul Cercueil439e1a22015-02-24 13:50:51 +010072struct iio_device_pdata {
73 int fd;
Paul Cercueil90189672015-03-16 11:41:53 +010074#ifdef WITH_NETWORK_GET_BUFFER
Paul Cercueil09a43482015-03-04 15:50:27 +010075 int memfd;
Paul Cercueile6e5a092015-03-04 16:33:26 +010076 void *mmap_addr;
Paul Cercueil09a43482015-03-04 15:50:27 +010077 size_t mmap_len;
Paul Cercueile6e5a092015-03-04 16:33:26 +010078#endif
Paul Cercueil09a43482015-03-04 15:50:27 +010079 bool wait_for_err_code, is_cyclic, is_tx;
Paul Cercueil388dcd62015-11-27 15:15:48 +010080 struct iio_mutex *lock;
Paul Cercueil439e1a22015-02-24 13:50:51 +010081};
82
Paul Cercueilab114932014-05-19 13:03:17 +020083#ifdef HAVE_AVAHI
84struct avahi_discovery_data {
85 AvahiSimplePoll *poll;
86 AvahiAddress *address;
87 uint16_t *port;
88 bool found, resolved;
89};
90
91static void __avahi_resolver_cb(AvahiServiceResolver *resolver,
92 __notused AvahiIfIndex iface, __notused AvahiProtocol proto,
93 __notused AvahiResolverEvent event, __notused const char *name,
94 __notused const char *type, __notused const char *domain,
95 __notused const char *host_name, const AvahiAddress *address,
96 uint16_t port, __notused AvahiStringList *txt,
97 __notused AvahiLookupResultFlags flags, void *d)
98{
99 struct avahi_discovery_data *ddata = (struct avahi_discovery_data *) d;
100
101 memcpy(ddata->address, address, sizeof(*address));
102 *ddata->port = port;
103 ddata->resolved = true;
104 avahi_service_resolver_free(resolver);
105}
106
107static void __avahi_browser_cb(AvahiServiceBrowser *browser,
108 AvahiIfIndex iface, AvahiProtocol proto,
109 AvahiBrowserEvent event, const char *name,
110 const char *type, const char *domain,
111 __notused AvahiLookupResultFlags flags, void *d)
112{
113 struct avahi_discovery_data *ddata = (struct avahi_discovery_data *) d;
114 struct AvahiClient *client = avahi_service_browser_get_client(browser);
115
116 switch (event) {
117 default:
118 case AVAHI_BROWSER_NEW:
119 ddata->found = !!avahi_service_resolver_new(client, iface,
120 proto, name, type, domain,
121 AVAHI_PROTO_UNSPEC, 0,
122 __avahi_resolver_cb, d);
123 break;
124 case AVAHI_BROWSER_ALL_FOR_NOW:
125 if (ddata->found) {
126 while (!ddata->resolved) {
127 struct timespec ts;
128 ts.tv_sec = 0;
129 ts.tv_nsec = 4000000;
130 nanosleep(&ts, NULL);
131 }
132 }
133 case AVAHI_BROWSER_FAILURE: /* fall-through */
134 avahi_simple_poll_quit(ddata->poll);
135 case AVAHI_BROWSER_CACHE_EXHAUSTED: /* fall-through */
136 break;
137 }
138}
139
140static int discover_host(AvahiAddress *addr, uint16_t *port)
141{
142 struct avahi_discovery_data ddata;
143 int ret = 0;
144 AvahiClient *client;
145 AvahiServiceBrowser *browser;
146 AvahiSimplePoll *poll = avahi_simple_poll_new();
147 if (!poll)
148 return -ENOMEM;
149
150 client = avahi_client_new(avahi_simple_poll_get(poll),
151 0, NULL, NULL, &ret);
152 if (!client) {
153 ERROR("Unable to start ZeroConf client :%s\n",
154 avahi_strerror(ret));
155 goto err_free_poll;
156 }
157
158 memset(&ddata, 0, sizeof(ddata));
159 ddata.poll = poll;
160 ddata.address = addr;
161 ddata.port = port;
162
163 browser = avahi_service_browser_new(client,
164 AVAHI_IF_UNSPEC, AVAHI_PROTO_UNSPEC,
165 "_iio._tcp", NULL, 0, __avahi_browser_cb, &ddata);
166 if (!browser) {
167 ret = avahi_client_errno(client);
168 ERROR("Unable to create ZeroConf browser: %s\n",
169 avahi_strerror(ret));
170 goto err_free_client;
171 }
172
173 DEBUG("Trying to discover host\n");
174 avahi_simple_poll_loop(poll);
175
176 if (!ddata.found)
177 ret = ENXIO;
178
179 avahi_service_browser_free(browser);
180err_free_client:
181 avahi_client_free(client);
182err_free_poll:
183 avahi_simple_poll_free(poll);
184 return -ret; /* we want a negative error code */
185}
186#endif /* HAVE_AVAHI */
187
Paul Cercueilc7bad0f2014-03-03 17:06:48 +0100188static ssize_t write_all(const void *src, size_t len, int fd)
189{
Paul Cercueil6e7f79e2014-04-04 12:27:24 +0200190 uintptr_t ptr = (uintptr_t) src;
Paul Cercueilc7bad0f2014-03-03 17:06:48 +0100191 while (len) {
Paul Cercueil4012cff2015-05-11 10:47:40 +0200192 ssize_t ret = send(fd, (const void *) ptr, (int) len, 0);
Lars-Peter Clausencb7b8bf2014-12-05 16:08:52 +0100193 if (ret < 0) {
Paul Cercueil135b3612015-06-30 14:10:14 +0200194#ifdef _WIN32
195 int err = WSAGetLastError();
196#else
197 int err = errno;
198#endif
Paul Cercueil0a96c062015-07-02 11:16:33 +0200199 if (err == EINTR)
Lars-Peter Clausencb7b8bf2014-12-05 16:08:52 +0100200 continue;
Paul Cercueil135b3612015-06-30 14:10:14 +0200201 return (ssize_t) -err;
Lars-Peter Clausencb7b8bf2014-12-05 16:08:52 +0100202 }
Paul Cercueilc7bad0f2014-03-03 17:06:48 +0100203 ptr += ret;
204 len -= ret;
205 }
Paul Cercueil4012cff2015-05-11 10:47:40 +0200206 return (ssize_t)(ptr - (uintptr_t) src);
Paul Cercueilc7bad0f2014-03-03 17:06:48 +0100207}
208
209static ssize_t read_all(void *dst, size_t len, int fd)
210{
Paul Cercueil6e7f79e2014-04-04 12:27:24 +0200211 uintptr_t ptr = (uintptr_t) dst;
Paul Cercueilc7bad0f2014-03-03 17:06:48 +0100212 while (len) {
Paul Cercueil4012cff2015-05-11 10:47:40 +0200213 ssize_t ret = recv(fd, (void *) ptr, (int) len, 0);
Lars-Peter Clausencb7b8bf2014-12-05 16:08:52 +0100214 if (ret < 0) {
Paul Cercueil135b3612015-06-30 14:10:14 +0200215#ifdef _WIN32
216 int err = WSAGetLastError();
217#else
218 int err = errno;
219#endif
Paul Cercueil0a96c062015-07-02 11:16:33 +0200220 if (err == EINTR)
Lars-Peter Clausencb7b8bf2014-12-05 16:08:52 +0100221 continue;
Paul Cercueil135b3612015-06-30 14:10:14 +0200222 return (ssize_t) -err;
Lars-Peter Clausencb7b8bf2014-12-05 16:08:52 +0100223 }
Paul Cercueil43eb7e82014-11-13 12:46:59 +0100224 if (ret == 0)
225 return -EPIPE;
Paul Cercueilc7bad0f2014-03-03 17:06:48 +0100226 ptr += ret;
227 len -= ret;
228 }
Paul Cercueil4012cff2015-05-11 10:47:40 +0200229 return (ssize_t)(ptr - (uintptr_t) dst);
Paul Cercueilc7bad0f2014-03-03 17:06:48 +0100230}
231
Paul Cercueile60c3ed2014-03-04 11:23:56 +0100232static int read_integer(int fd, long *val)
233{
234 unsigned int i;
235 char buf[1024], *ptr;
236 ssize_t ret;
237 bool found = false;
238
239 for (i = 0; i < sizeof(buf) - 1; i++) {
240 ret = read_all(buf + i, 1, fd);
241 if (ret < 0)
242 return (int) ret;
243
Paul Cercueil6691a3f2014-05-02 12:32:01 +0200244 /* Skip the eventual first few carriage returns.
245 * Also stop when a dot is found (for parsing floats) */
246 if (buf[i] != '\n' && buf[i] != '.')
Paul Cercueile60c3ed2014-03-04 11:23:56 +0100247 found = true;
248 else if (found)
249 break;
250 }
251
252 buf[i] = '\0';
253 ret = (ssize_t) strtol(buf, &ptr, 10);
254 if (ptr == buf)
255 return -EINVAL;
256 *val = (long) ret;
257 return 0;
258}
259
Paul Cercueilbb76bf92014-03-11 10:20:18 +0100260static ssize_t write_command(const char *cmd, int fd)
261{
262 ssize_t ret;
263
264 DEBUG("Writing command: %s\n", cmd);
265 ret = write_all(cmd, strlen(cmd), fd);
266 if (ret < 0) {
267 char buf[1024];
Paul Cercueil53fc4852015-05-22 10:57:53 +0200268 iio_strerror(-ret, buf, sizeof(buf));
Paul Cercueilbb76bf92014-03-11 10:20:18 +0100269 ERROR("Unable to send command: %s\n", buf);
270 }
271 return ret;
272}
273
274static long exec_command(const char *cmd, int fd)
275{
276 long resp;
277 ssize_t ret = write_command(cmd, fd);
278 if (ret < 0)
279 return (long) ret;
280
281 DEBUG("Reading response\n");
282 ret = read_integer(fd, &resp);
283 if (ret < 0) {
284 char buf[1024];
Paul Cercueil53fc4852015-05-22 10:57:53 +0200285 iio_strerror(-ret, buf, sizeof(buf));
Paul Cercueilbb76bf92014-03-11 10:20:18 +0100286 ERROR("Unable to read response: %s\n", buf);
287 return (long) ret;
288 }
289
Paul Cercueilc7fe2ea2014-03-28 11:38:45 +0100290#if LOG_LEVEL >= DEBUG_L
Paul Cercueilbb76bf92014-03-11 10:20:18 +0100291 if (resp < 0) {
292 char buf[1024];
Paul Cercueil53fc4852015-05-22 10:57:53 +0200293 iio_strerror(-resp, buf, sizeof(buf));
Paul Cercueilc7fe2ea2014-03-28 11:38:45 +0100294 DEBUG("Server returned an error: %s\n", buf);
Paul Cercueilbb76bf92014-03-11 10:20:18 +0100295 }
Paul Cercueilc7fe2ea2014-03-28 11:38:45 +0100296#endif
297
Paul Cercueilbb76bf92014-03-11 10:20:18 +0100298 return resp;
299}
300
Paul Cercueil4970ac32015-02-24 10:59:00 +0100301#ifndef _WIN32
Paul Cercueil4970ac32015-02-24 10:59:00 +0100302/* The purpose of this function is to provide a version of connect()
303 * that does not ignore timeouts... */
304static int do_connect(int fd, const struct sockaddr *addr,
305 socklen_t addrlen, struct timeval *timeout)
306{
307 int ret, error;
308 socklen_t len;
309 fd_set set;
310
311 FD_ZERO(&set);
312 FD_SET(fd, &set);
313
314 ret = set_blocking_mode(fd, false);
315 if (ret < 0)
316 return ret;
317
318 ret = connect(fd, addr, addrlen);
319 if (ret < 0 && errno != EINPROGRESS) {
320 ret = -errno;
321 goto end;
322 }
323
324 ret = select(fd + 1, &set, &set, NULL, timeout);
325 if (ret < 0) {
326 ret = -errno;
327 goto end;
328 }
329 if (ret == 0) {
330 ret = -ETIMEDOUT;
331 goto end;
332 }
333
334 /* Verify that we don't have an error */
335 len = sizeof(error);
336 ret = getsockopt(fd, SOL_SOCKET, SO_ERROR, &error, &len);
337 if(ret < 0) {
338 ret = -errno;
339 goto end;
340 }
341 if (error) {
342 ret = -error;
343 goto end;
344 }
345
346end:
347 /* Restore blocking mode */
348 set_blocking_mode(fd, true);
349 return ret;
350}
351
352static int set_socket_timeout(int fd, unsigned int timeout)
353{
354 struct timeval tv;
355
356 tv.tv_sec = timeout / 1000;
357 tv.tv_usec = (timeout % 1000) * 1000;
358 if (setsockopt(fd, SOL_SOCKET, SO_SNDTIMEO, &tv, sizeof(tv)) < 0 ||
359 setsockopt(fd, SOL_SOCKET, SO_RCVTIMEO,
360 &tv, sizeof(tv)) < 0)
361 return -errno;
362 else
363 return 0;
364}
365#else
366static int set_socket_timeout(int fd, unsigned int timeout)
367{
368 if (setsockopt(fd, SOL_SOCKET, SO_SNDTIMEO,
369 (const char *) &timeout, sizeof(timeout)) < 0 ||
370 setsockopt(fd, SOL_SOCKET, SO_RCVTIMEO,
371 (const char *) &timeout, sizeof(timeout)) < 0)
Paul Cercueil135b3612015-06-30 14:10:14 +0200372 return -WSAGetLastError();
Paul Cercueil4970ac32015-02-24 10:59:00 +0100373 else
374 return 0;
375}
376#endif /* !_WIN32 */
377
378static int create_socket(const struct addrinfo *addrinfo)
379{
380 struct timeval timeout;
381 int ret, fd, yes = 1;
382
Paul Cercueil4012cff2015-05-11 10:47:40 +0200383#ifdef _WIN32
384 SOCKET s = socket(addrinfo->ai_family, addrinfo->ai_socktype, 0);
385 fd = (s == INVALID_SOCKET) ? -1 : (int) s;
Paul Cercueil135b3612015-06-30 14:10:14 +0200386 if (fd < 0)
387 return -WSAGetLastError();
Paul Cercueil4012cff2015-05-11 10:47:40 +0200388#else
Paul Cercueil4970ac32015-02-24 10:59:00 +0100389 fd = socket(addrinfo->ai_family, addrinfo->ai_socktype, 0);
Paul Cercueil135b3612015-06-30 14:10:14 +0200390 if (fd < 0)
391 return -errno;
Paul Cercueil4012cff2015-05-11 10:47:40 +0200392#endif
Paul Cercueil4970ac32015-02-24 10:59:00 +0100393
394 timeout.tv_sec = DEFAULT_TIMEOUT_MS / 1000;
395 timeout.tv_usec = (DEFAULT_TIMEOUT_MS % 1000) * 1000;
396
397#ifndef _WIN32
398 ret = do_connect(fd, addrinfo->ai_addr, addrinfo->ai_addrlen, &timeout);
Paul Cercueil135b3612015-06-30 14:10:14 +0200399 if (ret < 0)
400 ret = -errno;
Paul Cercueil4970ac32015-02-24 10:59:00 +0100401#else
Paul Cercueil4012cff2015-05-11 10:47:40 +0200402 ret = connect(fd, addrinfo->ai_addr, (int) addrinfo->ai_addrlen);
Paul Cercueil135b3612015-06-30 14:10:14 +0200403 if (ret == SOCKET_ERROR)
404 ret = -WSAGetLastError();
Paul Cercueil4970ac32015-02-24 10:59:00 +0100405#endif
406 if (ret < 0) {
Paul Cercueil4970ac32015-02-24 10:59:00 +0100407 close(fd);
408 return ret;
409 }
410
411 set_socket_timeout(fd, DEFAULT_TIMEOUT_MS);
412 setsockopt(fd, IPPROTO_TCP, TCP_NODELAY,
413 (const char *) &yes, sizeof(yes));
414 return fd;
415}
416
Paul Cercueil92f15c22015-04-20 11:36:51 +0200417static int network_open(const struct iio_device *dev,
418 size_t samples_count, bool cyclic)
Paul Cercueilba059762014-03-14 11:02:02 +0100419{
Paul Cercueil439e1a22015-02-24 13:50:51 +0100420 struct iio_context_pdata *pdata = dev->ctx->pdata;
Paul Cercueilba059762014-03-14 11:02:02 +0100421 char buf[1024], *ptr;
Paul Cercueil4012cff2015-05-11 10:47:40 +0200422 size_t i;
Paul Cercueil439e1a22015-02-24 13:50:51 +0100423 int ret, fd;
Paul Cercueilba059762014-03-14 11:02:02 +0100424
Paul Cercueil439e1a22015-02-24 13:50:51 +0100425 if (dev->pdata->fd >= 0)
426 return -EBUSY;
427
428 fd = create_socket(pdata->addrinfo);
429 if (fd < 0)
430 return fd;
Paul Cercueilba059762014-03-14 11:02:02 +0100431
Paul Cercueil3c407f82014-04-02 14:11:59 +0200432 snprintf(buf, sizeof(buf), "OPEN %s %lu ",
433 dev->id, (unsigned long) samples_count);
Paul Cercueilba059762014-03-14 11:02:02 +0100434 ptr = buf + strlen(buf);
435
Paul Cercueil92f15c22015-04-20 11:36:51 +0200436 for (i = dev->words; i > 0; i--) {
437 snprintf(ptr, (ptr - buf) + i * 8, "%08x", dev->mask[i - 1]);
Paul Cercueilba059762014-03-14 11:02:02 +0100438 ptr += 8;
439 }
Paul Cercueil71694c72014-05-22 14:02:13 +0200440
441 strcpy(ptr, cyclic ? " CYCLIC\r\n" : "\r\n");
Paul Cercueilba059762014-03-14 11:02:02 +0100442
Paul Cercueil388dcd62015-11-27 15:15:48 +0100443 iio_mutex_lock(dev->pdata->lock);
Paul Cercueil439e1a22015-02-24 13:50:51 +0100444 ret = (int) exec_command(buf, fd);
Paul Cercueil388dcd62015-11-27 15:15:48 +0100445 iio_mutex_unlock(dev->pdata->lock);
Paul Cercueil1494b862014-05-05 12:49:07 +0200446
Paul Cercueil44ae11c2014-03-17 09:56:29 +0100447 if (ret < 0) {
Paul Cercueil439e1a22015-02-24 13:50:51 +0100448 close(fd);
Paul Cercueil44ae11c2014-03-17 09:56:29 +0100449 return ret;
Paul Cercueil44ae11c2014-03-17 09:56:29 +0100450 }
Paul Cercueil439e1a22015-02-24 13:50:51 +0100451
Lars-Peter Clausen62bd5522015-03-27 16:06:52 +0100452 dev->pdata->is_tx = iio_device_is_tx(dev);
Paul Cercueil1d70d442015-03-04 15:00:37 +0100453 dev->pdata->is_cyclic = cyclic;
Paul Cercueil439e1a22015-02-24 13:50:51 +0100454 dev->pdata->fd = fd;
Paul Cercueil8f7f6c42015-02-24 15:00:35 +0100455 dev->pdata->wait_for_err_code = false;
Paul Cercueild957b982015-08-05 14:39:01 +0200456#ifdef WITH_NETWORK_GET_BUFFER
457 dev->pdata->mmap_len = samples_count * iio_device_get_sample_size(dev);
458#endif
Paul Cercueil439e1a22015-02-24 13:50:51 +0100459 return 0;
Paul Cercueilba059762014-03-14 11:02:02 +0100460}
461
Paul Cercueil8f7f6c42015-02-24 15:00:35 +0100462static ssize_t read_error_code(int fd)
463{
464 /*
465 * The server returns two integer codes.
466 * The first one is returned right after the WRITEBUF command is issued,
467 * and corresponds to the error code returned when the server attempted
468 * to open the device.
469 * If zero, a second error code is returned, that corresponds (if positive)
470 * to the number of bytes written.
471 *
472 * To speed up things, we delay error reporting. We just send out the
473 * data without reading the error code that the server gives us, because
474 * the answer will take too much time. If an error occured, it will be
475 * reported by the next call to iio_buffer_push().
476 */
477
478 unsigned int i;
479 long resp = 0;
480
481 for (i = 0; i < 2; i++) {
482 ssize_t ret = read_integer(fd, &resp);
483 if (ret < 0)
484 return ret;
485 if (resp < 0)
486 return (ssize_t) resp;
487 }
488
Paul Cercueil7d7e5d32015-03-05 10:51:41 +0100489 return (ssize_t) resp;
Paul Cercueil8f7f6c42015-02-24 15:00:35 +0100490}
491
Paul Cercueil3c0da372015-03-05 11:36:39 +0100492static ssize_t write_rwbuf_command(const struct iio_device *dev,
493 const char *cmd, bool do_exec)
494{
495 struct iio_device_pdata *pdata = dev->pdata;
496 int fd = pdata->fd;
497
498 if (pdata->wait_for_err_code) {
499 ssize_t ret = read_error_code(fd);
500
501 pdata->wait_for_err_code = false;
502 if (ret < 0)
503 return ret;
504 }
505
506 return do_exec ? exec_command(cmd, fd) : write_command(cmd, fd);
507}
508
Paul Cercueilba059762014-03-14 11:02:02 +0100509static int network_close(const struct iio_device *dev)
510{
Paul Cercueil439e1a22015-02-24 13:50:51 +0100511 struct iio_device_pdata *pdata = dev->pdata;
Paul Cercueild5d84612015-06-08 21:24:15 +0200512 int ret = -EBADF;
Paul Cercueilba059762014-03-14 11:02:02 +0100513 char buf[1024];
Paul Cercueil439e1a22015-02-24 13:50:51 +0100514
Paul Cercueila34596e2015-03-05 14:33:46 +0100515 if (pdata->fd >= 0) {
516 snprintf(buf, sizeof(buf), "CLOSE %s\r\n", dev->id);
Paul Cercueil1494b862014-05-05 12:49:07 +0200517
Paul Cercueil388dcd62015-11-27 15:15:48 +0100518 iio_mutex_lock(pdata->lock);
Paul Cercueila34596e2015-03-05 14:33:46 +0100519 ret = (int) write_rwbuf_command(dev, buf, true);
Paul Cercueil1494b862014-05-05 12:49:07 +0200520
Paul Cercueila34596e2015-03-05 14:33:46 +0100521 write_command("\r\nEXIT\r\n", pdata->fd);
Paul Cercueilaa0db142015-03-04 16:25:24 +0100522
Paul Cercueila34596e2015-03-05 14:33:46 +0100523 close(pdata->fd);
524 pdata->fd = -1;
Paul Cercueil388dcd62015-11-27 15:15:48 +0100525 iio_mutex_unlock(pdata->lock);
Paul Cercueila34596e2015-03-05 14:33:46 +0100526 }
Paul Cercueile6e5a092015-03-04 16:33:26 +0100527
Paul Cercueil90189672015-03-16 11:41:53 +0100528#ifdef WITH_NETWORK_GET_BUFFER
Paul Cercueile6e5a092015-03-04 16:33:26 +0100529 if (pdata->memfd >= 0)
530 close(pdata->memfd);
531 pdata->memfd = -1;
532
533 if (pdata->mmap_addr) {
534 munmap(pdata->mmap_addr, pdata->mmap_len);
535 pdata->mmap_addr = NULL;
536 }
537#endif
Paul Cercueil1494b862014-05-05 12:49:07 +0200538 return ret;
Paul Cercueilba059762014-03-14 11:02:02 +0100539}
540
Paul Cercueil7d7e5d32015-03-05 10:51:41 +0100541static ssize_t network_read_mask(int fd, uint32_t *mask, size_t words)
542{
543 long read_len;
544 ssize_t ret;
545
546 ret = read_integer(fd, &read_len);
547 if (ret < 0)
548 return ret;
549
550 if (read_len > 0 && mask) {
Paul Cercueil4012cff2015-05-11 10:47:40 +0200551 size_t i;
Paul Cercueil7d7e5d32015-03-05 10:51:41 +0100552 char buf[9];
553
554 buf[8] = '\0';
555 DEBUG("Reading mask\n");
556
557 for (i = words; i > 0; i--) {
558 ret = read_all(buf, 8, fd);
559 if (ret < 0)
560 return ret;
561
562 sscanf(buf, "%08x", &mask[i - 1]);
563 DEBUG("mask[%i] = 0x%x\n", i - 1, mask[i - 1]);
564 }
565 }
566
567 if (read_len > 0) {
568 char c;
569 ssize_t nb = read_all(&c, 1, fd);
570 if (nb > 0 && c != '\n')
571 read_len = -EIO;
572 }
573
574 return (ssize_t) read_len;
575}
576
Paul Cercueil45c575d2014-03-20 15:14:01 +0100577static ssize_t network_read(const struct iio_device *dev, void *dst, size_t len,
578 uint32_t *mask, size_t words)
Paul Cercueilf9286452014-03-18 14:32:17 +0100579{
Paul Cercueil6e7f79e2014-04-04 12:27:24 +0200580 uintptr_t ptr = (uintptr_t) dst;
Paul Cercueilc5b00752015-02-24 14:29:53 +0100581 struct iio_device_pdata *pdata = dev->pdata;
582 int fd = pdata->fd;
Paul Cercueil45c575d2014-03-20 15:14:01 +0100583 ssize_t ret, read = 0;
Paul Cercueil9945bc82014-03-05 14:07:29 +0100584 char buf[1024];
585
Paul Cercueil45c575d2014-03-20 15:14:01 +0100586 if (!len || words != (dev->nb_channels + 31) / 32)
Paul Cercueil9945bc82014-03-05 14:07:29 +0100587 return -EINVAL;
588
Paul Cercueila78b6eb2014-03-17 17:28:07 +0100589 snprintf(buf, sizeof(buf), "READBUF %s %lu\r\n",
590 dev->id, (unsigned long) len);
Paul Cercueil1494b862014-05-05 12:49:07 +0200591
Paul Cercueil388dcd62015-11-27 15:15:48 +0100592 iio_mutex_lock(pdata->lock);
Paul Cercueil3c0da372015-03-05 11:36:39 +0100593 ret = write_rwbuf_command(dev, buf, false);
Paul Cercueil1494b862014-05-05 12:49:07 +0200594 if (ret < 0) {
Paul Cercueil388dcd62015-11-27 15:15:48 +0100595 iio_mutex_unlock(pdata->lock);
Paul Cercueil9945bc82014-03-05 14:07:29 +0100596 return ret;
Paul Cercueil1494b862014-05-05 12:49:07 +0200597 }
Paul Cercueil9945bc82014-03-05 14:07:29 +0100598
599 do {
Paul Cercueil7d7e5d32015-03-05 10:51:41 +0100600 ret = network_read_mask(fd, mask, words);
601 if (!ret)
Paul Cercueila78b6eb2014-03-17 17:28:07 +0100602 break;
Paul Cercueil5cab3ae2014-03-14 11:23:56 +0100603 if (ret < 0) {
Paul Cercueil53fc4852015-05-22 10:57:53 +0200604 iio_strerror(-ret, buf, sizeof(buf));
Paul Cercueil5cab3ae2014-03-14 11:23:56 +0100605 ERROR("Unable to read mask: %s\n", buf);
Paul Cercueil388dcd62015-11-27 15:15:48 +0100606 iio_mutex_unlock(pdata->lock);
Paul Cercueil6e7f79e2014-04-04 12:27:24 +0200607 return read ? read : ret;
Paul Cercueil5cab3ae2014-03-14 11:23:56 +0100608 }
609
Paul Cercueil7d7e5d32015-03-05 10:51:41 +0100610 mask = NULL; /* We read the mask only once */
611
612 ret = read_all((void *) ptr, ret, fd);
Paul Cercueil9945bc82014-03-05 14:07:29 +0100613 if (ret < 0) {
Paul Cercueil53fc4852015-05-22 10:57:53 +0200614 iio_strerror(-ret, buf, sizeof(buf));
Paul Cercueil9945bc82014-03-05 14:07:29 +0100615 ERROR("Unable to read response to READ: %s\n", buf);
Paul Cercueil388dcd62015-11-27 15:15:48 +0100616 iio_mutex_unlock(pdata->lock);
Paul Cercueil6e7f79e2014-04-04 12:27:24 +0200617 return read ? read : ret;
Paul Cercueil9945bc82014-03-05 14:07:29 +0100618 }
619
Paul Cercueil6e7f79e2014-04-04 12:27:24 +0200620 ptr += ret;
Paul Cercueilf9286452014-03-18 14:32:17 +0100621 read += ret;
Paul Cercueil7d7e5d32015-03-05 10:51:41 +0100622 len -= ret;
Paul Cercueil9945bc82014-03-05 14:07:29 +0100623 } while (len);
624
Paul Cercueil388dcd62015-11-27 15:15:48 +0100625 iio_mutex_unlock(pdata->lock);
Paul Cercueil9945bc82014-03-05 14:07:29 +0100626 return read;
627}
628
Paul Cercueila62f84e2015-02-24 14:16:08 +0100629static ssize_t network_write(const struct iio_device *dev,
630 const void *src, size_t len)
Paul Cercueil2725f702014-05-02 11:02:16 +0200631{
Paul Cercueilc5b00752015-02-24 14:29:53 +0100632 struct iio_device_pdata *pdata = dev->pdata;
Paul Cercueil439e1a22015-02-24 13:50:51 +0100633 int fd;
Paul Cercueil2725f702014-05-02 11:02:16 +0200634 ssize_t ret;
Paul Cercueil2725f702014-05-02 11:02:16 +0200635 long resp;
Paul Cercueila62f84e2015-02-24 14:16:08 +0100636 char buf[1024];
637
638 snprintf(buf, sizeof(buf), "WRITEBUF %s %lu\r\n",
639 dev->id, (unsigned long) len);
Paul Cercueil2725f702014-05-02 11:02:16 +0200640
Paul Cercueil388dcd62015-11-27 15:15:48 +0100641 iio_mutex_lock(pdata->lock);
Paul Cercueilc5b00752015-02-24 14:29:53 +0100642 fd = pdata->fd;
Paul Cercueil8f7f6c42015-02-24 15:00:35 +0100643
Paul Cercueil3c0da372015-03-05 11:36:39 +0100644 ret = write_rwbuf_command(dev, buf, pdata->is_cyclic);
Paul Cercueil2725f702014-05-02 11:02:16 +0200645 if (ret < 0)
Paul Cercueil1494b862014-05-05 12:49:07 +0200646 goto err_unlock;
Paul Cercueil2725f702014-05-02 11:02:16 +0200647
648 ret = write_all(src, len, fd);
649 if (ret < 0)
Paul Cercueil1494b862014-05-05 12:49:07 +0200650 goto err_unlock;
Paul Cercueil2725f702014-05-02 11:02:16 +0200651
Paul Cercueil1d70d442015-03-04 15:00:37 +0100652 if (pdata->is_cyclic) {
653 ret = read_integer(fd, &resp);
654 if (ret < 0)
655 goto err_unlock;
656 if (resp < 0) {
657 ret = (ssize_t) resp;
658 goto err_unlock;
659 }
660 } else {
661 pdata->wait_for_err_code = true;
662 }
Paul Cercueil388dcd62015-11-27 15:15:48 +0100663 iio_mutex_unlock(pdata->lock);
Paul Cercueil1494b862014-05-05 12:49:07 +0200664
Paul Cercueil8f7f6c42015-02-24 15:00:35 +0100665 /* We assume that the whole buffer was submitted.
666 * The error code will be returned by the next call to this function. */
667 return (ssize_t) len;
Paul Cercueil1494b862014-05-05 12:49:07 +0200668
669err_unlock:
Paul Cercueil388dcd62015-11-27 15:15:48 +0100670 iio_mutex_unlock(pdata->lock);
Paul Cercueil1494b862014-05-05 12:49:07 +0200671 return ret;
Paul Cercueil2725f702014-05-02 11:02:16 +0200672}
673
Paul Cercueil90189672015-03-16 11:41:53 +0100674#ifdef WITH_NETWORK_GET_BUFFER
Paul Cercueil7d7e5d32015-03-05 10:51:41 +0100675static ssize_t network_do_splice(int fd_out, int fd_in, size_t len)
Paul Cercueil09a43482015-03-04 15:50:27 +0100676{
677 int pipefd[2];
Paul Cercueil04065c22015-03-05 14:08:16 +0100678 ssize_t ret, read_len = len;
Paul Cercueil09a43482015-03-04 15:50:27 +0100679
680 ret = (ssize_t) pipe(pipefd);
681 if (ret < 0)
682 return -errno;
683
684 do {
Paul Cercueila107c6d2015-03-05 13:54:10 +0100685 /*
686 * SPLICE_F_NONBLOCK is just here to avoid a deadlock when
687 * splicing from a socket. As the socket is not in
688 * non-blocking mode, it should never return -EAGAIN.
689 * TODO(pcercuei): Find why it locks...
690 * */
691 ret = splice(fd_in, NULL, pipefd[1], NULL, len,
692 SPLICE_F_MOVE | SPLICE_F_NONBLOCK);
693 if (!ret)
694 ret = -EIO;
Paul Cercueil09a43482015-03-04 15:50:27 +0100695 if (ret < 0)
696 goto err_close_pipe;
697
Paul Cercueila107c6d2015-03-05 13:54:10 +0100698 ret = splice(pipefd[0], NULL, fd_out, NULL, ret,
699 SPLICE_F_MOVE | SPLICE_F_NONBLOCK);
700 if (!ret)
701 ret = -EIO;
Paul Cercueil09a43482015-03-04 15:50:27 +0100702 if (ret < 0)
703 goto err_close_pipe;
704
705 len -= ret;
706 } while (len);
707
708err_close_pipe:
709 close(pipefd[0]);
710 close(pipefd[1]);
Paul Cercueil04065c22015-03-05 14:08:16 +0100711 return ret < 0 ? ret : read_len;
Paul Cercueil09a43482015-03-04 15:50:27 +0100712}
713
714static ssize_t network_get_buffer(const struct iio_device *dev,
Paul Cercueil76ca8842015-03-05 11:16:16 +0100715 void **addr_ptr, size_t bytes_used,
716 uint32_t *mask, size_t words)
Paul Cercueil09a43482015-03-04 15:50:27 +0100717{
718 struct iio_device_pdata *pdata = dev->pdata;
Paul Cercueil04065c22015-03-05 14:08:16 +0100719 ssize_t ret, read = 0;
Paul Cercueilca9d3382015-05-04 14:30:09 +0200720 int memfd;
Paul Cercueil09a43482015-03-04 15:50:27 +0100721 bool tx;
Paul Cercueil09a43482015-03-04 15:50:27 +0100722
Paul Cercueil04065c22015-03-05 14:08:16 +0100723 if (pdata->is_cyclic)
Paul Cercueil09a43482015-03-04 15:50:27 +0100724 return -ENOSYS;
Paul Cercueilca9d3382015-05-04 14:30:09 +0200725
726 /* We check early that the temporary file can be created, so that we can
727 * return -ENOSYS in case it fails, which will indicate that the
728 * high-speed interface is not available.
729 *
730 * O_TMPFILE -> Linux 3.11.
731 * TODO: use memfd_create (Linux 3.17) */
732 memfd = open(P_tmpdir, O_RDWR | O_TMPFILE | O_EXCL, S_IRWXU);
733 if (memfd < 0)
734 return -ENOSYS;
735
736 if (!addr_ptr || words != (dev->nb_channels + 31) / 32) {
737 close(memfd);
Paul Cercueil09a43482015-03-04 15:50:27 +0100738 return -EINVAL;
Paul Cercueilca9d3382015-05-04 14:30:09 +0200739 }
Paul Cercueil09a43482015-03-04 15:50:27 +0100740
Paul Cercueile6e5a092015-03-04 16:33:26 +0100741 if (pdata->mmap_addr)
742 munmap(pdata->mmap_addr, pdata->mmap_len);
Paul Cercueil09a43482015-03-04 15:50:27 +0100743
Paul Cercueile6e5a092015-03-04 16:33:26 +0100744 if (pdata->mmap_addr && pdata->is_tx) {
Paul Cercueil09a43482015-03-04 15:50:27 +0100745 char buf[1024];
746 snprintf(buf, sizeof(buf), "WRITEBUF %s %lu\r\n",
Paul Cercueild957b982015-08-05 14:39:01 +0200747 dev->id, (unsigned long) bytes_used);
Paul Cercueil09a43482015-03-04 15:50:27 +0100748
Paul Cercueil388dcd62015-11-27 15:15:48 +0100749 iio_mutex_lock(pdata->lock);
Paul Cercueil09a43482015-03-04 15:50:27 +0100750
Paul Cercueil3c0da372015-03-05 11:36:39 +0100751 ret = write_rwbuf_command(dev, buf, false);
Paul Cercueil09a43482015-03-04 15:50:27 +0100752 if (ret < 0)
Paul Cercueilca9d3382015-05-04 14:30:09 +0200753 goto err_close_memfd;
Paul Cercueil09a43482015-03-04 15:50:27 +0100754
Paul Cercueild957b982015-08-05 14:39:01 +0200755 ret = network_do_splice(pdata->fd, pdata->memfd, bytes_used);
Paul Cercueil09a43482015-03-04 15:50:27 +0100756 if (ret < 0)
Paul Cercueilca9d3382015-05-04 14:30:09 +0200757 goto err_close_memfd;
Paul Cercueil09a43482015-03-04 15:50:27 +0100758
759 pdata->wait_for_err_code = true;
Paul Cercueil388dcd62015-11-27 15:15:48 +0100760 iio_mutex_unlock(pdata->lock);
Paul Cercueil09a43482015-03-04 15:50:27 +0100761 }
762
763 if (pdata->memfd >= 0)
764 close(pdata->memfd);
765
Paul Cercueilca9d3382015-05-04 14:30:09 +0200766 pdata->memfd = memfd;
Paul Cercueil09a43482015-03-04 15:50:27 +0100767
Paul Cercueilef32d582015-03-05 11:18:35 +0100768 ret = (ssize_t) ftruncate(pdata->memfd, pdata->mmap_len);
769 if (ret < 0) {
770 ret = -errno;
771 ERROR("Unable to truncate temp file: %zi\n", -ret);
772 return ret;
773 }
Paul Cercueil09a43482015-03-04 15:50:27 +0100774
Paul Cercueil04065c22015-03-05 14:08:16 +0100775 if (!pdata->is_tx) {
776 char buf[1024];
777 size_t len = pdata->mmap_len;
778
779 snprintf(buf, sizeof(buf), "READBUF %s %lu\r\n",
780 dev->id, (unsigned long) len);
781
Paul Cercueil388dcd62015-11-27 15:15:48 +0100782 iio_mutex_lock(pdata->lock);
Paul Cercueil04065c22015-03-05 14:08:16 +0100783 ret = write_rwbuf_command(dev, buf, false);
784 if (ret < 0)
785 goto err_unlock;
786
787 do {
788 ret = network_read_mask(pdata->fd, mask, words);
789 if (!ret)
790 break;
791 if (ret < 0)
792 goto err_unlock;
793
794 mask = NULL; /* We read the mask only once */
795
796 ret = network_do_splice(pdata->memfd, pdata->fd, ret);
797 if (ret < 0)
798 goto err_unlock;
799
800 read += ret;
801 len -= ret;
802 } while (len);
803
Paul Cercueil388dcd62015-11-27 15:15:48 +0100804 iio_mutex_unlock(pdata->lock);
Paul Cercueil04065c22015-03-05 14:08:16 +0100805 }
Paul Cercueil09a43482015-03-04 15:50:27 +0100806
Paul Cercueile6e5a092015-03-04 16:33:26 +0100807 pdata->mmap_addr = mmap(NULL, pdata->mmap_len,
Paul Cercueil09a43482015-03-04 15:50:27 +0100808 PROT_READ | PROT_WRITE, MAP_SHARED, pdata->memfd, 0);
Paul Cercueile6e5a092015-03-04 16:33:26 +0100809 if (pdata->mmap_addr == MAP_FAILED) {
810 pdata->mmap_addr = NULL;
Paul Cercueil09a43482015-03-04 15:50:27 +0100811 ret = -errno;
Paul Cercueil7d7e5d32015-03-05 10:51:41 +0100812 ERROR("Unable to mmap: %zi\n", -ret);
Paul Cercueil09a43482015-03-04 15:50:27 +0100813 return ret;
814 }
815
Paul Cercueile6e5a092015-03-04 16:33:26 +0100816 *addr_ptr = pdata->mmap_addr;
Paul Cercueil04065c22015-03-05 14:08:16 +0100817 return read ? read : bytes_used;
Paul Cercueil09a43482015-03-04 15:50:27 +0100818
Paul Cercueilca9d3382015-05-04 14:30:09 +0200819err_close_memfd:
820 close(memfd);
Paul Cercueil09a43482015-03-04 15:50:27 +0100821err_unlock:
Paul Cercueil388dcd62015-11-27 15:15:48 +0100822 iio_mutex_unlock(pdata->lock);
Paul Cercueil09a43482015-03-04 15:50:27 +0100823 return ret;
824}
825#endif
826
Paul Cercueil1494b862014-05-05 12:49:07 +0200827static ssize_t network_read_attr_helper(const struct iio_device *dev,
Paul Cercueil0cc0e162014-05-07 12:51:22 +0200828 const struct iio_channel *chn, const char *attr, char *dst,
Paul Cercueil1494b862014-05-05 12:49:07 +0200829 size_t len, bool is_debug)
Paul Cercueil3e94a5b2014-03-04 13:00:41 +0100830{
Paul Cercueil3e94a5b2014-03-04 13:00:41 +0100831 long read_len;
832 ssize_t ret;
833 char buf[1024];
Paul Cercueil05e26262014-05-09 11:32:43 +0200834 struct iio_context_pdata *pdata = dev->ctx->pdata;
835 int fd = pdata->fd;
Paul Cercueil1494b862014-05-05 12:49:07 +0200836 const char *id = dev->id;
Paul Cercueil3e94a5b2014-03-04 13:00:41 +0100837
Paul Cercueil99cf3d42014-03-06 12:35:26 +0100838 if (chn)
Paul Cercueil0cc0e162014-05-07 12:51:22 +0200839 snprintf(buf, sizeof(buf), "READ %s %s %s %s\r\n", id,
840 chn->is_output ? "OUTPUT" : "INPUT",
Paul Cercueil2a3e43d2014-05-21 16:58:45 +0200841 chn->id, attr ? attr : "");
Paul Cercueilc6f03612014-04-14 16:41:31 +0200842 else if (is_debug)
Paul Cercueil2a3e43d2014-05-21 16:58:45 +0200843 snprintf(buf, sizeof(buf), "READ %s DEBUG %s\r\n",
844 id, attr ? attr : "");
Paul Cercueil99cf3d42014-03-06 12:35:26 +0100845 else
Paul Cercueil2a3e43d2014-05-21 16:58:45 +0200846 snprintf(buf, sizeof(buf), "READ %s %s\r\n",
847 id, attr ? attr : "");
Paul Cercueil1494b862014-05-05 12:49:07 +0200848
Paul Cercueil388dcd62015-11-27 15:15:48 +0100849 iio_mutex_lock(pdata->lock);
Paul Cercueilbb76bf92014-03-11 10:20:18 +0100850 read_len = exec_command(buf, fd);
Paul Cercueil1494b862014-05-05 12:49:07 +0200851 if (read_len < 0) {
Paul Cercueil388dcd62015-11-27 15:15:48 +0100852 iio_mutex_unlock(pdata->lock);
Paul Cercueilbb76bf92014-03-11 10:20:18 +0100853 return (ssize_t) read_len;
Paul Cercueil1494b862014-05-05 12:49:07 +0200854 }
Paul Cercueil3e94a5b2014-03-04 13:00:41 +0100855
Paul Cercueil6e7f79e2014-04-04 12:27:24 +0200856 if ((unsigned long) read_len > len) {
Paul Cercueil3e94a5b2014-03-04 13:00:41 +0100857 ERROR("Value returned by server is too large\n");
Paul Cercueil388dcd62015-11-27 15:15:48 +0100858 iio_mutex_unlock(pdata->lock);
Paul Cercueil3e94a5b2014-03-04 13:00:41 +0100859 return -EIO;
860 }
861
862 ret = read_all(dst, read_len, fd);
Paul Cercueil388dcd62015-11-27 15:15:48 +0100863 iio_mutex_unlock(pdata->lock);
Paul Cercueil1494b862014-05-05 12:49:07 +0200864
Paul Cercueil3e94a5b2014-03-04 13:00:41 +0100865 if (ret < 0) {
Paul Cercueil53fc4852015-05-22 10:57:53 +0200866 iio_strerror(-ret, buf, sizeof(buf));
Paul Cercueil3e94a5b2014-03-04 13:00:41 +0100867 ERROR("Unable to read response to READ: %s\n", buf);
868 return ret;
869 }
870
Paul Cercueil7d95fd72014-05-22 14:26:44 +0200871 return read_len;
Paul Cercueil3e94a5b2014-03-04 13:00:41 +0100872}
873
Paul Cercueil1494b862014-05-05 12:49:07 +0200874static ssize_t network_write_attr_helper(const struct iio_device *dev,
Paul Cercueil0cc0e162014-05-07 12:51:22 +0200875 const struct iio_channel *chn, const char *attr,
876 const char *src, size_t len, bool is_debug)
Paul Cercueil3e94a5b2014-03-04 13:00:41 +0100877{
Paul Cercueila62f84e2015-02-24 14:16:08 +0100878 struct iio_context_pdata *pdata = dev->ctx->pdata;
879 int fd;
880 ssize_t ret;
881 long resp;
Paul Cercueil3e94a5b2014-03-04 13:00:41 +0100882 char buf[1024];
Paul Cercueil1494b862014-05-05 12:49:07 +0200883 const char *id = dev->id;
Paul Cercueil3e94a5b2014-03-04 13:00:41 +0100884
Paul Cercueil07897d32014-03-06 12:46:08 +0100885 if (chn)
Paul Cercueil0cc0e162014-05-07 12:51:22 +0200886 snprintf(buf, sizeof(buf), "WRITE %s %s %s %s %lu\r\n",
887 id, chn->is_output ? "OUTPUT" : "INPUT",
Paul Cercueil8747efe2014-05-22 11:12:12 +0200888 chn->id, attr ? attr : "", (unsigned long) len);
Paul Cercueilc6f03612014-04-14 16:41:31 +0200889 else if (is_debug)
Paul Cercueil8747efe2014-05-22 11:12:12 +0200890 snprintf(buf, sizeof(buf), "WRITE %s DEBUG %s %lu\r\n",
891 id, attr ? attr : "", (unsigned long) len);
Paul Cercueil07897d32014-03-06 12:46:08 +0100892 else
Paul Cercueilcecda352014-05-06 18:14:29 +0200893 snprintf(buf, sizeof(buf), "WRITE %s %s %lu\r\n",
Paul Cercueil8747efe2014-05-22 11:12:12 +0200894 id, attr ? attr : "", (unsigned long) len);
Paul Cercueila62f84e2015-02-24 14:16:08 +0100895
Paul Cercueil388dcd62015-11-27 15:15:48 +0100896 iio_mutex_lock(pdata->lock);
Paul Cercueila62f84e2015-02-24 14:16:08 +0100897 fd = pdata->fd;
898 ret = (ssize_t) write_command(buf, fd);
899 if (ret < 0)
900 goto err_unlock;
901
902 ret = write_all(src, len, fd);
903 if (ret < 0)
904 goto err_unlock;
905
906 ret = read_integer(fd, &resp);
Paul Cercueil388dcd62015-11-27 15:15:48 +0100907 iio_mutex_unlock(pdata->lock);
Paul Cercueila62f84e2015-02-24 14:16:08 +0100908
909 if (ret < 0)
910 return ret;
911 return (ssize_t) resp;
912
913err_unlock:
Paul Cercueil388dcd62015-11-27 15:15:48 +0100914 iio_mutex_unlock(pdata->lock);
Paul Cercueila62f84e2015-02-24 14:16:08 +0100915 return ret;
Paul Cercueil3e94a5b2014-03-04 13:00:41 +0100916}
917
Paul Cercueil99cf3d42014-03-06 12:35:26 +0100918static ssize_t network_read_dev_attr(const struct iio_device *dev,
Paul Cercueil50c762a2014-04-14 15:55:43 +0200919 const char *attr, char *dst, size_t len, bool is_debug)
Paul Cercueil99cf3d42014-03-06 12:35:26 +0100920{
Paul Cercueil5b577762014-06-03 15:31:42 +0200921 if (attr && ((is_debug && !iio_device_find_debug_attr(dev, attr)) ||
922 (!is_debug && !iio_device_find_attr(dev, attr))))
923 return -ENOENT;
924
Paul Cercueil1494b862014-05-05 12:49:07 +0200925 return network_read_attr_helper(dev, NULL, attr, dst, len, is_debug);
Paul Cercueil99cf3d42014-03-06 12:35:26 +0100926}
927
Paul Cercueil07897d32014-03-06 12:46:08 +0100928static ssize_t network_write_dev_attr(const struct iio_device *dev,
Paul Cercueilcecda352014-05-06 18:14:29 +0200929 const char *attr, const char *src, size_t len, bool is_debug)
Paul Cercueil07897d32014-03-06 12:46:08 +0100930{
Paul Cercueil5b577762014-06-03 15:31:42 +0200931 if (attr && ((is_debug && !iio_device_find_debug_attr(dev, attr)) ||
932 (!is_debug && !iio_device_find_attr(dev, attr))))
933 return -ENOENT;
934
Paul Cercueilcecda352014-05-06 18:14:29 +0200935 return network_write_attr_helper(dev, NULL, attr, src, len, is_debug);
Paul Cercueil07897d32014-03-06 12:46:08 +0100936}
937
Paul Cercueil99cf3d42014-03-06 12:35:26 +0100938static ssize_t network_read_chn_attr(const struct iio_channel *chn,
939 const char *attr, char *dst, size_t len)
940{
Paul Cercueil5b577762014-06-03 15:31:42 +0200941 if (attr && !iio_channel_find_attr(chn, attr))
942 return -ENOENT;
943
Paul Cercueil0cc0e162014-05-07 12:51:22 +0200944 return network_read_attr_helper(chn->dev, chn, attr, dst, len, false);
Paul Cercueil99cf3d42014-03-06 12:35:26 +0100945}
946
Paul Cercueil07897d32014-03-06 12:46:08 +0100947static ssize_t network_write_chn_attr(const struct iio_channel *chn,
Paul Cercueilcecda352014-05-06 18:14:29 +0200948 const char *attr, const char *src, size_t len)
Paul Cercueil07897d32014-03-06 12:46:08 +0100949{
Paul Cercueil5b577762014-06-03 15:31:42 +0200950 if (attr && !iio_channel_find_attr(chn, attr))
951 return -ENOENT;
952
Paul Cercueil0cc0e162014-05-07 12:51:22 +0200953 return network_write_attr_helper(chn->dev, chn, attr, src, len, false);
Paul Cercueil07897d32014-03-06 12:46:08 +0100954}
955
Paul Cercueildcab40c2014-03-11 10:59:14 +0100956static int network_get_trigger(const struct iio_device *dev,
957 const struct iio_device **trigger)
958{
959 struct iio_context_pdata *pdata = dev->ctx->pdata;
960 unsigned int i;
961 char buf[1024];
962 ssize_t ret;
963 long resp;
964
965 snprintf(buf, sizeof(buf), "GETTRIG %s\r\n", dev->id);
Paul Cercueil1494b862014-05-05 12:49:07 +0200966
Paul Cercueil388dcd62015-11-27 15:15:48 +0100967 iio_mutex_lock(dev->ctx->pdata->lock);
Paul Cercueildcab40c2014-03-11 10:59:14 +0100968 resp = exec_command(buf, pdata->fd);
969 if (resp < 0) {
Paul Cercueil388dcd62015-11-27 15:15:48 +0100970 iio_mutex_unlock(pdata->lock);
Paul Cercueildcab40c2014-03-11 10:59:14 +0100971 return (int) resp;
972 } else if (resp == 0) {
973 *trigger = NULL;
Paul Cercueil388dcd62015-11-27 15:15:48 +0100974 iio_mutex_unlock(pdata->lock);
Paul Cercueildcab40c2014-03-11 10:59:14 +0100975 return 0;
Paul Cercueil6e7f79e2014-04-04 12:27:24 +0200976 } else if ((unsigned long) resp > sizeof(buf)) {
Paul Cercueildcab40c2014-03-11 10:59:14 +0100977 ERROR("Value returned by server is too large\n");
Paul Cercueil388dcd62015-11-27 15:15:48 +0100978 iio_mutex_unlock(pdata->lock);
Paul Cercueildcab40c2014-03-11 10:59:14 +0100979 return -EIO;
980 }
981
982 ret = read_all(buf, resp, pdata->fd);
Paul Cercueil388dcd62015-11-27 15:15:48 +0100983 iio_mutex_unlock(pdata->lock);
Paul Cercueil1494b862014-05-05 12:49:07 +0200984
Paul Cercueildcab40c2014-03-11 10:59:14 +0100985 if (ret < 0) {
Paul Cercueil53fc4852015-05-22 10:57:53 +0200986 iio_strerror(-ret, buf, sizeof(buf));
Paul Cercueildcab40c2014-03-11 10:59:14 +0100987 ERROR("Unable to read response to GETTRIG: %s\n", buf);
988 return ret;
989 }
990
Lars-Peter Clausenb5cdc102014-08-21 14:45:52 +0200991 if (buf[0] == '\0') {
992 *trigger = NULL;
993 return 0;
994 }
995
Paul Cercueildcab40c2014-03-11 10:59:14 +0100996 for (i = 0; i < dev->ctx->nb_devices; i++) {
997 struct iio_device *cur = dev->ctx->devices[i];
998 if (iio_device_is_trigger(cur) &&
999 !strncmp(cur->name, buf, resp)) {
1000 *trigger = cur;
1001 return 0;
1002 }
1003 }
1004
1005 return -ENXIO;
1006}
1007
1008static int network_set_trigger(const struct iio_device *dev,
1009 const struct iio_device *trigger)
1010{
Paul Cercueil1494b862014-05-05 12:49:07 +02001011 int ret;
Paul Cercueildcab40c2014-03-11 10:59:14 +01001012 char buf[1024];
1013 if (trigger)
1014 snprintf(buf, sizeof(buf), "SETTRIG %s %s\r\n",
1015 dev->id, trigger->id);
1016 else
1017 snprintf(buf, sizeof(buf), "SETTRIG %s\r\n", dev->id);
Paul Cercueil1494b862014-05-05 12:49:07 +02001018
Paul Cercueil388dcd62015-11-27 15:15:48 +01001019 iio_mutex_lock(dev->ctx->pdata->lock);
Paul Cercueil1494b862014-05-05 12:49:07 +02001020 ret = (int) exec_command(buf, dev->ctx->pdata->fd);
Paul Cercueil388dcd62015-11-27 15:15:48 +01001021 iio_mutex_unlock(dev->ctx->pdata->lock);
Paul Cercueil1494b862014-05-05 12:49:07 +02001022 return ret;
Paul Cercueildcab40c2014-03-11 10:59:14 +01001023}
1024
Paul Cercueil8fd9c8f2014-03-03 17:21:31 +01001025static void network_shutdown(struct iio_context *ctx)
1026{
1027 struct iio_context_pdata *pdata = ctx->pdata;
Paul Cercueil44ae11c2014-03-17 09:56:29 +01001028 unsigned int i;
Paul Cercueil8fd9c8f2014-03-03 17:21:31 +01001029
Paul Cercueil388dcd62015-11-27 15:15:48 +01001030 iio_mutex_lock(pdata->lock);
Paul Cercueilbb76bf92014-03-11 10:20:18 +01001031 write_command("\r\nEXIT\r\n", pdata->fd);
Paul Cercueil8fd9c8f2014-03-03 17:21:31 +01001032 close(pdata->fd);
Paul Cercueil388dcd62015-11-27 15:15:48 +01001033 iio_mutex_unlock(pdata->lock);
Paul Cercueil1494b862014-05-05 12:49:07 +02001034
Paul Cercueil439e1a22015-02-24 13:50:51 +01001035 for (i = 0; i < ctx->nb_devices; i++) {
1036 struct iio_device *dev = ctx->devices[i];
Paul Cercueilc5b00752015-02-24 14:29:53 +01001037 struct iio_device_pdata *dpdata = dev->pdata;
Paul Cercueil439e1a22015-02-24 13:50:51 +01001038
Paul Cercueilc5b00752015-02-24 14:29:53 +01001039 if (dpdata) {
Paul Cercueilaa0db142015-03-04 16:25:24 +01001040 network_close(dev);
Paul Cercueil388dcd62015-11-27 15:15:48 +01001041 iio_mutex_destroy(dpdata->lock);
Paul Cercueilc5b00752015-02-24 14:29:53 +01001042 free(dpdata);
Paul Cercueil439e1a22015-02-24 13:50:51 +01001043 }
1044 }
1045
Paul Cercueil388dcd62015-11-27 15:15:48 +01001046 iio_mutex_destroy(pdata->lock);
Paul Cercueil2dd2c132015-02-24 10:41:01 +01001047 freeaddrinfo(pdata->addrinfo);
Paul Cercueil8fd9c8f2014-03-03 17:21:31 +01001048 free(pdata);
1049}
1050
Paul Cercueil6691a3f2014-05-02 12:32:01 +02001051static int network_get_version(const struct iio_context *ctx,
Paul Cercueil9de9e9d2014-05-20 13:18:19 +02001052 unsigned int *major, unsigned int *minor, char git_tag[8])
Paul Cercueil6691a3f2014-05-02 12:32:01 +02001053{
1054 struct iio_context_pdata *pdata = ctx->pdata;
1055 long maj, min;
1056 int ret;
Paul Cercueil6691a3f2014-05-02 12:32:01 +02001057
Paul Cercueil388dcd62015-11-27 15:15:48 +01001058 iio_mutex_lock(pdata->lock);
Paul Cercueil1494b862014-05-05 12:49:07 +02001059 ret = (int) write_command("VERSION\r\n", pdata->fd);
1060 if (ret < 0)
1061 goto err_unlock;
1062
1063 ret = read_integer(pdata->fd, &maj);
1064 if (!ret)
1065 ret = read_integer(pdata->fd, &min);
1066 if (!ret) {
Paul Cercueil9de9e9d2014-05-20 13:18:19 +02001067 char tag[8];
1068 tag[7] = '\0';
1069
1070 ret = read_all(tag, sizeof(tag) - 1, pdata->fd);
1071 if (ret < 0)
1072 goto err_unlock;
1073
Paul Cercueild15d9952014-05-20 11:40:08 +02001074 if (major)
1075 *major = (unsigned int) maj;
1076 if (minor)
1077 *minor = (unsigned int) min;
Paul Cercueil9de9e9d2014-05-20 13:18:19 +02001078 if (git_tag)
1079 strncpy(git_tag, tag, 8);
Paul Cercueil1494b862014-05-05 12:49:07 +02001080 }
1081
Paul Cercueil8e8f8992014-06-12 16:58:12 +02001082 ret = 0;
Paul Cercueil1494b862014-05-05 12:49:07 +02001083err_unlock:
Paul Cercueil388dcd62015-11-27 15:15:48 +01001084 iio_mutex_unlock(pdata->lock);
Paul Cercueil1494b862014-05-05 12:49:07 +02001085 return ret;
Paul Cercueil6691a3f2014-05-02 12:32:01 +02001086}
1087
Paul Cercueil8a266f12014-06-10 16:06:31 +02001088static unsigned int calculate_remote_timeout(unsigned int timeout)
1089{
1090 /* XXX(pcercuei): We currently hardcode timeout / 2 for the backend used
1091 * by the remote. Is there something better to do here? */
1092 return timeout / 2;
1093}
1094
Paul Cercueilbca3dbc2014-06-11 12:00:21 +02001095static int set_remote_timeout(struct iio_context *ctx, unsigned int timeout)
1096{
1097 char buf[1024];
1098 int ret;
1099
1100 snprintf(buf, sizeof(buf), "TIMEOUT %u\r\n", timeout);
Paul Cercueil388dcd62015-11-27 15:15:48 +01001101 iio_mutex_lock(ctx->pdata->lock);
Paul Cercueilbca3dbc2014-06-11 12:00:21 +02001102 ret = (int) exec_command(buf, ctx->pdata->fd);
Paul Cercueil388dcd62015-11-27 15:15:48 +01001103 iio_mutex_unlock(ctx->pdata->lock);
Paul Cercueilbca3dbc2014-06-11 12:00:21 +02001104 return ret;
1105}
1106
1107static int network_set_timeout(struct iio_context *ctx, unsigned int timeout)
1108{
1109 int ret = set_socket_timeout(ctx->pdata->fd, timeout);
1110 if (!ret) {
1111 timeout = calculate_remote_timeout(timeout);
1112 ret = set_remote_timeout(ctx, timeout);
1113 }
1114 if (ret < 0) {
1115 char buf[1024];
Paul Cercueil53fc4852015-05-22 10:57:53 +02001116 iio_strerror(-ret, buf, sizeof(buf));
Paul Cercueil8a266f12014-06-10 16:06:31 +02001117 WARNING("Unable to set R/W timeout: %s\n", buf);
1118 } else {
Paul Cercueil8a266f12014-06-10 16:06:31 +02001119 ctx->rw_timeout_ms = timeout;
1120 }
1121 return ret;
1122}
1123
Paul Cercueil61157f92015-11-19 17:48:22 +01001124static int network_set_kernel_buffers_count(const struct iio_device *dev,
1125 unsigned int nb_blocks)
1126{
1127 int ret;
1128 char buf[1024];
1129
1130 snprintf(buf, sizeof(buf), "SET %s BUFFERS_COUNT %u\r\n",
1131 dev->id, nb_blocks);
1132
Paul Cercueil388dcd62015-11-27 15:15:48 +01001133 iio_mutex_lock(dev->ctx->pdata->lock);
Paul Cercueil61157f92015-11-19 17:48:22 +01001134 ret = (int) exec_command(buf, dev->ctx->pdata->fd);
Paul Cercueil388dcd62015-11-27 15:15:48 +01001135 iio_mutex_unlock(dev->ctx->pdata->lock);
Paul Cercueil61157f92015-11-19 17:48:22 +01001136 return ret;
1137}
1138
Paul Cercueil12d41832014-10-28 14:35:53 +01001139static struct iio_context * network_clone(const struct iio_context *ctx)
1140{
Paul Cercueil7ef45ce2015-03-16 14:36:16 +01001141 if (ctx->description) {
1142 char *ptr = strchr(ctx->description, ' ');
1143 if (ptr) {
1144#ifdef HAVE_IPV6
1145 char buf[INET6_ADDRSTRLEN + IF_NAMESIZE + 2];
1146#else
1147 char buf[INET_ADDRSTRLEN + 1];
1148#endif
1149 strncpy(buf, ctx->description, sizeof(buf) - 1);
1150 buf[ptr - ctx->description] = '\0';
1151 return iio_create_network_context(buf);
1152 }
1153 }
1154
Paul Cercueild3d56ee2015-01-08 16:36:31 +01001155 return iio_create_network_context(ctx->description);
Paul Cercueil12d41832014-10-28 14:35:53 +01001156}
1157
Paul Cercueilc7bad0f2014-03-03 17:06:48 +01001158static struct iio_backend_ops network_ops = {
Paul Cercueil12d41832014-10-28 14:35:53 +01001159 .clone = network_clone,
Paul Cercueilba059762014-03-14 11:02:02 +01001160 .open = network_open,
1161 .close = network_close,
Paul Cercueil9945bc82014-03-05 14:07:29 +01001162 .read = network_read,
Paul Cercueil2725f702014-05-02 11:02:16 +02001163 .write = network_write,
Paul Cercueil90189672015-03-16 11:41:53 +01001164#ifdef WITH_NETWORK_GET_BUFFER
Paul Cercueil09a43482015-03-04 15:50:27 +01001165 .get_buffer = network_get_buffer,
1166#endif
Paul Cercueil3e94a5b2014-03-04 13:00:41 +01001167 .read_device_attr = network_read_dev_attr,
1168 .write_device_attr = network_write_dev_attr,
Paul Cercueil99cf3d42014-03-06 12:35:26 +01001169 .read_channel_attr = network_read_chn_attr,
Paul Cercueil07897d32014-03-06 12:46:08 +01001170 .write_channel_attr = network_write_chn_attr,
Paul Cercueildcab40c2014-03-11 10:59:14 +01001171 .get_trigger = network_get_trigger,
1172 .set_trigger = network_set_trigger,
Paul Cercueil8fd9c8f2014-03-03 17:21:31 +01001173 .shutdown = network_shutdown,
Paul Cercueil6691a3f2014-05-02 12:32:01 +02001174 .get_version = network_get_version,
Paul Cercueil8a266f12014-06-10 16:06:31 +02001175 .set_timeout = network_set_timeout,
Paul Cercueil61157f92015-11-19 17:48:22 +01001176 .set_kernel_buffers_count = network_set_kernel_buffers_count,
Paul Cercueilc7bad0f2014-03-03 17:06:48 +01001177};
1178
1179static struct iio_context * get_context(int fd)
1180{
1181 struct iio_context *ctx;
Paul Cercueile60c3ed2014-03-04 11:23:56 +01001182 char *xml;
Paul Cercueilbb76bf92014-03-11 10:20:18 +01001183 long xml_len = exec_command("PRINT\r\n", fd);
Paul Cercueilcc575532015-03-16 17:15:24 +01001184 if (xml_len < 0) {
1185 errno = (int) -xml_len;
Paul Cercueilc7bad0f2014-03-03 17:06:48 +01001186 return NULL;
Paul Cercueilcc575532015-03-16 17:15:24 +01001187 }
Paul Cercueile60c3ed2014-03-04 11:23:56 +01001188
1189 DEBUG("Server returned a XML string of length %li\n", xml_len);
Paul Cercueilc7bad0f2014-03-03 17:06:48 +01001190 xml = malloc(xml_len);
1191 if (!xml) {
Paul Cercueilcc575532015-03-16 17:15:24 +01001192 errno = ENOMEM;
Paul Cercueilc7bad0f2014-03-03 17:06:48 +01001193 return NULL;
1194 }
1195
1196 DEBUG("Reading XML string...\n");
1197 read_all(xml, xml_len, fd);
1198
1199 DEBUG("Creating context from XML...\n");
1200 ctx = iio_create_xml_context_mem(xml, xml_len);
Paul Cercueilfd387472015-08-05 10:34:19 +02001201 free(xml);
Paul Cercueilc7bad0f2014-03-03 17:06:48 +01001202 return ctx;
1203}
1204
Paul Cercueil63e52182014-12-11 12:52:48 +01001205struct iio_context * network_create_context(const char *host)
Paul Cercueilc7bad0f2014-03-03 17:06:48 +01001206{
Paul Cercueil2e38bbe2014-03-19 15:27:15 +01001207 struct addrinfo hints, *res;
Paul Cercueilc7bad0f2014-03-03 17:06:48 +01001208 struct iio_context *ctx;
Paul Cercueil8fd9c8f2014-03-03 17:21:31 +01001209 struct iio_context_pdata *pdata;
Paul Cercueil0e3c04d2015-05-13 17:37:11 +02001210 size_t i, len;
Paul Cercueil4970ac32015-02-24 10:59:00 +01001211 int fd, ret;
Paul Cercueilb03c9ef2015-03-16 14:07:58 +01001212 char *description;
Paul Cercueil1fef1a52014-04-07 16:31:15 +02001213#ifdef _WIN32
1214 WSADATA wsaData;
1215
1216 ret = WSAStartup(MAKEWORD(2, 0), &wsaData);
1217 if (ret < 0) {
1218 ERROR("WSAStartup failed with error %i\n", ret);
Paul Cercueilcc575532015-03-16 17:15:24 +01001219 errno = -ret;
Paul Cercueil1fef1a52014-04-07 16:31:15 +02001220 return NULL;
1221 }
1222#endif
Paul Cercueilc7bad0f2014-03-03 17:06:48 +01001223
Paul Cercueil2e38bbe2014-03-19 15:27:15 +01001224 memset(&hints, 0, sizeof(hints));
1225 hints.ai_family = AF_UNSPEC;
1226 hints.ai_socktype = SOCK_STREAM;
Paul Cercueilab114932014-05-19 13:03:17 +02001227
1228#ifdef HAVE_AVAHI
1229 if (!host) {
1230 char addr_str[AVAHI_ADDRESS_STR_MAX];
1231 char port_str[6];
1232 AvahiAddress address;
Paul Cercueil0f729d32014-06-05 17:38:54 +02001233 uint16_t port = IIOD_PORT;
Paul Cercueilab114932014-05-19 13:03:17 +02001234
1235 memset(&address, 0, sizeof(address));
1236
1237 ret = discover_host(&address, &port);
1238 if (ret < 0) {
Paul Cercueilcc575532015-03-16 17:15:24 +01001239 DEBUG("Unable to find host: %s\n", strerror(-ret));
1240 errno = -ret;
Paul Cercueilab114932014-05-19 13:03:17 +02001241 return NULL;
1242 }
1243
1244 avahi_address_snprint(addr_str, sizeof(addr_str), &address);
1245 snprintf(port_str, sizeof(port_str), "%hu", port);
1246 ret = getaddrinfo(addr_str, port_str, &hints, &res);
1247 } else
1248#endif
1249 {
1250 ret = getaddrinfo(host, IIOD_PORT_STR, &hints, &res);
1251 }
1252
Paul Cercueil2e38bbe2014-03-19 15:27:15 +01001253 if (ret) {
Paul Cercueilab114932014-05-19 13:03:17 +02001254 ERROR("Unable to find host: %s\n", gai_strerror(ret));
Paul Cercueild9eb4cb2015-03-23 14:30:20 +01001255#ifndef _WIN32
Paul Cercueilcc575532015-03-16 17:15:24 +01001256 if (ret != EAI_SYSTEM)
1257 errno = ret;
Paul Cercueild9eb4cb2015-03-23 14:30:20 +01001258#endif
Paul Cercueilc7bad0f2014-03-03 17:06:48 +01001259 return NULL;
Paul Cercueilc7bad0f2014-03-03 17:06:48 +01001260 }
1261
Paul Cercueil4970ac32015-02-24 10:59:00 +01001262 fd = create_socket(res);
Paul Cercueilcc575532015-03-16 17:15:24 +01001263 if (fd < 0) {
1264 errno = fd;
Paul Cercueil2dd2c132015-02-24 10:41:01 +01001265 goto err_free_addrinfo;
Paul Cercueilcc575532015-03-16 17:15:24 +01001266 }
Paul Cercueilbca3dbc2014-06-11 12:00:21 +02001267
Paul Cercueil8fd9c8f2014-03-03 17:21:31 +01001268 pdata = calloc(1, sizeof(*pdata));
1269 if (!pdata) {
Paul Cercueilcc575532015-03-16 17:15:24 +01001270 errno = ENOMEM;
Paul Cercueil8fd9c8f2014-03-03 17:21:31 +01001271 goto err_close_socket;
1272 }
1273
1274 pdata->fd = fd;
Paul Cercueil2dd2c132015-02-24 10:41:01 +01001275 pdata->addrinfo = res;
Paul Cercueil8fd9c8f2014-03-03 17:21:31 +01001276
Paul Cercueilc7bad0f2014-03-03 17:06:48 +01001277 DEBUG("Creating context...\n");
1278 ctx = get_context(fd);
1279 if (!ctx)
Paul Cercueild3d56ee2015-01-08 16:36:31 +01001280 goto err_free_pdata;
Paul Cercueilc7bad0f2014-03-03 17:06:48 +01001281
Paul Cercueil2057fd32014-10-28 14:44:19 +01001282 /* Override the name and low-level functions of the XML context
1283 * with those corresponding to the network context */
1284 ctx->name = "network";
1285 ctx->ops = &network_ops;
1286 ctx->pdata = pdata;
1287
Paul Cercueil06c479d2015-01-08 16:14:57 +01001288#ifdef HAVE_IPV6
Paul Cercueiled15e492015-01-12 15:52:28 +01001289 len = INET6_ADDRSTRLEN + IF_NAMESIZE + 2;
Paul Cercueil06c479d2015-01-08 16:14:57 +01001290#else
1291 len = INET_ADDRSTRLEN + 1;
1292#endif
Paul Cercueilb03c9ef2015-03-16 14:07:58 +01001293
1294 description = malloc(len);
1295 if (!description) {
Paul Cercueilcc575532015-03-16 17:15:24 +01001296 ret = -ENOMEM;
Paul Cercueil06c479d2015-01-08 16:14:57 +01001297 goto err_network_shutdown;
1298 }
1299
Paul Cercueilb03c9ef2015-03-16 14:07:58 +01001300 description[0] = '\0';
Paul Cercueil06c479d2015-01-08 16:14:57 +01001301
1302#ifdef HAVE_IPV6
1303 if (res->ai_family == AF_INET6) {
1304 struct sockaddr_in6 *in = (struct sockaddr_in6 *) res->ai_addr;
Paul Cercueiled15e492015-01-12 15:52:28 +01001305 char *ptr;
Paul Cercueil06c479d2015-01-08 16:14:57 +01001306 inet_ntop(AF_INET6, &in->sin6_addr,
Paul Cercueilb03c9ef2015-03-16 14:07:58 +01001307 description, INET6_ADDRSTRLEN);
Paul Cercueiled15e492015-01-12 15:52:28 +01001308
Paul Cercueilb03c9ef2015-03-16 14:07:58 +01001309 ptr = if_indextoname(in->sin6_scope_id, description +
1310 strlen(description) + 1);
Paul Cercueiled15e492015-01-12 15:52:28 +01001311 if (!ptr) {
Paul Cercueilcc575532015-03-16 17:15:24 +01001312 ret = -errno;
Paul Cercueiled15e492015-01-12 15:52:28 +01001313 ERROR("Unable to lookup interface of IPv6 address\n");
Paul Cercueilb03c9ef2015-03-16 14:07:58 +01001314 goto err_free_description;
Paul Cercueiled15e492015-01-12 15:52:28 +01001315 }
1316
1317 *(ptr - 1) = '%';
Paul Cercueil06c479d2015-01-08 16:14:57 +01001318 }
1319#endif
1320 if (res->ai_family == AF_INET) {
1321 struct sockaddr_in *in = (struct sockaddr_in *) res->ai_addr;
Paul Cercueile7a31692015-07-15 10:52:47 +02001322#if (!_WIN32 || _WIN32_WINNT >= 0x600)
Paul Cercueilb03c9ef2015-03-16 14:07:58 +01001323 inet_ntop(AF_INET, &in->sin_addr, description, INET_ADDRSTRLEN);
Paul Cercueile7a31692015-07-15 10:52:47 +02001324#else
1325 char *tmp = inet_ntoa(in->sin_addr);
1326 strncpy(description, tmp, len);
1327#endif
Paul Cercueil06c479d2015-01-08 16:14:57 +01001328 }
1329
Paul Cercueil44ae11c2014-03-17 09:56:29 +01001330 for (i = 0; i < ctx->nb_devices; i++) {
1331 struct iio_device *dev = ctx->devices[i];
Paul Cercueilff778232014-03-24 14:23:08 +01001332
Paul Cercueil439e1a22015-02-24 13:50:51 +01001333 dev->pdata = calloc(1, sizeof(*dev->pdata));
1334 if (!dev->pdata) {
Paul Cercueilcc575532015-03-16 17:15:24 +01001335 ret = -ENOMEM;
Paul Cercueilb03c9ef2015-03-16 14:07:58 +01001336 goto err_free_description;
Paul Cercueil439e1a22015-02-24 13:50:51 +01001337 }
1338
1339 dev->pdata->fd = -1;
Paul Cercueil90189672015-03-16 11:41:53 +01001340#ifdef WITH_NETWORK_GET_BUFFER
Paul Cercueil09a43482015-03-04 15:50:27 +01001341 dev->pdata->memfd = -1;
Paul Cercueile6e5a092015-03-04 16:33:26 +01001342#endif
Paul Cercueilc5b00752015-02-24 14:29:53 +01001343
Paul Cercueil388dcd62015-11-27 15:15:48 +01001344 dev->pdata->lock = iio_mutex_create();
1345 if (!dev->pdata->lock) {
1346 ret = -ENOMEM;
Paul Cercueilb03c9ef2015-03-16 14:07:58 +01001347 goto err_free_description;
Paul Cercueil388dcd62015-11-27 15:15:48 +01001348 }
Paul Cercueil44ae11c2014-03-17 09:56:29 +01001349 }
1350
Paul Cercueilfd387472015-08-05 10:34:19 +02001351 ret = iio_context_init(ctx);
1352 if (ret < 0)
1353 goto err_free_description;
Paul Cercueil4c6729d2014-04-04 17:24:41 +02001354
Paul Cercueil388dcd62015-11-27 15:15:48 +01001355 pdata->lock = iio_mutex_create();
1356 if (!pdata->lock) {
1357 ret = -ENOMEM;
Paul Cercueilb03c9ef2015-03-16 14:07:58 +01001358 goto err_free_description;
Paul Cercueil388dcd62015-11-27 15:15:48 +01001359 }
Paul Cercueil1494b862014-05-05 12:49:07 +02001360
Paul Cercueilb03c9ef2015-03-16 14:07:58 +01001361 if (ctx->description) {
Paul Cercueil0e3c04d2015-05-13 17:37:11 +02001362 size_t desc_len = strlen(description);
1363 size_t new_size = desc_len + strlen(ctx->description) + 2;
Paul Cercueilb03c9ef2015-03-16 14:07:58 +01001364 char *ptr, *new_description = realloc(description, new_size);
Paul Cercueilcc575532015-03-16 17:15:24 +01001365 if (!new_description) {
1366 ret = -ENOMEM;
Paul Cercueilb03c9ef2015-03-16 14:07:58 +01001367 goto err_free_description;
Paul Cercueilcc575532015-03-16 17:15:24 +01001368 }
Paul Cercueilb03c9ef2015-03-16 14:07:58 +01001369
1370 ptr = strrchr(new_description, '\0');
Paul Cercueil0e3c04d2015-05-13 17:37:11 +02001371 snprintf(ptr, new_size - desc_len, " %s", ctx->description);
Paul Cercueilb03c9ef2015-03-16 14:07:58 +01001372 free(ctx->description);
1373
1374 ctx->description = new_description;
1375 } else {
1376 ctx->description = description;
1377 }
1378
Paul Cercueilbca3dbc2014-06-11 12:00:21 +02001379 set_remote_timeout(ctx, calculate_remote_timeout(DEFAULT_TIMEOUT_MS));
Paul Cercueilc7bad0f2014-03-03 17:06:48 +01001380 return ctx;
1381
Paul Cercueilb03c9ef2015-03-16 14:07:58 +01001382err_free_description:
1383 free(description);
Paul Cercueil44ae11c2014-03-17 09:56:29 +01001384err_network_shutdown:
Paul Cercueil44ae11c2014-03-17 09:56:29 +01001385 iio_context_destroy(ctx);
Paul Cercueilcc575532015-03-16 17:15:24 +01001386 errno = -ret;
Paul Cercueil2057fd32014-10-28 14:44:19 +01001387 return NULL;
Paul Cercueil8fd9c8f2014-03-03 17:21:31 +01001388err_free_pdata:
1389 free(pdata);
Paul Cercueilc7bad0f2014-03-03 17:06:48 +01001390err_close_socket:
1391 close(fd);
Paul Cercueil2dd2c132015-02-24 10:41:01 +01001392err_free_addrinfo:
1393 freeaddrinfo(res);
Paul Cercueilc7bad0f2014-03-03 17:06:48 +01001394 return NULL;
1395}