Paul Cercueil / libiio

Dependencies:   libserialport libxml2

Committer:
pcercuei
Date:
Thu Aug 25 15:54:09 2016 +0000
Revision:
0:df031b60ca29
Child:
2:9eb0a9a1f958
Add first version of libiio, from upsteam commit 775b9f6 unmodified.

Who changed what in which revision?

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