blob: 19fd1ebf95c4c885a4d0b1ef76ee0311e26e87fc [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 Cercueilcecda352014-05-06 18:14:29 +0200284static ssize_t do_write(struct iio_context_pdata *pdata,
285 const char *command, const void *src, size_t len)
Paul Cercueil2725f702014-05-02 11:02:16 +0200286{
Paul Cercueilcecda352014-05-06 18:14:29 +0200287 int fd = pdata->fd;
Paul Cercueil2725f702014-05-02 11:02:16 +0200288 ssize_t ret;
Paul Cercueil2725f702014-05-02 11:02:16 +0200289 long resp;
290
Paul Cercueilcecda352014-05-06 18:14:29 +0200291 pthread_mutex_lock(&pdata->lock);
292 ret = (ssize_t) write_command(command, fd);
Paul Cercueil2725f702014-05-02 11:02:16 +0200293 if (ret < 0)
Paul Cercueil1494b862014-05-05 12:49:07 +0200294 goto err_unlock;
Paul Cercueil2725f702014-05-02 11:02:16 +0200295
296 ret = write_all(src, len, 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 = read_integer(fd, &resp);
Paul Cercueilcecda352014-05-06 18:14:29 +0200301 pthread_mutex_unlock(&pdata->lock);
Paul Cercueil1494b862014-05-05 12:49:07 +0200302
Paul Cercueil2725f702014-05-02 11:02:16 +0200303 if (ret < 0)
304 return ret;
305 return (ssize_t) resp;
Paul Cercueil1494b862014-05-05 12:49:07 +0200306
307err_unlock:
Paul Cercueilcecda352014-05-06 18:14:29 +0200308 pthread_mutex_unlock(&pdata->lock);
Paul Cercueil1494b862014-05-05 12:49:07 +0200309 return ret;
Paul Cercueil2725f702014-05-02 11:02:16 +0200310}
311
Paul Cercueilcecda352014-05-06 18:14:29 +0200312static ssize_t network_write(const struct iio_device *dev,
313 const void *src, size_t len)
314{
315 char buf[1024];
316 snprintf(buf, sizeof(buf), "WRITEBUF %s %lu\r\n",
317 dev->id, (unsigned long) len);
318 return do_write(dev->ctx->pdata, buf, src, len);
319}
320
Paul Cercueil1494b862014-05-05 12:49:07 +0200321static ssize_t network_read_attr_helper(const struct iio_device *dev,
322 const char *chn, const char *attr, char *dst,
323 size_t len, bool is_debug)
Paul Cercueil3e94a5b2014-03-04 13:00:41 +0100324{
Paul Cercueil3e94a5b2014-03-04 13:00:41 +0100325 long read_len;
326 ssize_t ret;
327 char buf[1024];
Paul Cercueil1494b862014-05-05 12:49:07 +0200328 int fd = dev->ctx->pdata->fd;
329 const char *id = dev->id;
Paul Cercueil3e94a5b2014-03-04 13:00:41 +0100330
Paul Cercueil99cf3d42014-03-06 12:35:26 +0100331 if (chn)
332 snprintf(buf, sizeof(buf), "READ %s %s %s\r\n", id, chn, attr);
Paul Cercueilc6f03612014-04-14 16:41:31 +0200333 else if (is_debug)
334 snprintf(buf, sizeof(buf), "READ %s debug %s\r\n", id, attr);
Paul Cercueil99cf3d42014-03-06 12:35:26 +0100335 else
336 snprintf(buf, sizeof(buf), "READ %s %s\r\n", id, attr);
Paul Cercueil1494b862014-05-05 12:49:07 +0200337
338 pthread_mutex_lock(&dev->ctx->pdata->lock);
Paul Cercueilbb76bf92014-03-11 10:20:18 +0100339 read_len = exec_command(buf, fd);
Paul Cercueil1494b862014-05-05 12:49:07 +0200340 if (read_len < 0) {
341 pthread_mutex_unlock(&dev->ctx->pdata->lock);
Paul Cercueilbb76bf92014-03-11 10:20:18 +0100342 return (ssize_t) read_len;
Paul Cercueil1494b862014-05-05 12:49:07 +0200343 }
Paul Cercueil3e94a5b2014-03-04 13:00:41 +0100344
Paul Cercueil6e7f79e2014-04-04 12:27:24 +0200345 if ((unsigned long) read_len > len) {
Paul Cercueil3e94a5b2014-03-04 13:00:41 +0100346 ERROR("Value returned by server is too large\n");
Paul Cercueil1494b862014-05-05 12:49:07 +0200347 pthread_mutex_unlock(&dev->ctx->pdata->lock);
Paul Cercueil3e94a5b2014-03-04 13:00:41 +0100348 return -EIO;
349 }
350
351 ret = read_all(dst, read_len, fd);
Paul Cercueil1494b862014-05-05 12:49:07 +0200352 pthread_mutex_unlock(&dev->ctx->pdata->lock);
353
Paul Cercueil3e94a5b2014-03-04 13:00:41 +0100354 if (ret < 0) {
355 strerror_r(-ret, buf, sizeof(buf));
356 ERROR("Unable to read response to READ: %s\n", buf);
357 return ret;
358 }
359
360 dst[read_len] = '\0';
361 return read_len + 1;
362}
363
Paul Cercueil1494b862014-05-05 12:49:07 +0200364static ssize_t network_write_attr_helper(const struct iio_device *dev,
Paul Cercueilc6f03612014-04-14 16:41:31 +0200365 const char *chn, const char *attr, const char *src,
Paul Cercueilcecda352014-05-06 18:14:29 +0200366 size_t len, bool is_debug)
Paul Cercueil3e94a5b2014-03-04 13:00:41 +0100367{
Paul Cercueil3e94a5b2014-03-04 13:00:41 +0100368 char buf[1024];
Paul Cercueil1494b862014-05-05 12:49:07 +0200369 const char *id = dev->id;
Paul Cercueil3e94a5b2014-03-04 13:00:41 +0100370
Paul Cercueil07897d32014-03-06 12:46:08 +0100371 if (chn)
Paul Cercueilcecda352014-05-06 18:14:29 +0200372 snprintf(buf, sizeof(buf), "WRITE %s %s %s %lu\r\n",
373 id, chn, attr, (unsigned long) len);
Paul Cercueilc6f03612014-04-14 16:41:31 +0200374 else if (is_debug)
Paul Cercueilcecda352014-05-06 18:14:29 +0200375 snprintf(buf, sizeof(buf), "WRITE %s debug %s %lu\r\n",
376 id, attr, (unsigned long) len);
Paul Cercueil07897d32014-03-06 12:46:08 +0100377 else
Paul Cercueilcecda352014-05-06 18:14:29 +0200378 snprintf(buf, sizeof(buf), "WRITE %s %s %lu\r\n",
379 id, attr, (unsigned long) len);
380 return do_write(dev->ctx->pdata, buf, src, len);
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 Cercueilcecda352014-05-06 18:14:29 +0200390 const char *attr, const char *src, size_t len, bool is_debug)
Paul Cercueil07897d32014-03-06 12:46:08 +0100391{
Paul Cercueilcecda352014-05-06 18:14:29 +0200392 return network_write_attr_helper(dev, NULL, attr, src, len, 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,
Paul Cercueilcecda352014-05-06 18:14:29 +0200403 const char *attr, const char *src, size_t len)
Paul Cercueil07897d32014-03-06 12:46:08 +0100404{
Paul Cercueilcecda352014-05-06 18:14:29 +0200405 return network_write_attr_helper(chn->dev, chn->id,
406 attr, src, len, false);
Paul Cercueil07897d32014-03-06 12:46:08 +0100407}
408
Paul Cercueildcab40c2014-03-11 10:59:14 +0100409static int network_get_trigger(const struct iio_device *dev,
410 const struct iio_device **trigger)
411{
412 struct iio_context_pdata *pdata = dev->ctx->pdata;
413 unsigned int i;
414 char buf[1024];
415 ssize_t ret;
416 long resp;
417
418 snprintf(buf, sizeof(buf), "GETTRIG %s\r\n", dev->id);
Paul Cercueil1494b862014-05-05 12:49:07 +0200419
420 pthread_mutex_lock(&dev->ctx->pdata->lock);
Paul Cercueildcab40c2014-03-11 10:59:14 +0100421 resp = exec_command(buf, pdata->fd);
422 if (resp < 0) {
Paul Cercueil1494b862014-05-05 12:49:07 +0200423 pthread_mutex_unlock(&dev->ctx->pdata->lock);
Paul Cercueildcab40c2014-03-11 10:59:14 +0100424 return (int) resp;
425 } else if (resp == 0) {
426 *trigger = NULL;
Paul Cercueil1494b862014-05-05 12:49:07 +0200427 pthread_mutex_unlock(&dev->ctx->pdata->lock);
Paul Cercueildcab40c2014-03-11 10:59:14 +0100428 return 0;
Paul Cercueil6e7f79e2014-04-04 12:27:24 +0200429 } else if ((unsigned long) resp > sizeof(buf)) {
Paul Cercueildcab40c2014-03-11 10:59:14 +0100430 ERROR("Value returned by server is too large\n");
Paul Cercueil1494b862014-05-05 12:49:07 +0200431 pthread_mutex_unlock(&dev->ctx->pdata->lock);
Paul Cercueildcab40c2014-03-11 10:59:14 +0100432 return -EIO;
433 }
434
435 ret = read_all(buf, resp, pdata->fd);
Paul Cercueil1494b862014-05-05 12:49:07 +0200436 pthread_mutex_unlock(&dev->ctx->pdata->lock);
437
Paul Cercueildcab40c2014-03-11 10:59:14 +0100438 if (ret < 0) {
439 strerror_r(-ret, buf, sizeof(buf));
440 ERROR("Unable to read response to GETTRIG: %s\n", buf);
441 return ret;
442 }
443
444 for (i = 0; i < dev->ctx->nb_devices; i++) {
445 struct iio_device *cur = dev->ctx->devices[i];
446 if (iio_device_is_trigger(cur) &&
447 !strncmp(cur->name, buf, resp)) {
448 *trigger = cur;
449 return 0;
450 }
451 }
452
453 return -ENXIO;
454}
455
456static int network_set_trigger(const struct iio_device *dev,
457 const struct iio_device *trigger)
458{
Paul Cercueil1494b862014-05-05 12:49:07 +0200459 int ret;
Paul Cercueildcab40c2014-03-11 10:59:14 +0100460 char buf[1024];
461 if (trigger)
462 snprintf(buf, sizeof(buf), "SETTRIG %s %s\r\n",
463 dev->id, trigger->id);
464 else
465 snprintf(buf, sizeof(buf), "SETTRIG %s\r\n", dev->id);
Paul Cercueil1494b862014-05-05 12:49:07 +0200466
467 pthread_mutex_lock(&dev->ctx->pdata->lock);
468 ret = (int) exec_command(buf, dev->ctx->pdata->fd);
469 pthread_mutex_unlock(&dev->ctx->pdata->lock);
470 return ret;
Paul Cercueildcab40c2014-03-11 10:59:14 +0100471}
472
Paul Cercueil8fd9c8f2014-03-03 17:21:31 +0100473static void network_shutdown(struct iio_context *ctx)
474{
475 struct iio_context_pdata *pdata = ctx->pdata;
Paul Cercueil44ae11c2014-03-17 09:56:29 +0100476 unsigned int i;
Paul Cercueil8fd9c8f2014-03-03 17:21:31 +0100477
Paul Cercueil1494b862014-05-05 12:49:07 +0200478 pthread_mutex_lock(&pdata->lock);
Paul Cercueilbb76bf92014-03-11 10:20:18 +0100479 write_command("\r\nEXIT\r\n", pdata->fd);
Paul Cercueil8fd9c8f2014-03-03 17:21:31 +0100480 close(pdata->fd);
Paul Cercueil1494b862014-05-05 12:49:07 +0200481 pthread_mutex_unlock(&pdata->lock);
482
483 /* XXX(pcercuei): is this safe? */
484 pthread_mutex_destroy(&pdata->lock);
Paul Cercueil8fd9c8f2014-03-03 17:21:31 +0100485 free(pdata);
Paul Cercueil44ae11c2014-03-17 09:56:29 +0100486
487 for (i = 0; i < ctx->nb_devices; i++) {
488 struct iio_device *dev = ctx->devices[i];
489 if (dev->pdata)
490 free(dev->pdata);
491 }
Paul Cercueil8fd9c8f2014-03-03 17:21:31 +0100492}
493
Paul Cercueil6691a3f2014-05-02 12:32:01 +0200494static int network_get_version(const struct iio_context *ctx,
495 unsigned int *major, unsigned int *minor)
496{
497 struct iio_context_pdata *pdata = ctx->pdata;
498 long maj, min;
499 int ret;
Paul Cercueil6691a3f2014-05-02 12:32:01 +0200500
Paul Cercueil1494b862014-05-05 12:49:07 +0200501 pthread_mutex_lock(&pdata->lock);
502 ret = (int) write_command("VERSION\r\n", pdata->fd);
503 if (ret < 0)
504 goto err_unlock;
505
506 ret = read_integer(pdata->fd, &maj);
507 if (!ret)
508 ret = read_integer(pdata->fd, &min);
509 if (!ret) {
510 *major = (unsigned int) maj;
511 *minor = (unsigned int) min;
512 }
513
514err_unlock:
515 pthread_mutex_unlock(&pdata->lock);
516 return ret;
Paul Cercueil6691a3f2014-05-02 12:32:01 +0200517}
518
Paul Cercueilc7bad0f2014-03-03 17:06:48 +0100519static struct iio_backend_ops network_ops = {
Paul Cercueilba059762014-03-14 11:02:02 +0100520 .open = network_open,
521 .close = network_close,
Paul Cercueil9945bc82014-03-05 14:07:29 +0100522 .read = network_read,
Paul Cercueil2725f702014-05-02 11:02:16 +0200523 .write = network_write,
Paul Cercueil3e94a5b2014-03-04 13:00:41 +0100524 .read_device_attr = network_read_dev_attr,
525 .write_device_attr = network_write_dev_attr,
Paul Cercueil99cf3d42014-03-06 12:35:26 +0100526 .read_channel_attr = network_read_chn_attr,
Paul Cercueil07897d32014-03-06 12:46:08 +0100527 .write_channel_attr = network_write_chn_attr,
Paul Cercueildcab40c2014-03-11 10:59:14 +0100528 .get_trigger = network_get_trigger,
529 .set_trigger = network_set_trigger,
Paul Cercueil8fd9c8f2014-03-03 17:21:31 +0100530 .shutdown = network_shutdown,
Paul Cercueil6691a3f2014-05-02 12:32:01 +0200531 .get_version = network_get_version,
Paul Cercueilc7bad0f2014-03-03 17:06:48 +0100532};
533
534static struct iio_context * get_context(int fd)
535{
536 struct iio_context *ctx;
Paul Cercueile60c3ed2014-03-04 11:23:56 +0100537 char *xml;
Paul Cercueilbb76bf92014-03-11 10:20:18 +0100538 long xml_len = exec_command("PRINT\r\n", fd);
539 if (xml_len < 0)
Paul Cercueilc7bad0f2014-03-03 17:06:48 +0100540 return NULL;
Paul Cercueile60c3ed2014-03-04 11:23:56 +0100541
542 DEBUG("Server returned a XML string of length %li\n", xml_len);
Paul Cercueilc7bad0f2014-03-03 17:06:48 +0100543 xml = malloc(xml_len);
544 if (!xml) {
545 ERROR("Unable to allocate data\n");
546 return NULL;
547 }
548
549 DEBUG("Reading XML string...\n");
550 read_all(xml, xml_len, fd);
551
552 DEBUG("Creating context from XML...\n");
553 ctx = iio_create_xml_context_mem(xml, xml_len);
554 free(xml);
555 return ctx;
556}
557
558struct iio_context * iio_create_network_context(const char *host)
559{
Paul Cercueil2e38bbe2014-03-19 15:27:15 +0100560 struct addrinfo hints, *res;
Paul Cercueilc7bad0f2014-03-03 17:06:48 +0100561 struct iio_context *ctx;
Paul Cercueil8fd9c8f2014-03-03 17:21:31 +0100562 struct iio_context_pdata *pdata;
Paul Cercueil44ae11c2014-03-17 09:56:29 +0100563 unsigned int i;
Paul Cercueil2e38bbe2014-03-19 15:27:15 +0100564 int fd, ret;
Paul Cercueil1fef1a52014-04-07 16:31:15 +0200565#ifdef _WIN32
566 WSADATA wsaData;
567
568 ret = WSAStartup(MAKEWORD(2, 0), &wsaData);
569 if (ret < 0) {
570 ERROR("WSAStartup failed with error %i\n", ret);
571 return NULL;
572 }
573#endif
Paul Cercueilc7bad0f2014-03-03 17:06:48 +0100574
Paul Cercueil2e38bbe2014-03-19 15:27:15 +0100575 memset(&hints, 0, sizeof(hints));
576 hints.ai_family = AF_UNSPEC;
577 hints.ai_socktype = SOCK_STREAM;
578 ret = getaddrinfo(host, IIOD_PORT_STR, &hints, &res);
579 if (ret) {
580 ERROR("Unable to find IP address for host %s: %s\n",
581 host, gai_strerror(ret));
Paul Cercueilc7bad0f2014-03-03 17:06:48 +0100582 return NULL;
Paul Cercueilc7bad0f2014-03-03 17:06:48 +0100583 }
584
Paul Cercueil2e38bbe2014-03-19 15:27:15 +0100585 fd = socket(res->ai_family, res->ai_socktype, 0);
Paul Cercueilc7bad0f2014-03-03 17:06:48 +0100586 if (fd < 0) {
587 ERROR("Unable to open socket\n");
588 return NULL;
589 }
590
Paul Cercueil2e38bbe2014-03-19 15:27:15 +0100591 if (connect(fd, res->ai_addr, res->ai_addrlen) < 0) {
Paul Cercueilc7bad0f2014-03-03 17:06:48 +0100592 ERROR("Unable to connect\n");
593 goto err_close_socket;
594 }
595
Paul Cercueil8fd9c8f2014-03-03 17:21:31 +0100596 pdata = calloc(1, sizeof(*pdata));
597 if (!pdata) {
598 ERROR("Unable to allocate memory\n");
599 goto err_close_socket;
600 }
601
602 pdata->fd = fd;
603
Paul Cercueilc7bad0f2014-03-03 17:06:48 +0100604 DEBUG("Creating context...\n");
605 ctx = get_context(fd);
606 if (!ctx)
Paul Cercueil8fd9c8f2014-03-03 17:21:31 +0100607 goto err_free_pdata;
Paul Cercueilc7bad0f2014-03-03 17:06:48 +0100608
Paul Cercueil44ae11c2014-03-17 09:56:29 +0100609 for (i = 0; i < ctx->nb_devices; i++) {
610 struct iio_device *dev = ctx->devices[i];
Paul Cercueilff778232014-03-24 14:23:08 +0100611 uint32_t *mask = NULL;
612
613 dev->words = (dev->nb_channels + 31) / 32;
614 if (dev->words) {
615 mask = calloc(dev->words, sizeof(*mask));
616 if (!mask)
617 goto err_network_shutdown;
618 }
619
620 dev->mask = mask;
Paul Cercueil44ae11c2014-03-17 09:56:29 +0100621 }
622
Paul Cercueilff778232014-03-24 14:23:08 +0100623
Paul Cercueilc7bad0f2014-03-03 17:06:48 +0100624 /* Override the name and low-level functions of the XML context
625 * with those corresponding to the network context */
626 ctx->name = "network";
627 ctx->ops = &network_ops;
Paul Cercueil8fd9c8f2014-03-03 17:21:31 +0100628 ctx->pdata = pdata;
Paul Cercueilc7bad0f2014-03-03 17:06:48 +0100629
Paul Cercueil4c6729d2014-04-04 17:24:41 +0200630 ret = iio_context_init(ctx);
631 if (ret < 0) {
632 char buf[1024];
633 strerror_r(-ret, buf, sizeof(buf));
634 ERROR("Unable to initialize context: %s\n", buf);
Paul Cercueildfcd6b12014-04-08 14:45:36 +0200635 goto err_network_shutdown;
Paul Cercueil4c6729d2014-04-04 17:24:41 +0200636 }
637
Paul Cercueil1494b862014-05-05 12:49:07 +0200638 ret = pthread_mutex_init(&pdata->lock, NULL);
639 if (ret < 0) {
640 char buf[1024];
641 strerror_r(-ret, buf, sizeof(buf));
642 ERROR("Unable to initialize mutex: %s\n", buf);
643 goto err_network_shutdown;
644 }
645
Paul Cercueilc7bad0f2014-03-03 17:06:48 +0100646 return ctx;
647
Paul Cercueil44ae11c2014-03-17 09:56:29 +0100648err_network_shutdown:
649 network_shutdown(ctx);
650 iio_context_destroy(ctx);
Paul Cercueil8fd9c8f2014-03-03 17:21:31 +0100651err_free_pdata:
652 free(pdata);
Paul Cercueilc7bad0f2014-03-03 17:06:48 +0100653err_close_socket:
654 close(fd);
655 return NULL;
656}