blob: 963ddea4d624a5b8cd95a8f5c47e88c0274d45e7 [file] [log] [blame]
Paul Cercueilc7bad0f2014-03-03 17:06:48 +01001/*
2 * libiio - Library for interfacing industrial I/O (IIO) devices
3 *
4 * Copyright (C) 2014 Analog Devices, Inc.
5 * Author: Paul Cercueil <paul.cercueil@analog.com>
6 *
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
11 *
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
16 *
17 * */
18
Paul Cercueilc7bad0f2014-03-03 17:06:48 +010019#include "iio-private.h"
20
Paul Cercueil9aabe892014-09-02 12:33:46 +020021#ifndef HAVE_PTHREAD
22#define HAVE_PTHREAD 1
23#endif
24
Paul Cercueilc7bad0f2014-03-03 17:06:48 +010025#include <errno.h>
Paul Cercueila7d445b2014-11-11 16:00:15 +010026#include <fcntl.h>
Paul Cercueile60c3ed2014-03-04 11:23:56 +010027#include <stdbool.h>
Paul Cercueilc7bad0f2014-03-03 17:06:48 +010028#include <string.h>
29#include <sys/types.h>
Paul Cercueilab114932014-05-19 13:03:17 +020030#include <time.h>
Paul Cercueil1fef1a52014-04-07 16:31:15 +020031
32#ifdef _WIN32
Paul Cercueil06c479d2015-01-08 16:14:57 +010033/* Override the default version of Windows supported by MinGW.
34 * This is required to use the function inet_ntop. */
35#undef _WIN32_WINNT
36#define _WIN32_WINNT 0x0600
37
Paul Cercueil1fef1a52014-04-07 16:31:15 +020038#include <winsock2.h>
39#include <ws2tcpip.h>
40#define close(s) closesocket(s)
41
42/* winsock2.h defines ERROR, we don't want that */
43#undef ERROR
44
45#else /* _WIN32 */
Paul Cercueil06c479d2015-01-08 16:14:57 +010046#include <arpa/inet.h>
Paul Cercueil1fef1a52014-04-07 16:31:15 +020047#include <netdb.h>
Paul Cercueil0c3ce452015-02-05 16:37:42 +010048#include <netinet/in.h>
Paul Cercueil0b584e12015-01-28 11:47:03 +010049#include <netinet/tcp.h>
Paul Cercueiled15e492015-01-12 15:52:28 +010050#include <net/if.h>
Paul Cercueil09a43482015-03-04 15:50:27 +010051#include <sys/mman.h>
Paul Cercueil83628b32014-11-24 11:26:21 +010052#include <sys/select.h>
Paul Cercueilc7bad0f2014-03-03 17:06:48 +010053#include <sys/socket.h>
54#include <unistd.h>
Paul Cercueil1fef1a52014-04-07 16:31:15 +020055#endif /* _WIN32 */
56
Paul Cercueil257e6ca2014-12-09 17:32:47 +010057#if HAVE_PTHREAD
58#include <pthread.h>
59#endif
60
Paul Cercueilab114932014-05-19 13:03:17 +020061#ifdef HAVE_AVAHI
62#include <avahi-client/client.h>
63#include <avahi-common/error.h>
64#include <avahi-client/lookup.h>
65#include <avahi-common/simple-watch.h>
66#endif
67
Paul Cercueil1fef1a52014-04-07 16:31:15 +020068#include "debug.h"
Paul Cercueilc7bad0f2014-03-03 17:06:48 +010069
Paul Cercueil8a266f12014-06-10 16:06:31 +020070#define DEFAULT_TIMEOUT_MS 5000
71
Paul Cercueil2e38bbe2014-03-19 15:27:15 +010072#define _STRINGIFY(x) #x
73#define STRINGIFY(x) _STRINGIFY(x)
74
Paul Cercueilc7bad0f2014-03-03 17:06:48 +010075#define IIOD_PORT 30431
Paul Cercueil2e38bbe2014-03-19 15:27:15 +010076#define IIOD_PORT_STR STRINGIFY(IIOD_PORT)
Paul Cercueilc7bad0f2014-03-03 17:06:48 +010077
Paul Cercueil8fd9c8f2014-03-03 17:21:31 +010078struct iio_context_pdata {
79 int fd;
Paul Cercueil2dd2c132015-02-24 10:41:01 +010080 struct addrinfo *addrinfo;
Paul Cercueil05e26262014-05-09 11:32:43 +020081#if HAVE_PTHREAD
Paul Cercueil1494b862014-05-05 12:49:07 +020082 pthread_mutex_t lock;
Paul Cercueil05e26262014-05-09 11:32:43 +020083#endif
Paul Cercueil8fd9c8f2014-03-03 17:21:31 +010084};
85
Paul Cercueil439e1a22015-02-24 13:50:51 +010086struct iio_device_pdata {
87 int fd;
Paul Cercueil90189672015-03-16 11:41:53 +010088#ifdef WITH_NETWORK_GET_BUFFER
Paul Cercueil09a43482015-03-04 15:50:27 +010089 int memfd;
Paul Cercueile6e5a092015-03-04 16:33:26 +010090 void *mmap_addr;
Paul Cercueil09a43482015-03-04 15:50:27 +010091 size_t mmap_len;
Paul Cercueile6e5a092015-03-04 16:33:26 +010092#endif
Paul Cercueil09a43482015-03-04 15:50:27 +010093 bool wait_for_err_code, is_cyclic, is_tx;
Paul Cercueilc5b00752015-02-24 14:29:53 +010094#if HAVE_PTHREAD
95 pthread_mutex_t lock;
96#endif
Paul Cercueil439e1a22015-02-24 13:50:51 +010097};
98
Paul Cercueilab114932014-05-19 13:03:17 +020099#ifdef HAVE_AVAHI
100struct avahi_discovery_data {
101 AvahiSimplePoll *poll;
102 AvahiAddress *address;
103 uint16_t *port;
104 bool found, resolved;
105};
106
107static void __avahi_resolver_cb(AvahiServiceResolver *resolver,
108 __notused AvahiIfIndex iface, __notused AvahiProtocol proto,
109 __notused AvahiResolverEvent event, __notused const char *name,
110 __notused const char *type, __notused const char *domain,
111 __notused const char *host_name, const AvahiAddress *address,
112 uint16_t port, __notused AvahiStringList *txt,
113 __notused AvahiLookupResultFlags flags, void *d)
114{
115 struct avahi_discovery_data *ddata = (struct avahi_discovery_data *) d;
116
117 memcpy(ddata->address, address, sizeof(*address));
118 *ddata->port = port;
119 ddata->resolved = true;
120 avahi_service_resolver_free(resolver);
121}
122
123static void __avahi_browser_cb(AvahiServiceBrowser *browser,
124 AvahiIfIndex iface, AvahiProtocol proto,
125 AvahiBrowserEvent event, const char *name,
126 const char *type, const char *domain,
127 __notused AvahiLookupResultFlags flags, void *d)
128{
129 struct avahi_discovery_data *ddata = (struct avahi_discovery_data *) d;
130 struct AvahiClient *client = avahi_service_browser_get_client(browser);
131
132 switch (event) {
133 default:
134 case AVAHI_BROWSER_NEW:
135 ddata->found = !!avahi_service_resolver_new(client, iface,
136 proto, name, type, domain,
137 AVAHI_PROTO_UNSPEC, 0,
138 __avahi_resolver_cb, d);
139 break;
140 case AVAHI_BROWSER_ALL_FOR_NOW:
141 if (ddata->found) {
142 while (!ddata->resolved) {
143 struct timespec ts;
144 ts.tv_sec = 0;
145 ts.tv_nsec = 4000000;
146 nanosleep(&ts, NULL);
147 }
148 }
149 case AVAHI_BROWSER_FAILURE: /* fall-through */
150 avahi_simple_poll_quit(ddata->poll);
151 case AVAHI_BROWSER_CACHE_EXHAUSTED: /* fall-through */
152 break;
153 }
154}
155
156static int discover_host(AvahiAddress *addr, uint16_t *port)
157{
158 struct avahi_discovery_data ddata;
159 int ret = 0;
160 AvahiClient *client;
161 AvahiServiceBrowser *browser;
162 AvahiSimplePoll *poll = avahi_simple_poll_new();
163 if (!poll)
164 return -ENOMEM;
165
166 client = avahi_client_new(avahi_simple_poll_get(poll),
167 0, NULL, NULL, &ret);
168 if (!client) {
169 ERROR("Unable to start ZeroConf client :%s\n",
170 avahi_strerror(ret));
171 goto err_free_poll;
172 }
173
174 memset(&ddata, 0, sizeof(ddata));
175 ddata.poll = poll;
176 ddata.address = addr;
177 ddata.port = port;
178
179 browser = avahi_service_browser_new(client,
180 AVAHI_IF_UNSPEC, AVAHI_PROTO_UNSPEC,
181 "_iio._tcp", NULL, 0, __avahi_browser_cb, &ddata);
182 if (!browser) {
183 ret = avahi_client_errno(client);
184 ERROR("Unable to create ZeroConf browser: %s\n",
185 avahi_strerror(ret));
186 goto err_free_client;
187 }
188
189 DEBUG("Trying to discover host\n");
190 avahi_simple_poll_loop(poll);
191
192 if (!ddata.found)
193 ret = ENXIO;
194
195 avahi_service_browser_free(browser);
196err_free_client:
197 avahi_client_free(client);
198err_free_poll:
199 avahi_simple_poll_free(poll);
200 return -ret; /* we want a negative error code */
201}
202#endif /* HAVE_AVAHI */
203
Paul Cercueil05e26262014-05-09 11:32:43 +0200204static void network_lock(struct iio_context_pdata *pdata)
205{
206#if HAVE_PTHREAD
207 pthread_mutex_lock(&pdata->lock);
208#endif
209}
210
211static void network_unlock(struct iio_context_pdata *pdata)
212{
213#if HAVE_PTHREAD
214 pthread_mutex_unlock(&pdata->lock);
215#endif
216}
217
Paul Cercueilc5b00752015-02-24 14:29:53 +0100218static void network_lock_dev(struct iio_device_pdata *pdata)
219{
220#if HAVE_PTHREAD
221 pthread_mutex_lock(&pdata->lock);
222#endif
223}
224
225static void network_unlock_dev(struct iio_device_pdata *pdata)
226{
227#if HAVE_PTHREAD
228 pthread_mutex_unlock(&pdata->lock);
229#endif
230}
231
Paul Cercueilc7bad0f2014-03-03 17:06:48 +0100232static ssize_t write_all(const void *src, size_t len, int fd)
233{
Paul Cercueil6e7f79e2014-04-04 12:27:24 +0200234 uintptr_t ptr = (uintptr_t) src;
Paul Cercueilc7bad0f2014-03-03 17:06:48 +0100235 while (len) {
Paul Cercueil6e7f79e2014-04-04 12:27:24 +0200236 ssize_t ret = send(fd, (const void *) ptr, len, 0);
Lars-Peter Clausencb7b8bf2014-12-05 16:08:52 +0100237 if (ret < 0) {
238 if (errno == EINTR) {
239 continue;
240 }
Paul Cercueilc7bad0f2014-03-03 17:06:48 +0100241 return -errno;
Lars-Peter Clausencb7b8bf2014-12-05 16:08:52 +0100242 }
Paul Cercueilc7bad0f2014-03-03 17:06:48 +0100243 ptr += ret;
244 len -= ret;
245 }
Paul Cercueil6e7f79e2014-04-04 12:27:24 +0200246 return ptr - (uintptr_t) src;
Paul Cercueilc7bad0f2014-03-03 17:06:48 +0100247}
248
249static ssize_t read_all(void *dst, size_t len, int fd)
250{
Paul Cercueil6e7f79e2014-04-04 12:27:24 +0200251 uintptr_t ptr = (uintptr_t) dst;
Paul Cercueilc7bad0f2014-03-03 17:06:48 +0100252 while (len) {
Paul Cercueil6e7f79e2014-04-04 12:27:24 +0200253 ssize_t ret = recv(fd, (void *) ptr, len, 0);
Lars-Peter Clausencb7b8bf2014-12-05 16:08:52 +0100254 if (ret < 0) {
255 if (errno == EINTR)
256 continue;
Paul Cercueilc7bad0f2014-03-03 17:06:48 +0100257 return -errno;
Lars-Peter Clausencb7b8bf2014-12-05 16:08:52 +0100258 }
Paul Cercueil43eb7e82014-11-13 12:46:59 +0100259 if (ret == 0)
260 return -EPIPE;
Paul Cercueilc7bad0f2014-03-03 17:06:48 +0100261 ptr += ret;
262 len -= ret;
263 }
Paul Cercueil6e7f79e2014-04-04 12:27:24 +0200264 return ptr - (uintptr_t) dst;
Paul Cercueilc7bad0f2014-03-03 17:06:48 +0100265}
266
Paul Cercueile60c3ed2014-03-04 11:23:56 +0100267static int read_integer(int fd, long *val)
268{
269 unsigned int i;
270 char buf[1024], *ptr;
271 ssize_t ret;
272 bool found = false;
273
274 for (i = 0; i < sizeof(buf) - 1; i++) {
275 ret = read_all(buf + i, 1, fd);
276 if (ret < 0)
277 return (int) ret;
278
Paul Cercueil6691a3f2014-05-02 12:32:01 +0200279 /* Skip the eventual first few carriage returns.
280 * Also stop when a dot is found (for parsing floats) */
281 if (buf[i] != '\n' && buf[i] != '.')
Paul Cercueile60c3ed2014-03-04 11:23:56 +0100282 found = true;
283 else if (found)
284 break;
285 }
286
287 buf[i] = '\0';
288 ret = (ssize_t) strtol(buf, &ptr, 10);
289 if (ptr == buf)
290 return -EINVAL;
291 *val = (long) ret;
292 return 0;
293}
294
Paul Cercueilbb76bf92014-03-11 10:20:18 +0100295static ssize_t write_command(const char *cmd, int fd)
296{
297 ssize_t ret;
298
299 DEBUG("Writing command: %s\n", cmd);
300 ret = write_all(cmd, strlen(cmd), fd);
301 if (ret < 0) {
302 char buf[1024];
303 strerror_r(-ret, buf, sizeof(buf));
304 ERROR("Unable to send command: %s\n", buf);
305 }
306 return ret;
307}
308
309static long exec_command(const char *cmd, int fd)
310{
311 long resp;
312 ssize_t ret = write_command(cmd, fd);
313 if (ret < 0)
314 return (long) ret;
315
316 DEBUG("Reading response\n");
317 ret = read_integer(fd, &resp);
318 if (ret < 0) {
319 char buf[1024];
320 strerror_r(-ret, buf, sizeof(buf));
321 ERROR("Unable to read response: %s\n", buf);
322 return (long) ret;
323 }
324
Paul Cercueilc7fe2ea2014-03-28 11:38:45 +0100325#if LOG_LEVEL >= DEBUG_L
Paul Cercueilbb76bf92014-03-11 10:20:18 +0100326 if (resp < 0) {
327 char buf[1024];
328 strerror_r(-resp, buf, sizeof(buf));
Paul Cercueilc7fe2ea2014-03-28 11:38:45 +0100329 DEBUG("Server returned an error: %s\n", buf);
Paul Cercueilbb76bf92014-03-11 10:20:18 +0100330 }
Paul Cercueilc7fe2ea2014-03-28 11:38:45 +0100331#endif
332
Paul Cercueilbb76bf92014-03-11 10:20:18 +0100333 return resp;
334}
335
Paul Cercueil4970ac32015-02-24 10:59:00 +0100336#ifndef _WIN32
337static int set_blocking_mode(int fd, bool blocking)
338{
339 int ret = fcntl(fd, F_GETFL, 0);
340 if (ret < 0)
341 return -errno;
342
343 if (blocking)
344 ret &= ~O_NONBLOCK;
345 else
346 ret |= O_NONBLOCK;
347
348 ret = fcntl(fd, F_SETFL, ret);
349 return ret < 0 ? -errno : 0;
350}
351
352/* The purpose of this function is to provide a version of connect()
353 * that does not ignore timeouts... */
354static int do_connect(int fd, const struct sockaddr *addr,
355 socklen_t addrlen, struct timeval *timeout)
356{
357 int ret, error;
358 socklen_t len;
359 fd_set set;
360
361 FD_ZERO(&set);
362 FD_SET(fd, &set);
363
364 ret = set_blocking_mode(fd, false);
365 if (ret < 0)
366 return ret;
367
368 ret = connect(fd, addr, addrlen);
369 if (ret < 0 && errno != EINPROGRESS) {
370 ret = -errno;
371 goto end;
372 }
373
374 ret = select(fd + 1, &set, &set, NULL, timeout);
375 if (ret < 0) {
376 ret = -errno;
377 goto end;
378 }
379 if (ret == 0) {
380 ret = -ETIMEDOUT;
381 goto end;
382 }
383
384 /* Verify that we don't have an error */
385 len = sizeof(error);
386 ret = getsockopt(fd, SOL_SOCKET, SO_ERROR, &error, &len);
387 if(ret < 0) {
388 ret = -errno;
389 goto end;
390 }
391 if (error) {
392 ret = -error;
393 goto end;
394 }
395
396end:
397 /* Restore blocking mode */
398 set_blocking_mode(fd, true);
399 return ret;
400}
401
402static int set_socket_timeout(int fd, unsigned int timeout)
403{
404 struct timeval tv;
405
406 tv.tv_sec = timeout / 1000;
407 tv.tv_usec = (timeout % 1000) * 1000;
408 if (setsockopt(fd, SOL_SOCKET, SO_SNDTIMEO, &tv, sizeof(tv)) < 0 ||
409 setsockopt(fd, SOL_SOCKET, SO_RCVTIMEO,
410 &tv, sizeof(tv)) < 0)
411 return -errno;
412 else
413 return 0;
414}
415#else
416static int set_socket_timeout(int fd, unsigned int timeout)
417{
418 if (setsockopt(fd, SOL_SOCKET, SO_SNDTIMEO,
419 (const char *) &timeout, sizeof(timeout)) < 0 ||
420 setsockopt(fd, SOL_SOCKET, SO_RCVTIMEO,
421 (const char *) &timeout, sizeof(timeout)) < 0)
422 return -errno;
423 else
424 return 0;
425}
426#endif /* !_WIN32 */
427
428static int create_socket(const struct addrinfo *addrinfo)
429{
430 struct timeval timeout;
431 int ret, fd, yes = 1;
432
433 fd = socket(addrinfo->ai_family, addrinfo->ai_socktype, 0);
434 if (fd < 0) {
435 ERROR("Unable to open socket\n");
436 return fd;
437 }
438
439 timeout.tv_sec = DEFAULT_TIMEOUT_MS / 1000;
440 timeout.tv_usec = (DEFAULT_TIMEOUT_MS % 1000) * 1000;
441
442#ifndef _WIN32
443 ret = do_connect(fd, addrinfo->ai_addr, addrinfo->ai_addrlen, &timeout);
444#else
445 ret = connect(fd, addrinfo->ai_addr, addrinfo->ai_addrlen);
446#endif
447 if (ret < 0) {
448 ERROR("Unable to connect\n");
449 close(fd);
450 return ret;
451 }
452
453 set_socket_timeout(fd, DEFAULT_TIMEOUT_MS);
454 setsockopt(fd, IPPROTO_TCP, TCP_NODELAY,
455 (const char *) &yes, sizeof(yes));
456 return fd;
457}
458
Paul Cercueil09a43482015-03-04 15:50:27 +0100459static bool is_tx(const struct iio_device *dev)
460{
461 unsigned int i;
462
463 for (i = 0; i < dev->nb_channels; i++) {
464 struct iio_channel *ch = dev->channels[i];
465 if (iio_channel_is_output(ch) && iio_channel_is_enabled(ch))
466 return true;
467 }
468
469 return false;
470}
471
Paul Cercueil71694c72014-05-22 14:02:13 +0200472static int network_open(const struct iio_device *dev, size_t samples_count,
473 uint32_t *mask, size_t nb, bool cyclic)
Paul Cercueilba059762014-03-14 11:02:02 +0100474{
Paul Cercueil439e1a22015-02-24 13:50:51 +0100475 struct iio_context_pdata *pdata = dev->ctx->pdata;
Paul Cercueilba059762014-03-14 11:02:02 +0100476 char buf[1024], *ptr;
477 unsigned int i;
Paul Cercueil439e1a22015-02-24 13:50:51 +0100478 int ret, fd;
Paul Cercueilba059762014-03-14 11:02:02 +0100479
Paul Cercueilff778232014-03-24 14:23:08 +0100480 if (nb != dev->words)
Paul Cercueilba059762014-03-14 11:02:02 +0100481 return -EINVAL;
Paul Cercueil439e1a22015-02-24 13:50:51 +0100482 if (dev->pdata->fd >= 0)
483 return -EBUSY;
484
485 fd = create_socket(pdata->addrinfo);
486 if (fd < 0)
487 return fd;
Paul Cercueilba059762014-03-14 11:02:02 +0100488
Paul Cercueil3c407f82014-04-02 14:11:59 +0200489 snprintf(buf, sizeof(buf), "OPEN %s %lu ",
490 dev->id, (unsigned long) samples_count);
Paul Cercueilba059762014-03-14 11:02:02 +0100491 ptr = buf + strlen(buf);
492
493 for (i = nb; i > 0; i--) {
Paul Cercueil8c29e412014-04-07 09:46:45 +0200494 snprintf(ptr, (ptr - buf) + i * 8, "%08x", mask[i - 1]);
Paul Cercueilba059762014-03-14 11:02:02 +0100495 ptr += 8;
496 }
Paul Cercueil71694c72014-05-22 14:02:13 +0200497
498 strcpy(ptr, cyclic ? " CYCLIC\r\n" : "\r\n");
Paul Cercueilba059762014-03-14 11:02:02 +0100499
Paul Cercueilc5b00752015-02-24 14:29:53 +0100500 network_lock_dev(dev->pdata);
Paul Cercueil439e1a22015-02-24 13:50:51 +0100501 ret = (int) exec_command(buf, fd);
Paul Cercueilc5b00752015-02-24 14:29:53 +0100502 network_unlock_dev(dev->pdata);
Paul Cercueil1494b862014-05-05 12:49:07 +0200503
Paul Cercueil44ae11c2014-03-17 09:56:29 +0100504 if (ret < 0) {
Paul Cercueil439e1a22015-02-24 13:50:51 +0100505 close(fd);
Paul Cercueil44ae11c2014-03-17 09:56:29 +0100506 return ret;
Paul Cercueil44ae11c2014-03-17 09:56:29 +0100507 }
Paul Cercueil439e1a22015-02-24 13:50:51 +0100508
Paul Cercueil09a43482015-03-04 15:50:27 +0100509 dev->pdata->is_tx = is_tx(dev);
Paul Cercueil1d70d442015-03-04 15:00:37 +0100510 dev->pdata->is_cyclic = cyclic;
Paul Cercueil439e1a22015-02-24 13:50:51 +0100511 dev->pdata->fd = fd;
Paul Cercueil8f7f6c42015-02-24 15:00:35 +0100512 dev->pdata->wait_for_err_code = false;
Paul Cercueil439e1a22015-02-24 13:50:51 +0100513 memcpy(dev->mask, mask, nb * sizeof(*mask));
514 return 0;
Paul Cercueilba059762014-03-14 11:02:02 +0100515}
516
Paul Cercueil8f7f6c42015-02-24 15:00:35 +0100517static ssize_t read_error_code(int fd)
518{
519 /*
520 * The server returns two integer codes.
521 * The first one is returned right after the WRITEBUF command is issued,
522 * and corresponds to the error code returned when the server attempted
523 * to open the device.
524 * If zero, a second error code is returned, that corresponds (if positive)
525 * to the number of bytes written.
526 *
527 * To speed up things, we delay error reporting. We just send out the
528 * data without reading the error code that the server gives us, because
529 * the answer will take too much time. If an error occured, it will be
530 * reported by the next call to iio_buffer_push().
531 */
532
533 unsigned int i;
534 long resp = 0;
535
536 for (i = 0; i < 2; i++) {
537 ssize_t ret = read_integer(fd, &resp);
538 if (ret < 0)
539 return ret;
540 if (resp < 0)
541 return (ssize_t) resp;
542 }
543
Paul Cercueil7d7e5d32015-03-05 10:51:41 +0100544 return (ssize_t) resp;
Paul Cercueil8f7f6c42015-02-24 15:00:35 +0100545}
546
Paul Cercueil3c0da372015-03-05 11:36:39 +0100547static ssize_t write_rwbuf_command(const struct iio_device *dev,
548 const char *cmd, bool do_exec)
549{
550 struct iio_device_pdata *pdata = dev->pdata;
551 int fd = pdata->fd;
552
553 if (pdata->wait_for_err_code) {
554 ssize_t ret = read_error_code(fd);
555
556 pdata->wait_for_err_code = false;
557 if (ret < 0)
558 return ret;
559 }
560
561 return do_exec ? exec_command(cmd, fd) : write_command(cmd, fd);
562}
563
Paul Cercueilba059762014-03-14 11:02:02 +0100564static int network_close(const struct iio_device *dev)
565{
Paul Cercueil439e1a22015-02-24 13:50:51 +0100566 struct iio_device_pdata *pdata = dev->pdata;
Paul Cercueil1494b862014-05-05 12:49:07 +0200567 int ret;
Paul Cercueilba059762014-03-14 11:02:02 +0100568 char buf[1024];
Paul Cercueil439e1a22015-02-24 13:50:51 +0100569
Paul Cercueila34596e2015-03-05 14:33:46 +0100570 if (pdata->fd >= 0) {
571 snprintf(buf, sizeof(buf), "CLOSE %s\r\n", dev->id);
Paul Cercueil1494b862014-05-05 12:49:07 +0200572
Paul Cercueila34596e2015-03-05 14:33:46 +0100573 network_lock_dev(pdata);
574 ret = (int) write_rwbuf_command(dev, buf, true);
Paul Cercueil1494b862014-05-05 12:49:07 +0200575
Paul Cercueila34596e2015-03-05 14:33:46 +0100576 write_command("\r\nEXIT\r\n", pdata->fd);
Paul Cercueilaa0db142015-03-04 16:25:24 +0100577
Paul Cercueila34596e2015-03-05 14:33:46 +0100578 close(pdata->fd);
579 pdata->fd = -1;
580 network_unlock_dev(pdata);
581 }
Paul Cercueile6e5a092015-03-04 16:33:26 +0100582
Paul Cercueil90189672015-03-16 11:41:53 +0100583#ifdef WITH_NETWORK_GET_BUFFER
Paul Cercueile6e5a092015-03-04 16:33:26 +0100584 if (pdata->memfd >= 0)
585 close(pdata->memfd);
586 pdata->memfd = -1;
587
588 if (pdata->mmap_addr) {
589 munmap(pdata->mmap_addr, pdata->mmap_len);
590 pdata->mmap_addr = NULL;
591 }
592#endif
Paul Cercueil1494b862014-05-05 12:49:07 +0200593 return ret;
Paul Cercueilba059762014-03-14 11:02:02 +0100594}
595
Paul Cercueil7d7e5d32015-03-05 10:51:41 +0100596static ssize_t network_read_mask(int fd, uint32_t *mask, size_t words)
597{
598 long read_len;
599 ssize_t ret;
600
601 ret = read_integer(fd, &read_len);
602 if (ret < 0)
603 return ret;
604
605 if (read_len > 0 && mask) {
606 unsigned int i;
607 char buf[9];
608
609 buf[8] = '\0';
610 DEBUG("Reading mask\n");
611
612 for (i = words; i > 0; i--) {
613 ret = read_all(buf, 8, fd);
614 if (ret < 0)
615 return ret;
616
617 sscanf(buf, "%08x", &mask[i - 1]);
618 DEBUG("mask[%i] = 0x%x\n", i - 1, mask[i - 1]);
619 }
620 }
621
622 if (read_len > 0) {
623 char c;
624 ssize_t nb = read_all(&c, 1, fd);
625 if (nb > 0 && c != '\n')
626 read_len = -EIO;
627 }
628
629 return (ssize_t) read_len;
630}
631
Paul Cercueil45c575d2014-03-20 15:14:01 +0100632static ssize_t network_read(const struct iio_device *dev, void *dst, size_t len,
633 uint32_t *mask, size_t words)
Paul Cercueilf9286452014-03-18 14:32:17 +0100634{
Paul Cercueil6e7f79e2014-04-04 12:27:24 +0200635 uintptr_t ptr = (uintptr_t) dst;
Paul Cercueilc5b00752015-02-24 14:29:53 +0100636 struct iio_device_pdata *pdata = dev->pdata;
637 int fd = pdata->fd;
Paul Cercueil45c575d2014-03-20 15:14:01 +0100638 ssize_t ret, read = 0;
Paul Cercueil9945bc82014-03-05 14:07:29 +0100639 char buf[1024];
640
Paul Cercueil45c575d2014-03-20 15:14:01 +0100641 if (!len || words != (dev->nb_channels + 31) / 32)
Paul Cercueil9945bc82014-03-05 14:07:29 +0100642 return -EINVAL;
643
Paul Cercueila78b6eb2014-03-17 17:28:07 +0100644 snprintf(buf, sizeof(buf), "READBUF %s %lu\r\n",
645 dev->id, (unsigned long) len);
Paul Cercueil1494b862014-05-05 12:49:07 +0200646
Paul Cercueilc5b00752015-02-24 14:29:53 +0100647 network_lock_dev(pdata);
Paul Cercueil3c0da372015-03-05 11:36:39 +0100648 ret = write_rwbuf_command(dev, buf, false);
Paul Cercueil1494b862014-05-05 12:49:07 +0200649 if (ret < 0) {
Paul Cercueilc5b00752015-02-24 14:29:53 +0100650 network_unlock_dev(pdata);
Paul Cercueil9945bc82014-03-05 14:07:29 +0100651 return ret;
Paul Cercueil1494b862014-05-05 12:49:07 +0200652 }
Paul Cercueil9945bc82014-03-05 14:07:29 +0100653
654 do {
Paul Cercueil7d7e5d32015-03-05 10:51:41 +0100655 ret = network_read_mask(fd, mask, words);
656 if (!ret)
Paul Cercueila78b6eb2014-03-17 17:28:07 +0100657 break;
Paul Cercueil5cab3ae2014-03-14 11:23:56 +0100658 if (ret < 0) {
659 strerror_r(-ret, buf, sizeof(buf));
660 ERROR("Unable to read mask: %s\n", buf);
Paul Cercueilc5b00752015-02-24 14:29:53 +0100661 network_unlock_dev(pdata);
Paul Cercueil6e7f79e2014-04-04 12:27:24 +0200662 return read ? read : ret;
Paul Cercueil5cab3ae2014-03-14 11:23:56 +0100663 }
664
Paul Cercueil7d7e5d32015-03-05 10:51:41 +0100665 mask = NULL; /* We read the mask only once */
666
667 ret = read_all((void *) ptr, ret, fd);
Paul Cercueil9945bc82014-03-05 14:07:29 +0100668 if (ret < 0) {
669 strerror_r(-ret, buf, sizeof(buf));
670 ERROR("Unable to read response to READ: %s\n", buf);
Paul Cercueilc5b00752015-02-24 14:29:53 +0100671 network_unlock_dev(pdata);
Paul Cercueil6e7f79e2014-04-04 12:27:24 +0200672 return read ? read : ret;
Paul Cercueil9945bc82014-03-05 14:07:29 +0100673 }
674
Paul Cercueil6e7f79e2014-04-04 12:27:24 +0200675 ptr += ret;
Paul Cercueilf9286452014-03-18 14:32:17 +0100676 read += ret;
Paul Cercueil7d7e5d32015-03-05 10:51:41 +0100677 len -= ret;
Paul Cercueil9945bc82014-03-05 14:07:29 +0100678 } while (len);
679
Paul Cercueilc5b00752015-02-24 14:29:53 +0100680 network_unlock_dev(pdata);
Paul Cercueil9945bc82014-03-05 14:07:29 +0100681 return read;
682}
683
Paul Cercueila62f84e2015-02-24 14:16:08 +0100684static ssize_t network_write(const struct iio_device *dev,
685 const void *src, size_t len)
Paul Cercueil2725f702014-05-02 11:02:16 +0200686{
Paul Cercueilc5b00752015-02-24 14:29:53 +0100687 struct iio_device_pdata *pdata = dev->pdata;
Paul Cercueil439e1a22015-02-24 13:50:51 +0100688 int fd;
Paul Cercueil2725f702014-05-02 11:02:16 +0200689 ssize_t ret;
Paul Cercueil2725f702014-05-02 11:02:16 +0200690 long resp;
Paul Cercueila62f84e2015-02-24 14:16:08 +0100691 char buf[1024];
692
693 snprintf(buf, sizeof(buf), "WRITEBUF %s %lu\r\n",
694 dev->id, (unsigned long) len);
Paul Cercueil2725f702014-05-02 11:02:16 +0200695
Paul Cercueilc5b00752015-02-24 14:29:53 +0100696 network_lock_dev(pdata);
697 fd = pdata->fd;
Paul Cercueil8f7f6c42015-02-24 15:00:35 +0100698
Paul Cercueil3c0da372015-03-05 11:36:39 +0100699 ret = write_rwbuf_command(dev, buf, pdata->is_cyclic);
Paul Cercueil2725f702014-05-02 11:02:16 +0200700 if (ret < 0)
Paul Cercueil1494b862014-05-05 12:49:07 +0200701 goto err_unlock;
Paul Cercueil2725f702014-05-02 11:02:16 +0200702
703 ret = write_all(src, len, fd);
704 if (ret < 0)
Paul Cercueil1494b862014-05-05 12:49:07 +0200705 goto err_unlock;
Paul Cercueil2725f702014-05-02 11:02:16 +0200706
Paul Cercueil1d70d442015-03-04 15:00:37 +0100707 if (pdata->is_cyclic) {
708 ret = read_integer(fd, &resp);
709 if (ret < 0)
710 goto err_unlock;
711 if (resp < 0) {
712 ret = (ssize_t) resp;
713 goto err_unlock;
714 }
715 } else {
716 pdata->wait_for_err_code = true;
717 }
Paul Cercueilc5b00752015-02-24 14:29:53 +0100718 network_unlock_dev(pdata);
Paul Cercueil1494b862014-05-05 12:49:07 +0200719
Paul Cercueil8f7f6c42015-02-24 15:00:35 +0100720 /* We assume that the whole buffer was submitted.
721 * The error code will be returned by the next call to this function. */
722 return (ssize_t) len;
Paul Cercueil1494b862014-05-05 12:49:07 +0200723
724err_unlock:
Paul Cercueilc5b00752015-02-24 14:29:53 +0100725 network_unlock_dev(pdata);
Paul Cercueil1494b862014-05-05 12:49:07 +0200726 return ret;
Paul Cercueil2725f702014-05-02 11:02:16 +0200727}
728
Paul Cercueil90189672015-03-16 11:41:53 +0100729#ifdef WITH_NETWORK_GET_BUFFER
Paul Cercueil7d7e5d32015-03-05 10:51:41 +0100730static ssize_t network_do_splice(int fd_out, int fd_in, size_t len)
Paul Cercueil09a43482015-03-04 15:50:27 +0100731{
732 int pipefd[2];
Paul Cercueil04065c22015-03-05 14:08:16 +0100733 ssize_t ret, read_len = len;
Paul Cercueil09a43482015-03-04 15:50:27 +0100734
735 ret = (ssize_t) pipe(pipefd);
736 if (ret < 0)
737 return -errno;
738
739 do {
Paul Cercueila107c6d2015-03-05 13:54:10 +0100740 /*
741 * SPLICE_F_NONBLOCK is just here to avoid a deadlock when
742 * splicing from a socket. As the socket is not in
743 * non-blocking mode, it should never return -EAGAIN.
744 * TODO(pcercuei): Find why it locks...
745 * */
746 ret = splice(fd_in, NULL, pipefd[1], NULL, len,
747 SPLICE_F_MOVE | SPLICE_F_NONBLOCK);
748 if (!ret)
749 ret = -EIO;
Paul Cercueil09a43482015-03-04 15:50:27 +0100750 if (ret < 0)
751 goto err_close_pipe;
752
Paul Cercueila107c6d2015-03-05 13:54:10 +0100753 ret = splice(pipefd[0], NULL, fd_out, NULL, ret,
754 SPLICE_F_MOVE | SPLICE_F_NONBLOCK);
755 if (!ret)
756 ret = -EIO;
Paul Cercueil09a43482015-03-04 15:50:27 +0100757 if (ret < 0)
758 goto err_close_pipe;
759
760 len -= ret;
761 } while (len);
762
763err_close_pipe:
764 close(pipefd[0]);
765 close(pipefd[1]);
Paul Cercueil04065c22015-03-05 14:08:16 +0100766 return ret < 0 ? ret : read_len;
Paul Cercueil09a43482015-03-04 15:50:27 +0100767}
768
769static ssize_t network_get_buffer(const struct iio_device *dev,
Paul Cercueil76ca8842015-03-05 11:16:16 +0100770 void **addr_ptr, size_t bytes_used,
771 uint32_t *mask, size_t words)
Paul Cercueil09a43482015-03-04 15:50:27 +0100772{
773 struct iio_device_pdata *pdata = dev->pdata;
Paul Cercueil04065c22015-03-05 14:08:16 +0100774 ssize_t ret, read = 0;
Paul Cercueil09a43482015-03-04 15:50:27 +0100775 bool tx;
Paul Cercueil09a43482015-03-04 15:50:27 +0100776
Paul Cercueil04065c22015-03-05 14:08:16 +0100777 if (pdata->is_cyclic)
Paul Cercueil09a43482015-03-04 15:50:27 +0100778 return -ENOSYS;
Paul Cercueil76ca8842015-03-05 11:16:16 +0100779 if (!addr_ptr || words != (dev->nb_channels + 31) / 32)
Paul Cercueil09a43482015-03-04 15:50:27 +0100780 return -EINVAL;
781
Paul Cercueile6e5a092015-03-04 16:33:26 +0100782 if (pdata->mmap_addr)
783 munmap(pdata->mmap_addr, pdata->mmap_len);
Paul Cercueil09a43482015-03-04 15:50:27 +0100784
Paul Cercueile6e5a092015-03-04 16:33:26 +0100785 if (pdata->mmap_addr && pdata->is_tx) {
Paul Cercueil09a43482015-03-04 15:50:27 +0100786 char buf[1024];
787 snprintf(buf, sizeof(buf), "WRITEBUF %s %lu\r\n",
788 dev->id, (unsigned long) pdata->mmap_len);
789
790 network_lock_dev(pdata);
791
Paul Cercueil3c0da372015-03-05 11:36:39 +0100792 ret = write_rwbuf_command(dev, buf, false);
Paul Cercueil09a43482015-03-04 15:50:27 +0100793 if (ret < 0)
794 goto err_unlock;
795
796 ret = network_do_splice(pdata->fd,
797 pdata->memfd, pdata->mmap_len);
798 if (ret < 0)
799 goto err_unlock;
800
801 pdata->wait_for_err_code = true;
802 network_unlock_dev(pdata);
803 }
804
805 if (pdata->memfd >= 0)
806 close(pdata->memfd);
807
808 if (bytes_used)
809 pdata->mmap_len = bytes_used;
810
811 /* O_TMPFILE -> Linux 3.11.
812 * TODO: use memfd_create (Linux 3.17) */
813 pdata->memfd = open(P_tmpdir, O_RDWR | O_TMPFILE | O_EXCL, S_IRWXU);
814 if (pdata->memfd < 0) {
815 ret = -errno;
Paul Cercueil7d7e5d32015-03-05 10:51:41 +0100816 ERROR("Unable to create temp file: %zi\n", -ret);
Paul Cercueil09a43482015-03-04 15:50:27 +0100817 return ret;
818 }
819
Paul Cercueilef32d582015-03-05 11:18:35 +0100820 ret = (ssize_t) ftruncate(pdata->memfd, pdata->mmap_len);
821 if (ret < 0) {
822 ret = -errno;
823 ERROR("Unable to truncate temp file: %zi\n", -ret);
824 return ret;
825 }
Paul Cercueil09a43482015-03-04 15:50:27 +0100826
Paul Cercueil04065c22015-03-05 14:08:16 +0100827 if (!pdata->is_tx) {
828 char buf[1024];
829 size_t len = pdata->mmap_len;
830
831 snprintf(buf, sizeof(buf), "READBUF %s %lu\r\n",
832 dev->id, (unsigned long) len);
833
834 network_lock_dev(pdata);
835 ret = write_rwbuf_command(dev, buf, false);
836 if (ret < 0)
837 goto err_unlock;
838
839 do {
840 ret = network_read_mask(pdata->fd, mask, words);
841 if (!ret)
842 break;
843 if (ret < 0)
844 goto err_unlock;
845
846 mask = NULL; /* We read the mask only once */
847
848 ret = network_do_splice(pdata->memfd, pdata->fd, ret);
849 if (ret < 0)
850 goto err_unlock;
851
852 read += ret;
853 len -= ret;
854 } while (len);
855
856 network_unlock_dev(pdata);
857 }
Paul Cercueil09a43482015-03-04 15:50:27 +0100858
Paul Cercueile6e5a092015-03-04 16:33:26 +0100859 pdata->mmap_addr = mmap(NULL, pdata->mmap_len,
Paul Cercueil09a43482015-03-04 15:50:27 +0100860 PROT_READ | PROT_WRITE, MAP_SHARED, pdata->memfd, 0);
Paul Cercueile6e5a092015-03-04 16:33:26 +0100861 if (pdata->mmap_addr == MAP_FAILED) {
862 pdata->mmap_addr = NULL;
Paul Cercueil09a43482015-03-04 15:50:27 +0100863 ret = -errno;
Paul Cercueil7d7e5d32015-03-05 10:51:41 +0100864 ERROR("Unable to mmap: %zi\n", -ret);
Paul Cercueil09a43482015-03-04 15:50:27 +0100865 return ret;
866 }
867
Paul Cercueile6e5a092015-03-04 16:33:26 +0100868 *addr_ptr = pdata->mmap_addr;
Paul Cercueil04065c22015-03-05 14:08:16 +0100869 return read ? read : bytes_used;
Paul Cercueil09a43482015-03-04 15:50:27 +0100870
871err_unlock:
872 network_unlock_dev(pdata);
873 return ret;
874}
875#endif
876
Paul Cercueil1494b862014-05-05 12:49:07 +0200877static ssize_t network_read_attr_helper(const struct iio_device *dev,
Paul Cercueil0cc0e162014-05-07 12:51:22 +0200878 const struct iio_channel *chn, const char *attr, char *dst,
Paul Cercueil1494b862014-05-05 12:49:07 +0200879 size_t len, bool is_debug)
Paul Cercueil3e94a5b2014-03-04 13:00:41 +0100880{
Paul Cercueil3e94a5b2014-03-04 13:00:41 +0100881 long read_len;
882 ssize_t ret;
883 char buf[1024];
Paul Cercueil05e26262014-05-09 11:32:43 +0200884 struct iio_context_pdata *pdata = dev->ctx->pdata;
885 int fd = pdata->fd;
Paul Cercueil1494b862014-05-05 12:49:07 +0200886 const char *id = dev->id;
Paul Cercueil3e94a5b2014-03-04 13:00:41 +0100887
Paul Cercueil99cf3d42014-03-06 12:35:26 +0100888 if (chn)
Paul Cercueil0cc0e162014-05-07 12:51:22 +0200889 snprintf(buf, sizeof(buf), "READ %s %s %s %s\r\n", id,
890 chn->is_output ? "OUTPUT" : "INPUT",
Paul Cercueil2a3e43d2014-05-21 16:58:45 +0200891 chn->id, attr ? attr : "");
Paul Cercueilc6f03612014-04-14 16:41:31 +0200892 else if (is_debug)
Paul Cercueil2a3e43d2014-05-21 16:58:45 +0200893 snprintf(buf, sizeof(buf), "READ %s DEBUG %s\r\n",
894 id, attr ? attr : "");
Paul Cercueil99cf3d42014-03-06 12:35:26 +0100895 else
Paul Cercueil2a3e43d2014-05-21 16:58:45 +0200896 snprintf(buf, sizeof(buf), "READ %s %s\r\n",
897 id, attr ? attr : "");
Paul Cercueil1494b862014-05-05 12:49:07 +0200898
Paul Cercueil05e26262014-05-09 11:32:43 +0200899 network_lock(pdata);
Paul Cercueilbb76bf92014-03-11 10:20:18 +0100900 read_len = exec_command(buf, fd);
Paul Cercueil1494b862014-05-05 12:49:07 +0200901 if (read_len < 0) {
Paul Cercueil05e26262014-05-09 11:32:43 +0200902 network_unlock(pdata);
Paul Cercueilbb76bf92014-03-11 10:20:18 +0100903 return (ssize_t) read_len;
Paul Cercueil1494b862014-05-05 12:49:07 +0200904 }
Paul Cercueil3e94a5b2014-03-04 13:00:41 +0100905
Paul Cercueil6e7f79e2014-04-04 12:27:24 +0200906 if ((unsigned long) read_len > len) {
Paul Cercueil3e94a5b2014-03-04 13:00:41 +0100907 ERROR("Value returned by server is too large\n");
Paul Cercueil05e26262014-05-09 11:32:43 +0200908 network_unlock(pdata);
Paul Cercueil3e94a5b2014-03-04 13:00:41 +0100909 return -EIO;
910 }
911
912 ret = read_all(dst, read_len, fd);
Paul Cercueil05e26262014-05-09 11:32:43 +0200913 network_unlock(pdata);
Paul Cercueil1494b862014-05-05 12:49:07 +0200914
Paul Cercueil3e94a5b2014-03-04 13:00:41 +0100915 if (ret < 0) {
916 strerror_r(-ret, buf, sizeof(buf));
917 ERROR("Unable to read response to READ: %s\n", buf);
918 return ret;
919 }
920
Paul Cercueil7d95fd72014-05-22 14:26:44 +0200921 return read_len;
Paul Cercueil3e94a5b2014-03-04 13:00:41 +0100922}
923
Paul Cercueil1494b862014-05-05 12:49:07 +0200924static ssize_t network_write_attr_helper(const struct iio_device *dev,
Paul Cercueil0cc0e162014-05-07 12:51:22 +0200925 const struct iio_channel *chn, const char *attr,
926 const char *src, size_t len, bool is_debug)
Paul Cercueil3e94a5b2014-03-04 13:00:41 +0100927{
Paul Cercueila62f84e2015-02-24 14:16:08 +0100928 struct iio_context_pdata *pdata = dev->ctx->pdata;
929 int fd;
930 ssize_t ret;
931 long resp;
Paul Cercueil3e94a5b2014-03-04 13:00:41 +0100932 char buf[1024];
Paul Cercueil1494b862014-05-05 12:49:07 +0200933 const char *id = dev->id;
Paul Cercueil3e94a5b2014-03-04 13:00:41 +0100934
Paul Cercueil07897d32014-03-06 12:46:08 +0100935 if (chn)
Paul Cercueil0cc0e162014-05-07 12:51:22 +0200936 snprintf(buf, sizeof(buf), "WRITE %s %s %s %s %lu\r\n",
937 id, chn->is_output ? "OUTPUT" : "INPUT",
Paul Cercueil8747efe2014-05-22 11:12:12 +0200938 chn->id, attr ? attr : "", (unsigned long) len);
Paul Cercueilc6f03612014-04-14 16:41:31 +0200939 else if (is_debug)
Paul Cercueil8747efe2014-05-22 11:12:12 +0200940 snprintf(buf, sizeof(buf), "WRITE %s DEBUG %s %lu\r\n",
941 id, attr ? attr : "", (unsigned long) len);
Paul Cercueil07897d32014-03-06 12:46:08 +0100942 else
Paul Cercueilcecda352014-05-06 18:14:29 +0200943 snprintf(buf, sizeof(buf), "WRITE %s %s %lu\r\n",
Paul Cercueil8747efe2014-05-22 11:12:12 +0200944 id, attr ? attr : "", (unsigned long) len);
Paul Cercueila62f84e2015-02-24 14:16:08 +0100945
946 network_lock(pdata);
947 fd = pdata->fd;
948 ret = (ssize_t) write_command(buf, fd);
949 if (ret < 0)
950 goto err_unlock;
951
952 ret = write_all(src, len, fd);
953 if (ret < 0)
954 goto err_unlock;
955
956 ret = read_integer(fd, &resp);
957 network_unlock(pdata);
958
959 if (ret < 0)
960 return ret;
961 return (ssize_t) resp;
962
963err_unlock:
964 network_unlock(pdata);
965 return ret;
Paul Cercueil3e94a5b2014-03-04 13:00:41 +0100966}
967
Paul Cercueil99cf3d42014-03-06 12:35:26 +0100968static ssize_t network_read_dev_attr(const struct iio_device *dev,
Paul Cercueil50c762a2014-04-14 15:55:43 +0200969 const char *attr, char *dst, size_t len, bool is_debug)
Paul Cercueil99cf3d42014-03-06 12:35:26 +0100970{
Paul Cercueil5b577762014-06-03 15:31:42 +0200971 if (attr && ((is_debug && !iio_device_find_debug_attr(dev, attr)) ||
972 (!is_debug && !iio_device_find_attr(dev, attr))))
973 return -ENOENT;
974
Paul Cercueil1494b862014-05-05 12:49:07 +0200975 return network_read_attr_helper(dev, NULL, attr, dst, len, is_debug);
Paul Cercueil99cf3d42014-03-06 12:35:26 +0100976}
977
Paul Cercueil07897d32014-03-06 12:46:08 +0100978static ssize_t network_write_dev_attr(const struct iio_device *dev,
Paul Cercueilcecda352014-05-06 18:14:29 +0200979 const char *attr, const char *src, size_t len, bool is_debug)
Paul Cercueil07897d32014-03-06 12:46:08 +0100980{
Paul Cercueil5b577762014-06-03 15:31:42 +0200981 if (attr && ((is_debug && !iio_device_find_debug_attr(dev, attr)) ||
982 (!is_debug && !iio_device_find_attr(dev, attr))))
983 return -ENOENT;
984
Paul Cercueilcecda352014-05-06 18:14:29 +0200985 return network_write_attr_helper(dev, NULL, attr, src, len, is_debug);
Paul Cercueil07897d32014-03-06 12:46:08 +0100986}
987
Paul Cercueil99cf3d42014-03-06 12:35:26 +0100988static ssize_t network_read_chn_attr(const struct iio_channel *chn,
989 const char *attr, char *dst, size_t len)
990{
Paul Cercueil5b577762014-06-03 15:31:42 +0200991 if (attr && !iio_channel_find_attr(chn, attr))
992 return -ENOENT;
993
Paul Cercueil0cc0e162014-05-07 12:51:22 +0200994 return network_read_attr_helper(chn->dev, chn, attr, dst, len, false);
Paul Cercueil99cf3d42014-03-06 12:35:26 +0100995}
996
Paul Cercueil07897d32014-03-06 12:46:08 +0100997static ssize_t network_write_chn_attr(const struct iio_channel *chn,
Paul Cercueilcecda352014-05-06 18:14:29 +0200998 const char *attr, const char *src, size_t len)
Paul Cercueil07897d32014-03-06 12:46:08 +0100999{
Paul Cercueil5b577762014-06-03 15:31:42 +02001000 if (attr && !iio_channel_find_attr(chn, attr))
1001 return -ENOENT;
1002
Paul Cercueil0cc0e162014-05-07 12:51:22 +02001003 return network_write_attr_helper(chn->dev, chn, attr, src, len, false);
Paul Cercueil07897d32014-03-06 12:46:08 +01001004}
1005
Paul Cercueildcab40c2014-03-11 10:59:14 +01001006static int network_get_trigger(const struct iio_device *dev,
1007 const struct iio_device **trigger)
1008{
1009 struct iio_context_pdata *pdata = dev->ctx->pdata;
1010 unsigned int i;
1011 char buf[1024];
1012 ssize_t ret;
1013 long resp;
1014
1015 snprintf(buf, sizeof(buf), "GETTRIG %s\r\n", dev->id);
Paul Cercueil1494b862014-05-05 12:49:07 +02001016
Paul Cercueil05e26262014-05-09 11:32:43 +02001017 network_lock(dev->ctx->pdata);
Paul Cercueildcab40c2014-03-11 10:59:14 +01001018 resp = exec_command(buf, pdata->fd);
1019 if (resp < 0) {
Paul Cercueil05e26262014-05-09 11:32:43 +02001020 network_unlock(pdata);
Paul Cercueildcab40c2014-03-11 10:59:14 +01001021 return (int) resp;
1022 } else if (resp == 0) {
1023 *trigger = NULL;
Paul Cercueil05e26262014-05-09 11:32:43 +02001024 network_unlock(pdata);
Paul Cercueildcab40c2014-03-11 10:59:14 +01001025 return 0;
Paul Cercueil6e7f79e2014-04-04 12:27:24 +02001026 } else if ((unsigned long) resp > sizeof(buf)) {
Paul Cercueildcab40c2014-03-11 10:59:14 +01001027 ERROR("Value returned by server is too large\n");
Paul Cercueil05e26262014-05-09 11:32:43 +02001028 network_unlock(pdata);
Paul Cercueildcab40c2014-03-11 10:59:14 +01001029 return -EIO;
1030 }
1031
1032 ret = read_all(buf, resp, pdata->fd);
Paul Cercueil05e26262014-05-09 11:32:43 +02001033 network_unlock(pdata);
Paul Cercueil1494b862014-05-05 12:49:07 +02001034
Paul Cercueildcab40c2014-03-11 10:59:14 +01001035 if (ret < 0) {
1036 strerror_r(-ret, buf, sizeof(buf));
1037 ERROR("Unable to read response to GETTRIG: %s\n", buf);
1038 return ret;
1039 }
1040
Lars-Peter Clausenb5cdc102014-08-21 14:45:52 +02001041 if (buf[0] == '\0') {
1042 *trigger = NULL;
1043 return 0;
1044 }
1045
Paul Cercueildcab40c2014-03-11 10:59:14 +01001046 for (i = 0; i < dev->ctx->nb_devices; i++) {
1047 struct iio_device *cur = dev->ctx->devices[i];
1048 if (iio_device_is_trigger(cur) &&
1049 !strncmp(cur->name, buf, resp)) {
1050 *trigger = cur;
1051 return 0;
1052 }
1053 }
1054
1055 return -ENXIO;
1056}
1057
1058static int network_set_trigger(const struct iio_device *dev,
1059 const struct iio_device *trigger)
1060{
Paul Cercueil1494b862014-05-05 12:49:07 +02001061 int ret;
Paul Cercueildcab40c2014-03-11 10:59:14 +01001062 char buf[1024];
1063 if (trigger)
1064 snprintf(buf, sizeof(buf), "SETTRIG %s %s\r\n",
1065 dev->id, trigger->id);
1066 else
1067 snprintf(buf, sizeof(buf), "SETTRIG %s\r\n", dev->id);
Paul Cercueil1494b862014-05-05 12:49:07 +02001068
Paul Cercueil05e26262014-05-09 11:32:43 +02001069 network_lock(dev->ctx->pdata);
Paul Cercueil1494b862014-05-05 12:49:07 +02001070 ret = (int) exec_command(buf, dev->ctx->pdata->fd);
Paul Cercueil05e26262014-05-09 11:32:43 +02001071 network_unlock(dev->ctx->pdata);
Paul Cercueil1494b862014-05-05 12:49:07 +02001072 return ret;
Paul Cercueildcab40c2014-03-11 10:59:14 +01001073}
1074
Paul Cercueil8fd9c8f2014-03-03 17:21:31 +01001075static void network_shutdown(struct iio_context *ctx)
1076{
1077 struct iio_context_pdata *pdata = ctx->pdata;
Paul Cercueil44ae11c2014-03-17 09:56:29 +01001078 unsigned int i;
Paul Cercueil8fd9c8f2014-03-03 17:21:31 +01001079
Paul Cercueil05e26262014-05-09 11:32:43 +02001080 network_lock(pdata);
Paul Cercueilbb76bf92014-03-11 10:20:18 +01001081 write_command("\r\nEXIT\r\n", pdata->fd);
Paul Cercueil8fd9c8f2014-03-03 17:21:31 +01001082 close(pdata->fd);
Paul Cercueil05e26262014-05-09 11:32:43 +02001083 network_unlock(pdata);
Paul Cercueil1494b862014-05-05 12:49:07 +02001084
Paul Cercueil439e1a22015-02-24 13:50:51 +01001085 for (i = 0; i < ctx->nb_devices; i++) {
1086 struct iio_device *dev = ctx->devices[i];
Paul Cercueilc5b00752015-02-24 14:29:53 +01001087 struct iio_device_pdata *dpdata = dev->pdata;
Paul Cercueil439e1a22015-02-24 13:50:51 +01001088
Paul Cercueilc5b00752015-02-24 14:29:53 +01001089 if (dpdata) {
Paul Cercueilaa0db142015-03-04 16:25:24 +01001090 network_close(dev);
Paul Cercueilc5b00752015-02-24 14:29:53 +01001091#if HAVE_PTHREAD
Paul Cercueilaa0db142015-03-04 16:25:24 +01001092 pthread_mutex_destroy(&dpdata->lock);
Paul Cercueilc5b00752015-02-24 14:29:53 +01001093#endif
Paul Cercueilc5b00752015-02-24 14:29:53 +01001094 free(dpdata);
Paul Cercueil439e1a22015-02-24 13:50:51 +01001095 }
1096 }
1097
Paul Cercueil05e26262014-05-09 11:32:43 +02001098#if HAVE_PTHREAD
Paul Cercueil1494b862014-05-05 12:49:07 +02001099 pthread_mutex_destroy(&pdata->lock);
Paul Cercueil05e26262014-05-09 11:32:43 +02001100#endif
Paul Cercueil2dd2c132015-02-24 10:41:01 +01001101 freeaddrinfo(pdata->addrinfo);
Paul Cercueil8fd9c8f2014-03-03 17:21:31 +01001102 free(pdata);
1103}
1104
Paul Cercueil6691a3f2014-05-02 12:32:01 +02001105static int network_get_version(const struct iio_context *ctx,
Paul Cercueil9de9e9d2014-05-20 13:18:19 +02001106 unsigned int *major, unsigned int *minor, char git_tag[8])
Paul Cercueil6691a3f2014-05-02 12:32:01 +02001107{
1108 struct iio_context_pdata *pdata = ctx->pdata;
1109 long maj, min;
1110 int ret;
Paul Cercueil6691a3f2014-05-02 12:32:01 +02001111
Paul Cercueil05e26262014-05-09 11:32:43 +02001112 network_lock(pdata);
Paul Cercueil1494b862014-05-05 12:49:07 +02001113 ret = (int) write_command("VERSION\r\n", pdata->fd);
1114 if (ret < 0)
1115 goto err_unlock;
1116
1117 ret = read_integer(pdata->fd, &maj);
1118 if (!ret)
1119 ret = read_integer(pdata->fd, &min);
1120 if (!ret) {
Paul Cercueil9de9e9d2014-05-20 13:18:19 +02001121 char tag[8];
1122 tag[7] = '\0';
1123
1124 ret = read_all(tag, sizeof(tag) - 1, pdata->fd);
1125 if (ret < 0)
1126 goto err_unlock;
1127
Paul Cercueild15d9952014-05-20 11:40:08 +02001128 if (major)
1129 *major = (unsigned int) maj;
1130 if (minor)
1131 *minor = (unsigned int) min;
Paul Cercueil9de9e9d2014-05-20 13:18:19 +02001132 if (git_tag)
1133 strncpy(git_tag, tag, 8);
Paul Cercueil1494b862014-05-05 12:49:07 +02001134 }
1135
Paul Cercueil8e8f8992014-06-12 16:58:12 +02001136 ret = 0;
Paul Cercueil1494b862014-05-05 12:49:07 +02001137err_unlock:
Paul Cercueil05e26262014-05-09 11:32:43 +02001138 network_unlock(pdata);
Paul Cercueil1494b862014-05-05 12:49:07 +02001139 return ret;
Paul Cercueil6691a3f2014-05-02 12:32:01 +02001140}
1141
Paul Cercueil8a266f12014-06-10 16:06:31 +02001142static unsigned int calculate_remote_timeout(unsigned int timeout)
1143{
1144 /* XXX(pcercuei): We currently hardcode timeout / 2 for the backend used
1145 * by the remote. Is there something better to do here? */
1146 return timeout / 2;
1147}
1148
Paul Cercueilbca3dbc2014-06-11 12:00:21 +02001149static int set_remote_timeout(struct iio_context *ctx, unsigned int timeout)
1150{
1151 char buf[1024];
1152 int ret;
1153
1154 snprintf(buf, sizeof(buf), "TIMEOUT %u\r\n", timeout);
1155 network_lock(ctx->pdata);
1156 ret = (int) exec_command(buf, ctx->pdata->fd);
1157 network_unlock(ctx->pdata);
1158 return ret;
1159}
1160
1161static int network_set_timeout(struct iio_context *ctx, unsigned int timeout)
1162{
1163 int ret = set_socket_timeout(ctx->pdata->fd, timeout);
1164 if (!ret) {
1165 timeout = calculate_remote_timeout(timeout);
1166 ret = set_remote_timeout(ctx, timeout);
1167 }
1168 if (ret < 0) {
1169 char buf[1024];
1170 strerror_r(-ret, buf, sizeof(buf));
Paul Cercueil8a266f12014-06-10 16:06:31 +02001171 WARNING("Unable to set R/W timeout: %s\n", buf);
1172 } else {
Paul Cercueil8a266f12014-06-10 16:06:31 +02001173 ctx->rw_timeout_ms = timeout;
1174 }
1175 return ret;
1176}
1177
Paul Cercueil12d41832014-10-28 14:35:53 +01001178static struct iio_context * network_clone(const struct iio_context *ctx)
1179{
Paul Cercueil7ef45ce2015-03-16 14:36:16 +01001180 if (ctx->description) {
1181 char *ptr = strchr(ctx->description, ' ');
1182 if (ptr) {
1183#ifdef HAVE_IPV6
1184 char buf[INET6_ADDRSTRLEN + IF_NAMESIZE + 2];
1185#else
1186 char buf[INET_ADDRSTRLEN + 1];
1187#endif
1188 strncpy(buf, ctx->description, sizeof(buf) - 1);
1189 buf[ptr - ctx->description] = '\0';
1190 return iio_create_network_context(buf);
1191 }
1192 }
1193
Paul Cercueild3d56ee2015-01-08 16:36:31 +01001194 return iio_create_network_context(ctx->description);
Paul Cercueil12d41832014-10-28 14:35:53 +01001195}
1196
Paul Cercueilc7bad0f2014-03-03 17:06:48 +01001197static struct iio_backend_ops network_ops = {
Paul Cercueil12d41832014-10-28 14:35:53 +01001198 .clone = network_clone,
Paul Cercueilba059762014-03-14 11:02:02 +01001199 .open = network_open,
1200 .close = network_close,
Paul Cercueil9945bc82014-03-05 14:07:29 +01001201 .read = network_read,
Paul Cercueil2725f702014-05-02 11:02:16 +02001202 .write = network_write,
Paul Cercueil90189672015-03-16 11:41:53 +01001203#ifdef WITH_NETWORK_GET_BUFFER
Paul Cercueil09a43482015-03-04 15:50:27 +01001204 .get_buffer = network_get_buffer,
1205#endif
Paul Cercueil3e94a5b2014-03-04 13:00:41 +01001206 .read_device_attr = network_read_dev_attr,
1207 .write_device_attr = network_write_dev_attr,
Paul Cercueil99cf3d42014-03-06 12:35:26 +01001208 .read_channel_attr = network_read_chn_attr,
Paul Cercueil07897d32014-03-06 12:46:08 +01001209 .write_channel_attr = network_write_chn_attr,
Paul Cercueildcab40c2014-03-11 10:59:14 +01001210 .get_trigger = network_get_trigger,
1211 .set_trigger = network_set_trigger,
Paul Cercueil8fd9c8f2014-03-03 17:21:31 +01001212 .shutdown = network_shutdown,
Paul Cercueil6691a3f2014-05-02 12:32:01 +02001213 .get_version = network_get_version,
Paul Cercueil8a266f12014-06-10 16:06:31 +02001214 .set_timeout = network_set_timeout,
Paul Cercueilc7bad0f2014-03-03 17:06:48 +01001215};
1216
1217static struct iio_context * get_context(int fd)
1218{
1219 struct iio_context *ctx;
Paul Cercueile60c3ed2014-03-04 11:23:56 +01001220 char *xml;
Paul Cercueilbb76bf92014-03-11 10:20:18 +01001221 long xml_len = exec_command("PRINT\r\n", fd);
1222 if (xml_len < 0)
Paul Cercueilc7bad0f2014-03-03 17:06:48 +01001223 return NULL;
Paul Cercueile60c3ed2014-03-04 11:23:56 +01001224
1225 DEBUG("Server returned a XML string of length %li\n", xml_len);
Paul Cercueilc7bad0f2014-03-03 17:06:48 +01001226 xml = malloc(xml_len);
1227 if (!xml) {
1228 ERROR("Unable to allocate data\n");
1229 return NULL;
1230 }
1231
1232 DEBUG("Reading XML string...\n");
1233 read_all(xml, xml_len, fd);
1234
1235 DEBUG("Creating context from XML...\n");
1236 ctx = iio_create_xml_context_mem(xml, xml_len);
Paul Cercueilc1ed8482014-06-11 16:29:43 +02001237
1238 if (ctx)
1239 ctx->xml = xml;
1240 else
1241 free(xml);
Paul Cercueilc7bad0f2014-03-03 17:06:48 +01001242 return ctx;
1243}
1244
Paul Cercueil63e52182014-12-11 12:52:48 +01001245struct iio_context * network_create_context(const char *host)
Paul Cercueilc7bad0f2014-03-03 17:06:48 +01001246{
Paul Cercueil2e38bbe2014-03-19 15:27:15 +01001247 struct addrinfo hints, *res;
Paul Cercueilc7bad0f2014-03-03 17:06:48 +01001248 struct iio_context *ctx;
Paul Cercueil8fd9c8f2014-03-03 17:21:31 +01001249 struct iio_context_pdata *pdata;
Paul Cercueil06c479d2015-01-08 16:14:57 +01001250 unsigned int i, len;
Paul Cercueil4970ac32015-02-24 10:59:00 +01001251 int fd, ret;
Paul Cercueilb03c9ef2015-03-16 14:07:58 +01001252 char *description;
Paul Cercueil1fef1a52014-04-07 16:31:15 +02001253#ifdef _WIN32
1254 WSADATA wsaData;
1255
1256 ret = WSAStartup(MAKEWORD(2, 0), &wsaData);
1257 if (ret < 0) {
1258 ERROR("WSAStartup failed with error %i\n", ret);
1259 return NULL;
1260 }
1261#endif
Paul Cercueilc7bad0f2014-03-03 17:06:48 +01001262
Paul Cercueil2e38bbe2014-03-19 15:27:15 +01001263 memset(&hints, 0, sizeof(hints));
1264 hints.ai_family = AF_UNSPEC;
1265 hints.ai_socktype = SOCK_STREAM;
Paul Cercueilab114932014-05-19 13:03:17 +02001266
1267#ifdef HAVE_AVAHI
1268 if (!host) {
1269 char addr_str[AVAHI_ADDRESS_STR_MAX];
1270 char port_str[6];
1271 AvahiAddress address;
Paul Cercueil0f729d32014-06-05 17:38:54 +02001272 uint16_t port = IIOD_PORT;
Paul Cercueilab114932014-05-19 13:03:17 +02001273
1274 memset(&address, 0, sizeof(address));
1275
1276 ret = discover_host(&address, &port);
1277 if (ret < 0) {
1278 ERROR("Unable to find host: %s\n", strerror(-ret));
1279 return NULL;
1280 }
1281
1282 avahi_address_snprint(addr_str, sizeof(addr_str), &address);
1283 snprintf(port_str, sizeof(port_str), "%hu", port);
1284 ret = getaddrinfo(addr_str, port_str, &hints, &res);
1285 } else
1286#endif
1287 {
1288 ret = getaddrinfo(host, IIOD_PORT_STR, &hints, &res);
1289 }
1290
Paul Cercueil2e38bbe2014-03-19 15:27:15 +01001291 if (ret) {
Paul Cercueilab114932014-05-19 13:03:17 +02001292 ERROR("Unable to find host: %s\n", gai_strerror(ret));
Paul Cercueilc7bad0f2014-03-03 17:06:48 +01001293 return NULL;
Paul Cercueilc7bad0f2014-03-03 17:06:48 +01001294 }
1295
Paul Cercueil4970ac32015-02-24 10:59:00 +01001296 fd = create_socket(res);
1297 if (fd < 0)
Paul Cercueil2dd2c132015-02-24 10:41:01 +01001298 goto err_free_addrinfo;
Paul Cercueilbca3dbc2014-06-11 12:00:21 +02001299
Paul Cercueil8fd9c8f2014-03-03 17:21:31 +01001300 pdata = calloc(1, sizeof(*pdata));
1301 if (!pdata) {
1302 ERROR("Unable to allocate memory\n");
1303 goto err_close_socket;
1304 }
1305
1306 pdata->fd = fd;
Paul Cercueil2dd2c132015-02-24 10:41:01 +01001307 pdata->addrinfo = res;
Paul Cercueil8fd9c8f2014-03-03 17:21:31 +01001308
Paul Cercueilc7bad0f2014-03-03 17:06:48 +01001309 DEBUG("Creating context...\n");
1310 ctx = get_context(fd);
1311 if (!ctx)
Paul Cercueild3d56ee2015-01-08 16:36:31 +01001312 goto err_free_pdata;
Paul Cercueilc7bad0f2014-03-03 17:06:48 +01001313
Paul Cercueil2057fd32014-10-28 14:44:19 +01001314 /* Override the name and low-level functions of the XML context
1315 * with those corresponding to the network context */
1316 ctx->name = "network";
1317 ctx->ops = &network_ops;
1318 ctx->pdata = pdata;
1319
Paul Cercueil06c479d2015-01-08 16:14:57 +01001320#ifdef HAVE_IPV6
Paul Cercueiled15e492015-01-12 15:52:28 +01001321 len = INET6_ADDRSTRLEN + IF_NAMESIZE + 2;
Paul Cercueil06c479d2015-01-08 16:14:57 +01001322#else
1323 len = INET_ADDRSTRLEN + 1;
1324#endif
Paul Cercueilb03c9ef2015-03-16 14:07:58 +01001325
1326 description = malloc(len);
1327 if (!description) {
Paul Cercueil06c479d2015-01-08 16:14:57 +01001328 ERROR("Unable to allocate memory\n");
1329 goto err_network_shutdown;
1330 }
1331
Paul Cercueilb03c9ef2015-03-16 14:07:58 +01001332 description[0] = '\0';
Paul Cercueil06c479d2015-01-08 16:14:57 +01001333
1334#ifdef HAVE_IPV6
1335 if (res->ai_family == AF_INET6) {
1336 struct sockaddr_in6 *in = (struct sockaddr_in6 *) res->ai_addr;
Paul Cercueiled15e492015-01-12 15:52:28 +01001337 char *ptr;
Paul Cercueil06c479d2015-01-08 16:14:57 +01001338 inet_ntop(AF_INET6, &in->sin6_addr,
Paul Cercueilb03c9ef2015-03-16 14:07:58 +01001339 description, INET6_ADDRSTRLEN);
Paul Cercueiled15e492015-01-12 15:52:28 +01001340
Paul Cercueilb03c9ef2015-03-16 14:07:58 +01001341 ptr = if_indextoname(in->sin6_scope_id, description +
1342 strlen(description) + 1);
Paul Cercueiled15e492015-01-12 15:52:28 +01001343 if (!ptr) {
1344 ERROR("Unable to lookup interface of IPv6 address\n");
Paul Cercueilb03c9ef2015-03-16 14:07:58 +01001345 goto err_free_description;
Paul Cercueiled15e492015-01-12 15:52:28 +01001346 }
1347
1348 *(ptr - 1) = '%';
Paul Cercueil06c479d2015-01-08 16:14:57 +01001349 }
1350#endif
1351 if (res->ai_family == AF_INET) {
1352 struct sockaddr_in *in = (struct sockaddr_in *) res->ai_addr;
Paul Cercueilb03c9ef2015-03-16 14:07:58 +01001353 inet_ntop(AF_INET, &in->sin_addr, description, INET_ADDRSTRLEN);
Paul Cercueil06c479d2015-01-08 16:14:57 +01001354 }
1355
Paul Cercueil44ae11c2014-03-17 09:56:29 +01001356 for (i = 0; i < ctx->nb_devices; i++) {
1357 struct iio_device *dev = ctx->devices[i];
Paul Cercueilff778232014-03-24 14:23:08 +01001358
1359 dev->words = (dev->nb_channels + 31) / 32;
1360 if (dev->words) {
Paul Cercueil439e1a22015-02-24 13:50:51 +01001361 dev->mask = calloc(dev->words, sizeof(*dev->mask));
1362 if (!dev->mask) {
Paul Cercueil2057fd32014-10-28 14:44:19 +01001363 ERROR("Unable to allocate memory\n");
Paul Cercueilb03c9ef2015-03-16 14:07:58 +01001364 goto err_free_description;
Paul Cercueil2057fd32014-10-28 14:44:19 +01001365 }
Paul Cercueilff778232014-03-24 14:23:08 +01001366 }
1367
Paul Cercueil439e1a22015-02-24 13:50:51 +01001368 dev->pdata = calloc(1, sizeof(*dev->pdata));
1369 if (!dev->pdata) {
1370 ERROR("Unable to allocate memory\n");
Paul Cercueilb03c9ef2015-03-16 14:07:58 +01001371 goto err_free_description;
Paul Cercueil439e1a22015-02-24 13:50:51 +01001372 }
1373
1374 dev->pdata->fd = -1;
Paul Cercueil90189672015-03-16 11:41:53 +01001375#ifdef WITH_NETWORK_GET_BUFFER
Paul Cercueil09a43482015-03-04 15:50:27 +01001376 dev->pdata->memfd = -1;
Paul Cercueile6e5a092015-03-04 16:33:26 +01001377#endif
Paul Cercueilc5b00752015-02-24 14:29:53 +01001378
1379#if HAVE_PTHREAD
1380 ret = pthread_mutex_init(&dev->pdata->lock, NULL);
1381 if (ret < 0) {
1382 char buf[1024];
1383 strerror_r(-ret, buf, sizeof(buf));
1384 ERROR("Unable to initialize mutex: %s\n", buf);
Paul Cercueilb03c9ef2015-03-16 14:07:58 +01001385 goto err_free_description;
Paul Cercueilc5b00752015-02-24 14:29:53 +01001386 }
1387#endif
Paul Cercueil44ae11c2014-03-17 09:56:29 +01001388 }
1389
Paul Cercueilc1ed8482014-06-11 16:29:43 +02001390 iio_context_init(ctx);
Paul Cercueil4c6729d2014-04-04 17:24:41 +02001391
Paul Cercueil05e26262014-05-09 11:32:43 +02001392#if HAVE_PTHREAD
Paul Cercueil1494b862014-05-05 12:49:07 +02001393 ret = pthread_mutex_init(&pdata->lock, NULL);
1394 if (ret < 0) {
1395 char buf[1024];
1396 strerror_r(-ret, buf, sizeof(buf));
1397 ERROR("Unable to initialize mutex: %s\n", buf);
Paul Cercueilb03c9ef2015-03-16 14:07:58 +01001398 goto err_free_description;
Paul Cercueil1494b862014-05-05 12:49:07 +02001399 }
Paul Cercueil05e26262014-05-09 11:32:43 +02001400#endif
Paul Cercueil1494b862014-05-05 12:49:07 +02001401
Paul Cercueilb03c9ef2015-03-16 14:07:58 +01001402 if (ctx->description) {
1403 size_t new_size = len + strlen(ctx->description) + 1;
1404 char *ptr, *new_description = realloc(description, new_size);
1405 if (!new_description)
1406 goto err_free_description;
1407
1408 ptr = strrchr(new_description, '\0');
1409 snprintf(ptr, new_size - len, " %s", ctx->description);
1410 free(ctx->description);
1411
1412 ctx->description = new_description;
1413 } else {
1414 ctx->description = description;
1415 }
1416
Paul Cercueilbca3dbc2014-06-11 12:00:21 +02001417 set_remote_timeout(ctx, calculate_remote_timeout(DEFAULT_TIMEOUT_MS));
Paul Cercueilc7bad0f2014-03-03 17:06:48 +01001418 return ctx;
1419
Paul Cercueilb03c9ef2015-03-16 14:07:58 +01001420err_free_description:
1421 free(description);
Paul Cercueil44ae11c2014-03-17 09:56:29 +01001422err_network_shutdown:
Paul Cercueil44ae11c2014-03-17 09:56:29 +01001423 iio_context_destroy(ctx);
Paul Cercueil2057fd32014-10-28 14:44:19 +01001424 return NULL;
Paul Cercueil8fd9c8f2014-03-03 17:21:31 +01001425err_free_pdata:
1426 free(pdata);
Paul Cercueilc7bad0f2014-03-03 17:06:48 +01001427err_close_socket:
1428 close(fd);
Paul Cercueil2dd2c132015-02-24 10:41:01 +01001429err_free_addrinfo:
1430 freeaddrinfo(res);
Paul Cercueilc7bad0f2014-03-03 17:06:48 +01001431 return NULL;
1432}