static void network_shutdown(struct iio_context *ctx) { struct iio_context_pdata *pdata = ctx->pdata; unsigned int i; iio_mutex_lock(pdata->lock); write_command("\r\nEXIT\r\n", pdata->fd); close(pdata->fd); iio_mutex_unlock(pdata->lock); for (i = 0; i < ctx->nb_devices; i++) { struct iio_device *dev = ctx->devices[i]; struct iio_device_pdata *dpdata = dev->pdata; if (dpdata) { network_close(dev); iio_mutex_destroy(dpdata->lock); free(dpdata); } } iiod_client_destroy(pdata->iiod_client); iio_mutex_destroy(pdata->lock); freeaddrinfo(pdata->addrinfo); free(pdata); }
static int network_close(const struct iio_device *dev) { struct iio_device_pdata *pdata = dev->pdata; int ret = -EBADF; iio_mutex_lock(pdata->lock); if (pdata->fd >= 0) { ret = iiod_client_close_unlocked(dev->ctx->pdata->iiod_client, pdata->fd, dev); write_command("\r\nEXIT\r\n", pdata->fd); close(pdata->fd); pdata->fd = -1; } #ifdef WITH_NETWORK_GET_BUFFER if (pdata->memfd >= 0) close(pdata->memfd); pdata->memfd = -1; if (pdata->mmap_addr) { munmap(pdata->mmap_addr, pdata->mmap_len); pdata->mmap_addr = NULL; } #endif iio_mutex_unlock(pdata->lock); return ret; }
ssize_t iiod_client_read_attr(struct iiod_client *client, int desc, const struct iio_device *dev, const struct iio_channel *chn, const char *attr, char *dest, size_t len, bool is_debug) { 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 if (is_debug) { if (!iio_device_find_debug_attr(dev, attr)) return -ENOENT; } else { if (!iio_device_find_attr(dev, attr)) return -ENOENT; } } if (chn) 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 if (is_debug) snprintf(buf, sizeof(buf), "READ %s DEBUG %s\r\n", id, attr ? attr : ""); else snprintf(buf, sizeof(buf), "READ %s %s\r\n", id, attr ? attr : ""); 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) { 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, int desc, const struct iio_device *dev, const struct iio_channel *chn, const char *attr, const char *src, size_t len, bool is_debug) { 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 if (is_debug) { if (!iio_device_find_debug_attr(dev, attr)) return -ENOENT; } else { if (!iio_device_find_attr(dev, attr)) return -ENOENT; } } if (chn) 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 if (is_debug) snprintf(buf, sizeof(buf), "WRITE %s DEBUG %s %lu\r\n", id, attr ? attr : "", (unsigned long) len); else snprintf(buf, sizeof(buf), "WRITE %s %s %lu\r\n", id, attr ? attr : "", (unsigned long) len); 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; }
int iiod_client_get_trigger(struct iiod_client *client, int 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; 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; }
static ssize_t network_write(const struct iio_device *dev, const void *src, size_t len) { struct iio_device_pdata *pdata = dev->pdata; ssize_t ret; iio_mutex_lock(pdata->lock); ret = iiod_client_write_unlocked(dev->ctx->pdata->iiod_client, pdata->fd, dev, src, len); iio_mutex_unlock(pdata->lock); return ret; }
static ssize_t network_read(const struct iio_device *dev, void *dst, size_t len, uint32_t *mask, size_t words) { struct iio_device_pdata *pdata = dev->pdata; ssize_t ret; iio_mutex_lock(pdata->lock); ret = iiod_client_read_unlocked(dev->ctx->pdata->iiod_client, pdata->fd, dev, dst, len, mask, words); iio_mutex_unlock(pdata->lock); return ret; }
int iiod_client_set_timeout(struct iiod_client *client, int desc, unsigned int timeout) { int ret; char buf[1024]; 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; }
int iiod_client_set_kernel_buffers_count(struct iiod_client *client, int desc, const struct iio_device *dev, unsigned int nb_blocks) { int ret; char buf[1024]; 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_get_version(struct iiod_client *client, int 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_set_trigger(struct iiod_client *client, int desc, const struct iio_device *dev, const struct iio_device *trigger) { char buf[1024]; int ret; if (trigger) snprintf(buf, sizeof(buf), "SETTRIG %s %s\r\n", iio_device_get_id(dev), iio_device_get_id(trigger)); else 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; }
struct iio_context * iiod_client_create_context( struct iiod_client *client, int 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; }
static int network_open(const struct iio_device *dev, size_t samples_count, bool cyclic) { struct iio_context_pdata *pdata = dev->ctx->pdata; struct iio_device_pdata *ppdata = dev->pdata; int fd, ret = -EBUSY; iio_mutex_lock(ppdata->lock); if (ppdata->fd >= 0) goto out_mutex_unlock; ret = create_socket(pdata->addrinfo); if (ret < 0) goto out_mutex_unlock; fd = ret; ret = iiod_client_open_unlocked(pdata->iiod_client, fd, dev, samples_count, cyclic); if (ret < 0) { close(fd); goto out_mutex_unlock; } ppdata->is_tx = iio_device_is_tx(dev); ppdata->is_cyclic = cyclic; ppdata->fd = fd; ppdata->wait_for_err_code = false; #ifdef WITH_NETWORK_GET_BUFFER ppdata->mmap_len = samples_count * iio_device_get_sample_size(dev); #endif out_mutex_unlock: iio_mutex_unlock(ppdata->lock); return ret; }
static ssize_t network_get_buffer(const struct iio_device *dev, void **addr_ptr, size_t bytes_used, uint32_t *mask, size_t words) { struct iio_device_pdata *pdata = dev->pdata; ssize_t ret, read = 0; int memfd; bool tx; if (pdata->is_cyclic) return -ENOSYS; /* We check early that the temporary file can be created, so that we can * return -ENOSYS in case it fails, which will indicate that the * high-speed interface is not available. * * O_TMPFILE -> Linux 3.11. * TODO: use memfd_create (Linux 3.17) */ memfd = open(P_tmpdir, O_RDWR | O_TMPFILE | O_EXCL, S_IRWXU); if (memfd < 0) return -ENOSYS; if (!addr_ptr || words != (dev->nb_channels + 31) / 32) { close(memfd); return -EINVAL; } if (pdata->mmap_addr) munmap(pdata->mmap_addr, pdata->mmap_len); if (pdata->mmap_addr && pdata->is_tx) { char buf[1024]; snprintf(buf, sizeof(buf), "WRITEBUF %s %lu\r\n", dev->id, (unsigned long) bytes_used); iio_mutex_lock(pdata->lock); ret = write_rwbuf_command(dev, buf, false); if (ret < 0) goto err_close_memfd; ret = network_do_splice(pdata->fd, pdata->memfd, bytes_used); if (ret < 0) goto err_close_memfd; pdata->wait_for_err_code = true; iio_mutex_unlock(pdata->lock); } if (pdata->memfd >= 0) close(pdata->memfd); pdata->memfd = memfd; ret = (ssize_t) ftruncate(pdata->memfd, pdata->mmap_len); if (ret < 0) { ret = -errno; ERROR("Unable to truncate temp file: %zi\n", -ret); return ret; } if (!pdata->is_tx) { char buf[1024]; size_t len = pdata->mmap_len; snprintf(buf, sizeof(buf), "READBUF %s %lu\r\n", dev->id, (unsigned long) len); iio_mutex_lock(pdata->lock); ret = write_rwbuf_command(dev, buf, false); if (ret < 0) goto err_unlock; do { ret = network_read_mask(pdata->fd, mask, words); if (!ret) break; if (ret < 0) goto err_unlock; mask = NULL; /* We read the mask only once */ ret = network_do_splice(pdata->memfd, pdata->fd, ret); if (ret < 0) goto err_unlock; read += ret; len -= ret; } while (len); iio_mutex_unlock(pdata->lock); } pdata->mmap_addr = mmap(NULL, pdata->mmap_len, PROT_READ | PROT_WRITE, MAP_SHARED, pdata->memfd, 0); if (pdata->mmap_addr == MAP_FAILED) { pdata->mmap_addr = NULL; ret = -errno; ERROR("Unable to mmap: %zi\n", -ret); return ret; } *addr_ptr = pdata->mmap_addr; return read ? read : bytes_used; err_close_memfd: close(memfd); err_unlock: iio_mutex_unlock(pdata->lock); return ret; }