blob: e61dfa3b0e6c0aaedb602b59d219431006259d56 [file] [log] [blame]
Paul Cercueile001add2016-08-30 17:22:10 +02001/*
2 * libiio - Library for interfacing industrial I/O (IIO) devices
3 *
Robin Getzaf161e02020-02-12 10:54:06 -05004 * Copyright (C) 2014-2020 Analog Devices, Inc.
Paul Cercueile001add2016-08-30 17:22:10 +02005 * 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 Cercueil1f75a8f2015-12-02 11:51:14 +010019#include "debug.h"
Paul Cercueil2cb884a2015-11-30 15:01:25 +010020#include "iiod-client.h"
21#include "iio-lock.h"
Paul Cercueilba870932015-12-01 18:17:57 +010022#include "iio-private.h"
Paul Cercueil2cb884a2015-11-30 15:01:25 +010023
24#include <errno.h>
Paul Cercueil9f1586d2016-04-28 17:17:27 +020025#include <inttypes.h>
Paul Cercueil2cb884a2015-11-30 15:01:25 +010026#include <string.h>
Paul Cercueil6a785882015-11-30 16:36:19 +010027#include <stdio.h>
Paul Cercueil2cb884a2015-11-30 15:01:25 +010028
Harvey Yangbc3f48e2019-10-22 11:17:28 +080029#define REQUEST_CLIENT_ID "REQUEST_CLIENT_ID\r\n"
30
Paul Cercueil2cb884a2015-11-30 15:01:25 +010031struct iiod_client {
32 struct iio_context_pdata *pdata;
33 const struct iiod_client_ops *ops;
34 struct iio_mutex *lock;
35};
36
Paul Cercueil6a785882015-11-30 16:36:19 +010037static ssize_t iiod_client_read_integer(struct iiod_client *client,
Lars-Peter Clausen2767d4d2016-06-23 14:19:02 +020038 void *desc, int *val)
Paul Cercueil6a785882015-11-30 16:36:19 +010039{
Paul Cercueil6a785882015-11-30 16:36:19 +010040 unsigned int i;
41 char buf[1024], *ptr = NULL, *end;
42 ssize_t ret;
43 int value;
44
45 do {
46 ret = client->ops->read_line(client->pdata,
47 desc, buf, sizeof(buf));
Robin Getzaf161e02020-02-12 10:54:06 -050048 if (ret < 0) {
49 ERROR("READ LINE: %zu\n", ret);
Paul Cercueil6a785882015-11-30 16:36:19 +010050 return ret;
Robin Getzaf161e02020-02-12 10:54:06 -050051 }
Paul Cercueil6a785882015-11-30 16:36:19 +010052
53 for (i = 0; i < (unsigned int) ret; i++) {
54 if (buf[i] != '\n') {
55 if (!ptr)
56 ptr = &buf[i];
57 } else if (!!ptr) {
58 break;
59 }
60 }
61 } while (!ptr);
62
63 buf[i] = '\0';
64
65 value = (int) strtol(ptr, &end, 10);
66 if (ptr == end)
67 return -EINVAL;
68
69 *val = value;
70 return 0;
71}
72
73static int iiod_client_exec_command(struct iiod_client *client,
Lars-Peter Clausen2767d4d2016-06-23 14:19:02 +020074 void *desc, const char *cmd)
Paul Cercueil6a785882015-11-30 16:36:19 +010075{
76 int resp;
77 ssize_t ret;
78
79 ret = client->ops->write(client->pdata, desc, cmd, strlen(cmd));
80 if (ret < 0)
81 return (int) ret;
82
83 ret = iiod_client_read_integer(client, desc, &resp);
84 return ret < 0 ? (int) ret : resp;
85}
86
Paul Cercueil408b9672015-11-30 18:39:31 +010087static ssize_t iiod_client_write_all(struct iiod_client *client,
Lars-Peter Clausen2767d4d2016-06-23 14:19:02 +020088 void *desc, const void *src, size_t len)
Paul Cercueil408b9672015-11-30 18:39:31 +010089{
90 struct iio_context_pdata *pdata = client->pdata;
91 const struct iiod_client_ops *ops = client->ops;
92 uintptr_t ptr = (uintptr_t) src;
93
94 while (len) {
95 ssize_t ret = ops->write(pdata, desc, (const void *) ptr, len);
96
97 if (ret < 0) {
98 if (ret == -EINTR)
99 continue;
100 else
101 return ret;
102 }
103
104 if (ret == 0)
105 return -EPIPE;
106
107 ptr += ret;
108 len -= ret;
109 }
110
111 return (ssize_t) (ptr - (uintptr_t) src);
112}
113
114static ssize_t iiod_client_read_all(struct iiod_client *client,
Lars-Peter Clausen2767d4d2016-06-23 14:19:02 +0200115 void *desc, void *dst, size_t len)
Paul Cercueil408b9672015-11-30 18:39:31 +0100116{
117 struct iio_context_pdata *pdata = client->pdata;
118 const struct iiod_client_ops *ops = client->ops;
119 uintptr_t ptr = (uintptr_t) dst;
120
121 while (len) {
122 ssize_t ret = ops->read(pdata, desc, (void *) ptr, len);
123
124 if (ret < 0) {
125 if (ret == -EINTR)
126 continue;
127 else
128 return ret;
129 }
130
131 if (ret == 0)
132 return -EPIPE;
133
134 ptr += ret;
135 len -= ret;
136 }
137
138 return (ssize_t) (ptr - (uintptr_t) dst);
139}
140
Paul Cercueil2cb884a2015-11-30 15:01:25 +0100141struct iiod_client * iiod_client_new(struct iio_context_pdata *pdata,
142 struct iio_mutex *lock, const struct iiod_client_ops *ops)
143{
144 struct iiod_client *client;
145
146 client = malloc(sizeof(*client));
147 if (!client) {
148 errno = ENOMEM;
149 return NULL;
150 }
151
152 client->lock = lock;
153 client->pdata = pdata;
154 client->ops = ops;
155 return client;
156}
157
158void iiod_client_destroy(struct iiod_client *client)
159{
160 free(client);
161}
162
Harvey Yangbc3f48e2019-10-22 11:17:28 +0800163int iiod_client_request_client_id(struct iiod_client *client, void *desc)
164{
165 struct iio_context_pdata *pdata = client->pdata;
166 const struct iiod_client_ops *ops = client->ops;
167 char buf[256], *ptr = buf, *end;
168 int ret, to_read;
169
170 iio_mutex_lock(client->lock);
171
172 ret = ops->write(pdata, desc, REQUEST_CLIENT_ID, strlen(REQUEST_CLIENT_ID));
173 if (ret < 0) {
174 iio_mutex_unlock(client->lock);
175 return ret;
176 }
177
178 ret = iiod_client_read_integer(client, desc, &to_read);
179
180 iio_mutex_unlock(client->lock);
181 if (ret < 0)
182 return ret;
183
184 return to_read;
185}
186
Lars-Peter Clausen2767d4d2016-06-23 14:19:02 +0200187int iiod_client_get_version(struct iiod_client *client, void *desc,
Paul Cercueil2cb884a2015-11-30 15:01:25 +0100188 unsigned int *major, unsigned int *minor, char *git_tag)
189{
190 struct iio_context_pdata *pdata = client->pdata;
191 const struct iiod_client_ops *ops = client->ops;
192 char buf[256], *ptr = buf, *end;
193 long maj, min;
194 int ret;
195
196 iio_mutex_lock(client->lock);
197
198 ret = ops->write(pdata, desc, "VERSION\r\n", sizeof("VERSION\r\n") - 1);
199 if (ret < 0) {
200 iio_mutex_unlock(client->lock);
201 return ret;
202 }
203
Paul Cercueileb772192016-04-08 14:54:02 +0200204 ret = ops->read_line(pdata, desc, buf, sizeof(buf));
Paul Cercueil2cb884a2015-11-30 15:01:25 +0100205 iio_mutex_unlock(client->lock);
206
207 if (ret < 0)
208 return ret;
209
210 maj = strtol(ptr, &end, 10);
211 if (ptr == end)
212 return -EIO;
213
214 ptr = end + 1;
215 min = strtol(ptr, &end, 10);
216 if (ptr == end)
217 return -EIO;
218
219 ptr = end + 1;
220 if (buf + ret < ptr + 8)
221 return -EIO;
222
223 /* Strip the \n */
224 ptr[buf + ret - ptr - 1] = '\0';
225
226 if (major)
227 *major = (unsigned int) maj;
228 if (minor)
229 *minor = (unsigned int) min;
230 if (git_tag)
231 strncpy(git_tag, ptr, 8);
232 return 0;
233}
Paul Cercueil6a785882015-11-30 16:36:19 +0100234
Lars-Peter Clausen2767d4d2016-06-23 14:19:02 +0200235int iiod_client_get_trigger(struct iiod_client *client, void *desc,
Paul Cercueil6a785882015-11-30 16:36:19 +0100236 const struct iio_device *dev, const struct iio_device **trigger)
237{
Paul Cercueil6a785882015-11-30 16:36:19 +0100238 const struct iio_context *ctx = iio_device_get_context(dev);
239 unsigned int i, nb_devices = iio_context_get_devices_count(ctx);
240 char buf[1024];
241 unsigned int name_len;
242 int ret;
243
Paul Cercueil9c9a5562017-01-24 10:48:31 +0100244 iio_snprintf(buf, sizeof(buf), "GETTRIG %s\r\n",
245 iio_device_get_id(dev));
Paul Cercueil6a785882015-11-30 16:36:19 +0100246
247 iio_mutex_lock(client->lock);
248 ret = iiod_client_exec_command(client, desc, buf);
249
250 if (ret == 0)
251 *trigger = NULL;
252 if (ret <= 0)
253 goto out_unlock;
254
Lars-Peter Clausenb3192d82016-01-28 14:25:57 +0100255 if ((unsigned int) ret > sizeof(buf) - 1) {
Paul Cercueil6a785882015-11-30 16:36:19 +0100256 ret = -EIO;
257 goto out_unlock;
258 }
259
260 name_len = ret;
261
Lars-Peter Clausen5bfba432016-02-03 15:24:08 +0100262 ret = (int) iiod_client_read_all(client, desc, buf, name_len + 1);
Paul Cercueil6a785882015-11-30 16:36:19 +0100263 if (ret < 0)
264 goto out_unlock;
265
266 ret = -ENXIO;
267
268 for (i = 0; i < nb_devices; i++) {
269 struct iio_device *cur = iio_context_get_device(ctx, i);
270
271 if (iio_device_is_trigger(cur)) {
272 const char *name = iio_device_get_name(cur);
273
274 if (!name)
275 continue;
276
277 if (!strncmp(name, buf, name_len)) {
278 *trigger = cur;
Lars-Peter Clausen9decc952016-01-15 12:39:50 +0100279 ret = 0;
280 goto out_unlock;
Paul Cercueil6a785882015-11-30 16:36:19 +0100281 }
282 }
283 }
284
285out_unlock:
286 iio_mutex_unlock(client->lock);
287 return ret;
288}
289
Lars-Peter Clausen2767d4d2016-06-23 14:19:02 +0200290int iiod_client_set_trigger(struct iiod_client *client, void *desc,
Paul Cercueil6a785882015-11-30 16:36:19 +0100291 const struct iio_device *dev, const struct iio_device *trigger)
292{
Paul Cercueil6a785882015-11-30 16:36:19 +0100293 char buf[1024];
294 int ret;
295
Paul Cercueil9c9a5562017-01-24 10:48:31 +0100296 if (trigger) {
297 iio_snprintf(buf, sizeof(buf), "SETTRIG %s %s\r\n",
Paul Cercueil6a785882015-11-30 16:36:19 +0100298 iio_device_get_id(dev),
299 iio_device_get_id(trigger));
Paul Cercueil9c9a5562017-01-24 10:48:31 +0100300 } else {
301 iio_snprintf(buf, sizeof(buf), "SETTRIG %s\r\n",
Paul Cercueil6a785882015-11-30 16:36:19 +0100302 iio_device_get_id(dev));
Paul Cercueil9c9a5562017-01-24 10:48:31 +0100303 }
Paul Cercueil6a785882015-11-30 16:36:19 +0100304
305 iio_mutex_lock(client->lock);
306 ret = iiod_client_exec_command(client, desc, buf);
307 iio_mutex_unlock(client->lock);
308 return ret;
309}
Paul Cercueile7d4db32015-11-30 16:54:51 +0100310
Lars-Peter Clausen2767d4d2016-06-23 14:19:02 +0200311int iiod_client_set_kernel_buffers_count(struct iiod_client *client, void *desc,
Paul Cercueile7d4db32015-11-30 16:54:51 +0100312 const struct iio_device *dev, unsigned int nb_blocks)
313{
314 int ret;
315 char buf[1024];
316
Paul Cercueil9c9a5562017-01-24 10:48:31 +0100317 iio_snprintf(buf, sizeof(buf), "SET %s BUFFERS_COUNT %u\r\n",
Paul Cercueile7d4db32015-11-30 16:54:51 +0100318 iio_device_get_id(dev), nb_blocks);
319
320 iio_mutex_lock(client->lock);
321 ret = iiod_client_exec_command(client, desc, buf);
322 iio_mutex_unlock(client->lock);
323 return ret;
324}
Paul Cercueil408b9672015-11-30 18:39:31 +0100325
Paul Cercueil3ce60382015-12-03 12:28:48 +0100326int iiod_client_set_timeout(struct iiod_client *client,
Lars-Peter Clausen2767d4d2016-06-23 14:19:02 +0200327 void *desc, unsigned int timeout)
Paul Cercueil3ce60382015-12-03 12:28:48 +0100328{
329 int ret;
330 char buf[1024];
331
Paul Cercueil9c9a5562017-01-24 10:48:31 +0100332 iio_snprintf(buf, sizeof(buf), "TIMEOUT %u\r\n", timeout);
Paul Cercueil3ce60382015-12-03 12:28:48 +0100333
334 iio_mutex_lock(client->lock);
335 ret = iiod_client_exec_command(client, desc, buf);
336 iio_mutex_unlock(client->lock);
337 return ret;
338}
339
Paul Cercueilcf1831e2016-10-31 16:29:19 +0100340static int iiod_client_discard(struct iiod_client *client, void *desc,
341 char *buf, size_t buf_len, size_t to_discard)
342{
343 do {
344 size_t read_len;
345 ssize_t ret;
346
347 if (to_discard > buf_len)
348 read_len = buf_len;
349 else
350 read_len = to_discard;
351
352 ret = iiod_client_read_all(client, desc, buf, read_len);
353 if (ret < 0)
354 return ret;
355
356 to_discard -= (size_t) ret;
357 } while (to_discard);
358
359 return 0;
360}
361
Lars-Peter Clausen2767d4d2016-06-23 14:19:02 +0200362ssize_t iiod_client_read_attr(struct iiod_client *client, void *desc,
Paul Cercueil408b9672015-11-30 18:39:31 +0100363 const struct iio_device *dev, const struct iio_channel *chn,
Matt Fornero81f04a52017-11-30 14:36:37 -0500364 const char *attr, char *dest, size_t len, enum iio_attr_type type)
Paul Cercueil408b9672015-11-30 18:39:31 +0100365{
Paul Cercueil408b9672015-11-30 18:39:31 +0100366 const char *id = iio_device_get_id(dev);
367 char buf[1024];
Paul Cercueil58bcbd42015-12-11 11:35:55 +0100368 ssize_t ret;
Paul Cercueil408b9672015-11-30 18:39:31 +0100369
370 if (attr) {
371 if (chn) {
372 if (!iio_channel_find_attr(chn, attr))
373 return -ENOENT;
Paul Cercueil408b9672015-11-30 18:39:31 +0100374 } else {
Matt Fornero81f04a52017-11-30 14:36:37 -0500375 switch (type) {
376 case IIO_ATTR_TYPE_DEVICE:
377 if (!iio_device_find_attr(dev, attr))
378 return -ENOENT;
379 break;
380 case IIO_ATTR_TYPE_DEBUG:
381 if (!iio_device_find_debug_attr(dev, attr))
382 return -ENOENT;
383 break;
384 case IIO_ATTR_TYPE_BUFFER:
385 if (!iio_device_find_buffer_attr(dev, attr))
386 return -ENOENT;
387 break;
388 default:
389 return -EINVAL;
390 }
Paul Cercueil408b9672015-11-30 18:39:31 +0100391 }
392 }
393
Paul Cercueil9c9a5562017-01-24 10:48:31 +0100394 if (chn) {
395 iio_snprintf(buf, sizeof(buf), "READ %s %s %s %s\r\n", id,
Paul Cercueil408b9672015-11-30 18:39:31 +0100396 iio_channel_is_output(chn) ? "OUTPUT" : "INPUT",
397 iio_channel_get_id(chn), attr ? attr : "");
Paul Cercueil9c9a5562017-01-24 10:48:31 +0100398 } else {
Matt Fornero81f04a52017-11-30 14:36:37 -0500399 switch (type) {
400 case IIO_ATTR_TYPE_DEVICE:
401 iio_snprintf(buf, sizeof(buf), "READ %s %s\r\n",
402 id, attr ? attr : "");
403 break;
404 case IIO_ATTR_TYPE_DEBUG:
405 iio_snprintf(buf, sizeof(buf), "READ %s DEBUG %s\r\n",
406 id, attr ? attr : "");
407 break;
408 case IIO_ATTR_TYPE_BUFFER:
409 iio_snprintf(buf, sizeof(buf), "READ %s BUFFER %s\r\n",
410 id, attr ? attr : "");
411 break;
412 }
Paul Cercueil9c9a5562017-01-24 10:48:31 +0100413 }
Paul Cercueil408b9672015-11-30 18:39:31 +0100414
415 iio_mutex_lock(client->lock);
416
417 ret = (ssize_t) iiod_client_exec_command(client, desc, buf);
418 if (ret < 0)
419 goto out_unlock;
420
421 if ((size_t) ret + 1 > len) {
Paul Cercueilcf1831e2016-10-31 16:29:19 +0100422 iiod_client_discard(client, desc, dest, len, ret + 1);
Paul Cercueil408b9672015-11-30 18:39:31 +0100423 ret = -EIO;
424 goto out_unlock;
425 }
426
427 /* +1: Also read the trailing \n */
428 ret = iiod_client_read_all(client, desc, dest, ret + 1);
429
Paul Cercueil08bb36b2015-12-18 10:51:13 +0100430 if (ret > 0) {
431 /* Discard the trailing \n */
432 ret--;
433
434 /* Replace it with a \0 just in case */
435 dest[ret] = '\0';
436 }
437
Paul Cercueil408b9672015-11-30 18:39:31 +0100438out_unlock:
439 iio_mutex_unlock(client->lock);
440 return ret;
441}
442
Lars-Peter Clausen2767d4d2016-06-23 14:19:02 +0200443ssize_t iiod_client_write_attr(struct iiod_client *client, void *desc,
Paul Cercueil408b9672015-11-30 18:39:31 +0100444 const struct iio_device *dev, const struct iio_channel *chn,
Matt Fornero81f04a52017-11-30 14:36:37 -0500445 const char *attr, const char *src, size_t len, enum iio_attr_type type)
Paul Cercueil408b9672015-11-30 18:39:31 +0100446{
447 struct iio_context_pdata *pdata = client->pdata;
448 const struct iiod_client_ops *ops = client->ops;
449 const char *id = iio_device_get_id(dev);
450 char buf[1024];
Paul Cercueil58bcbd42015-12-11 11:35:55 +0100451 ssize_t ret;
Paul Cercueil408b9672015-11-30 18:39:31 +0100452 int resp;
453
454 if (attr) {
455 if (chn) {
456 if (!iio_channel_find_attr(chn, attr))
457 return -ENOENT;
Paul Cercueil408b9672015-11-30 18:39:31 +0100458 } else {
Matt Fornero81f04a52017-11-30 14:36:37 -0500459 switch (type) {
460 case IIO_ATTR_TYPE_DEVICE:
461 if (!iio_device_find_attr(dev, attr))
462 return -ENOENT;
463 break;
464 case IIO_ATTR_TYPE_DEBUG:
465 if (!iio_device_find_debug_attr(dev, attr))
466 return -ENOENT;
467 break;
468 case IIO_ATTR_TYPE_BUFFER:
469 if (!iio_device_find_buffer_attr(dev, attr))
470 return -ENOENT;
471 break;
472 default:
473 return -EINVAL;
474 }
Paul Cercueil408b9672015-11-30 18:39:31 +0100475 }
476 }
477
Paul Cercueil9c9a5562017-01-24 10:48:31 +0100478 if (chn) {
479 iio_snprintf(buf, sizeof(buf), "WRITE %s %s %s %s %lu\r\n", id,
Paul Cercueil408b9672015-11-30 18:39:31 +0100480 iio_channel_is_output(chn) ? "OUTPUT" : "INPUT",
481 iio_channel_get_id(chn), attr ? attr : "",
482 (unsigned long) len);
Paul Cercueil9c9a5562017-01-24 10:48:31 +0100483 } else {
Matt Fornero81f04a52017-11-30 14:36:37 -0500484 switch (type) {
485 case IIO_ATTR_TYPE_DEVICE:
486 iio_snprintf(buf, sizeof(buf), "WRITE %s %s %lu\r\n",
487 id, attr ? attr : "", (unsigned long) len);
488 break;
489 case IIO_ATTR_TYPE_DEBUG:
490 iio_snprintf(buf, sizeof(buf), "WRITE %s DEBUG %s %lu\r\n",
491 id, attr ? attr : "", (unsigned long) len);
492 break;
493 case IIO_ATTR_TYPE_BUFFER:
494 iio_snprintf(buf, sizeof(buf), "WRITE %s BUFFER %s %lu\r\n",
495 id, attr ? attr : "", (unsigned long) len);
496 break;
497 }
Paul Cercueil9c9a5562017-01-24 10:48:31 +0100498 }
Paul Cercueil408b9672015-11-30 18:39:31 +0100499
500 iio_mutex_lock(client->lock);
501 ret = ops->write(pdata, desc, buf, strlen(buf));
502 if (ret < 0)
503 goto out_unlock;
504
505 ret = iiod_client_write_all(client, desc, src, len);
506 if (ret < 0)
507 goto out_unlock;
508
509 ret = iiod_client_read_integer(client, desc, &resp);
510 if (ret < 0)
511 goto out_unlock;
512
513 ret = (ssize_t) resp;
514
515out_unlock:
516 iio_mutex_unlock(client->lock);
517 return ret;
518}
Paul Cercueil8fd10d22015-12-01 11:15:36 +0100519
520struct iio_context * iiod_client_create_context(
Lars-Peter Clausen2767d4d2016-06-23 14:19:02 +0200521 struct iiod_client *client, void *desc)
Paul Cercueil8fd10d22015-12-01 11:15:36 +0100522{
523 struct iio_context *ctx = NULL;
524 size_t xml_len;
Paul Cercueil221c0dd2016-02-09 15:17:20 +0000525 char *xml;
Paul Cercueil8fd10d22015-12-01 11:15:36 +0100526 int ret;
527
Harvey Yangbc3f48e2019-10-22 11:17:28 +0800528 int client_id = iiod_client_request_client_id(client, desc);
529
Paul Cercueil8fd10d22015-12-01 11:15:36 +0100530 iio_mutex_lock(client->lock);
531 ret = iiod_client_exec_command(client, desc, "PRINT\r\n");
532 if (ret < 0)
533 goto out_unlock;
534
535 xml_len = (size_t) ret;
Paul Cercueil221c0dd2016-02-09 15:17:20 +0000536 xml = malloc(xml_len + 1);
Paul Cercueil8fd10d22015-12-01 11:15:36 +0100537 if (!xml) {
538 ret = -ENOMEM;
539 goto out_unlock;
540 }
541
Paul Cercueil221c0dd2016-02-09 15:17:20 +0000542 /* +1: Also read the trailing \n */
543 ret = (int) iiod_client_read_all(client, desc, xml, xml_len + 1);
Paul Cercueil8fd10d22015-12-01 11:15:36 +0100544 if (ret < 0)
545 goto out_free_xml;
546
Paul Cercueil8fd10d22015-12-01 11:15:36 +0100547 ctx = iio_create_xml_context_mem(xml, xml_len);
548 if (!ctx)
549 ret = -errno;
Harvey Yangbc3f48e2019-10-22 11:17:28 +0800550 if (client_id >= 0)
551 ctx->client_id = client_id;
Paul Cercueil8fd10d22015-12-01 11:15:36 +0100552
553out_free_xml:
554 free(xml);
555out_unlock:
556 iio_mutex_unlock(client->lock);
557 if (!ctx)
558 errno = -ret;
559 return ctx;
560}
Paul Cercueilba870932015-12-01 18:17:57 +0100561
Lars-Peter Clausen2767d4d2016-06-23 14:19:02 +0200562int iiod_client_open_unlocked(struct iiod_client *client, void *desc,
Paul Cercueilba870932015-12-01 18:17:57 +0100563 const struct iio_device *dev, size_t samples_count, bool cyclic)
564{
565 char buf[1024], *ptr;
566 size_t i;
567
Paul Cercueil9c9a5562017-01-24 10:48:31 +0100568 iio_snprintf(buf, sizeof(buf), "OPEN %s %lu ",
Paul Cercueilba870932015-12-01 18:17:57 +0100569 iio_device_get_id(dev), (unsigned long) samples_count);
570 ptr = buf + strlen(buf);
571
Paul Cercueil9c9a5562017-01-24 10:48:31 +0100572 for (i = dev->words; i > 0; i--, ptr += 8) {
573 iio_snprintf(ptr, (ptr - buf) + i * 8, "%08" PRIx32,
Paul Cercueil9f1586d2016-04-28 17:17:27 +0200574 dev->mask[i - 1]);
Paul Cercueil9c9a5562017-01-24 10:48:31 +0100575 }
Paul Cercueilba870932015-12-01 18:17:57 +0100576
577 strcpy(ptr, cyclic ? " CYCLIC\r\n" : "\r\n");
578
579 return iiod_client_exec_command(client, desc, buf);
580}
581
Lars-Peter Clausen2767d4d2016-06-23 14:19:02 +0200582int iiod_client_close_unlocked(struct iiod_client *client, void *desc,
Paul Cercueilba870932015-12-01 18:17:57 +0100583 const struct iio_device *dev)
584{
585 char buf[1024];
586
Paul Cercueil9c9a5562017-01-24 10:48:31 +0100587 iio_snprintf(buf, sizeof(buf), "CLOSE %s\r\n", iio_device_get_id(dev));
Paul Cercueilba870932015-12-01 18:17:57 +0100588 return iiod_client_exec_command(client, desc, buf);
589}
Paul Cercueil1f75a8f2015-12-02 11:51:14 +0100590
591static int iiod_client_read_mask(struct iiod_client *client,
Lars-Peter Clausen2767d4d2016-06-23 14:19:02 +0200592 void *desc, uint32_t *mask, size_t words)
Paul Cercueil1f75a8f2015-12-02 11:51:14 +0100593{
594 size_t i;
595 ssize_t ret;
596 char *buf, *ptr;
597
598 buf = malloc(words * 8 + 1);
599 if (!buf)
600 return -ENOMEM;
601
602 ret = iiod_client_read_all(client, desc, buf, words * 8 + 1);
Robin Getzaf161e02020-02-12 10:54:06 -0500603 if (ret < 0) {
604 ERROR("READ ALL: %zu\n", ret);
Paul Cercueil1f75a8f2015-12-02 11:51:14 +0100605 goto out_buf_free;
Robin Getzaf161e02020-02-12 10:54:06 -0500606 } else
Paul Cercueil1f75a8f2015-12-02 11:51:14 +0100607 ret = 0;
608
Lars-Peter Clausenabd2c102016-02-22 11:33:32 +0100609 buf[words*8] = '\0';
610
Paul Cercueil1f75a8f2015-12-02 11:51:14 +0100611 DEBUG("Reading mask\n");
612
613 for (i = words, ptr = buf; i > 0; i--) {
Paul Cercueil9f1586d2016-04-28 17:17:27 +0200614 sscanf(ptr, "%08" PRIx32, &mask[i - 1]);
615 DEBUG("mask[%lu] = 0x%08" PRIx32 "\n",
Paul Cercueil8835bbb2016-04-18 11:56:59 +0200616 (unsigned long)(i - 1), mask[i - 1]);
Paul Cercueil1f75a8f2015-12-02 11:51:14 +0100617
618 ptr = (char *) ((uintptr_t) ptr + 8);
619 }
620
621out_buf_free:
622 free(buf);
623 return (int) ret;
624}
625
Harvey Yangbc3f48e2019-10-22 11:17:28 +0800626int iiod_client_register_client_id(struct iiod_client *client, void *desc,
627 int client_id)
628{
629 char buf[1024];
630 ssize_t ret;
631 int to_read;
632
633 iio_snprintf(buf, sizeof(buf), "REGISTER_CLIENT_ID %i\r\n", client_id);
634
635 ret = iiod_client_write_all(client, desc, buf, strlen(buf));
636 if (ret < 0)
637 return ret;
638
639 ret = iiod_client_read_integer(client, desc, &to_read);
640 if (ret < 0)
641 return ret;
642
643 return to_read;
644}
645
Lars-Peter Clausen2767d4d2016-06-23 14:19:02 +0200646ssize_t iiod_client_read_unlocked(struct iiod_client *client, void *desc,
Paul Cercueil1f75a8f2015-12-02 11:51:14 +0100647 const struct iio_device *dev, void *dst, size_t len,
648 uint32_t *mask, size_t words)
649{
650 unsigned int nb_channels = iio_device_get_channels_count(dev);
651 uintptr_t ptr = (uintptr_t) dst;
Paul Cercueil1f75a8f2015-12-02 11:51:14 +0100652 char buf[1024];
653 ssize_t ret, read = 0;
654
655 if (!len || words != (nb_channels + 31) / 32)
656 return -EINVAL;
657
Paul Cercueil9c9a5562017-01-24 10:48:31 +0100658 iio_snprintf(buf, sizeof(buf), "READBUF %s %lu\r\n",
Paul Cercueil1f75a8f2015-12-02 11:51:14 +0100659 iio_device_get_id(dev), (unsigned long) len);
660
661 ret = iiod_client_write_all(client, desc, buf, strlen(buf));
Robin Getzaf161e02020-02-12 10:54:06 -0500662 if (ret < 0) {
663 ERROR("WRITE ALL: %zu\n", ret);
Paul Cercueil1f75a8f2015-12-02 11:51:14 +0100664 return ret;
Robin Getzaf161e02020-02-12 10:54:06 -0500665 }
Paul Cercueil1f75a8f2015-12-02 11:51:14 +0100666
667 do {
668 int to_read;
669
670 ret = iiod_client_read_integer(client, desc, &to_read);
Robin Getzaf161e02020-02-12 10:54:06 -0500671 if (ret < 0) {
672 ERROR("READ INTEGER: %zu\n", ret);
Paul Cercueil1f75a8f2015-12-02 11:51:14 +0100673 return ret;
Robin Getzaf161e02020-02-12 10:54:06 -0500674 }
Lars-Peter Clausenc263f8e2016-04-12 15:24:10 +0200675 if (to_read < 0)
676 return (ssize_t) to_read;
Paul Cercueil1f75a8f2015-12-02 11:51:14 +0100677 if (!to_read)
678 break;
679
680 if (mask) {
681 ret = iiod_client_read_mask(client, desc, mask, words);
Robin Getzaf161e02020-02-12 10:54:06 -0500682 if (ret < 0) {
683 ERROR("READ ALL: %zu\n", ret);
Paul Cercueil1f75a8f2015-12-02 11:51:14 +0100684 return ret;
Robin Getzaf161e02020-02-12 10:54:06 -0500685 }
Paul Cercueil1f75a8f2015-12-02 11:51:14 +0100686
687 mask = NULL; /* We read the mask only once */
688 }
689
690 ret = iiod_client_read_all(client, desc, (char *) ptr, to_read);
691 if (ret < 0)
692 return ret;
693
694 ptr += ret;
695 read += ret;
696 len -= ret;
697 } while (len);
698
699 return read;
700}
Paul Cercueil90fd85c2015-12-02 17:57:07 +0100701
Lars-Peter Clausen2767d4d2016-06-23 14:19:02 +0200702ssize_t iiod_client_write_unlocked(struct iiod_client *client, void *desc,
Paul Cercueil90fd85c2015-12-02 17:57:07 +0100703 const struct iio_device *dev, const void *src, size_t len)
704{
Paul Cercueil90fd85c2015-12-02 17:57:07 +0100705 ssize_t ret;
706 char buf[1024];
707 int val;
708
Paul Cercueil9c9a5562017-01-24 10:48:31 +0100709 iio_snprintf(buf, sizeof(buf), "WRITEBUF %s %lu\r\n",
Paul Cercueil90fd85c2015-12-02 17:57:07 +0100710 dev->id, (unsigned long) len);
711
712 ret = iiod_client_write_all(client, desc, buf, strlen(buf));
713 if (ret < 0)
714 return ret;
715
716 ret = iiod_client_read_integer(client, desc, &val);
717 if (ret < 0)
718 return ret;
719 if (val < 0)
720 return (ssize_t) val;
721
722 ret = iiod_client_write_all(client, desc, src, len);
723 if (ret < 0)
724 return ret;
725
726 ret = iiod_client_read_integer(client, desc, &val);
727 if (ret < 0)
728 return ret;
729 if (val < 0)
730 return (ssize_t) val;
731
732 return (ssize_t) len;
733}