blob: ef07da8fc4ff812fd64ec1b56250e83bb6fa8bea [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
21#include <errno.h>
Paul Cercueil1494b862014-05-05 12:49:07 +020022#include <pthread.h>
Paul Cercueile60c3ed2014-03-04 11:23:56 +010023#include <stdbool.h>
Paul Cercueilc7bad0f2014-03-03 17:06:48 +010024#include <string.h>
25#include <sys/types.h>
Paul Cercueil1fef1a52014-04-07 16:31:15 +020026
27#ifdef _WIN32
28#include <winsock2.h>
29#include <ws2tcpip.h>
30#define close(s) closesocket(s)
31
32/* winsock2.h defines ERROR, we don't want that */
33#undef ERROR
34
35#else /* _WIN32 */
36#include <netdb.h>
Paul Cercueilc7bad0f2014-03-03 17:06:48 +010037#include <sys/socket.h>
38#include <unistd.h>
Paul Cercueil1fef1a52014-04-07 16:31:15 +020039#endif /* _WIN32 */
40
41#include "debug.h"
Paul Cercueilc7bad0f2014-03-03 17:06:48 +010042
Paul Cercueil2e38bbe2014-03-19 15:27:15 +010043#define _STRINGIFY(x) #x
44#define STRINGIFY(x) _STRINGIFY(x)
45
Paul Cercueilc7bad0f2014-03-03 17:06:48 +010046#define IIOD_PORT 30431
Paul Cercueil2e38bbe2014-03-19 15:27:15 +010047#define IIOD_PORT_STR STRINGIFY(IIOD_PORT)
Paul Cercueilc7bad0f2014-03-03 17:06:48 +010048
Paul Cercueil8fd9c8f2014-03-03 17:21:31 +010049struct iio_context_pdata {
50 int fd;
Paul Cercueil1494b862014-05-05 12:49:07 +020051 pthread_mutex_t lock;
Paul Cercueil8fd9c8f2014-03-03 17:21:31 +010052};
53
Paul Cercueilc7bad0f2014-03-03 17:06:48 +010054static ssize_t write_all(const void *src, size_t len, int fd)
55{
Paul Cercueil6e7f79e2014-04-04 12:27:24 +020056 uintptr_t ptr = (uintptr_t) src;
Paul Cercueilc7bad0f2014-03-03 17:06:48 +010057 while (len) {
Paul Cercueil6e7f79e2014-04-04 12:27:24 +020058 ssize_t ret = send(fd, (const void *) ptr, len, 0);
Paul Cercueilc7bad0f2014-03-03 17:06:48 +010059 if (ret < 0)
60 return -errno;
61 ptr += ret;
62 len -= ret;
63 }
Paul Cercueil6e7f79e2014-04-04 12:27:24 +020064 return ptr - (uintptr_t) src;
Paul Cercueilc7bad0f2014-03-03 17:06:48 +010065}
66
67static ssize_t read_all(void *dst, size_t len, int fd)
68{
Paul Cercueil6e7f79e2014-04-04 12:27:24 +020069 uintptr_t ptr = (uintptr_t) dst;
Paul Cercueilc7bad0f2014-03-03 17:06:48 +010070 while (len) {
Paul Cercueil6e7f79e2014-04-04 12:27:24 +020071 ssize_t ret = recv(fd, (void *) ptr, len, 0);
Paul Cercueilc7bad0f2014-03-03 17:06:48 +010072 if (ret < 0)
73 return -errno;
74 ptr += ret;
75 len -= ret;
76 }
Paul Cercueil6e7f79e2014-04-04 12:27:24 +020077 return ptr - (uintptr_t) dst;
Paul Cercueilc7bad0f2014-03-03 17:06:48 +010078}
79
Paul Cercueile60c3ed2014-03-04 11:23:56 +010080static int read_integer(int fd, long *val)
81{
82 unsigned int i;
83 char buf[1024], *ptr;
84 ssize_t ret;
85 bool found = false;
86
87 for (i = 0; i < sizeof(buf) - 1; i++) {
88 ret = read_all(buf + i, 1, fd);
89 if (ret < 0)
90 return (int) ret;
91
Paul Cercueil6691a3f2014-05-02 12:32:01 +020092 /* Skip the eventual first few carriage returns.
93 * Also stop when a dot is found (for parsing floats) */
94 if (buf[i] != '\n' && buf[i] != '.')
Paul Cercueile60c3ed2014-03-04 11:23:56 +010095 found = true;
96 else if (found)
97 break;
98 }
99
100 buf[i] = '\0';
101 ret = (ssize_t) strtol(buf, &ptr, 10);
102 if (ptr == buf)
103 return -EINVAL;
104 *val = (long) ret;
105 return 0;
106}
107
Paul Cercueilbb76bf92014-03-11 10:20:18 +0100108static ssize_t write_command(const char *cmd, int fd)
109{
110 ssize_t ret;
111
112 DEBUG("Writing command: %s\n", cmd);
113 ret = write_all(cmd, strlen(cmd), fd);
114 if (ret < 0) {
115 char buf[1024];
116 strerror_r(-ret, buf, sizeof(buf));
117 ERROR("Unable to send command: %s\n", buf);
118 }
119 return ret;
120}
121
122static long exec_command(const char *cmd, int fd)
123{
124 long resp;
125 ssize_t ret = write_command(cmd, fd);
126 if (ret < 0)
127 return (long) ret;
128
129 DEBUG("Reading response\n");
130 ret = read_integer(fd, &resp);
131 if (ret < 0) {
132 char buf[1024];
133 strerror_r(-ret, buf, sizeof(buf));
134 ERROR("Unable to read response: %s\n", buf);
135 return (long) ret;
136 }
137
Paul Cercueilc7fe2ea2014-03-28 11:38:45 +0100138#if LOG_LEVEL >= DEBUG_L
Paul Cercueilbb76bf92014-03-11 10:20:18 +0100139 if (resp < 0) {
140 char buf[1024];
141 strerror_r(-resp, buf, sizeof(buf));
Paul Cercueilc7fe2ea2014-03-28 11:38:45 +0100142 DEBUG("Server returned an error: %s\n", buf);
Paul Cercueilbb76bf92014-03-11 10:20:18 +0100143 }
Paul Cercueilc7fe2ea2014-03-28 11:38:45 +0100144#endif
145
Paul Cercueilbb76bf92014-03-11 10:20:18 +0100146 return resp;
147}
148
Paul Cercueil3c407f82014-04-02 14:11:59 +0200149static int network_open(const struct iio_device *dev,
150 size_t samples_count, uint32_t *mask, size_t nb)
Paul Cercueilba059762014-03-14 11:02:02 +0100151{
152 char buf[1024], *ptr;
153 unsigned int i;
Paul Cercueil44ae11c2014-03-17 09:56:29 +0100154 int ret;
Paul Cercueilba059762014-03-14 11:02:02 +0100155
Paul Cercueilff778232014-03-24 14:23:08 +0100156 if (nb != dev->words)
Paul Cercueilba059762014-03-14 11:02:02 +0100157 return -EINVAL;
158
Paul Cercueil3c407f82014-04-02 14:11:59 +0200159 snprintf(buf, sizeof(buf), "OPEN %s %lu ",
160 dev->id, (unsigned long) samples_count);
Paul Cercueilba059762014-03-14 11:02:02 +0100161 ptr = buf + strlen(buf);
162
163 for (i = nb; i > 0; i--) {
Paul Cercueil8c29e412014-04-07 09:46:45 +0200164 snprintf(ptr, (ptr - buf) + i * 8, "%08x", mask[i - 1]);
Paul Cercueilba059762014-03-14 11:02:02 +0100165 ptr += 8;
166 }
167 strcpy(ptr, "\r\n");
168
Paul Cercueil1494b862014-05-05 12:49:07 +0200169 pthread_mutex_lock(&dev->ctx->pdata->lock);
Paul Cercueil44ae11c2014-03-17 09:56:29 +0100170 ret = (int) exec_command(buf, dev->ctx->pdata->fd);
Paul Cercueil1494b862014-05-05 12:49:07 +0200171 pthread_mutex_unlock(&dev->ctx->pdata->lock);
172
Paul Cercueil44ae11c2014-03-17 09:56:29 +0100173 if (ret < 0) {
Paul Cercueil44ae11c2014-03-17 09:56:29 +0100174 return ret;
175 } else {
Paul Cercueilff778232014-03-24 14:23:08 +0100176 memcpy(dev->mask, mask, nb * sizeof(*mask));
Paul Cercueil44ae11c2014-03-17 09:56:29 +0100177 return 0;
178 }
Paul Cercueilba059762014-03-14 11:02:02 +0100179}
180
181static int network_close(const struct iio_device *dev)
182{
Paul Cercueil1494b862014-05-05 12:49:07 +0200183 int ret;
Paul Cercueilba059762014-03-14 11:02:02 +0100184 char buf[1024];
185 snprintf(buf, sizeof(buf), "CLOSE %s\r\n", dev->id);
Paul Cercueil1494b862014-05-05 12:49:07 +0200186
187 pthread_mutex_lock(&dev->ctx->pdata->lock);
188 ret = (int) exec_command(buf, dev->ctx->pdata->fd);
189 pthread_mutex_unlock(&dev->ctx->pdata->lock);
190
191 return ret;
Paul Cercueilba059762014-03-14 11:02:02 +0100192}
193
Paul Cercueil45c575d2014-03-20 15:14:01 +0100194static ssize_t network_read(const struct iio_device *dev, void *dst, size_t len,
195 uint32_t *mask, size_t words)
Paul Cercueilf9286452014-03-18 14:32:17 +0100196{
Paul Cercueil6e7f79e2014-04-04 12:27:24 +0200197 uintptr_t ptr = (uintptr_t) dst;
Paul Cercueil9945bc82014-03-05 14:07:29 +0100198 int fd = dev->ctx->pdata->fd;
Paul Cercueil45c575d2014-03-20 15:14:01 +0100199 ssize_t ret, read = 0;
Paul Cercueil9945bc82014-03-05 14:07:29 +0100200 char buf[1024];
Paul Cercueil45c575d2014-03-20 15:14:01 +0100201 bool read_mask = true;
Paul Cercueil9945bc82014-03-05 14:07:29 +0100202
Paul Cercueil45c575d2014-03-20 15:14:01 +0100203 if (!len || words != (dev->nb_channels + 31) / 32)
Paul Cercueil9945bc82014-03-05 14:07:29 +0100204 return -EINVAL;
205
Paul Cercueila78b6eb2014-03-17 17:28:07 +0100206 snprintf(buf, sizeof(buf), "READBUF %s %lu\r\n",
207 dev->id, (unsigned long) len);
Paul Cercueil1494b862014-05-05 12:49:07 +0200208
209 pthread_mutex_lock(&dev->ctx->pdata->lock);
Paul Cercueilbb76bf92014-03-11 10:20:18 +0100210 ret = write_command(buf, fd);
Paul Cercueil1494b862014-05-05 12:49:07 +0200211 if (ret < 0) {
212 pthread_mutex_unlock(&dev->ctx->pdata->lock);
Paul Cercueil9945bc82014-03-05 14:07:29 +0100213 return ret;
Paul Cercueil1494b862014-05-05 12:49:07 +0200214 }
Paul Cercueil9945bc82014-03-05 14:07:29 +0100215
216 do {
Paul Cercueil5cab3ae2014-03-14 11:23:56 +0100217 unsigned int i;
Paul Cercueil9945bc82014-03-05 14:07:29 +0100218 long read_len;
219
220 DEBUG("Reading READ response\n");
221 ret = read_integer(fd, &read_len);
222 if (ret < 0) {
223 strerror_r(-ret, buf, sizeof(buf));
224 ERROR("Unable to read response to READ: %s\n", buf);
Paul Cercueil1494b862014-05-05 12:49:07 +0200225 pthread_mutex_unlock(&dev->ctx->pdata->lock);
Paul Cercueil6e7f79e2014-04-04 12:27:24 +0200226 return read ? read : ret;
Paul Cercueil9945bc82014-03-05 14:07:29 +0100227 }
228
229 if (read_len < 0) {
230 strerror_r(-read_len, buf, sizeof(buf));
231 ERROR("Server returned an error: %s\n", buf);
Paul Cercueil1494b862014-05-05 12:49:07 +0200232 pthread_mutex_unlock(&dev->ctx->pdata->lock);
Paul Cercueil6e7f79e2014-04-04 12:27:24 +0200233 return read ? read : read_len;
Paul Cercueila78b6eb2014-03-17 17:28:07 +0100234 } else if (read_len == 0) {
235 break;
Paul Cercueil9945bc82014-03-05 14:07:29 +0100236 }
237
238 DEBUG("Bytes to read: %li\n", read_len);
239
Paul Cercueil43c1e6c2014-03-20 14:26:20 +0100240 if (read_mask) {
241 DEBUG("Reading mask\n");
242 buf[8] = '\0';
Paul Cercueil45c575d2014-03-20 15:14:01 +0100243 for (i = words; i > 0; i--) {
Paul Cercueil43c1e6c2014-03-20 14:26:20 +0100244 ret = read_all(buf, 8, fd);
245 if (ret < 0)
246 break;
247 sscanf(buf, "%08x", &mask[i - 1]);
248 DEBUG("mask[%i] = 0x%x\n", i - 1, mask[i - 1]);
Paul Cercueil43c1e6c2014-03-20 14:26:20 +0100249 }
250 read_mask = false;
Paul Cercueil5cab3ae2014-03-14 11:23:56 +0100251 }
252
253 if (ret > 0) {
254 char c;
255 ret = recv(fd, &c, 1, 0);
256 if (ret > 0 && c != '\n')
257 ret = -EIO;
258 }
259
260 if (ret < 0) {
261 strerror_r(-ret, buf, sizeof(buf));
262 ERROR("Unable to read mask: %s\n", buf);
Paul Cercueil1494b862014-05-05 12:49:07 +0200263 pthread_mutex_unlock(&dev->ctx->pdata->lock);
Paul Cercueil6e7f79e2014-04-04 12:27:24 +0200264 return read ? read : ret;
Paul Cercueil5cab3ae2014-03-14 11:23:56 +0100265 }
266
Paul Cercueil6e7f79e2014-04-04 12:27:24 +0200267 ret = read_all((void *) ptr, read_len, fd);
Paul Cercueil9945bc82014-03-05 14:07:29 +0100268 if (ret < 0) {
269 strerror_r(-ret, buf, sizeof(buf));
270 ERROR("Unable to read response to READ: %s\n", buf);
Paul Cercueil1494b862014-05-05 12:49:07 +0200271 pthread_mutex_unlock(&dev->ctx->pdata->lock);
Paul Cercueil6e7f79e2014-04-04 12:27:24 +0200272 return read ? read : ret;
Paul Cercueil9945bc82014-03-05 14:07:29 +0100273 }
274
Paul Cercueil6e7f79e2014-04-04 12:27:24 +0200275 ptr += ret;
Paul Cercueilf9286452014-03-18 14:32:17 +0100276 read += ret;
Paul Cercueil9945bc82014-03-05 14:07:29 +0100277 len -= read_len;
278 } while (len);
279
Paul Cercueil1494b862014-05-05 12:49:07 +0200280 pthread_mutex_unlock(&dev->ctx->pdata->lock);
Paul Cercueil9945bc82014-03-05 14:07:29 +0100281 return read;
282}
283
Paul Cercueil2725f702014-05-02 11:02:16 +0200284static ssize_t network_write(const struct iio_device *dev,
285 const void *src, size_t len)
286{
287 int fd = dev->ctx->pdata->fd;
288 ssize_t ret;
289 char buf[1024];
290 long resp;
291
292 snprintf(buf, sizeof(buf), "WRITEBUF %s %lu\r\n",
293 dev->id, (unsigned long) len);
Paul Cercueil1494b862014-05-05 12:49:07 +0200294
295 pthread_mutex_lock(&dev->ctx->pdata->lock);
Paul Cercueil2725f702014-05-02 11:02:16 +0200296 ret = (ssize_t) exec_command(buf, fd);
297 if (ret < 0)
Paul Cercueil1494b862014-05-05 12:49:07 +0200298 goto err_unlock;
Paul Cercueil2725f702014-05-02 11:02:16 +0200299
300 ret = write_all(src, len, fd);
301 if (ret < 0)
Paul Cercueil1494b862014-05-05 12:49:07 +0200302 goto err_unlock;
Paul Cercueil2725f702014-05-02 11:02:16 +0200303
304 ret = read_integer(fd, &resp);
Paul Cercueil1494b862014-05-05 12:49:07 +0200305 pthread_mutex_unlock(&dev->ctx->pdata->lock);
306
Paul Cercueil2725f702014-05-02 11:02:16 +0200307 if (ret < 0)
308 return ret;
309 return (ssize_t) resp;
Paul Cercueil1494b862014-05-05 12:49:07 +0200310
311err_unlock:
312 pthread_mutex_unlock(&dev->ctx->pdata->lock);
313 return ret;
Paul Cercueil2725f702014-05-02 11:02:16 +0200314}
315
Paul Cercueil1494b862014-05-05 12:49:07 +0200316static ssize_t network_read_attr_helper(const struct iio_device *dev,
317 const char *chn, const char *attr, char *dst,
318 size_t len, bool is_debug)
Paul Cercueil3e94a5b2014-03-04 13:00:41 +0100319{
Paul Cercueil3e94a5b2014-03-04 13:00:41 +0100320 long read_len;
321 ssize_t ret;
322 char buf[1024];
Paul Cercueil1494b862014-05-05 12:49:07 +0200323 int fd = dev->ctx->pdata->fd;
324 const char *id = dev->id;
Paul Cercueil3e94a5b2014-03-04 13:00:41 +0100325
Paul Cercueil99cf3d42014-03-06 12:35:26 +0100326 if (chn)
327 snprintf(buf, sizeof(buf), "READ %s %s %s\r\n", id, chn, attr);
Paul Cercueilc6f03612014-04-14 16:41:31 +0200328 else if (is_debug)
329 snprintf(buf, sizeof(buf), "READ %s debug %s\r\n", id, attr);
Paul Cercueil99cf3d42014-03-06 12:35:26 +0100330 else
331 snprintf(buf, sizeof(buf), "READ %s %s\r\n", id, attr);
Paul Cercueil1494b862014-05-05 12:49:07 +0200332
333 pthread_mutex_lock(&dev->ctx->pdata->lock);
Paul Cercueilbb76bf92014-03-11 10:20:18 +0100334 read_len = exec_command(buf, fd);
Paul Cercueil1494b862014-05-05 12:49:07 +0200335 if (read_len < 0) {
336 pthread_mutex_unlock(&dev->ctx->pdata->lock);
Paul Cercueilbb76bf92014-03-11 10:20:18 +0100337 return (ssize_t) read_len;
Paul Cercueil1494b862014-05-05 12:49:07 +0200338 }
Paul Cercueil3e94a5b2014-03-04 13:00:41 +0100339
Paul Cercueil6e7f79e2014-04-04 12:27:24 +0200340 if ((unsigned long) read_len > len) {
Paul Cercueil3e94a5b2014-03-04 13:00:41 +0100341 ERROR("Value returned by server is too large\n");
Paul Cercueil1494b862014-05-05 12:49:07 +0200342 pthread_mutex_unlock(&dev->ctx->pdata->lock);
Paul Cercueil3e94a5b2014-03-04 13:00:41 +0100343 return -EIO;
344 }
345
346 ret = read_all(dst, read_len, fd);
Paul Cercueil1494b862014-05-05 12:49:07 +0200347 pthread_mutex_unlock(&dev->ctx->pdata->lock);
348
Paul Cercueil3e94a5b2014-03-04 13:00:41 +0100349 if (ret < 0) {
350 strerror_r(-ret, buf, sizeof(buf));
351 ERROR("Unable to read response to READ: %s\n", buf);
352 return ret;
353 }
354
355 dst[read_len] = '\0';
356 return read_len + 1;
357}
358
Paul Cercueil1494b862014-05-05 12:49:07 +0200359static ssize_t network_write_attr_helper(const struct iio_device *dev,
Paul Cercueilc6f03612014-04-14 16:41:31 +0200360 const char *chn, const char *attr, const char *src,
361 bool is_debug)
Paul Cercueil3e94a5b2014-03-04 13:00:41 +0100362{
Paul Cercueil3e94a5b2014-03-04 13:00:41 +0100363 char buf[1024];
Paul Cercueil1494b862014-05-05 12:49:07 +0200364 ssize_t ret;
365 int fd = dev->ctx->pdata->fd;
366 const char *id = dev->id;
Paul Cercueil3e94a5b2014-03-04 13:00:41 +0100367
Paul Cercueil07897d32014-03-06 12:46:08 +0100368 if (chn)
369 snprintf(buf, sizeof(buf), "WRITE %s %s %s %s\r\n",
370 id, chn, attr, src);
Paul Cercueilc6f03612014-04-14 16:41:31 +0200371 else if (is_debug)
372 snprintf(buf, sizeof(buf), "WRITE %s debug %s %s\r\n",
373 id, attr, src);
Paul Cercueil07897d32014-03-06 12:46:08 +0100374 else
375 snprintf(buf, sizeof(buf), "WRITE %s %s %s\r\n", id, attr, src);
Paul Cercueil1494b862014-05-05 12:49:07 +0200376
377 pthread_mutex_lock(&dev->ctx->pdata->lock);
378 ret = (ssize_t) exec_command(buf, fd);
379 pthread_mutex_unlock(&dev->ctx->pdata->lock);
380 return ret;
Paul Cercueil3e94a5b2014-03-04 13:00:41 +0100381}
382
Paul Cercueil99cf3d42014-03-06 12:35:26 +0100383static ssize_t network_read_dev_attr(const struct iio_device *dev,
Paul Cercueil50c762a2014-04-14 15:55:43 +0200384 const char *attr, char *dst, size_t len, bool is_debug)
Paul Cercueil99cf3d42014-03-06 12:35:26 +0100385{
Paul Cercueil1494b862014-05-05 12:49:07 +0200386 return network_read_attr_helper(dev, NULL, attr, dst, len, is_debug);
Paul Cercueil99cf3d42014-03-06 12:35:26 +0100387}
388
Paul Cercueil07897d32014-03-06 12:46:08 +0100389static ssize_t network_write_dev_attr(const struct iio_device *dev,
Paul Cercueil50c762a2014-04-14 15:55:43 +0200390 const char *attr, const char *src, bool is_debug)
Paul Cercueil07897d32014-03-06 12:46:08 +0100391{
Paul Cercueil1494b862014-05-05 12:49:07 +0200392 return network_write_attr_helper(dev, NULL, attr, src, is_debug);
Paul Cercueil07897d32014-03-06 12:46:08 +0100393}
394
Paul Cercueil99cf3d42014-03-06 12:35:26 +0100395static ssize_t network_read_chn_attr(const struct iio_channel *chn,
396 const char *attr, char *dst, size_t len)
397{
Paul Cercueil1494b862014-05-05 12:49:07 +0200398 return network_read_attr_helper(chn->dev,
Paul Cercueilc6f03612014-04-14 16:41:31 +0200399 chn->id, attr, dst, len, false);
Paul Cercueil99cf3d42014-03-06 12:35:26 +0100400}
401
Paul Cercueil07897d32014-03-06 12:46:08 +0100402static ssize_t network_write_chn_attr(const struct iio_channel *chn,
403 const char *attr, const char *src)
404{
Paul Cercueil1494b862014-05-05 12:49:07 +0200405 return network_write_attr_helper(chn->dev, chn->id, attr, src, false);
Paul Cercueil07897d32014-03-06 12:46:08 +0100406}
407
Paul Cercueildcab40c2014-03-11 10:59:14 +0100408static int network_get_trigger(const struct iio_device *dev,
409 const struct iio_device **trigger)
410{
411 struct iio_context_pdata *pdata = dev->ctx->pdata;
412 unsigned int i;
413 char buf[1024];
414 ssize_t ret;
415 long resp;
416
417 snprintf(buf, sizeof(buf), "GETTRIG %s\r\n", dev->id);
Paul Cercueil1494b862014-05-05 12:49:07 +0200418
419 pthread_mutex_lock(&dev->ctx->pdata->lock);
Paul Cercueildcab40c2014-03-11 10:59:14 +0100420 resp = exec_command(buf, pdata->fd);
421 if (resp < 0) {
Paul Cercueil1494b862014-05-05 12:49:07 +0200422 pthread_mutex_unlock(&dev->ctx->pdata->lock);
Paul Cercueildcab40c2014-03-11 10:59:14 +0100423 return (int) resp;
424 } else if (resp == 0) {
425 *trigger = NULL;
Paul Cercueil1494b862014-05-05 12:49:07 +0200426 pthread_mutex_unlock(&dev->ctx->pdata->lock);
Paul Cercueildcab40c2014-03-11 10:59:14 +0100427 return 0;
Paul Cercueil6e7f79e2014-04-04 12:27:24 +0200428 } else if ((unsigned long) resp > sizeof(buf)) {
Paul Cercueildcab40c2014-03-11 10:59:14 +0100429 ERROR("Value returned by server is too large\n");
Paul Cercueil1494b862014-05-05 12:49:07 +0200430 pthread_mutex_unlock(&dev->ctx->pdata->lock);
Paul Cercueildcab40c2014-03-11 10:59:14 +0100431 return -EIO;
432 }
433
434 ret = read_all(buf, resp, pdata->fd);
Paul Cercueil1494b862014-05-05 12:49:07 +0200435 pthread_mutex_unlock(&dev->ctx->pdata->lock);
436
Paul Cercueildcab40c2014-03-11 10:59:14 +0100437 if (ret < 0) {
438 strerror_r(-ret, buf, sizeof(buf));
439 ERROR("Unable to read response to GETTRIG: %s\n", buf);
440 return ret;
441 }
442
443 for (i = 0; i < dev->ctx->nb_devices; i++) {
444 struct iio_device *cur = dev->ctx->devices[i];
445 if (iio_device_is_trigger(cur) &&
446 !strncmp(cur->name, buf, resp)) {
447 *trigger = cur;
448 return 0;
449 }
450 }
451
452 return -ENXIO;
453}
454
455static int network_set_trigger(const struct iio_device *dev,
456 const struct iio_device *trigger)
457{
Paul Cercueil1494b862014-05-05 12:49:07 +0200458 int ret;
Paul Cercueildcab40c2014-03-11 10:59:14 +0100459 char buf[1024];
460 if (trigger)
461 snprintf(buf, sizeof(buf), "SETTRIG %s %s\r\n",
462 dev->id, trigger->id);
463 else
464 snprintf(buf, sizeof(buf), "SETTRIG %s\r\n", dev->id);
Paul Cercueil1494b862014-05-05 12:49:07 +0200465
466 pthread_mutex_lock(&dev->ctx->pdata->lock);
467 ret = (int) exec_command(buf, dev->ctx->pdata->fd);
468 pthread_mutex_unlock(&dev->ctx->pdata->lock);
469 return ret;
Paul Cercueildcab40c2014-03-11 10:59:14 +0100470}
471
Paul Cercueil8fd9c8f2014-03-03 17:21:31 +0100472static void network_shutdown(struct iio_context *ctx)
473{
474 struct iio_context_pdata *pdata = ctx->pdata;
Paul Cercueil44ae11c2014-03-17 09:56:29 +0100475 unsigned int i;
Paul Cercueil8fd9c8f2014-03-03 17:21:31 +0100476
Paul Cercueil1494b862014-05-05 12:49:07 +0200477 pthread_mutex_lock(&pdata->lock);
Paul Cercueilbb76bf92014-03-11 10:20:18 +0100478 write_command("\r\nEXIT\r\n", pdata->fd);
Paul Cercueil8fd9c8f2014-03-03 17:21:31 +0100479 close(pdata->fd);
Paul Cercueil1494b862014-05-05 12:49:07 +0200480 pthread_mutex_unlock(&pdata->lock);
481
482 /* XXX(pcercuei): is this safe? */
483 pthread_mutex_destroy(&pdata->lock);
Paul Cercueil8fd9c8f2014-03-03 17:21:31 +0100484 free(pdata);
Paul Cercueil44ae11c2014-03-17 09:56:29 +0100485
486 for (i = 0; i < ctx->nb_devices; i++) {
487 struct iio_device *dev = ctx->devices[i];
488 if (dev->pdata)
489 free(dev->pdata);
490 }
Paul Cercueil8fd9c8f2014-03-03 17:21:31 +0100491}
492
Paul Cercueil6691a3f2014-05-02 12:32:01 +0200493static int network_get_version(const struct iio_context *ctx,
494 unsigned int *major, unsigned int *minor)
495{
496 struct iio_context_pdata *pdata = ctx->pdata;
497 long maj, min;
498 int ret;
Paul Cercueil6691a3f2014-05-02 12:32:01 +0200499
Paul Cercueil1494b862014-05-05 12:49:07 +0200500 pthread_mutex_lock(&pdata->lock);
501 ret = (int) write_command("VERSION\r\n", pdata->fd);
502 if (ret < 0)
503 goto err_unlock;
504
505 ret = read_integer(pdata->fd, &maj);
506 if (!ret)
507 ret = read_integer(pdata->fd, &min);
508 if (!ret) {
509 *major = (unsigned int) maj;
510 *minor = (unsigned int) min;
511 }
512
513err_unlock:
514 pthread_mutex_unlock(&pdata->lock);
515 return ret;
Paul Cercueil6691a3f2014-05-02 12:32:01 +0200516}
517
Paul Cercueilc7bad0f2014-03-03 17:06:48 +0100518static struct iio_backend_ops network_ops = {
Paul Cercueilba059762014-03-14 11:02:02 +0100519 .open = network_open,
520 .close = network_close,
Paul Cercueil9945bc82014-03-05 14:07:29 +0100521 .read = network_read,
Paul Cercueil2725f702014-05-02 11:02:16 +0200522 .write = network_write,
Paul Cercueil3e94a5b2014-03-04 13:00:41 +0100523 .read_device_attr = network_read_dev_attr,
524 .write_device_attr = network_write_dev_attr,
Paul Cercueil99cf3d42014-03-06 12:35:26 +0100525 .read_channel_attr = network_read_chn_attr,
Paul Cercueil07897d32014-03-06 12:46:08 +0100526 .write_channel_attr = network_write_chn_attr,
Paul Cercueildcab40c2014-03-11 10:59:14 +0100527 .get_trigger = network_get_trigger,
528 .set_trigger = network_set_trigger,
Paul Cercueil8fd9c8f2014-03-03 17:21:31 +0100529 .shutdown = network_shutdown,
Paul Cercueil6691a3f2014-05-02 12:32:01 +0200530 .get_version = network_get_version,
Paul Cercueilc7bad0f2014-03-03 17:06:48 +0100531};
532
533static struct iio_context * get_context(int fd)
534{
535 struct iio_context *ctx;
Paul Cercueile60c3ed2014-03-04 11:23:56 +0100536 char *xml;
Paul Cercueilbb76bf92014-03-11 10:20:18 +0100537 long xml_len = exec_command("PRINT\r\n", fd);
538 if (xml_len < 0)
Paul Cercueilc7bad0f2014-03-03 17:06:48 +0100539 return NULL;
Paul Cercueile60c3ed2014-03-04 11:23:56 +0100540
541 DEBUG("Server returned a XML string of length %li\n", xml_len);
Paul Cercueilc7bad0f2014-03-03 17:06:48 +0100542 xml = malloc(xml_len);
543 if (!xml) {
544 ERROR("Unable to allocate data\n");
545 return NULL;
546 }
547
548 DEBUG("Reading XML string...\n");
549 read_all(xml, xml_len, fd);
550
551 DEBUG("Creating context from XML...\n");
552 ctx = iio_create_xml_context_mem(xml, xml_len);
553 free(xml);
554 return ctx;
555}
556
557struct iio_context * iio_create_network_context(const char *host)
558{
Paul Cercueil2e38bbe2014-03-19 15:27:15 +0100559 struct addrinfo hints, *res;
Paul Cercueilc7bad0f2014-03-03 17:06:48 +0100560 struct iio_context *ctx;
Paul Cercueil8fd9c8f2014-03-03 17:21:31 +0100561 struct iio_context_pdata *pdata;
Paul Cercueil44ae11c2014-03-17 09:56:29 +0100562 unsigned int i;
Paul Cercueil2e38bbe2014-03-19 15:27:15 +0100563 int fd, ret;
Paul Cercueil1fef1a52014-04-07 16:31:15 +0200564#ifdef _WIN32
565 WSADATA wsaData;
566
567 ret = WSAStartup(MAKEWORD(2, 0), &wsaData);
568 if (ret < 0) {
569 ERROR("WSAStartup failed with error %i\n", ret);
570 return NULL;
571 }
572#endif
Paul Cercueilc7bad0f2014-03-03 17:06:48 +0100573
Paul Cercueil2e38bbe2014-03-19 15:27:15 +0100574 memset(&hints, 0, sizeof(hints));
575 hints.ai_family = AF_UNSPEC;
576 hints.ai_socktype = SOCK_STREAM;
577 ret = getaddrinfo(host, IIOD_PORT_STR, &hints, &res);
578 if (ret) {
579 ERROR("Unable to find IP address for host %s: %s\n",
580 host, gai_strerror(ret));
Paul Cercueilc7bad0f2014-03-03 17:06:48 +0100581 return NULL;
Paul Cercueilc7bad0f2014-03-03 17:06:48 +0100582 }
583
Paul Cercueil2e38bbe2014-03-19 15:27:15 +0100584 fd = socket(res->ai_family, res->ai_socktype, 0);
Paul Cercueilc7bad0f2014-03-03 17:06:48 +0100585 if (fd < 0) {
586 ERROR("Unable to open socket\n");
587 return NULL;
588 }
589
Paul Cercueil2e38bbe2014-03-19 15:27:15 +0100590 if (connect(fd, res->ai_addr, res->ai_addrlen) < 0) {
Paul Cercueilc7bad0f2014-03-03 17:06:48 +0100591 ERROR("Unable to connect\n");
592 goto err_close_socket;
593 }
594
Paul Cercueil8fd9c8f2014-03-03 17:21:31 +0100595 pdata = calloc(1, sizeof(*pdata));
596 if (!pdata) {
597 ERROR("Unable to allocate memory\n");
598 goto err_close_socket;
599 }
600
601 pdata->fd = fd;
602
Paul Cercueilc7bad0f2014-03-03 17:06:48 +0100603 DEBUG("Creating context...\n");
604 ctx = get_context(fd);
605 if (!ctx)
Paul Cercueil8fd9c8f2014-03-03 17:21:31 +0100606 goto err_free_pdata;
Paul Cercueilc7bad0f2014-03-03 17:06:48 +0100607
Paul Cercueil44ae11c2014-03-17 09:56:29 +0100608 for (i = 0; i < ctx->nb_devices; i++) {
609 struct iio_device *dev = ctx->devices[i];
Paul Cercueilff778232014-03-24 14:23:08 +0100610 uint32_t *mask = NULL;
611
612 dev->words = (dev->nb_channels + 31) / 32;
613 if (dev->words) {
614 mask = calloc(dev->words, sizeof(*mask));
615 if (!mask)
616 goto err_network_shutdown;
617 }
618
619 dev->mask = mask;
Paul Cercueil44ae11c2014-03-17 09:56:29 +0100620 }
621
Paul Cercueilff778232014-03-24 14:23:08 +0100622
Paul Cercueilc7bad0f2014-03-03 17:06:48 +0100623 /* Override the name and low-level functions of the XML context
624 * with those corresponding to the network context */
625 ctx->name = "network";
626 ctx->ops = &network_ops;
Paul Cercueil8fd9c8f2014-03-03 17:21:31 +0100627 ctx->pdata = pdata;
Paul Cercueilc7bad0f2014-03-03 17:06:48 +0100628
Paul Cercueil4c6729d2014-04-04 17:24:41 +0200629 ret = iio_context_init(ctx);
630 if (ret < 0) {
631 char buf[1024];
632 strerror_r(-ret, buf, sizeof(buf));
633 ERROR("Unable to initialize context: %s\n", buf);
Paul Cercueildfcd6b12014-04-08 14:45:36 +0200634 goto err_network_shutdown;
Paul Cercueil4c6729d2014-04-04 17:24:41 +0200635 }
636
Paul Cercueil1494b862014-05-05 12:49:07 +0200637 ret = pthread_mutex_init(&pdata->lock, NULL);
638 if (ret < 0) {
639 char buf[1024];
640 strerror_r(-ret, buf, sizeof(buf));
641 ERROR("Unable to initialize mutex: %s\n", buf);
642 goto err_network_shutdown;
643 }
644
Paul Cercueilc7bad0f2014-03-03 17:06:48 +0100645 return ctx;
646
Paul Cercueil44ae11c2014-03-17 09:56:29 +0100647err_network_shutdown:
648 network_shutdown(ctx);
649 iio_context_destroy(ctx);
Paul Cercueil8fd9c8f2014-03-03 17:21:31 +0100650err_free_pdata:
651 free(pdata);
Paul Cercueilc7bad0f2014-03-03 17:06:48 +0100652err_close_socket:
653 close(fd);
654 return NULL;
655}