diff options
Diffstat (limited to 'iiod-client.c')
-rw-r--r-- | iiod-client.c | 674 |
1 files changed, 0 insertions, 674 deletions
diff --git a/iiod-client.c b/iiod-client.c deleted file mode 100644 index 1798cd6..0000000 --- a/iiod-client.c +++ /dev/null @@ -1,674 +0,0 @@ -/* - * libiio - Library for interfacing industrial I/O (IIO) devices - * - * Copyright (C) 2014-2016 Analog Devices, Inc. - * Author: Paul Cercueil <paul.cercueil@analog.com> - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - */ - -#include "debug.h" -#include "iiod-client.h" -#include "iio-lock.h" -#include "iio-private.h" - -#include <errno.h> -#include <inttypes.h> -#include <string.h> -#include <stdio.h> - -struct iiod_client { - struct iio_context_pdata *pdata; - const struct iiod_client_ops *ops; - struct iio_mutex *lock; -}; - -static ssize_t iiod_client_read_integer(struct iiod_client *client, - void *desc, int *val) -{ - unsigned int i; - char buf[1024], *ptr = NULL, *end; - ssize_t ret; - int value; - - do { - ret = client->ops->read_line(client->pdata, - desc, buf, sizeof(buf)); - if (ret < 0) - return ret; - - for (i = 0; i < (unsigned int) ret; i++) { - if (buf[i] != '\n') { - if (!ptr) - ptr = &buf[i]; - } else if (!!ptr) { - break; - } - } - } while (!ptr); - - buf[i] = '\0'; - - value = (int) strtol(ptr, &end, 10); - if (ptr == end) - return -EINVAL; - - *val = value; - return 0; -} - -static int iiod_client_exec_command(struct iiod_client *client, - void *desc, const char *cmd) -{ - int resp; - ssize_t ret; - - ret = client->ops->write(client->pdata, desc, cmd, strlen(cmd)); - if (ret < 0) - return (int) ret; - - ret = iiod_client_read_integer(client, desc, &resp); - return ret < 0 ? (int) ret : resp; -} - -static ssize_t iiod_client_write_all(struct iiod_client *client, - void *desc, const void *src, size_t len) -{ - struct iio_context_pdata *pdata = client->pdata; - const struct iiod_client_ops *ops = client->ops; - uintptr_t ptr = (uintptr_t) src; - - while (len) { - ssize_t ret = ops->write(pdata, desc, (const void *) ptr, len); - - if (ret < 0) { - if (ret == -EINTR) - continue; - else - return ret; - } - - if (ret == 0) - return -EPIPE; - - ptr += ret; - len -= ret; - } - - return (ssize_t) (ptr - (uintptr_t) src); -} - -static ssize_t iiod_client_read_all(struct iiod_client *client, - void *desc, void *dst, size_t len) -{ - struct iio_context_pdata *pdata = client->pdata; - const struct iiod_client_ops *ops = client->ops; - uintptr_t ptr = (uintptr_t) dst; - - while (len) { - ssize_t ret = ops->read(pdata, desc, (void *) ptr, len); - - if (ret < 0) { - if (ret == -EINTR) - continue; - else - return ret; - } - - if (ret == 0) - return -EPIPE; - - ptr += ret; - len -= ret; - } - - return (ssize_t) (ptr - (uintptr_t) dst); -} - -struct iiod_client * iiod_client_new(struct iio_context_pdata *pdata, - struct iio_mutex *lock, const struct iiod_client_ops *ops) -{ - struct iiod_client *client; - - client = malloc(sizeof(*client)); - if (!client) { - errno = ENOMEM; - return NULL; - } - - client->lock = lock; - client->pdata = pdata; - client->ops = ops; - return client; -} - -void iiod_client_destroy(struct iiod_client *client) -{ - free(client); -} - -int iiod_client_get_version(struct iiod_client *client, void *desc, - unsigned int *major, unsigned int *minor, char *git_tag) -{ - struct iio_context_pdata *pdata = client->pdata; - const struct iiod_client_ops *ops = client->ops; - char buf[256], *ptr = buf, *end; - long maj, min; - int ret; - - iio_mutex_lock(client->lock); - - ret = ops->write(pdata, desc, "VERSION\r\n", sizeof("VERSION\r\n") - 1); - if (ret < 0) { - iio_mutex_unlock(client->lock); - return ret; - } - - ret = ops->read_line(pdata, desc, buf, sizeof(buf)); - iio_mutex_unlock(client->lock); - - if (ret < 0) - return ret; - - maj = strtol(ptr, &end, 10); - if (ptr == end) - return -EIO; - - ptr = end + 1; - min = strtol(ptr, &end, 10); - if (ptr == end) - return -EIO; - - ptr = end + 1; - if (buf + ret < ptr + 8) - return -EIO; - - /* Strip the \n */ - ptr[buf + ret - ptr - 1] = '\0'; - - if (major) - *major = (unsigned int) maj; - if (minor) - *minor = (unsigned int) min; - if (git_tag) - strncpy(git_tag, ptr, 8); - return 0; -} - -int iiod_client_get_trigger(struct iiod_client *client, void *desc, - const struct iio_device *dev, const struct iio_device **trigger) -{ - const struct iio_context *ctx = iio_device_get_context(dev); - unsigned int i, nb_devices = iio_context_get_devices_count(ctx); - char buf[1024]; - unsigned int name_len; - int ret; - - iio_snprintf(buf, sizeof(buf), "GETTRIG %s\r\n", - iio_device_get_id(dev)); - - iio_mutex_lock(client->lock); - ret = iiod_client_exec_command(client, desc, buf); - - if (ret == 0) - *trigger = NULL; - if (ret <= 0) - goto out_unlock; - - if ((unsigned int) ret > sizeof(buf) - 1) { - ret = -EIO; - goto out_unlock; - } - - name_len = ret; - - ret = (int) iiod_client_read_all(client, desc, buf, name_len + 1); - if (ret < 0) - goto out_unlock; - - ret = -ENXIO; - - for (i = 0; i < nb_devices; i++) { - struct iio_device *cur = iio_context_get_device(ctx, i); - - if (iio_device_is_trigger(cur)) { - const char *name = iio_device_get_name(cur); - - if (!name) - continue; - - if (!strncmp(name, buf, name_len)) { - *trigger = cur; - ret = 0; - goto out_unlock; - } - } - } - -out_unlock: - iio_mutex_unlock(client->lock); - return ret; -} - -int iiod_client_set_trigger(struct iiod_client *client, void *desc, - const struct iio_device *dev, const struct iio_device *trigger) -{ - char buf[1024]; - int ret; - - if (trigger) { - iio_snprintf(buf, sizeof(buf), "SETTRIG %s %s\r\n", - iio_device_get_id(dev), - iio_device_get_id(trigger)); - } else { - iio_snprintf(buf, sizeof(buf), "SETTRIG %s\r\n", - iio_device_get_id(dev)); - } - - iio_mutex_lock(client->lock); - ret = iiod_client_exec_command(client, desc, buf); - iio_mutex_unlock(client->lock); - return ret; -} - -int iiod_client_set_kernel_buffers_count(struct iiod_client *client, void *desc, - const struct iio_device *dev, unsigned int nb_blocks) -{ - int ret; - char buf[1024]; - - iio_snprintf(buf, sizeof(buf), "SET %s BUFFERS_COUNT %u\r\n", - iio_device_get_id(dev), nb_blocks); - - iio_mutex_lock(client->lock); - ret = iiod_client_exec_command(client, desc, buf); - iio_mutex_unlock(client->lock); - return ret; -} - -int iiod_client_set_timeout(struct iiod_client *client, - void *desc, unsigned int timeout) -{ - int ret; - char buf[1024]; - - iio_snprintf(buf, sizeof(buf), "TIMEOUT %u\r\n", timeout); - - iio_mutex_lock(client->lock); - ret = iiod_client_exec_command(client, desc, buf); - iio_mutex_unlock(client->lock); - return ret; -} - -static int iiod_client_discard(struct iiod_client *client, void *desc, - char *buf, size_t buf_len, size_t to_discard) -{ - do { - size_t read_len; - ssize_t ret; - - if (to_discard > buf_len) - read_len = buf_len; - else - read_len = to_discard; - - ret = iiod_client_read_all(client, desc, buf, read_len); - if (ret < 0) - return ret; - - to_discard -= (size_t) ret; - } while (to_discard); - - return 0; -} - -ssize_t iiod_client_read_attr(struct iiod_client *client, void *desc, - const struct iio_device *dev, const struct iio_channel *chn, - const char *attr, char *dest, size_t len, enum iio_attr_type type) -{ - const char *id = iio_device_get_id(dev); - char buf[1024]; - ssize_t ret; - - if (attr) { - if (chn) { - if (!iio_channel_find_attr(chn, attr)) - return -ENOENT; - } else { - switch (type) { - case IIO_ATTR_TYPE_DEVICE: - if (!iio_device_find_attr(dev, attr)) - return -ENOENT; - break; - case IIO_ATTR_TYPE_DEBUG: - if (!iio_device_find_debug_attr(dev, attr)) - return -ENOENT; - break; - case IIO_ATTR_TYPE_BUFFER: - if (!iio_device_find_buffer_attr(dev, attr)) - return -ENOENT; - break; - default: - return -EINVAL; - } - } - } - - if (chn) { - iio_snprintf(buf, sizeof(buf), "READ %s %s %s %s\r\n", id, - iio_channel_is_output(chn) ? "OUTPUT" : "INPUT", - iio_channel_get_id(chn), attr ? attr : ""); - } else { - switch (type) { - case IIO_ATTR_TYPE_DEVICE: - iio_snprintf(buf, sizeof(buf), "READ %s %s\r\n", - id, attr ? attr : ""); - break; - case IIO_ATTR_TYPE_DEBUG: - iio_snprintf(buf, sizeof(buf), "READ %s DEBUG %s\r\n", - id, attr ? attr : ""); - break; - case IIO_ATTR_TYPE_BUFFER: - iio_snprintf(buf, sizeof(buf), "READ %s BUFFER %s\r\n", - id, attr ? attr : ""); - break; - } - } - - iio_mutex_lock(client->lock); - - ret = (ssize_t) iiod_client_exec_command(client, desc, buf); - if (ret < 0) - goto out_unlock; - - if ((size_t) ret + 1 > len) { - iiod_client_discard(client, desc, dest, len, ret + 1); - ret = -EIO; - goto out_unlock; - } - - /* +1: Also read the trailing \n */ - ret = iiod_client_read_all(client, desc, dest, ret + 1); - - if (ret > 0) { - /* Discard the trailing \n */ - ret--; - - /* Replace it with a \0 just in case */ - dest[ret] = '\0'; - } - -out_unlock: - iio_mutex_unlock(client->lock); - return ret; -} - -ssize_t iiod_client_write_attr(struct iiod_client *client, void *desc, - const struct iio_device *dev, const struct iio_channel *chn, - const char *attr, const char *src, size_t len, enum iio_attr_type type) -{ - struct iio_context_pdata *pdata = client->pdata; - const struct iiod_client_ops *ops = client->ops; - const char *id = iio_device_get_id(dev); - char buf[1024]; - ssize_t ret; - int resp; - - if (attr) { - if (chn) { - if (!iio_channel_find_attr(chn, attr)) - return -ENOENT; - } else { - switch (type) { - case IIO_ATTR_TYPE_DEVICE: - if (!iio_device_find_attr(dev, attr)) - return -ENOENT; - break; - case IIO_ATTR_TYPE_DEBUG: - if (!iio_device_find_debug_attr(dev, attr)) - return -ENOENT; - break; - case IIO_ATTR_TYPE_BUFFER: - if (!iio_device_find_buffer_attr(dev, attr)) - return -ENOENT; - break; - default: - return -EINVAL; - } - } - } - - if (chn) { - iio_snprintf(buf, sizeof(buf), "WRITE %s %s %s %s %lu\r\n", id, - iio_channel_is_output(chn) ? "OUTPUT" : "INPUT", - iio_channel_get_id(chn), attr ? attr : "", - (unsigned long) len); - } else { - switch (type) { - case IIO_ATTR_TYPE_DEVICE: - iio_snprintf(buf, sizeof(buf), "WRITE %s %s %lu\r\n", - id, attr ? attr : "", (unsigned long) len); - break; - case IIO_ATTR_TYPE_DEBUG: - iio_snprintf(buf, sizeof(buf), "WRITE %s DEBUG %s %lu\r\n", - id, attr ? attr : "", (unsigned long) len); - break; - case IIO_ATTR_TYPE_BUFFER: - iio_snprintf(buf, sizeof(buf), "WRITE %s BUFFER %s %lu\r\n", - id, attr ? attr : "", (unsigned long) len); - break; - } - } - - iio_mutex_lock(client->lock); - ret = ops->write(pdata, desc, buf, strlen(buf)); - if (ret < 0) - goto out_unlock; - - ret = iiod_client_write_all(client, desc, src, len); - if (ret < 0) - goto out_unlock; - - ret = iiod_client_read_integer(client, desc, &resp); - if (ret < 0) - goto out_unlock; - - ret = (ssize_t) resp; - -out_unlock: - iio_mutex_unlock(client->lock); - return ret; -} - -struct iio_context * iiod_client_create_context( - struct iiod_client *client, void *desc) -{ - struct iio_context *ctx = NULL; - size_t xml_len; - char *xml; - int ret; - - iio_mutex_lock(client->lock); - ret = iiod_client_exec_command(client, desc, "PRINT\r\n"); - if (ret < 0) - goto out_unlock; - - xml_len = (size_t) ret; - xml = malloc(xml_len + 1); - if (!xml) { - ret = -ENOMEM; - goto out_unlock; - } - - /* +1: Also read the trailing \n */ - ret = (int) iiod_client_read_all(client, desc, xml, xml_len + 1); - if (ret < 0) - goto out_free_xml; - - ctx = iio_create_xml_context_mem(xml, xml_len); - if (!ctx) - ret = -errno; - -out_free_xml: - free(xml); -out_unlock: - iio_mutex_unlock(client->lock); - if (!ctx) - errno = -ret; - return ctx; -} - -int iiod_client_open_unlocked(struct iiod_client *client, void *desc, - const struct iio_device *dev, size_t samples_count, bool cyclic) -{ - char buf[1024], *ptr; - size_t i; - - iio_snprintf(buf, sizeof(buf), "OPEN %s %lu ", - iio_device_get_id(dev), (unsigned long) samples_count); - ptr = buf + strlen(buf); - - for (i = dev->words; i > 0; i--, ptr += 8) { - iio_snprintf(ptr, (ptr - buf) + i * 8, "%08" PRIx32, - dev->mask[i - 1]); - } - - strcpy(ptr, cyclic ? " CYCLIC\r\n" : "\r\n"); - - return iiod_client_exec_command(client, desc, buf); -} - -int iiod_client_close_unlocked(struct iiod_client *client, void *desc, - const struct iio_device *dev) -{ - char buf[1024]; - - iio_snprintf(buf, sizeof(buf), "CLOSE %s\r\n", iio_device_get_id(dev)); - return iiod_client_exec_command(client, desc, buf); -} - -static int iiod_client_read_mask(struct iiod_client *client, - void *desc, uint32_t *mask, size_t words) -{ - size_t i; - ssize_t ret; - char *buf, *ptr; - - buf = malloc(words * 8 + 1); - if (!buf) - return -ENOMEM; - - ret = iiod_client_read_all(client, desc, buf, words * 8 + 1); - if (ret < 0) - goto out_buf_free; - else - ret = 0; - - buf[words*8] = '\0'; - - DEBUG("Reading mask\n"); - - for (i = words, ptr = buf; i > 0; i--) { - sscanf(ptr, "%08" PRIx32, &mask[i - 1]); - DEBUG("mask[%lu] = 0x%08" PRIx32 "\n", - (unsigned long)(i - 1), mask[i - 1]); - - ptr = (char *) ((uintptr_t) ptr + 8); - } - -out_buf_free: - free(buf); - return (int) ret; -} - -ssize_t iiod_client_read_unlocked(struct iiod_client *client, void *desc, - const struct iio_device *dev, void *dst, size_t len, - uint32_t *mask, size_t words) -{ - unsigned int nb_channels = iio_device_get_channels_count(dev); - uintptr_t ptr = (uintptr_t) dst; - char buf[1024]; - ssize_t ret, read = 0; - - if (!len || words != (nb_channels + 31) / 32) - return -EINVAL; - - iio_snprintf(buf, sizeof(buf), "READBUF %s %lu\r\n", - iio_device_get_id(dev), (unsigned long) len); - - ret = iiod_client_write_all(client, desc, buf, strlen(buf)); - if (ret < 0) - return ret; - - do { - int to_read; - - ret = iiod_client_read_integer(client, desc, &to_read); - if (ret < 0) - return ret; - if (to_read < 0) - return (ssize_t) to_read; - if (!to_read) - break; - - if (mask) { - ret = iiod_client_read_mask(client, desc, mask, words); - if (ret < 0) - return ret; - - mask = NULL; /* We read the mask only once */ - } - - ret = iiod_client_read_all(client, desc, (char *) ptr, to_read); - if (ret < 0) - return ret; - - ptr += ret; - read += ret; - len -= ret; - } while (len); - - return read; -} - -ssize_t iiod_client_write_unlocked(struct iiod_client *client, void *desc, - const struct iio_device *dev, const void *src, size_t len) -{ - ssize_t ret; - char buf[1024]; - int val; - - iio_snprintf(buf, sizeof(buf), "WRITEBUF %s %lu\r\n", - dev->id, (unsigned long) len); - - ret = iiod_client_write_all(client, desc, buf, strlen(buf)); - if (ret < 0) - return ret; - - ret = iiod_client_read_integer(client, desc, &val); - if (ret < 0) - return ret; - if (val < 0) - return (ssize_t) val; - - ret = iiod_client_write_all(client, desc, src, len); - if (ret < 0) - return ret; - - ret = iiod_client_read_integer(client, desc, &val); - if (ret < 0) - return ret; - if (val < 0) - return (ssize_t) val; - - return (ssize_t) len; -} |