blob: 8ab41939924603f7a07e28c4565b6fb2700a58bf [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
19#include "debug.h"
20#include "iio-private.h"
21
22#include <errno.h>
23#include <netdb.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>
27#include <sys/socket.h>
28#include <unistd.h>
29
Paul Cercueil2e38bbe2014-03-19 15:27:15 +010030#define _STRINGIFY(x) #x
31#define STRINGIFY(x) _STRINGIFY(x)
32
Paul Cercueilc7bad0f2014-03-03 17:06:48 +010033#define IIOD_PORT 30431
Paul Cercueil2e38bbe2014-03-19 15:27:15 +010034#define IIOD_PORT_STR STRINGIFY(IIOD_PORT)
Paul Cercueilc7bad0f2014-03-03 17:06:48 +010035
Paul Cercueil8fd9c8f2014-03-03 17:21:31 +010036struct iio_context_pdata {
37 int fd;
38};
39
Paul Cercueilc7bad0f2014-03-03 17:06:48 +010040static ssize_t write_all(const void *src, size_t len, int fd)
41{
Paul Cercueil6e7f79e2014-04-04 12:27:24 +020042 uintptr_t ptr = (uintptr_t) src;
Paul Cercueilc7bad0f2014-03-03 17:06:48 +010043 while (len) {
Paul Cercueil6e7f79e2014-04-04 12:27:24 +020044 ssize_t ret = send(fd, (const void *) ptr, len, 0);
Paul Cercueilc7bad0f2014-03-03 17:06:48 +010045 if (ret < 0)
46 return -errno;
47 ptr += ret;
48 len -= ret;
49 }
Paul Cercueil6e7f79e2014-04-04 12:27:24 +020050 return ptr - (uintptr_t) src;
Paul Cercueilc7bad0f2014-03-03 17:06:48 +010051}
52
53static ssize_t read_all(void *dst, size_t len, int fd)
54{
Paul Cercueil6e7f79e2014-04-04 12:27:24 +020055 uintptr_t ptr = (uintptr_t) dst;
Paul Cercueilc7bad0f2014-03-03 17:06:48 +010056 while (len) {
Paul Cercueil6e7f79e2014-04-04 12:27:24 +020057 ssize_t ret = recv(fd, (void *) ptr, len, 0);
Paul Cercueilc7bad0f2014-03-03 17:06:48 +010058 if (ret < 0)
59 return -errno;
60 ptr += ret;
61 len -= ret;
62 }
Paul Cercueil6e7f79e2014-04-04 12:27:24 +020063 return ptr - (uintptr_t) dst;
Paul Cercueilc7bad0f2014-03-03 17:06:48 +010064}
65
Paul Cercueile60c3ed2014-03-04 11:23:56 +010066static int read_integer(int fd, long *val)
67{
68 unsigned int i;
69 char buf[1024], *ptr;
70 ssize_t ret;
71 bool found = false;
72
73 for (i = 0; i < sizeof(buf) - 1; i++) {
74 ret = read_all(buf + i, 1, fd);
75 if (ret < 0)
76 return (int) ret;
77
78 /* Skip the eventual first few carriage returns */
79 if (buf[i] != '\n')
80 found = true;
81 else if (found)
82 break;
83 }
84
85 buf[i] = '\0';
86 ret = (ssize_t) strtol(buf, &ptr, 10);
87 if (ptr == buf)
88 return -EINVAL;
89 *val = (long) ret;
90 return 0;
91}
92
Paul Cercueilbb76bf92014-03-11 10:20:18 +010093static ssize_t write_command(const char *cmd, int fd)
94{
95 ssize_t ret;
96
97 DEBUG("Writing command: %s\n", cmd);
98 ret = write_all(cmd, strlen(cmd), fd);
99 if (ret < 0) {
100 char buf[1024];
101 strerror_r(-ret, buf, sizeof(buf));
102 ERROR("Unable to send command: %s\n", buf);
103 }
104 return ret;
105}
106
107static long exec_command(const char *cmd, int fd)
108{
109 long resp;
110 ssize_t ret = write_command(cmd, fd);
111 if (ret < 0)
112 return (long) ret;
113
114 DEBUG("Reading response\n");
115 ret = read_integer(fd, &resp);
116 if (ret < 0) {
117 char buf[1024];
118 strerror_r(-ret, buf, sizeof(buf));
119 ERROR("Unable to read response: %s\n", buf);
120 return (long) ret;
121 }
122
Paul Cercueilc7fe2ea2014-03-28 11:38:45 +0100123#if LOG_LEVEL >= DEBUG_L
Paul Cercueilbb76bf92014-03-11 10:20:18 +0100124 if (resp < 0) {
125 char buf[1024];
126 strerror_r(-resp, buf, sizeof(buf));
Paul Cercueilc7fe2ea2014-03-28 11:38:45 +0100127 DEBUG("Server returned an error: %s\n", buf);
Paul Cercueilbb76bf92014-03-11 10:20:18 +0100128 }
Paul Cercueilc7fe2ea2014-03-28 11:38:45 +0100129#endif
130
Paul Cercueilbb76bf92014-03-11 10:20:18 +0100131 return resp;
132}
133
Paul Cercueil3c407f82014-04-02 14:11:59 +0200134static int network_open(const struct iio_device *dev,
135 size_t samples_count, uint32_t *mask, size_t nb)
Paul Cercueilba059762014-03-14 11:02:02 +0100136{
137 char buf[1024], *ptr;
138 unsigned int i;
Paul Cercueil44ae11c2014-03-17 09:56:29 +0100139 int ret;
Paul Cercueilba059762014-03-14 11:02:02 +0100140
Paul Cercueilff778232014-03-24 14:23:08 +0100141 if (nb != dev->words)
Paul Cercueilba059762014-03-14 11:02:02 +0100142 return -EINVAL;
143
Paul Cercueil3c407f82014-04-02 14:11:59 +0200144 snprintf(buf, sizeof(buf), "OPEN %s %lu ",
145 dev->id, (unsigned long) samples_count);
Paul Cercueilba059762014-03-14 11:02:02 +0100146 ptr = buf + strlen(buf);
147
148 for (i = nb; i > 0; i--) {
149 sprintf(ptr, "%08x", mask[i - 1]);
150 ptr += 8;
151 }
152 strcpy(ptr, "\r\n");
153
Paul Cercueil44ae11c2014-03-17 09:56:29 +0100154 ret = (int) exec_command(buf, dev->ctx->pdata->fd);
155 if (ret < 0) {
Paul Cercueil44ae11c2014-03-17 09:56:29 +0100156 return ret;
157 } else {
Paul Cercueilff778232014-03-24 14:23:08 +0100158 memcpy(dev->mask, mask, nb * sizeof(*mask));
Paul Cercueil44ae11c2014-03-17 09:56:29 +0100159 return 0;
160 }
Paul Cercueilba059762014-03-14 11:02:02 +0100161}
162
163static int network_close(const struct iio_device *dev)
164{
165 char buf[1024];
166 snprintf(buf, sizeof(buf), "CLOSE %s\r\n", dev->id);
Paul Cercueilff778232014-03-24 14:23:08 +0100167 return (int) exec_command(buf, dev->ctx->pdata->fd);
Paul Cercueilba059762014-03-14 11:02:02 +0100168}
169
Paul Cercueil45c575d2014-03-20 15:14:01 +0100170static ssize_t network_read(const struct iio_device *dev, void *dst, size_t len,
171 uint32_t *mask, size_t words)
Paul Cercueilf9286452014-03-18 14:32:17 +0100172{
Paul Cercueil6e7f79e2014-04-04 12:27:24 +0200173 uintptr_t ptr = (uintptr_t) dst;
Paul Cercueil9945bc82014-03-05 14:07:29 +0100174 int fd = dev->ctx->pdata->fd;
Paul Cercueil45c575d2014-03-20 15:14:01 +0100175 ssize_t ret, read = 0;
Paul Cercueil9945bc82014-03-05 14:07:29 +0100176 char buf[1024];
Paul Cercueil45c575d2014-03-20 15:14:01 +0100177 bool read_mask = true;
Paul Cercueil9945bc82014-03-05 14:07:29 +0100178
Paul Cercueil45c575d2014-03-20 15:14:01 +0100179 if (!len || words != (dev->nb_channels + 31) / 32)
Paul Cercueil9945bc82014-03-05 14:07:29 +0100180 return -EINVAL;
181
Paul Cercueila78b6eb2014-03-17 17:28:07 +0100182 snprintf(buf, sizeof(buf), "READBUF %s %lu\r\n",
183 dev->id, (unsigned long) len);
Paul Cercueilbb76bf92014-03-11 10:20:18 +0100184 ret = write_command(buf, fd);
Paul Cercueil45c575d2014-03-20 15:14:01 +0100185 if (ret < 0)
Paul Cercueil9945bc82014-03-05 14:07:29 +0100186 return ret;
Paul Cercueil9945bc82014-03-05 14:07:29 +0100187
188 do {
Paul Cercueil5cab3ae2014-03-14 11:23:56 +0100189 unsigned int i;
Paul Cercueil9945bc82014-03-05 14:07:29 +0100190 long read_len;
191
192 DEBUG("Reading READ response\n");
193 ret = read_integer(fd, &read_len);
194 if (ret < 0) {
195 strerror_r(-ret, buf, sizeof(buf));
196 ERROR("Unable to read response to READ: %s\n", buf);
Paul Cercueil6e7f79e2014-04-04 12:27:24 +0200197 return read ? read : ret;
Paul Cercueil9945bc82014-03-05 14:07:29 +0100198 }
199
200 if (read_len < 0) {
201 strerror_r(-read_len, buf, sizeof(buf));
202 ERROR("Server returned an error: %s\n", buf);
Paul Cercueil6e7f79e2014-04-04 12:27:24 +0200203 return read ? read : read_len;
Paul Cercueila78b6eb2014-03-17 17:28:07 +0100204 } else if (read_len == 0) {
205 break;
Paul Cercueil9945bc82014-03-05 14:07:29 +0100206 }
207
208 DEBUG("Bytes to read: %li\n", read_len);
209
Paul Cercueil43c1e6c2014-03-20 14:26:20 +0100210 if (read_mask) {
211 DEBUG("Reading mask\n");
212 buf[8] = '\0';
Paul Cercueil45c575d2014-03-20 15:14:01 +0100213 for (i = words; i > 0; i--) {
Paul Cercueil43c1e6c2014-03-20 14:26:20 +0100214 ret = read_all(buf, 8, fd);
215 if (ret < 0)
216 break;
217 sscanf(buf, "%08x", &mask[i - 1]);
218 DEBUG("mask[%i] = 0x%x\n", i - 1, mask[i - 1]);
Paul Cercueil43c1e6c2014-03-20 14:26:20 +0100219 }
220 read_mask = false;
Paul Cercueil5cab3ae2014-03-14 11:23:56 +0100221 }
222
223 if (ret > 0) {
224 char c;
225 ret = recv(fd, &c, 1, 0);
226 if (ret > 0 && c != '\n')
227 ret = -EIO;
228 }
229
230 if (ret < 0) {
231 strerror_r(-ret, buf, sizeof(buf));
232 ERROR("Unable to read mask: %s\n", buf);
Paul Cercueil6e7f79e2014-04-04 12:27:24 +0200233 return read ? read : ret;
Paul Cercueil5cab3ae2014-03-14 11:23:56 +0100234 }
235
Paul Cercueil6e7f79e2014-04-04 12:27:24 +0200236 ret = read_all((void *) ptr, read_len, fd);
Paul Cercueil9945bc82014-03-05 14:07:29 +0100237 if (ret < 0) {
238 strerror_r(-ret, buf, sizeof(buf));
239 ERROR("Unable to read response to READ: %s\n", buf);
Paul Cercueil6e7f79e2014-04-04 12:27:24 +0200240 return read ? read : ret;
Paul Cercueil9945bc82014-03-05 14:07:29 +0100241 }
242
Paul Cercueil6e7f79e2014-04-04 12:27:24 +0200243 ptr += ret;
Paul Cercueilf9286452014-03-18 14:32:17 +0100244 read += ret;
Paul Cercueil9945bc82014-03-05 14:07:29 +0100245 len -= read_len;
246 } while (len);
247
248 return read;
249}
250
Paul Cercueil99cf3d42014-03-06 12:35:26 +0100251static ssize_t network_read_attr_helper(int fd, const char *id,
252 const char *chn, const char *attr, char *dst, size_t len)
Paul Cercueil3e94a5b2014-03-04 13:00:41 +0100253{
Paul Cercueil3e94a5b2014-03-04 13:00:41 +0100254 long read_len;
255 ssize_t ret;
256 char buf[1024];
257
Paul Cercueil99cf3d42014-03-06 12:35:26 +0100258 if (chn)
259 snprintf(buf, sizeof(buf), "READ %s %s %s\r\n", id, chn, attr);
260 else
261 snprintf(buf, sizeof(buf), "READ %s %s\r\n", id, attr);
Paul Cercueilbb76bf92014-03-11 10:20:18 +0100262 read_len = exec_command(buf, fd);
263 if (read_len < 0)
264 return (ssize_t) read_len;
Paul Cercueil3e94a5b2014-03-04 13:00:41 +0100265
Paul Cercueil6e7f79e2014-04-04 12:27:24 +0200266 if ((unsigned long) read_len > len) {
Paul Cercueil3e94a5b2014-03-04 13:00:41 +0100267 ERROR("Value returned by server is too large\n");
268 return -EIO;
269 }
270
271 ret = read_all(dst, read_len, fd);
272 if (ret < 0) {
273 strerror_r(-ret, buf, sizeof(buf));
274 ERROR("Unable to read response to READ: %s\n", buf);
275 return ret;
276 }
277
278 dst[read_len] = '\0';
279 return read_len + 1;
280}
281
Paul Cercueil07897d32014-03-06 12:46:08 +0100282static ssize_t network_write_attr_helper(int fd, const char *id,
283 const char *chn, const char *attr, const char *src)
Paul Cercueil3e94a5b2014-03-04 13:00:41 +0100284{
Paul Cercueil3e94a5b2014-03-04 13:00:41 +0100285 char buf[1024];
286
Paul Cercueil07897d32014-03-06 12:46:08 +0100287 if (chn)
288 snprintf(buf, sizeof(buf), "WRITE %s %s %s %s\r\n",
289 id, chn, attr, src);
290 else
291 snprintf(buf, sizeof(buf), "WRITE %s %s %s\r\n", id, attr, src);
Paul Cercueilbb76bf92014-03-11 10:20:18 +0100292 return (ssize_t) exec_command(buf, fd);
Paul Cercueil3e94a5b2014-03-04 13:00:41 +0100293}
294
Paul Cercueil99cf3d42014-03-06 12:35:26 +0100295static ssize_t network_read_dev_attr(const struct iio_device *dev,
296 const char *attr, char *dst, size_t len)
297{
298 return network_read_attr_helper(dev->ctx->pdata->fd, dev->id,
299 NULL, attr, dst, len);
300}
301
Paul Cercueil07897d32014-03-06 12:46:08 +0100302static ssize_t network_write_dev_attr(const struct iio_device *dev,
303 const char *attr, const char *src)
304{
305 return network_write_attr_helper(dev->ctx->pdata->fd, dev->id,
306 NULL, attr, src);
307}
308
Paul Cercueil99cf3d42014-03-06 12:35:26 +0100309static ssize_t network_read_chn_attr(const struct iio_channel *chn,
310 const char *attr, char *dst, size_t len)
311{
312 return network_read_attr_helper(chn->dev->ctx->pdata->fd, chn->dev->id,
313 chn->id, attr, dst, len);
314}
315
Paul Cercueil07897d32014-03-06 12:46:08 +0100316static ssize_t network_write_chn_attr(const struct iio_channel *chn,
317 const char *attr, const char *src)
318{
319 return network_write_attr_helper(chn->dev->ctx->pdata->fd, chn->dev->id,
320 chn->id, attr, src);
321}
322
Paul Cercueildcab40c2014-03-11 10:59:14 +0100323static int network_get_trigger(const struct iio_device *dev,
324 const struct iio_device **trigger)
325{
326 struct iio_context_pdata *pdata = dev->ctx->pdata;
327 unsigned int i;
328 char buf[1024];
329 ssize_t ret;
330 long resp;
331
332 snprintf(buf, sizeof(buf), "GETTRIG %s\r\n", dev->id);
333 resp = exec_command(buf, pdata->fd);
334 if (resp < 0) {
335 return (int) resp;
336 } else if (resp == 0) {
337 *trigger = NULL;
338 return 0;
Paul Cercueil6e7f79e2014-04-04 12:27:24 +0200339 } else if ((unsigned long) resp > sizeof(buf)) {
Paul Cercueildcab40c2014-03-11 10:59:14 +0100340 ERROR("Value returned by server is too large\n");
341 return -EIO;
342 }
343
344 ret = read_all(buf, resp, pdata->fd);
345 if (ret < 0) {
346 strerror_r(-ret, buf, sizeof(buf));
347 ERROR("Unable to read response to GETTRIG: %s\n", buf);
348 return ret;
349 }
350
351 for (i = 0; i < dev->ctx->nb_devices; i++) {
352 struct iio_device *cur = dev->ctx->devices[i];
353 if (iio_device_is_trigger(cur) &&
354 !strncmp(cur->name, buf, resp)) {
355 *trigger = cur;
356 return 0;
357 }
358 }
359
360 return -ENXIO;
361}
362
363static int network_set_trigger(const struct iio_device *dev,
364 const struct iio_device *trigger)
365{
366 char buf[1024];
367 if (trigger)
368 snprintf(buf, sizeof(buf), "SETTRIG %s %s\r\n",
369 dev->id, trigger->id);
370 else
371 snprintf(buf, sizeof(buf), "SETTRIG %s\r\n", dev->id);
372 return (int) exec_command(buf, dev->ctx->pdata->fd);
373}
374
Paul Cercueil8fd9c8f2014-03-03 17:21:31 +0100375static void network_shutdown(struct iio_context *ctx)
376{
377 struct iio_context_pdata *pdata = ctx->pdata;
Paul Cercueil44ae11c2014-03-17 09:56:29 +0100378 unsigned int i;
Paul Cercueil8fd9c8f2014-03-03 17:21:31 +0100379
Paul Cercueilbb76bf92014-03-11 10:20:18 +0100380 write_command("\r\nEXIT\r\n", pdata->fd);
Paul Cercueil8fd9c8f2014-03-03 17:21:31 +0100381 close(pdata->fd);
382 free(pdata);
Paul Cercueil44ae11c2014-03-17 09:56:29 +0100383
384 for (i = 0; i < ctx->nb_devices; i++) {
385 struct iio_device *dev = ctx->devices[i];
386 if (dev->pdata)
387 free(dev->pdata);
388 }
Paul Cercueil8fd9c8f2014-03-03 17:21:31 +0100389}
390
Paul Cercueilc7bad0f2014-03-03 17:06:48 +0100391static struct iio_backend_ops network_ops = {
Paul Cercueilba059762014-03-14 11:02:02 +0100392 .open = network_open,
393 .close = network_close,
Paul Cercueil9945bc82014-03-05 14:07:29 +0100394 .read = network_read,
Paul Cercueil3e94a5b2014-03-04 13:00:41 +0100395 .read_device_attr = network_read_dev_attr,
396 .write_device_attr = network_write_dev_attr,
Paul Cercueil99cf3d42014-03-06 12:35:26 +0100397 .read_channel_attr = network_read_chn_attr,
Paul Cercueil07897d32014-03-06 12:46:08 +0100398 .write_channel_attr = network_write_chn_attr,
Paul Cercueildcab40c2014-03-11 10:59:14 +0100399 .get_trigger = network_get_trigger,
400 .set_trigger = network_set_trigger,
Paul Cercueil8fd9c8f2014-03-03 17:21:31 +0100401 .shutdown = network_shutdown,
Paul Cercueilc7bad0f2014-03-03 17:06:48 +0100402};
403
404static struct iio_context * get_context(int fd)
405{
406 struct iio_context *ctx;
Paul Cercueile60c3ed2014-03-04 11:23:56 +0100407 char *xml;
Paul Cercueilbb76bf92014-03-11 10:20:18 +0100408 long xml_len = exec_command("PRINT\r\n", fd);
409 if (xml_len < 0)
Paul Cercueilc7bad0f2014-03-03 17:06:48 +0100410 return NULL;
Paul Cercueile60c3ed2014-03-04 11:23:56 +0100411
412 DEBUG("Server returned a XML string of length %li\n", xml_len);
Paul Cercueilc7bad0f2014-03-03 17:06:48 +0100413 xml = malloc(xml_len);
414 if (!xml) {
415 ERROR("Unable to allocate data\n");
416 return NULL;
417 }
418
419 DEBUG("Reading XML string...\n");
420 read_all(xml, xml_len, fd);
421
422 DEBUG("Creating context from XML...\n");
423 ctx = iio_create_xml_context_mem(xml, xml_len);
424 free(xml);
425 return ctx;
426}
427
428struct iio_context * iio_create_network_context(const char *host)
429{
Paul Cercueil2e38bbe2014-03-19 15:27:15 +0100430 struct addrinfo hints, *res;
Paul Cercueilc7bad0f2014-03-03 17:06:48 +0100431 struct iio_context *ctx;
Paul Cercueil8fd9c8f2014-03-03 17:21:31 +0100432 struct iio_context_pdata *pdata;
Paul Cercueil44ae11c2014-03-17 09:56:29 +0100433 unsigned int i;
Paul Cercueil2e38bbe2014-03-19 15:27:15 +0100434 int fd, ret;
Paul Cercueilc7bad0f2014-03-03 17:06:48 +0100435
Paul Cercueil2e38bbe2014-03-19 15:27:15 +0100436 memset(&hints, 0, sizeof(hints));
437 hints.ai_family = AF_UNSPEC;
438 hints.ai_socktype = SOCK_STREAM;
439 ret = getaddrinfo(host, IIOD_PORT_STR, &hints, &res);
440 if (ret) {
441 ERROR("Unable to find IP address for host %s: %s\n",
442 host, gai_strerror(ret));
Paul Cercueilc7bad0f2014-03-03 17:06:48 +0100443 return NULL;
Paul Cercueilc7bad0f2014-03-03 17:06:48 +0100444 }
445
Paul Cercueil2e38bbe2014-03-19 15:27:15 +0100446 fd = socket(res->ai_family, res->ai_socktype, 0);
Paul Cercueilc7bad0f2014-03-03 17:06:48 +0100447 if (fd < 0) {
448 ERROR("Unable to open socket\n");
449 return NULL;
450 }
451
Paul Cercueil2e38bbe2014-03-19 15:27:15 +0100452 if (connect(fd, res->ai_addr, res->ai_addrlen) < 0) {
Paul Cercueilc7bad0f2014-03-03 17:06:48 +0100453 ERROR("Unable to connect\n");
454 goto err_close_socket;
455 }
456
Paul Cercueil8fd9c8f2014-03-03 17:21:31 +0100457 pdata = calloc(1, sizeof(*pdata));
458 if (!pdata) {
459 ERROR("Unable to allocate memory\n");
460 goto err_close_socket;
461 }
462
463 pdata->fd = fd;
464
Paul Cercueilc7bad0f2014-03-03 17:06:48 +0100465 DEBUG("Creating context...\n");
466 ctx = get_context(fd);
467 if (!ctx)
Paul Cercueil8fd9c8f2014-03-03 17:21:31 +0100468 goto err_free_pdata;
Paul Cercueilc7bad0f2014-03-03 17:06:48 +0100469
Paul Cercueil44ae11c2014-03-17 09:56:29 +0100470 for (i = 0; i < ctx->nb_devices; i++) {
471 struct iio_device *dev = ctx->devices[i];
Paul Cercueilff778232014-03-24 14:23:08 +0100472 uint32_t *mask = NULL;
473
474 dev->words = (dev->nb_channels + 31) / 32;
475 if (dev->words) {
476 mask = calloc(dev->words, sizeof(*mask));
477 if (!mask)
478 goto err_network_shutdown;
479 }
480
481 dev->mask = mask;
Paul Cercueil44ae11c2014-03-17 09:56:29 +0100482 }
483
Paul Cercueilff778232014-03-24 14:23:08 +0100484
Paul Cercueilc7bad0f2014-03-03 17:06:48 +0100485 /* Override the name and low-level functions of the XML context
486 * with those corresponding to the network context */
487 ctx->name = "network";
488 ctx->ops = &network_ops;
Paul Cercueil8fd9c8f2014-03-03 17:21:31 +0100489 ctx->pdata = pdata;
Paul Cercueilc7bad0f2014-03-03 17:06:48 +0100490
Paul Cercueilcd6ce842014-03-14 13:21:06 +0100491 iio_context_init_channels(ctx);
Paul Cercueilc7bad0f2014-03-03 17:06:48 +0100492 return ctx;
493
Paul Cercueil44ae11c2014-03-17 09:56:29 +0100494err_network_shutdown:
495 network_shutdown(ctx);
496 iio_context_destroy(ctx);
Paul Cercueil8fd9c8f2014-03-03 17:21:31 +0100497err_free_pdata:
498 free(pdata);
Paul Cercueilc7bad0f2014-03-03 17:06:48 +0100499err_close_socket:
500 close(fd);
501 return NULL;
502}