Paul Cercueil / libiio

Dependencies:   libserialport libxml2

Committer:
pcercuei
Date:
Mon Jun 26 14:30:10 2017 +0000
Revision:
4:ad69b39bf124
Parent:
3:d147beabba0e
Update to upstream version v0.10

Who changed what in which revision?

UserRevisionLine numberNew contents of line
pcercuei 2:9eb0a9a1f958 1 /*
pcercuei 2:9eb0a9a1f958 2 * libiio - Library for interfacing industrial I/O (IIO) devices
pcercuei 2:9eb0a9a1f958 3 *
pcercuei 2:9eb0a9a1f958 4 * Copyright (C) 2014-2016 Analog Devices, Inc.
pcercuei 2:9eb0a9a1f958 5 * Author: Paul Cercueil <paul.cercueil@analog.com>
pcercuei 2:9eb0a9a1f958 6 *
pcercuei 2:9eb0a9a1f958 7 * This library is free software; you can redistribute it and/or
pcercuei 2:9eb0a9a1f958 8 * modify it under the terms of the GNU Lesser General Public
pcercuei 2:9eb0a9a1f958 9 * License as published by the Free Software Foundation; either
pcercuei 2:9eb0a9a1f958 10 * version 2.1 of the License, or (at your option) any later version.
pcercuei 2:9eb0a9a1f958 11 *
pcercuei 2:9eb0a9a1f958 12 * This library is distributed in the hope that it will be useful,
pcercuei 2:9eb0a9a1f958 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
pcercuei 2:9eb0a9a1f958 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
pcercuei 2:9eb0a9a1f958 15 * Lesser General Public License for more details.
pcercuei 2:9eb0a9a1f958 16 *
pcercuei 2:9eb0a9a1f958 17 */
pcercuei 2:9eb0a9a1f958 18
pcercuei 0:df031b60ca29 19 #include "debug.h"
pcercuei 0:df031b60ca29 20 #include "iiod-client.h"
pcercuei 0:df031b60ca29 21 #include "iio-lock.h"
pcercuei 0:df031b60ca29 22 #include "iio-private.h"
pcercuei 0:df031b60ca29 23
pcercuei 2:9eb0a9a1f958 24 #include <errno.h>
pcercuei 0:df031b60ca29 25 #include <inttypes.h>
pcercuei 0:df031b60ca29 26 #include <string.h>
pcercuei 0:df031b60ca29 27 #include <stdio.h>
pcercuei 0:df031b60ca29 28
pcercuei 0:df031b60ca29 29 struct iiod_client {
pcercuei 0:df031b60ca29 30 struct iio_context_pdata *pdata;
pcercuei 0:df031b60ca29 31 const struct iiod_client_ops *ops;
pcercuei 0:df031b60ca29 32 struct iio_mutex *lock;
pcercuei 0:df031b60ca29 33 };
pcercuei 0:df031b60ca29 34
pcercuei 0:df031b60ca29 35 static ssize_t iiod_client_read_integer(struct iiod_client *client,
pcercuei 0:df031b60ca29 36 void *desc, int *val)
pcercuei 0:df031b60ca29 37 {
pcercuei 0:df031b60ca29 38 unsigned int i;
pcercuei 0:df031b60ca29 39 char buf[1024], *ptr = NULL, *end;
pcercuei 0:df031b60ca29 40 ssize_t ret;
pcercuei 0:df031b60ca29 41 int value;
pcercuei 0:df031b60ca29 42
pcercuei 0:df031b60ca29 43 do {
pcercuei 0:df031b60ca29 44 ret = client->ops->read_line(client->pdata,
pcercuei 0:df031b60ca29 45 desc, buf, sizeof(buf));
pcercuei 0:df031b60ca29 46 if (ret < 0)
pcercuei 0:df031b60ca29 47 return ret;
pcercuei 0:df031b60ca29 48
pcercuei 0:df031b60ca29 49 for (i = 0; i < (unsigned int) ret; i++) {
pcercuei 0:df031b60ca29 50 if (buf[i] != '\n') {
pcercuei 0:df031b60ca29 51 if (!ptr)
pcercuei 0:df031b60ca29 52 ptr = &buf[i];
pcercuei 0:df031b60ca29 53 } else if (!!ptr) {
pcercuei 0:df031b60ca29 54 break;
pcercuei 0:df031b60ca29 55 }
pcercuei 0:df031b60ca29 56 }
pcercuei 0:df031b60ca29 57 } while (!ptr);
pcercuei 0:df031b60ca29 58
pcercuei 0:df031b60ca29 59 buf[i] = '\0';
pcercuei 0:df031b60ca29 60
pcercuei 0:df031b60ca29 61 value = (int) strtol(ptr, &end, 10);
pcercuei 0:df031b60ca29 62 if (ptr == end)
pcercuei 0:df031b60ca29 63 return -EINVAL;
pcercuei 0:df031b60ca29 64
pcercuei 0:df031b60ca29 65 *val = value;
pcercuei 0:df031b60ca29 66 return 0;
pcercuei 0:df031b60ca29 67 }
pcercuei 0:df031b60ca29 68
pcercuei 0:df031b60ca29 69 static int iiod_client_exec_command(struct iiod_client *client,
pcercuei 0:df031b60ca29 70 void *desc, const char *cmd)
pcercuei 0:df031b60ca29 71 {
pcercuei 0:df031b60ca29 72 int resp;
pcercuei 0:df031b60ca29 73 ssize_t ret;
pcercuei 0:df031b60ca29 74
pcercuei 0:df031b60ca29 75 ret = client->ops->write(client->pdata, desc, cmd, strlen(cmd));
pcercuei 0:df031b60ca29 76 if (ret < 0)
pcercuei 0:df031b60ca29 77 return (int) ret;
pcercuei 0:df031b60ca29 78
pcercuei 0:df031b60ca29 79 ret = iiod_client_read_integer(client, desc, &resp);
pcercuei 0:df031b60ca29 80 return ret < 0 ? (int) ret : resp;
pcercuei 0:df031b60ca29 81 }
pcercuei 0:df031b60ca29 82
pcercuei 0:df031b60ca29 83 static ssize_t iiod_client_write_all(struct iiod_client *client,
pcercuei 0:df031b60ca29 84 void *desc, const void *src, size_t len)
pcercuei 0:df031b60ca29 85 {
pcercuei 0:df031b60ca29 86 struct iio_context_pdata *pdata = client->pdata;
pcercuei 0:df031b60ca29 87 const struct iiod_client_ops *ops = client->ops;
pcercuei 0:df031b60ca29 88 uintptr_t ptr = (uintptr_t) src;
pcercuei 0:df031b60ca29 89
pcercuei 0:df031b60ca29 90 while (len) {
pcercuei 0:df031b60ca29 91 ssize_t ret = ops->write(pdata, desc, (const void *) ptr, len);
pcercuei 0:df031b60ca29 92
pcercuei 0:df031b60ca29 93 if (ret < 0) {
pcercuei 0:df031b60ca29 94 if (ret == -EINTR)
pcercuei 0:df031b60ca29 95 continue;
pcercuei 0:df031b60ca29 96 else
pcercuei 0:df031b60ca29 97 return ret;
pcercuei 0:df031b60ca29 98 }
pcercuei 0:df031b60ca29 99
pcercuei 0:df031b60ca29 100 if (ret == 0)
pcercuei 0:df031b60ca29 101 return -EPIPE;
pcercuei 0:df031b60ca29 102
pcercuei 0:df031b60ca29 103 ptr += ret;
pcercuei 0:df031b60ca29 104 len -= ret;
pcercuei 0:df031b60ca29 105 }
pcercuei 0:df031b60ca29 106
pcercuei 0:df031b60ca29 107 return (ssize_t) (ptr - (uintptr_t) src);
pcercuei 0:df031b60ca29 108 }
pcercuei 0:df031b60ca29 109
pcercuei 0:df031b60ca29 110 static ssize_t iiod_client_read_all(struct iiod_client *client,
pcercuei 0:df031b60ca29 111 void *desc, void *dst, size_t len)
pcercuei 0:df031b60ca29 112 {
pcercuei 0:df031b60ca29 113 struct iio_context_pdata *pdata = client->pdata;
pcercuei 0:df031b60ca29 114 const struct iiod_client_ops *ops = client->ops;
pcercuei 0:df031b60ca29 115 uintptr_t ptr = (uintptr_t) dst;
pcercuei 0:df031b60ca29 116
pcercuei 0:df031b60ca29 117 while (len) {
pcercuei 0:df031b60ca29 118 ssize_t ret = ops->read(pdata, desc, (void *) ptr, len);
pcercuei 0:df031b60ca29 119
pcercuei 0:df031b60ca29 120 if (ret < 0) {
pcercuei 0:df031b60ca29 121 if (ret == -EINTR)
pcercuei 0:df031b60ca29 122 continue;
pcercuei 0:df031b60ca29 123 else
pcercuei 0:df031b60ca29 124 return ret;
pcercuei 0:df031b60ca29 125 }
pcercuei 0:df031b60ca29 126
pcercuei 0:df031b60ca29 127 if (ret == 0)
pcercuei 0:df031b60ca29 128 return -EPIPE;
pcercuei 0:df031b60ca29 129
pcercuei 0:df031b60ca29 130 ptr += ret;
pcercuei 0:df031b60ca29 131 len -= ret;
pcercuei 0:df031b60ca29 132 }
pcercuei 0:df031b60ca29 133
pcercuei 0:df031b60ca29 134 return (ssize_t) (ptr - (uintptr_t) dst);
pcercuei 0:df031b60ca29 135 }
pcercuei 0:df031b60ca29 136
pcercuei 0:df031b60ca29 137 struct iiod_client * iiod_client_new(struct iio_context_pdata *pdata,
pcercuei 0:df031b60ca29 138 struct iio_mutex *lock, const struct iiod_client_ops *ops)
pcercuei 0:df031b60ca29 139 {
pcercuei 0:df031b60ca29 140 struct iiod_client *client;
pcercuei 0:df031b60ca29 141
pcercuei 0:df031b60ca29 142 client = malloc(sizeof(*client));
pcercuei 0:df031b60ca29 143 if (!client) {
pcercuei 0:df031b60ca29 144 errno = ENOMEM;
pcercuei 0:df031b60ca29 145 return NULL;
pcercuei 0:df031b60ca29 146 }
pcercuei 0:df031b60ca29 147
pcercuei 0:df031b60ca29 148 client->lock = lock;
pcercuei 0:df031b60ca29 149 client->pdata = pdata;
pcercuei 0:df031b60ca29 150 client->ops = ops;
pcercuei 0:df031b60ca29 151 return client;
pcercuei 0:df031b60ca29 152 }
pcercuei 0:df031b60ca29 153
pcercuei 0:df031b60ca29 154 void iiod_client_destroy(struct iiod_client *client)
pcercuei 0:df031b60ca29 155 {
pcercuei 0:df031b60ca29 156 free(client);
pcercuei 0:df031b60ca29 157 }
pcercuei 0:df031b60ca29 158
pcercuei 0:df031b60ca29 159 int iiod_client_get_version(struct iiod_client *client, void *desc,
pcercuei 0:df031b60ca29 160 unsigned int *major, unsigned int *minor, char *git_tag)
pcercuei 0:df031b60ca29 161 {
pcercuei 0:df031b60ca29 162 struct iio_context_pdata *pdata = client->pdata;
pcercuei 0:df031b60ca29 163 const struct iiod_client_ops *ops = client->ops;
pcercuei 0:df031b60ca29 164 char buf[256], *ptr = buf, *end;
pcercuei 0:df031b60ca29 165 long maj, min;
pcercuei 0:df031b60ca29 166 int ret;
pcercuei 0:df031b60ca29 167
pcercuei 0:df031b60ca29 168 iio_mutex_lock(client->lock);
pcercuei 0:df031b60ca29 169
pcercuei 0:df031b60ca29 170 ret = ops->write(pdata, desc, "VERSION\r\n", sizeof("VERSION\r\n") - 1);
pcercuei 0:df031b60ca29 171 if (ret < 0) {
pcercuei 0:df031b60ca29 172 iio_mutex_unlock(client->lock);
pcercuei 0:df031b60ca29 173 return ret;
pcercuei 0:df031b60ca29 174 }
pcercuei 0:df031b60ca29 175
pcercuei 0:df031b60ca29 176 ret = ops->read_line(pdata, desc, buf, sizeof(buf));
pcercuei 0:df031b60ca29 177 iio_mutex_unlock(client->lock);
pcercuei 0:df031b60ca29 178
pcercuei 0:df031b60ca29 179 if (ret < 0)
pcercuei 0:df031b60ca29 180 return ret;
pcercuei 0:df031b60ca29 181
pcercuei 0:df031b60ca29 182 maj = strtol(ptr, &end, 10);
pcercuei 0:df031b60ca29 183 if (ptr == end)
pcercuei 0:df031b60ca29 184 return -EIO;
pcercuei 0:df031b60ca29 185
pcercuei 0:df031b60ca29 186 ptr = end + 1;
pcercuei 0:df031b60ca29 187 min = strtol(ptr, &end, 10);
pcercuei 0:df031b60ca29 188 if (ptr == end)
pcercuei 0:df031b60ca29 189 return -EIO;
pcercuei 0:df031b60ca29 190
pcercuei 0:df031b60ca29 191 ptr = end + 1;
pcercuei 0:df031b60ca29 192 if (buf + ret < ptr + 8)
pcercuei 0:df031b60ca29 193 return -EIO;
pcercuei 0:df031b60ca29 194
pcercuei 0:df031b60ca29 195 /* Strip the \n */
pcercuei 0:df031b60ca29 196 ptr[buf + ret - ptr - 1] = '\0';
pcercuei 0:df031b60ca29 197
pcercuei 0:df031b60ca29 198 if (major)
pcercuei 0:df031b60ca29 199 *major = (unsigned int) maj;
pcercuei 0:df031b60ca29 200 if (minor)
pcercuei 0:df031b60ca29 201 *minor = (unsigned int) min;
pcercuei 0:df031b60ca29 202 if (git_tag)
pcercuei 0:df031b60ca29 203 strncpy(git_tag, ptr, 8);
pcercuei 0:df031b60ca29 204 return 0;
pcercuei 0:df031b60ca29 205 }
pcercuei 0:df031b60ca29 206
pcercuei 0:df031b60ca29 207 int iiod_client_get_trigger(struct iiod_client *client, void *desc,
pcercuei 0:df031b60ca29 208 const struct iio_device *dev, const struct iio_device **trigger)
pcercuei 0:df031b60ca29 209 {
pcercuei 0:df031b60ca29 210 const struct iio_context *ctx = iio_device_get_context(dev);
pcercuei 0:df031b60ca29 211 unsigned int i, nb_devices = iio_context_get_devices_count(ctx);
pcercuei 0:df031b60ca29 212 char buf[1024];
pcercuei 0:df031b60ca29 213 unsigned int name_len;
pcercuei 0:df031b60ca29 214 int ret;
pcercuei 0:df031b60ca29 215
pcercuei 3:d147beabba0e 216 iio_snprintf(buf, sizeof(buf), "GETTRIG %s\r\n",
pcercuei 3:d147beabba0e 217 iio_device_get_id(dev));
pcercuei 0:df031b60ca29 218
pcercuei 0:df031b60ca29 219 iio_mutex_lock(client->lock);
pcercuei 0:df031b60ca29 220 ret = iiod_client_exec_command(client, desc, buf);
pcercuei 0:df031b60ca29 221
pcercuei 0:df031b60ca29 222 if (ret == 0)
pcercuei 0:df031b60ca29 223 *trigger = NULL;
pcercuei 0:df031b60ca29 224 if (ret <= 0)
pcercuei 0:df031b60ca29 225 goto out_unlock;
pcercuei 0:df031b60ca29 226
pcercuei 0:df031b60ca29 227 if ((unsigned int) ret > sizeof(buf) - 1) {
pcercuei 0:df031b60ca29 228 ret = -EIO;
pcercuei 0:df031b60ca29 229 goto out_unlock;
pcercuei 0:df031b60ca29 230 }
pcercuei 0:df031b60ca29 231
pcercuei 0:df031b60ca29 232 name_len = ret;
pcercuei 0:df031b60ca29 233
pcercuei 0:df031b60ca29 234 ret = (int) iiod_client_read_all(client, desc, buf, name_len + 1);
pcercuei 0:df031b60ca29 235 if (ret < 0)
pcercuei 0:df031b60ca29 236 goto out_unlock;
pcercuei 0:df031b60ca29 237
pcercuei 0:df031b60ca29 238 ret = -ENXIO;
pcercuei 0:df031b60ca29 239
pcercuei 0:df031b60ca29 240 for (i = 0; i < nb_devices; i++) {
pcercuei 0:df031b60ca29 241 struct iio_device *cur = iio_context_get_device(ctx, i);
pcercuei 0:df031b60ca29 242
pcercuei 0:df031b60ca29 243 if (iio_device_is_trigger(cur)) {
pcercuei 0:df031b60ca29 244 const char *name = iio_device_get_name(cur);
pcercuei 0:df031b60ca29 245
pcercuei 0:df031b60ca29 246 if (!name)
pcercuei 0:df031b60ca29 247 continue;
pcercuei 0:df031b60ca29 248
pcercuei 0:df031b60ca29 249 if (!strncmp(name, buf, name_len)) {
pcercuei 0:df031b60ca29 250 *trigger = cur;
pcercuei 0:df031b60ca29 251 ret = 0;
pcercuei 0:df031b60ca29 252 goto out_unlock;
pcercuei 0:df031b60ca29 253 }
pcercuei 0:df031b60ca29 254 }
pcercuei 0:df031b60ca29 255 }
pcercuei 0:df031b60ca29 256
pcercuei 0:df031b60ca29 257 out_unlock:
pcercuei 0:df031b60ca29 258 iio_mutex_unlock(client->lock);
pcercuei 0:df031b60ca29 259 return ret;
pcercuei 0:df031b60ca29 260 }
pcercuei 0:df031b60ca29 261
pcercuei 0:df031b60ca29 262 int iiod_client_set_trigger(struct iiod_client *client, void *desc,
pcercuei 0:df031b60ca29 263 const struct iio_device *dev, const struct iio_device *trigger)
pcercuei 0:df031b60ca29 264 {
pcercuei 0:df031b60ca29 265 char buf[1024];
pcercuei 0:df031b60ca29 266 int ret;
pcercuei 0:df031b60ca29 267
pcercuei 3:d147beabba0e 268 if (trigger) {
pcercuei 3:d147beabba0e 269 iio_snprintf(buf, sizeof(buf), "SETTRIG %s %s\r\n",
pcercuei 0:df031b60ca29 270 iio_device_get_id(dev),
pcercuei 0:df031b60ca29 271 iio_device_get_id(trigger));
pcercuei 3:d147beabba0e 272 } else {
pcercuei 3:d147beabba0e 273 iio_snprintf(buf, sizeof(buf), "SETTRIG %s\r\n",
pcercuei 0:df031b60ca29 274 iio_device_get_id(dev));
pcercuei 3:d147beabba0e 275 }
pcercuei 0:df031b60ca29 276
pcercuei 0:df031b60ca29 277 iio_mutex_lock(client->lock);
pcercuei 0:df031b60ca29 278 ret = iiod_client_exec_command(client, desc, buf);
pcercuei 0:df031b60ca29 279 iio_mutex_unlock(client->lock);
pcercuei 0:df031b60ca29 280 return ret;
pcercuei 0:df031b60ca29 281 }
pcercuei 0:df031b60ca29 282
pcercuei 0:df031b60ca29 283 int iiod_client_set_kernel_buffers_count(struct iiod_client *client, void *desc,
pcercuei 0:df031b60ca29 284 const struct iio_device *dev, unsigned int nb_blocks)
pcercuei 0:df031b60ca29 285 {
pcercuei 0:df031b60ca29 286 int ret;
pcercuei 0:df031b60ca29 287 char buf[1024];
pcercuei 0:df031b60ca29 288
pcercuei 3:d147beabba0e 289 iio_snprintf(buf, sizeof(buf), "SET %s BUFFERS_COUNT %u\r\n",
pcercuei 0:df031b60ca29 290 iio_device_get_id(dev), nb_blocks);
pcercuei 0:df031b60ca29 291
pcercuei 0:df031b60ca29 292 iio_mutex_lock(client->lock);
pcercuei 0:df031b60ca29 293 ret = iiod_client_exec_command(client, desc, buf);
pcercuei 0:df031b60ca29 294 iio_mutex_unlock(client->lock);
pcercuei 0:df031b60ca29 295 return ret;
pcercuei 0:df031b60ca29 296 }
pcercuei 0:df031b60ca29 297
pcercuei 0:df031b60ca29 298 int iiod_client_set_timeout(struct iiod_client *client,
pcercuei 0:df031b60ca29 299 void *desc, unsigned int timeout)
pcercuei 0:df031b60ca29 300 {
pcercuei 0:df031b60ca29 301 int ret;
pcercuei 0:df031b60ca29 302 char buf[1024];
pcercuei 0:df031b60ca29 303
pcercuei 3:d147beabba0e 304 iio_snprintf(buf, sizeof(buf), "TIMEOUT %u\r\n", timeout);
pcercuei 0:df031b60ca29 305
pcercuei 0:df031b60ca29 306 iio_mutex_lock(client->lock);
pcercuei 0:df031b60ca29 307 ret = iiod_client_exec_command(client, desc, buf);
pcercuei 0:df031b60ca29 308 iio_mutex_unlock(client->lock);
pcercuei 0:df031b60ca29 309 return ret;
pcercuei 0:df031b60ca29 310 }
pcercuei 0:df031b60ca29 311
pcercuei 3:d147beabba0e 312 static int iiod_client_discard(struct iiod_client *client, void *desc,
pcercuei 3:d147beabba0e 313 char *buf, size_t buf_len, size_t to_discard)
pcercuei 3:d147beabba0e 314 {
pcercuei 3:d147beabba0e 315 do {
pcercuei 3:d147beabba0e 316 size_t read_len;
pcercuei 3:d147beabba0e 317 ssize_t ret;
pcercuei 3:d147beabba0e 318
pcercuei 3:d147beabba0e 319 if (to_discard > buf_len)
pcercuei 3:d147beabba0e 320 read_len = buf_len;
pcercuei 3:d147beabba0e 321 else
pcercuei 3:d147beabba0e 322 read_len = to_discard;
pcercuei 3:d147beabba0e 323
pcercuei 3:d147beabba0e 324 ret = iiod_client_read_all(client, desc, buf, read_len);
pcercuei 3:d147beabba0e 325 if (ret < 0)
pcercuei 3:d147beabba0e 326 return ret;
pcercuei 3:d147beabba0e 327
pcercuei 3:d147beabba0e 328 to_discard -= (size_t) ret;
pcercuei 3:d147beabba0e 329 } while (to_discard);
pcercuei 3:d147beabba0e 330
pcercuei 3:d147beabba0e 331 return 0;
pcercuei 3:d147beabba0e 332 }
pcercuei 3:d147beabba0e 333
pcercuei 0:df031b60ca29 334 ssize_t iiod_client_read_attr(struct iiod_client *client, void *desc,
pcercuei 0:df031b60ca29 335 const struct iio_device *dev, const struct iio_channel *chn,
pcercuei 0:df031b60ca29 336 const char *attr, char *dest, size_t len, bool is_debug)
pcercuei 0:df031b60ca29 337 {
pcercuei 0:df031b60ca29 338 const char *id = iio_device_get_id(dev);
pcercuei 0:df031b60ca29 339 char buf[1024];
pcercuei 0:df031b60ca29 340 ssize_t ret;
pcercuei 0:df031b60ca29 341
pcercuei 0:df031b60ca29 342 if (attr) {
pcercuei 0:df031b60ca29 343 if (chn) {
pcercuei 0:df031b60ca29 344 if (!iio_channel_find_attr(chn, attr))
pcercuei 0:df031b60ca29 345 return -ENOENT;
pcercuei 0:df031b60ca29 346 } else if (is_debug) {
pcercuei 0:df031b60ca29 347 if (!iio_device_find_debug_attr(dev, attr))
pcercuei 0:df031b60ca29 348 return -ENOENT;
pcercuei 0:df031b60ca29 349 } else {
pcercuei 0:df031b60ca29 350 if (!iio_device_find_attr(dev, attr))
pcercuei 0:df031b60ca29 351 return -ENOENT;
pcercuei 0:df031b60ca29 352 }
pcercuei 0:df031b60ca29 353 }
pcercuei 0:df031b60ca29 354
pcercuei 3:d147beabba0e 355 if (chn) {
pcercuei 3:d147beabba0e 356 iio_snprintf(buf, sizeof(buf), "READ %s %s %s %s\r\n", id,
pcercuei 0:df031b60ca29 357 iio_channel_is_output(chn) ? "OUTPUT" : "INPUT",
pcercuei 0:df031b60ca29 358 iio_channel_get_id(chn), attr ? attr : "");
pcercuei 3:d147beabba0e 359 } else if (is_debug) {
pcercuei 3:d147beabba0e 360 iio_snprintf(buf, sizeof(buf), "READ %s DEBUG %s\r\n",
pcercuei 0:df031b60ca29 361 id, attr ? attr : "");
pcercuei 3:d147beabba0e 362 } else {
pcercuei 3:d147beabba0e 363 iio_snprintf(buf, sizeof(buf), "READ %s %s\r\n",
pcercuei 0:df031b60ca29 364 id, attr ? attr : "");
pcercuei 3:d147beabba0e 365 }
pcercuei 0:df031b60ca29 366
pcercuei 0:df031b60ca29 367 iio_mutex_lock(client->lock);
pcercuei 0:df031b60ca29 368
pcercuei 0:df031b60ca29 369 ret = (ssize_t) iiod_client_exec_command(client, desc, buf);
pcercuei 0:df031b60ca29 370 if (ret < 0)
pcercuei 0:df031b60ca29 371 goto out_unlock;
pcercuei 0:df031b60ca29 372
pcercuei 0:df031b60ca29 373 if ((size_t) ret + 1 > len) {
pcercuei 3:d147beabba0e 374 iiod_client_discard(client, desc, dest, len, ret + 1);
pcercuei 0:df031b60ca29 375 ret = -EIO;
pcercuei 0:df031b60ca29 376 goto out_unlock;
pcercuei 0:df031b60ca29 377 }
pcercuei 0:df031b60ca29 378
pcercuei 0:df031b60ca29 379 /* +1: Also read the trailing \n */
pcercuei 0:df031b60ca29 380 ret = iiod_client_read_all(client, desc, dest, ret + 1);
pcercuei 0:df031b60ca29 381
pcercuei 0:df031b60ca29 382 if (ret > 0) {
pcercuei 0:df031b60ca29 383 /* Discard the trailing \n */
pcercuei 0:df031b60ca29 384 ret--;
pcercuei 0:df031b60ca29 385
pcercuei 0:df031b60ca29 386 /* Replace it with a \0 just in case */
pcercuei 0:df031b60ca29 387 dest[ret] = '\0';
pcercuei 0:df031b60ca29 388 }
pcercuei 0:df031b60ca29 389
pcercuei 0:df031b60ca29 390 out_unlock:
pcercuei 0:df031b60ca29 391 iio_mutex_unlock(client->lock);
pcercuei 0:df031b60ca29 392 return ret;
pcercuei 0:df031b60ca29 393 }
pcercuei 0:df031b60ca29 394
pcercuei 0:df031b60ca29 395 ssize_t iiod_client_write_attr(struct iiod_client *client, void *desc,
pcercuei 0:df031b60ca29 396 const struct iio_device *dev, const struct iio_channel *chn,
pcercuei 0:df031b60ca29 397 const char *attr, const char *src, size_t len, bool is_debug)
pcercuei 0:df031b60ca29 398 {
pcercuei 0:df031b60ca29 399 struct iio_context_pdata *pdata = client->pdata;
pcercuei 0:df031b60ca29 400 const struct iiod_client_ops *ops = client->ops;
pcercuei 0:df031b60ca29 401 const char *id = iio_device_get_id(dev);
pcercuei 0:df031b60ca29 402 char buf[1024];
pcercuei 0:df031b60ca29 403 ssize_t ret;
pcercuei 0:df031b60ca29 404 int resp;
pcercuei 0:df031b60ca29 405
pcercuei 0:df031b60ca29 406 if (attr) {
pcercuei 0:df031b60ca29 407 if (chn) {
pcercuei 0:df031b60ca29 408 if (!iio_channel_find_attr(chn, attr))
pcercuei 0:df031b60ca29 409 return -ENOENT;
pcercuei 0:df031b60ca29 410 } else if (is_debug) {
pcercuei 0:df031b60ca29 411 if (!iio_device_find_debug_attr(dev, attr))
pcercuei 0:df031b60ca29 412 return -ENOENT;
pcercuei 0:df031b60ca29 413 } else {
pcercuei 0:df031b60ca29 414 if (!iio_device_find_attr(dev, attr))
pcercuei 0:df031b60ca29 415 return -ENOENT;
pcercuei 0:df031b60ca29 416 }
pcercuei 0:df031b60ca29 417 }
pcercuei 0:df031b60ca29 418
pcercuei 3:d147beabba0e 419 if (chn) {
pcercuei 3:d147beabba0e 420 iio_snprintf(buf, sizeof(buf), "WRITE %s %s %s %s %lu\r\n", id,
pcercuei 0:df031b60ca29 421 iio_channel_is_output(chn) ? "OUTPUT" : "INPUT",
pcercuei 0:df031b60ca29 422 iio_channel_get_id(chn), attr ? attr : "",
pcercuei 0:df031b60ca29 423 (unsigned long) len);
pcercuei 3:d147beabba0e 424 } else if (is_debug) {
pcercuei 3:d147beabba0e 425 iio_snprintf(buf, sizeof(buf), "WRITE %s DEBUG %s %lu\r\n",
pcercuei 0:df031b60ca29 426 id, attr ? attr : "", (unsigned long) len);
pcercuei 3:d147beabba0e 427 } else {
pcercuei 3:d147beabba0e 428 iio_snprintf(buf, sizeof(buf), "WRITE %s %s %lu\r\n",
pcercuei 0:df031b60ca29 429 id, attr ? attr : "", (unsigned long) len);
pcercuei 3:d147beabba0e 430 }
pcercuei 0:df031b60ca29 431
pcercuei 0:df031b60ca29 432 iio_mutex_lock(client->lock);
pcercuei 0:df031b60ca29 433 ret = ops->write(pdata, desc, buf, strlen(buf));
pcercuei 0:df031b60ca29 434 if (ret < 0)
pcercuei 0:df031b60ca29 435 goto out_unlock;
pcercuei 0:df031b60ca29 436
pcercuei 0:df031b60ca29 437 ret = iiod_client_write_all(client, desc, src, len);
pcercuei 0:df031b60ca29 438 if (ret < 0)
pcercuei 0:df031b60ca29 439 goto out_unlock;
pcercuei 0:df031b60ca29 440
pcercuei 0:df031b60ca29 441 ret = iiod_client_read_integer(client, desc, &resp);
pcercuei 0:df031b60ca29 442 if (ret < 0)
pcercuei 0:df031b60ca29 443 goto out_unlock;
pcercuei 0:df031b60ca29 444
pcercuei 0:df031b60ca29 445 ret = (ssize_t) resp;
pcercuei 0:df031b60ca29 446
pcercuei 0:df031b60ca29 447 out_unlock:
pcercuei 0:df031b60ca29 448 iio_mutex_unlock(client->lock);
pcercuei 0:df031b60ca29 449 return ret;
pcercuei 0:df031b60ca29 450 }
pcercuei 0:df031b60ca29 451
pcercuei 0:df031b60ca29 452 struct iio_context * iiod_client_create_context(
pcercuei 0:df031b60ca29 453 struct iiod_client *client, void *desc)
pcercuei 0:df031b60ca29 454 {
pcercuei 0:df031b60ca29 455 struct iio_context *ctx = NULL;
pcercuei 0:df031b60ca29 456 size_t xml_len;
pcercuei 0:df031b60ca29 457 char *xml;
pcercuei 0:df031b60ca29 458 int ret;
pcercuei 0:df031b60ca29 459
pcercuei 0:df031b60ca29 460 iio_mutex_lock(client->lock);
pcercuei 0:df031b60ca29 461 ret = iiod_client_exec_command(client, desc, "PRINT\r\n");
pcercuei 0:df031b60ca29 462 if (ret < 0)
pcercuei 0:df031b60ca29 463 goto out_unlock;
pcercuei 0:df031b60ca29 464
pcercuei 0:df031b60ca29 465 xml_len = (size_t) ret;
pcercuei 0:df031b60ca29 466 xml = malloc(xml_len + 1);
pcercuei 0:df031b60ca29 467 if (!xml) {
pcercuei 0:df031b60ca29 468 ret = -ENOMEM;
pcercuei 0:df031b60ca29 469 goto out_unlock;
pcercuei 0:df031b60ca29 470 }
pcercuei 0:df031b60ca29 471
pcercuei 0:df031b60ca29 472 /* +1: Also read the trailing \n */
pcercuei 0:df031b60ca29 473 ret = (int) iiod_client_read_all(client, desc, xml, xml_len + 1);
pcercuei 0:df031b60ca29 474 if (ret < 0)
pcercuei 0:df031b60ca29 475 goto out_free_xml;
pcercuei 0:df031b60ca29 476
pcercuei 0:df031b60ca29 477 ctx = iio_create_xml_context_mem(xml, xml_len);
pcercuei 0:df031b60ca29 478 if (!ctx)
pcercuei 0:df031b60ca29 479 ret = -errno;
pcercuei 0:df031b60ca29 480
pcercuei 0:df031b60ca29 481 out_free_xml:
pcercuei 0:df031b60ca29 482 free(xml);
pcercuei 0:df031b60ca29 483 out_unlock:
pcercuei 0:df031b60ca29 484 iio_mutex_unlock(client->lock);
pcercuei 0:df031b60ca29 485 if (!ctx)
pcercuei 0:df031b60ca29 486 errno = -ret;
pcercuei 0:df031b60ca29 487 return ctx;
pcercuei 0:df031b60ca29 488 }
pcercuei 0:df031b60ca29 489
pcercuei 0:df031b60ca29 490 int iiod_client_open_unlocked(struct iiod_client *client, void *desc,
pcercuei 0:df031b60ca29 491 const struct iio_device *dev, size_t samples_count, bool cyclic)
pcercuei 0:df031b60ca29 492 {
pcercuei 0:df031b60ca29 493 char buf[1024], *ptr;
pcercuei 0:df031b60ca29 494 size_t i;
pcercuei 0:df031b60ca29 495
pcercuei 3:d147beabba0e 496 iio_snprintf(buf, sizeof(buf), "OPEN %s %lu ",
pcercuei 0:df031b60ca29 497 iio_device_get_id(dev), (unsigned long) samples_count);
pcercuei 0:df031b60ca29 498 ptr = buf + strlen(buf);
pcercuei 0:df031b60ca29 499
pcercuei 3:d147beabba0e 500 for (i = dev->words; i > 0; i--, ptr += 8) {
pcercuei 3:d147beabba0e 501 iio_snprintf(ptr, (ptr - buf) + i * 8, "%08" PRIx32,
pcercuei 0:df031b60ca29 502 dev->mask[i - 1]);
pcercuei 3:d147beabba0e 503 }
pcercuei 0:df031b60ca29 504
pcercuei 0:df031b60ca29 505 strcpy(ptr, cyclic ? " CYCLIC\r\n" : "\r\n");
pcercuei 0:df031b60ca29 506
pcercuei 0:df031b60ca29 507 return iiod_client_exec_command(client, desc, buf);
pcercuei 0:df031b60ca29 508 }
pcercuei 0:df031b60ca29 509
pcercuei 0:df031b60ca29 510 int iiod_client_close_unlocked(struct iiod_client *client, void *desc,
pcercuei 0:df031b60ca29 511 const struct iio_device *dev)
pcercuei 0:df031b60ca29 512 {
pcercuei 0:df031b60ca29 513 char buf[1024];
pcercuei 0:df031b60ca29 514
pcercuei 3:d147beabba0e 515 iio_snprintf(buf, sizeof(buf), "CLOSE %s\r\n", iio_device_get_id(dev));
pcercuei 0:df031b60ca29 516 return iiod_client_exec_command(client, desc, buf);
pcercuei 0:df031b60ca29 517 }
pcercuei 0:df031b60ca29 518
pcercuei 0:df031b60ca29 519 static int iiod_client_read_mask(struct iiod_client *client,
pcercuei 0:df031b60ca29 520 void *desc, uint32_t *mask, size_t words)
pcercuei 0:df031b60ca29 521 {
pcercuei 0:df031b60ca29 522 size_t i;
pcercuei 0:df031b60ca29 523 ssize_t ret;
pcercuei 0:df031b60ca29 524 char *buf, *ptr;
pcercuei 0:df031b60ca29 525
pcercuei 0:df031b60ca29 526 buf = malloc(words * 8 + 1);
pcercuei 0:df031b60ca29 527 if (!buf)
pcercuei 0:df031b60ca29 528 return -ENOMEM;
pcercuei 0:df031b60ca29 529
pcercuei 0:df031b60ca29 530 ret = iiod_client_read_all(client, desc, buf, words * 8 + 1);
pcercuei 0:df031b60ca29 531 if (ret < 0)
pcercuei 0:df031b60ca29 532 goto out_buf_free;
pcercuei 0:df031b60ca29 533 else
pcercuei 0:df031b60ca29 534 ret = 0;
pcercuei 0:df031b60ca29 535
pcercuei 0:df031b60ca29 536 buf[words*8] = '\0';
pcercuei 0:df031b60ca29 537
pcercuei 0:df031b60ca29 538 DEBUG("Reading mask\n");
pcercuei 0:df031b60ca29 539
pcercuei 0:df031b60ca29 540 for (i = words, ptr = buf; i > 0; i--) {
pcercuei 0:df031b60ca29 541 sscanf(ptr, "%08" PRIx32, &mask[i - 1]);
pcercuei 0:df031b60ca29 542 DEBUG("mask[%lu] = 0x%08" PRIx32 "\n",
pcercuei 0:df031b60ca29 543 (unsigned long)(i - 1), mask[i - 1]);
pcercuei 0:df031b60ca29 544
pcercuei 0:df031b60ca29 545 ptr = (char *) ((uintptr_t) ptr + 8);
pcercuei 0:df031b60ca29 546 }
pcercuei 0:df031b60ca29 547
pcercuei 0:df031b60ca29 548 out_buf_free:
pcercuei 0:df031b60ca29 549 free(buf);
pcercuei 0:df031b60ca29 550 return (int) ret;
pcercuei 0:df031b60ca29 551 }
pcercuei 0:df031b60ca29 552
pcercuei 0:df031b60ca29 553 ssize_t iiod_client_read_unlocked(struct iiod_client *client, void *desc,
pcercuei 0:df031b60ca29 554 const struct iio_device *dev, void *dst, size_t len,
pcercuei 0:df031b60ca29 555 uint32_t *mask, size_t words)
pcercuei 0:df031b60ca29 556 {
pcercuei 0:df031b60ca29 557 unsigned int nb_channels = iio_device_get_channels_count(dev);
pcercuei 0:df031b60ca29 558 uintptr_t ptr = (uintptr_t) dst;
pcercuei 0:df031b60ca29 559 char buf[1024];
pcercuei 0:df031b60ca29 560 ssize_t ret, read = 0;
pcercuei 0:df031b60ca29 561
pcercuei 0:df031b60ca29 562 if (!len || words != (nb_channels + 31) / 32)
pcercuei 0:df031b60ca29 563 return -EINVAL;
pcercuei 0:df031b60ca29 564
pcercuei 3:d147beabba0e 565 iio_snprintf(buf, sizeof(buf), "READBUF %s %lu\r\n",
pcercuei 0:df031b60ca29 566 iio_device_get_id(dev), (unsigned long) len);
pcercuei 0:df031b60ca29 567
pcercuei 0:df031b60ca29 568 ret = iiod_client_write_all(client, desc, buf, strlen(buf));
pcercuei 0:df031b60ca29 569 if (ret < 0)
pcercuei 0:df031b60ca29 570 return ret;
pcercuei 0:df031b60ca29 571
pcercuei 0:df031b60ca29 572 do {
pcercuei 0:df031b60ca29 573 int to_read;
pcercuei 0:df031b60ca29 574
pcercuei 0:df031b60ca29 575 ret = iiod_client_read_integer(client, desc, &to_read);
pcercuei 0:df031b60ca29 576 if (ret < 0)
pcercuei 0:df031b60ca29 577 return ret;
pcercuei 0:df031b60ca29 578 if (to_read < 0)
pcercuei 0:df031b60ca29 579 return (ssize_t) to_read;
pcercuei 0:df031b60ca29 580 if (!to_read)
pcercuei 0:df031b60ca29 581 break;
pcercuei 0:df031b60ca29 582
pcercuei 0:df031b60ca29 583 if (mask) {
pcercuei 0:df031b60ca29 584 ret = iiod_client_read_mask(client, desc, mask, words);
pcercuei 0:df031b60ca29 585 if (ret < 0)
pcercuei 0:df031b60ca29 586 return ret;
pcercuei 0:df031b60ca29 587
pcercuei 0:df031b60ca29 588 mask = NULL; /* We read the mask only once */
pcercuei 0:df031b60ca29 589 }
pcercuei 0:df031b60ca29 590
pcercuei 0:df031b60ca29 591 ret = iiod_client_read_all(client, desc, (char *) ptr, to_read);
pcercuei 0:df031b60ca29 592 if (ret < 0)
pcercuei 0:df031b60ca29 593 return ret;
pcercuei 0:df031b60ca29 594
pcercuei 0:df031b60ca29 595 ptr += ret;
pcercuei 0:df031b60ca29 596 read += ret;
pcercuei 0:df031b60ca29 597 len -= ret;
pcercuei 0:df031b60ca29 598 } while (len);
pcercuei 0:df031b60ca29 599
pcercuei 0:df031b60ca29 600 return read;
pcercuei 0:df031b60ca29 601 }
pcercuei 0:df031b60ca29 602
pcercuei 0:df031b60ca29 603 ssize_t iiod_client_write_unlocked(struct iiod_client *client, void *desc,
pcercuei 0:df031b60ca29 604 const struct iio_device *dev, const void *src, size_t len)
pcercuei 0:df031b60ca29 605 {
pcercuei 0:df031b60ca29 606 ssize_t ret;
pcercuei 0:df031b60ca29 607 char buf[1024];
pcercuei 0:df031b60ca29 608 int val;
pcercuei 0:df031b60ca29 609
pcercuei 3:d147beabba0e 610 iio_snprintf(buf, sizeof(buf), "WRITEBUF %s %lu\r\n",
pcercuei 0:df031b60ca29 611 dev->id, (unsigned long) len);
pcercuei 0:df031b60ca29 612
pcercuei 0:df031b60ca29 613 ret = iiod_client_write_all(client, desc, buf, strlen(buf));
pcercuei 0:df031b60ca29 614 if (ret < 0)
pcercuei 0:df031b60ca29 615 return ret;
pcercuei 0:df031b60ca29 616
pcercuei 0:df031b60ca29 617 ret = iiod_client_read_integer(client, desc, &val);
pcercuei 0:df031b60ca29 618 if (ret < 0)
pcercuei 0:df031b60ca29 619 return ret;
pcercuei 0:df031b60ca29 620 if (val < 0)
pcercuei 0:df031b60ca29 621 return (ssize_t) val;
pcercuei 0:df031b60ca29 622
pcercuei 0:df031b60ca29 623 ret = iiod_client_write_all(client, desc, src, len);
pcercuei 0:df031b60ca29 624 if (ret < 0)
pcercuei 0:df031b60ca29 625 return ret;
pcercuei 0:df031b60ca29 626
pcercuei 0:df031b60ca29 627 ret = iiod_client_read_integer(client, desc, &val);
pcercuei 0:df031b60ca29 628 if (ret < 0)
pcercuei 0:df031b60ca29 629 return ret;
pcercuei 0:df031b60ca29 630 if (val < 0)
pcercuei 0:df031b60ca29 631 return (ssize_t) val;
pcercuei 0:df031b60ca29 632
pcercuei 0:df031b60ca29 633 return (ssize_t) len;
pcercuei 0:df031b60ca29 634 }
pcercuei 0:df031b60ca29 635