Paul Cercueil / libiio

Dependencies:   libserialport libxml2

Committer:
pcercuei
Date:
Tue Sep 20 15:34:31 2016 +0000
Revision:
2:9eb0a9a1f958
Parent:
0:df031b60ca29
Child:
3:d147beabba0e
Update latest libiio master (git tag 6d1923f)

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 0:df031b60ca29 216 snprintf(buf, sizeof(buf), "GETTRIG %s\r\n", iio_device_get_id(dev));
pcercuei 0:df031b60ca29 217
pcercuei 0:df031b60ca29 218 iio_mutex_lock(client->lock);
pcercuei 0:df031b60ca29 219 ret = iiod_client_exec_command(client, desc, buf);
pcercuei 0:df031b60ca29 220
pcercuei 0:df031b60ca29 221 if (ret == 0)
pcercuei 0:df031b60ca29 222 *trigger = NULL;
pcercuei 0:df031b60ca29 223 if (ret <= 0)
pcercuei 0:df031b60ca29 224 goto out_unlock;
pcercuei 0:df031b60ca29 225
pcercuei 0:df031b60ca29 226 if ((unsigned int) ret > sizeof(buf) - 1) {
pcercuei 0:df031b60ca29 227 ret = -EIO;
pcercuei 0:df031b60ca29 228 goto out_unlock;
pcercuei 0:df031b60ca29 229 }
pcercuei 0:df031b60ca29 230
pcercuei 0:df031b60ca29 231 name_len = ret;
pcercuei 0:df031b60ca29 232
pcercuei 0:df031b60ca29 233 ret = (int) iiod_client_read_all(client, desc, buf, name_len + 1);
pcercuei 0:df031b60ca29 234 if (ret < 0)
pcercuei 0:df031b60ca29 235 goto out_unlock;
pcercuei 0:df031b60ca29 236
pcercuei 0:df031b60ca29 237 ret = -ENXIO;
pcercuei 0:df031b60ca29 238
pcercuei 0:df031b60ca29 239 for (i = 0; i < nb_devices; i++) {
pcercuei 0:df031b60ca29 240 struct iio_device *cur = iio_context_get_device(ctx, i);
pcercuei 0:df031b60ca29 241
pcercuei 0:df031b60ca29 242 if (iio_device_is_trigger(cur)) {
pcercuei 0:df031b60ca29 243 const char *name = iio_device_get_name(cur);
pcercuei 0:df031b60ca29 244
pcercuei 0:df031b60ca29 245 if (!name)
pcercuei 0:df031b60ca29 246 continue;
pcercuei 0:df031b60ca29 247
pcercuei 0:df031b60ca29 248 if (!strncmp(name, buf, name_len)) {
pcercuei 0:df031b60ca29 249 *trigger = cur;
pcercuei 0:df031b60ca29 250 ret = 0;
pcercuei 0:df031b60ca29 251 goto out_unlock;
pcercuei 0:df031b60ca29 252 }
pcercuei 0:df031b60ca29 253 }
pcercuei 0:df031b60ca29 254 }
pcercuei 0:df031b60ca29 255
pcercuei 0:df031b60ca29 256 out_unlock:
pcercuei 0:df031b60ca29 257 iio_mutex_unlock(client->lock);
pcercuei 0:df031b60ca29 258 return ret;
pcercuei 0:df031b60ca29 259 }
pcercuei 0:df031b60ca29 260
pcercuei 0:df031b60ca29 261 int iiod_client_set_trigger(struct iiod_client *client, void *desc,
pcercuei 0:df031b60ca29 262 const struct iio_device *dev, const struct iio_device *trigger)
pcercuei 0:df031b60ca29 263 {
pcercuei 0:df031b60ca29 264 char buf[1024];
pcercuei 0:df031b60ca29 265 int ret;
pcercuei 0:df031b60ca29 266
pcercuei 0:df031b60ca29 267 if (trigger)
pcercuei 0:df031b60ca29 268 snprintf(buf, sizeof(buf), "SETTRIG %s %s\r\n",
pcercuei 0:df031b60ca29 269 iio_device_get_id(dev),
pcercuei 0:df031b60ca29 270 iio_device_get_id(trigger));
pcercuei 0:df031b60ca29 271 else
pcercuei 0:df031b60ca29 272 snprintf(buf, sizeof(buf), "SETTRIG %s\r\n",
pcercuei 0:df031b60ca29 273 iio_device_get_id(dev));
pcercuei 0:df031b60ca29 274
pcercuei 0:df031b60ca29 275 iio_mutex_lock(client->lock);
pcercuei 0:df031b60ca29 276 ret = iiod_client_exec_command(client, desc, buf);
pcercuei 0:df031b60ca29 277 iio_mutex_unlock(client->lock);
pcercuei 0:df031b60ca29 278 return ret;
pcercuei 0:df031b60ca29 279 }
pcercuei 0:df031b60ca29 280
pcercuei 0:df031b60ca29 281 int iiod_client_set_kernel_buffers_count(struct iiod_client *client, void *desc,
pcercuei 0:df031b60ca29 282 const struct iio_device *dev, unsigned int nb_blocks)
pcercuei 0:df031b60ca29 283 {
pcercuei 0:df031b60ca29 284 int ret;
pcercuei 0:df031b60ca29 285 char buf[1024];
pcercuei 0:df031b60ca29 286
pcercuei 0:df031b60ca29 287 snprintf(buf, sizeof(buf), "SET %s BUFFERS_COUNT %u\r\n",
pcercuei 0:df031b60ca29 288 iio_device_get_id(dev), nb_blocks);
pcercuei 0:df031b60ca29 289
pcercuei 0:df031b60ca29 290 iio_mutex_lock(client->lock);
pcercuei 0:df031b60ca29 291 ret = iiod_client_exec_command(client, desc, buf);
pcercuei 0:df031b60ca29 292 iio_mutex_unlock(client->lock);
pcercuei 0:df031b60ca29 293 return ret;
pcercuei 0:df031b60ca29 294 }
pcercuei 0:df031b60ca29 295
pcercuei 0:df031b60ca29 296 int iiod_client_set_timeout(struct iiod_client *client,
pcercuei 0:df031b60ca29 297 void *desc, unsigned int timeout)
pcercuei 0:df031b60ca29 298 {
pcercuei 0:df031b60ca29 299 int ret;
pcercuei 0:df031b60ca29 300 char buf[1024];
pcercuei 0:df031b60ca29 301
pcercuei 0:df031b60ca29 302 snprintf(buf, sizeof(buf), "TIMEOUT %u\r\n", timeout);
pcercuei 0:df031b60ca29 303
pcercuei 0:df031b60ca29 304 iio_mutex_lock(client->lock);
pcercuei 0:df031b60ca29 305 ret = iiod_client_exec_command(client, desc, buf);
pcercuei 0:df031b60ca29 306 iio_mutex_unlock(client->lock);
pcercuei 0:df031b60ca29 307 return ret;
pcercuei 0:df031b60ca29 308 }
pcercuei 0:df031b60ca29 309
pcercuei 0:df031b60ca29 310 ssize_t iiod_client_read_attr(struct iiod_client *client, void *desc,
pcercuei 0:df031b60ca29 311 const struct iio_device *dev, const struct iio_channel *chn,
pcercuei 0:df031b60ca29 312 const char *attr, char *dest, size_t len, bool is_debug)
pcercuei 0:df031b60ca29 313 {
pcercuei 0:df031b60ca29 314 const char *id = iio_device_get_id(dev);
pcercuei 0:df031b60ca29 315 char buf[1024];
pcercuei 0:df031b60ca29 316 ssize_t ret;
pcercuei 0:df031b60ca29 317
pcercuei 0:df031b60ca29 318 if (attr) {
pcercuei 0:df031b60ca29 319 if (chn) {
pcercuei 0:df031b60ca29 320 if (!iio_channel_find_attr(chn, attr))
pcercuei 0:df031b60ca29 321 return -ENOENT;
pcercuei 0:df031b60ca29 322 } else if (is_debug) {
pcercuei 0:df031b60ca29 323 if (!iio_device_find_debug_attr(dev, attr))
pcercuei 0:df031b60ca29 324 return -ENOENT;
pcercuei 0:df031b60ca29 325 } else {
pcercuei 0:df031b60ca29 326 if (!iio_device_find_attr(dev, attr))
pcercuei 0:df031b60ca29 327 return -ENOENT;
pcercuei 0:df031b60ca29 328 }
pcercuei 0:df031b60ca29 329 }
pcercuei 0:df031b60ca29 330
pcercuei 0:df031b60ca29 331 if (chn)
pcercuei 0:df031b60ca29 332 snprintf(buf, sizeof(buf), "READ %s %s %s %s\r\n", id,
pcercuei 0:df031b60ca29 333 iio_channel_is_output(chn) ? "OUTPUT" : "INPUT",
pcercuei 0:df031b60ca29 334 iio_channel_get_id(chn), attr ? attr : "");
pcercuei 0:df031b60ca29 335 else if (is_debug)
pcercuei 0:df031b60ca29 336 snprintf(buf, sizeof(buf), "READ %s DEBUG %s\r\n",
pcercuei 0:df031b60ca29 337 id, attr ? attr : "");
pcercuei 0:df031b60ca29 338 else
pcercuei 0:df031b60ca29 339 snprintf(buf, sizeof(buf), "READ %s %s\r\n",
pcercuei 0:df031b60ca29 340 id, attr ? attr : "");
pcercuei 0:df031b60ca29 341
pcercuei 0:df031b60ca29 342 iio_mutex_lock(client->lock);
pcercuei 0:df031b60ca29 343
pcercuei 0:df031b60ca29 344 ret = (ssize_t) iiod_client_exec_command(client, desc, buf);
pcercuei 0:df031b60ca29 345 if (ret < 0)
pcercuei 0:df031b60ca29 346 goto out_unlock;
pcercuei 0:df031b60ca29 347
pcercuei 0:df031b60ca29 348 if ((size_t) ret + 1 > len) {
pcercuei 0:df031b60ca29 349 ret = -EIO;
pcercuei 0:df031b60ca29 350 goto out_unlock;
pcercuei 0:df031b60ca29 351 }
pcercuei 0:df031b60ca29 352
pcercuei 0:df031b60ca29 353 /* +1: Also read the trailing \n */
pcercuei 0:df031b60ca29 354 ret = iiod_client_read_all(client, desc, dest, ret + 1);
pcercuei 0:df031b60ca29 355
pcercuei 0:df031b60ca29 356 if (ret > 0) {
pcercuei 0:df031b60ca29 357 /* Discard the trailing \n */
pcercuei 0:df031b60ca29 358 ret--;
pcercuei 0:df031b60ca29 359
pcercuei 0:df031b60ca29 360 /* Replace it with a \0 just in case */
pcercuei 0:df031b60ca29 361 dest[ret] = '\0';
pcercuei 0:df031b60ca29 362 }
pcercuei 0:df031b60ca29 363
pcercuei 0:df031b60ca29 364 out_unlock:
pcercuei 0:df031b60ca29 365 iio_mutex_unlock(client->lock);
pcercuei 0:df031b60ca29 366 return ret;
pcercuei 0:df031b60ca29 367 }
pcercuei 0:df031b60ca29 368
pcercuei 0:df031b60ca29 369 ssize_t iiod_client_write_attr(struct iiod_client *client, void *desc,
pcercuei 0:df031b60ca29 370 const struct iio_device *dev, const struct iio_channel *chn,
pcercuei 0:df031b60ca29 371 const char *attr, const char *src, size_t len, bool is_debug)
pcercuei 0:df031b60ca29 372 {
pcercuei 0:df031b60ca29 373 struct iio_context_pdata *pdata = client->pdata;
pcercuei 0:df031b60ca29 374 const struct iiod_client_ops *ops = client->ops;
pcercuei 0:df031b60ca29 375 const char *id = iio_device_get_id(dev);
pcercuei 0:df031b60ca29 376 char buf[1024];
pcercuei 0:df031b60ca29 377 ssize_t ret;
pcercuei 0:df031b60ca29 378 int resp;
pcercuei 0:df031b60ca29 379
pcercuei 0:df031b60ca29 380 if (attr) {
pcercuei 0:df031b60ca29 381 if (chn) {
pcercuei 0:df031b60ca29 382 if (!iio_channel_find_attr(chn, attr))
pcercuei 0:df031b60ca29 383 return -ENOENT;
pcercuei 0:df031b60ca29 384 } else if (is_debug) {
pcercuei 0:df031b60ca29 385 if (!iio_device_find_debug_attr(dev, attr))
pcercuei 0:df031b60ca29 386 return -ENOENT;
pcercuei 0:df031b60ca29 387 } else {
pcercuei 0:df031b60ca29 388 if (!iio_device_find_attr(dev, attr))
pcercuei 0:df031b60ca29 389 return -ENOENT;
pcercuei 0:df031b60ca29 390 }
pcercuei 0:df031b60ca29 391 }
pcercuei 0:df031b60ca29 392
pcercuei 0:df031b60ca29 393 if (chn)
pcercuei 0:df031b60ca29 394 snprintf(buf, sizeof(buf), "WRITE %s %s %s %s %lu\r\n", id,
pcercuei 0:df031b60ca29 395 iio_channel_is_output(chn) ? "OUTPUT" : "INPUT",
pcercuei 0:df031b60ca29 396 iio_channel_get_id(chn), attr ? attr : "",
pcercuei 0:df031b60ca29 397 (unsigned long) len);
pcercuei 0:df031b60ca29 398 else if (is_debug)
pcercuei 0:df031b60ca29 399 snprintf(buf, sizeof(buf), "WRITE %s DEBUG %s %lu\r\n",
pcercuei 0:df031b60ca29 400 id, attr ? attr : "", (unsigned long) len);
pcercuei 0:df031b60ca29 401 else
pcercuei 0:df031b60ca29 402 snprintf(buf, sizeof(buf), "WRITE %s %s %lu\r\n",
pcercuei 0:df031b60ca29 403 id, attr ? attr : "", (unsigned long) len);
pcercuei 0:df031b60ca29 404
pcercuei 0:df031b60ca29 405 iio_mutex_lock(client->lock);
pcercuei 0:df031b60ca29 406 ret = ops->write(pdata, desc, buf, strlen(buf));
pcercuei 0:df031b60ca29 407 if (ret < 0)
pcercuei 0:df031b60ca29 408 goto out_unlock;
pcercuei 0:df031b60ca29 409
pcercuei 0:df031b60ca29 410 ret = iiod_client_write_all(client, desc, src, len);
pcercuei 0:df031b60ca29 411 if (ret < 0)
pcercuei 0:df031b60ca29 412 goto out_unlock;
pcercuei 0:df031b60ca29 413
pcercuei 0:df031b60ca29 414 ret = iiod_client_read_integer(client, desc, &resp);
pcercuei 0:df031b60ca29 415 if (ret < 0)
pcercuei 0:df031b60ca29 416 goto out_unlock;
pcercuei 0:df031b60ca29 417
pcercuei 0:df031b60ca29 418 ret = (ssize_t) resp;
pcercuei 0:df031b60ca29 419
pcercuei 0:df031b60ca29 420 out_unlock:
pcercuei 0:df031b60ca29 421 iio_mutex_unlock(client->lock);
pcercuei 0:df031b60ca29 422 return ret;
pcercuei 0:df031b60ca29 423 }
pcercuei 0:df031b60ca29 424
pcercuei 0:df031b60ca29 425 struct iio_context * iiod_client_create_context(
pcercuei 0:df031b60ca29 426 struct iiod_client *client, void *desc)
pcercuei 0:df031b60ca29 427 {
pcercuei 0:df031b60ca29 428 struct iio_context *ctx = NULL;
pcercuei 0:df031b60ca29 429 size_t xml_len;
pcercuei 0:df031b60ca29 430 char *xml;
pcercuei 0:df031b60ca29 431 int ret;
pcercuei 0:df031b60ca29 432
pcercuei 0:df031b60ca29 433 iio_mutex_lock(client->lock);
pcercuei 0:df031b60ca29 434 ret = iiod_client_exec_command(client, desc, "PRINT\r\n");
pcercuei 0:df031b60ca29 435 if (ret < 0)
pcercuei 0:df031b60ca29 436 goto out_unlock;
pcercuei 0:df031b60ca29 437
pcercuei 0:df031b60ca29 438 xml_len = (size_t) ret;
pcercuei 0:df031b60ca29 439 xml = malloc(xml_len + 1);
pcercuei 0:df031b60ca29 440 if (!xml) {
pcercuei 0:df031b60ca29 441 ret = -ENOMEM;
pcercuei 0:df031b60ca29 442 goto out_unlock;
pcercuei 0:df031b60ca29 443 }
pcercuei 0:df031b60ca29 444
pcercuei 0:df031b60ca29 445 /* +1: Also read the trailing \n */
pcercuei 0:df031b60ca29 446 ret = (int) iiod_client_read_all(client, desc, xml, xml_len + 1);
pcercuei 0:df031b60ca29 447 if (ret < 0)
pcercuei 0:df031b60ca29 448 goto out_free_xml;
pcercuei 0:df031b60ca29 449
pcercuei 0:df031b60ca29 450 ctx = iio_create_xml_context_mem(xml, xml_len);
pcercuei 0:df031b60ca29 451 if (!ctx)
pcercuei 0:df031b60ca29 452 ret = -errno;
pcercuei 0:df031b60ca29 453
pcercuei 0:df031b60ca29 454 out_free_xml:
pcercuei 0:df031b60ca29 455 free(xml);
pcercuei 0:df031b60ca29 456 out_unlock:
pcercuei 0:df031b60ca29 457 iio_mutex_unlock(client->lock);
pcercuei 0:df031b60ca29 458 if (!ctx)
pcercuei 0:df031b60ca29 459 errno = -ret;
pcercuei 0:df031b60ca29 460 return ctx;
pcercuei 0:df031b60ca29 461 }
pcercuei 0:df031b60ca29 462
pcercuei 0:df031b60ca29 463 int iiod_client_open_unlocked(struct iiod_client *client, void *desc,
pcercuei 0:df031b60ca29 464 const struct iio_device *dev, size_t samples_count, bool cyclic)
pcercuei 0:df031b60ca29 465 {
pcercuei 0:df031b60ca29 466 char buf[1024], *ptr;
pcercuei 0:df031b60ca29 467 size_t i;
pcercuei 0:df031b60ca29 468
pcercuei 0:df031b60ca29 469 snprintf(buf, sizeof(buf), "OPEN %s %lu ",
pcercuei 0:df031b60ca29 470 iio_device_get_id(dev), (unsigned long) samples_count);
pcercuei 0:df031b60ca29 471 ptr = buf + strlen(buf);
pcercuei 0:df031b60ca29 472
pcercuei 0:df031b60ca29 473 for (i = dev->words; i > 0; i--, ptr += 8)
pcercuei 0:df031b60ca29 474 snprintf(ptr, (ptr - buf) + i * 8, "%08" PRIx32,
pcercuei 0:df031b60ca29 475 dev->mask[i - 1]);
pcercuei 0:df031b60ca29 476
pcercuei 0:df031b60ca29 477 strcpy(ptr, cyclic ? " CYCLIC\r\n" : "\r\n");
pcercuei 0:df031b60ca29 478
pcercuei 0:df031b60ca29 479 return iiod_client_exec_command(client, desc, buf);
pcercuei 0:df031b60ca29 480 }
pcercuei 0:df031b60ca29 481
pcercuei 0:df031b60ca29 482 int iiod_client_close_unlocked(struct iiod_client *client, void *desc,
pcercuei 0:df031b60ca29 483 const struct iio_device *dev)
pcercuei 0:df031b60ca29 484 {
pcercuei 0:df031b60ca29 485 char buf[1024];
pcercuei 0:df031b60ca29 486
pcercuei 0:df031b60ca29 487 snprintf(buf, sizeof(buf), "CLOSE %s\r\n", iio_device_get_id(dev));
pcercuei 0:df031b60ca29 488 return iiod_client_exec_command(client, desc, buf);
pcercuei 0:df031b60ca29 489 }
pcercuei 0:df031b60ca29 490
pcercuei 0:df031b60ca29 491 static int iiod_client_read_mask(struct iiod_client *client,
pcercuei 0:df031b60ca29 492 void *desc, uint32_t *mask, size_t words)
pcercuei 0:df031b60ca29 493 {
pcercuei 0:df031b60ca29 494 size_t i;
pcercuei 0:df031b60ca29 495 ssize_t ret;
pcercuei 0:df031b60ca29 496 char *buf, *ptr;
pcercuei 0:df031b60ca29 497
pcercuei 0:df031b60ca29 498 buf = malloc(words * 8 + 1);
pcercuei 0:df031b60ca29 499 if (!buf)
pcercuei 0:df031b60ca29 500 return -ENOMEM;
pcercuei 0:df031b60ca29 501
pcercuei 0:df031b60ca29 502 ret = iiod_client_read_all(client, desc, buf, words * 8 + 1);
pcercuei 0:df031b60ca29 503 if (ret < 0)
pcercuei 0:df031b60ca29 504 goto out_buf_free;
pcercuei 0:df031b60ca29 505 else
pcercuei 0:df031b60ca29 506 ret = 0;
pcercuei 0:df031b60ca29 507
pcercuei 0:df031b60ca29 508 buf[words*8] = '\0';
pcercuei 0:df031b60ca29 509
pcercuei 0:df031b60ca29 510 DEBUG("Reading mask\n");
pcercuei 0:df031b60ca29 511
pcercuei 0:df031b60ca29 512 for (i = words, ptr = buf; i > 0; i--) {
pcercuei 0:df031b60ca29 513 sscanf(ptr, "%08" PRIx32, &mask[i - 1]);
pcercuei 0:df031b60ca29 514 DEBUG("mask[%lu] = 0x%08" PRIx32 "\n",
pcercuei 0:df031b60ca29 515 (unsigned long)(i - 1), mask[i - 1]);
pcercuei 0:df031b60ca29 516
pcercuei 0:df031b60ca29 517 ptr = (char *) ((uintptr_t) ptr + 8);
pcercuei 0:df031b60ca29 518 }
pcercuei 0:df031b60ca29 519
pcercuei 0:df031b60ca29 520 out_buf_free:
pcercuei 0:df031b60ca29 521 free(buf);
pcercuei 0:df031b60ca29 522 return (int) ret;
pcercuei 0:df031b60ca29 523 }
pcercuei 0:df031b60ca29 524
pcercuei 0:df031b60ca29 525 ssize_t iiod_client_read_unlocked(struct iiod_client *client, void *desc,
pcercuei 0:df031b60ca29 526 const struct iio_device *dev, void *dst, size_t len,
pcercuei 0:df031b60ca29 527 uint32_t *mask, size_t words)
pcercuei 0:df031b60ca29 528 {
pcercuei 0:df031b60ca29 529 unsigned int nb_channels = iio_device_get_channels_count(dev);
pcercuei 0:df031b60ca29 530 uintptr_t ptr = (uintptr_t) dst;
pcercuei 0:df031b60ca29 531 char buf[1024];
pcercuei 0:df031b60ca29 532 ssize_t ret, read = 0;
pcercuei 0:df031b60ca29 533
pcercuei 0:df031b60ca29 534 if (!len || words != (nb_channels + 31) / 32)
pcercuei 0:df031b60ca29 535 return -EINVAL;
pcercuei 0:df031b60ca29 536
pcercuei 0:df031b60ca29 537 snprintf(buf, sizeof(buf), "READBUF %s %lu\r\n",
pcercuei 0:df031b60ca29 538 iio_device_get_id(dev), (unsigned long) len);
pcercuei 0:df031b60ca29 539
pcercuei 0:df031b60ca29 540 ret = iiod_client_write_all(client, desc, buf, strlen(buf));
pcercuei 0:df031b60ca29 541 if (ret < 0)
pcercuei 0:df031b60ca29 542 return ret;
pcercuei 0:df031b60ca29 543
pcercuei 0:df031b60ca29 544 do {
pcercuei 0:df031b60ca29 545 int to_read;
pcercuei 0:df031b60ca29 546
pcercuei 0:df031b60ca29 547 ret = iiod_client_read_integer(client, desc, &to_read);
pcercuei 0:df031b60ca29 548 if (ret < 0)
pcercuei 0:df031b60ca29 549 return ret;
pcercuei 0:df031b60ca29 550 if (to_read < 0)
pcercuei 0:df031b60ca29 551 return (ssize_t) to_read;
pcercuei 0:df031b60ca29 552 if (!to_read)
pcercuei 0:df031b60ca29 553 break;
pcercuei 0:df031b60ca29 554
pcercuei 0:df031b60ca29 555 if (mask) {
pcercuei 0:df031b60ca29 556 ret = iiod_client_read_mask(client, desc, mask, words);
pcercuei 0:df031b60ca29 557 if (ret < 0)
pcercuei 0:df031b60ca29 558 return ret;
pcercuei 0:df031b60ca29 559
pcercuei 0:df031b60ca29 560 mask = NULL; /* We read the mask only once */
pcercuei 0:df031b60ca29 561 }
pcercuei 0:df031b60ca29 562
pcercuei 0:df031b60ca29 563 ret = iiod_client_read_all(client, desc, (char *) ptr, to_read);
pcercuei 0:df031b60ca29 564 if (ret < 0)
pcercuei 0:df031b60ca29 565 return ret;
pcercuei 0:df031b60ca29 566
pcercuei 0:df031b60ca29 567 ptr += ret;
pcercuei 0:df031b60ca29 568 read += ret;
pcercuei 0:df031b60ca29 569 len -= ret;
pcercuei 0:df031b60ca29 570 } while (len);
pcercuei 0:df031b60ca29 571
pcercuei 0:df031b60ca29 572 return read;
pcercuei 0:df031b60ca29 573 }
pcercuei 0:df031b60ca29 574
pcercuei 0:df031b60ca29 575 ssize_t iiod_client_write_unlocked(struct iiod_client *client, void *desc,
pcercuei 0:df031b60ca29 576 const struct iio_device *dev, const void *src, size_t len)
pcercuei 0:df031b60ca29 577 {
pcercuei 0:df031b60ca29 578 ssize_t ret;
pcercuei 0:df031b60ca29 579 char buf[1024];
pcercuei 0:df031b60ca29 580 int val;
pcercuei 0:df031b60ca29 581
pcercuei 0:df031b60ca29 582 snprintf(buf, sizeof(buf), "WRITEBUF %s %lu\r\n",
pcercuei 0:df031b60ca29 583 dev->id, (unsigned long) len);
pcercuei 0:df031b60ca29 584
pcercuei 0:df031b60ca29 585 ret = iiod_client_write_all(client, desc, buf, strlen(buf));
pcercuei 0:df031b60ca29 586 if (ret < 0)
pcercuei 0:df031b60ca29 587 return ret;
pcercuei 0:df031b60ca29 588
pcercuei 0:df031b60ca29 589 ret = iiod_client_read_integer(client, desc, &val);
pcercuei 0:df031b60ca29 590 if (ret < 0)
pcercuei 0:df031b60ca29 591 return ret;
pcercuei 0:df031b60ca29 592 if (val < 0)
pcercuei 0:df031b60ca29 593 return (ssize_t) val;
pcercuei 0:df031b60ca29 594
pcercuei 0:df031b60ca29 595 ret = iiod_client_write_all(client, desc, src, len);
pcercuei 0:df031b60ca29 596 if (ret < 0)
pcercuei 0:df031b60ca29 597 return ret;
pcercuei 0:df031b60ca29 598
pcercuei 0:df031b60ca29 599 ret = iiod_client_read_integer(client, desc, &val);
pcercuei 0:df031b60ca29 600 if (ret < 0)
pcercuei 0:df031b60ca29 601 return ret;
pcercuei 0:df031b60ca29 602 if (val < 0)
pcercuei 0:df031b60ca29 603 return (ssize_t) val;
pcercuei 0:df031b60ca29 604
pcercuei 0:df031b60ca29 605 return (ssize_t) len;
pcercuei 0:df031b60ca29 606 }
pcercuei 0:df031b60ca29 607