Library for interfacing with IIO devices. Licensed under the LGPLv2+

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 0:df031b60ca29 1 /*
pcercuei 0:df031b60ca29 2 * libiio - Library for interfacing industrial I/O (IIO) devices
pcercuei 0:df031b60ca29 3 *
pcercuei 0:df031b60ca29 4 * Copyright (C) 2014-2016 Analog Devices, Inc.
pcercuei 0:df031b60ca29 5 * Author: Paul Cercueil <paul.cercueil@analog.com>
pcercuei 0:df031b60ca29 6 *
pcercuei 0:df031b60ca29 7 * This library is free software; you can redistribute it and/or
pcercuei 0:df031b60ca29 8 * modify it under the terms of the GNU Lesser General Public
pcercuei 0:df031b60ca29 9 * License as published by the Free Software Foundation; either
pcercuei 0:df031b60ca29 10 * version 2.1 of the License, or (at your option) any later version.
pcercuei 0:df031b60ca29 11 *
pcercuei 0:df031b60ca29 12 * This library is distributed in the hope that it will be useful,
pcercuei 0:df031b60ca29 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
pcercuei 0:df031b60ca29 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
pcercuei 0:df031b60ca29 15 * Lesser General Public License for more details.
pcercuei 0:df031b60ca29 16 *
pcercuei 0:df031b60ca29 17 * */
pcercuei 0:df031b60ca29 18
pcercuei 0:df031b60ca29 19 #include "debug.h"
pcercuei 0:df031b60ca29 20 #include "iio-private.h"
pcercuei 0:df031b60ca29 21 #include "iio-lock.h"
pcercuei 0:df031b60ca29 22 #include "iiod-client.h"
pcercuei 0:df031b60ca29 23
pcercuei 2:9eb0a9a1f958 24 #include <errno.h>
pcercuei 0:df031b60ca29 25 #include <libserialport.h>
pcercuei 0:df031b60ca29 26 #include <stdio.h>
pcercuei 0:df031b60ca29 27 #include <stdlib.h>
pcercuei 0:df031b60ca29 28 #include <string.h>
pcercuei 0:df031b60ca29 29
pcercuei 0:df031b60ca29 30 #define DEFAULT_TIMEOUT_MS 1000
pcercuei 0:df031b60ca29 31
pcercuei 0:df031b60ca29 32 struct iio_context_pdata {
pcercuei 0:df031b60ca29 33 struct sp_port *port;
pcercuei 0:df031b60ca29 34 struct iio_mutex *lock;
pcercuei 0:df031b60ca29 35 struct iiod_client *iiod_client;
pcercuei 0:df031b60ca29 36
pcercuei 0:df031b60ca29 37 unsigned int timeout_ms;
pcercuei 0:df031b60ca29 38 };
pcercuei 0:df031b60ca29 39
pcercuei 0:df031b60ca29 40 struct iio_device_pdata {
pcercuei 0:df031b60ca29 41 bool opened;
pcercuei 0:df031b60ca29 42 };
pcercuei 0:df031b60ca29 43
pcercuei 0:df031b60ca29 44 static inline int libserialport_to_errno(enum sp_return ret)
pcercuei 0:df031b60ca29 45 {
pcercuei 0:df031b60ca29 46 switch (ret) {
pcercuei 0:df031b60ca29 47 case SP_ERR_ARG:
pcercuei 0:df031b60ca29 48 return -EINVAL;
pcercuei 0:df031b60ca29 49 case SP_ERR_FAIL:
pcercuei 0:df031b60ca29 50 return -sp_last_error_code();
pcercuei 0:df031b60ca29 51 case SP_ERR_MEM:
pcercuei 0:df031b60ca29 52 return -ENOMEM;
pcercuei 0:df031b60ca29 53 case SP_ERR_SUPP:
pcercuei 0:df031b60ca29 54 return -ENOSYS;
pcercuei 0:df031b60ca29 55 default:
pcercuei 0:df031b60ca29 56 return (int) ret;
pcercuei 0:df031b60ca29 57 }
pcercuei 0:df031b60ca29 58 }
pcercuei 0:df031b60ca29 59
pcercuei 0:df031b60ca29 60 static int serial_get_version(const struct iio_context *ctx,
pcercuei 0:df031b60ca29 61 unsigned int *major, unsigned int *minor, char git_tag[8])
pcercuei 0:df031b60ca29 62 {
pcercuei 0:df031b60ca29 63 struct iio_context_pdata *pdata = ctx->pdata;
pcercuei 0:df031b60ca29 64
pcercuei 0:df031b60ca29 65 return iiod_client_get_version(pdata->iiod_client, NULL,
pcercuei 0:df031b60ca29 66 major, minor, git_tag);
pcercuei 0:df031b60ca29 67 }
pcercuei 0:df031b60ca29 68
pcercuei 0:df031b60ca29 69 static int serial_open(const struct iio_device *dev,
pcercuei 0:df031b60ca29 70 size_t samples_count, bool cyclic)
pcercuei 0:df031b60ca29 71 {
pcercuei 0:df031b60ca29 72 const struct iio_context *ctx = iio_device_get_context(dev);
pcercuei 0:df031b60ca29 73 struct iio_context_pdata *ctx_pdata = ctx->pdata;
pcercuei 0:df031b60ca29 74 struct iio_device_pdata *pdata = dev->pdata;
pcercuei 0:df031b60ca29 75 int ret = -EBUSY;
pcercuei 0:df031b60ca29 76
pcercuei 0:df031b60ca29 77 iio_mutex_lock(ctx_pdata->lock);
pcercuei 0:df031b60ca29 78 if (pdata->opened)
pcercuei 0:df031b60ca29 79 goto out_unlock;
pcercuei 0:df031b60ca29 80
pcercuei 0:df031b60ca29 81 ret = iiod_client_open_unlocked(ctx_pdata->iiod_client, NULL,
pcercuei 0:df031b60ca29 82 dev, samples_count, cyclic);
pcercuei 0:df031b60ca29 83
pcercuei 0:df031b60ca29 84 pdata->opened = !ret;
pcercuei 0:df031b60ca29 85
pcercuei 0:df031b60ca29 86 out_unlock:
pcercuei 0:df031b60ca29 87 iio_mutex_unlock(ctx_pdata->lock);
pcercuei 0:df031b60ca29 88 return ret;
pcercuei 0:df031b60ca29 89 }
pcercuei 0:df031b60ca29 90
pcercuei 0:df031b60ca29 91 static int serial_close(const struct iio_device *dev)
pcercuei 0:df031b60ca29 92 {
pcercuei 0:df031b60ca29 93 const struct iio_context *ctx = iio_device_get_context(dev);
pcercuei 0:df031b60ca29 94 struct iio_context_pdata *ctx_pdata = ctx->pdata;
pcercuei 0:df031b60ca29 95 struct iio_device_pdata *pdata = dev->pdata;
pcercuei 0:df031b60ca29 96 int ret = -EBADF;
pcercuei 0:df031b60ca29 97
pcercuei 0:df031b60ca29 98 iio_mutex_lock(ctx_pdata->lock);
pcercuei 0:df031b60ca29 99 if (!pdata->opened)
pcercuei 0:df031b60ca29 100 goto out_unlock;
pcercuei 0:df031b60ca29 101
pcercuei 0:df031b60ca29 102 ret = iiod_client_close_unlocked(ctx_pdata->iiod_client, NULL, dev);
pcercuei 0:df031b60ca29 103 pdata->opened = false;
pcercuei 0:df031b60ca29 104
pcercuei 0:df031b60ca29 105 out_unlock:
pcercuei 0:df031b60ca29 106 iio_mutex_unlock(ctx_pdata->lock);
pcercuei 0:df031b60ca29 107 return ret;
pcercuei 0:df031b60ca29 108 }
pcercuei 0:df031b60ca29 109
pcercuei 0:df031b60ca29 110 static ssize_t serial_read(const struct iio_device *dev, void *dst, size_t len,
pcercuei 0:df031b60ca29 111 uint32_t *mask, size_t words)
pcercuei 0:df031b60ca29 112 {
pcercuei 0:df031b60ca29 113 const struct iio_context *ctx = iio_device_get_context(dev);
pcercuei 0:df031b60ca29 114 struct iio_context_pdata *pdata = ctx->pdata;
pcercuei 0:df031b60ca29 115 ssize_t ret;
pcercuei 0:df031b60ca29 116
pcercuei 0:df031b60ca29 117 iio_mutex_lock(pdata->lock);
pcercuei 0:df031b60ca29 118 ret = iiod_client_read_unlocked(pdata->iiod_client, NULL,
pcercuei 0:df031b60ca29 119 dev, dst, len, mask, words);
pcercuei 0:df031b60ca29 120 iio_mutex_unlock(pdata->lock);
pcercuei 0:df031b60ca29 121
pcercuei 0:df031b60ca29 122 return ret;
pcercuei 0:df031b60ca29 123 }
pcercuei 0:df031b60ca29 124
pcercuei 0:df031b60ca29 125 static ssize_t serial_write(const struct iio_device *dev,
pcercuei 0:df031b60ca29 126 const void *src, size_t len)
pcercuei 0:df031b60ca29 127 {
pcercuei 0:df031b60ca29 128 const struct iio_context *ctx = iio_device_get_context(dev);
pcercuei 0:df031b60ca29 129 struct iio_context_pdata *pdata = ctx->pdata;
pcercuei 0:df031b60ca29 130 ssize_t ret;
pcercuei 0:df031b60ca29 131
pcercuei 0:df031b60ca29 132 iio_mutex_lock(pdata->lock);
pcercuei 0:df031b60ca29 133 ret = iiod_client_write_unlocked(pdata->iiod_client, NULL, dev, src, len);
pcercuei 0:df031b60ca29 134 iio_mutex_unlock(pdata->lock);
pcercuei 0:df031b60ca29 135
pcercuei 0:df031b60ca29 136 return ret;
pcercuei 0:df031b60ca29 137 }
pcercuei 0:df031b60ca29 138
pcercuei 0:df031b60ca29 139 static ssize_t serial_read_dev_attr(const struct iio_device *dev,
pcercuei 0:df031b60ca29 140 const char *attr, char *dst, size_t len, bool is_debug)
pcercuei 0:df031b60ca29 141 {
pcercuei 0:df031b60ca29 142 const struct iio_context *ctx = iio_device_get_context(dev);
pcercuei 0:df031b60ca29 143 struct iio_context_pdata *pdata = ctx->pdata;
pcercuei 0:df031b60ca29 144
pcercuei 0:df031b60ca29 145 return iiod_client_read_attr(pdata->iiod_client, NULL,
pcercuei 0:df031b60ca29 146 dev, NULL, attr, dst, len, is_debug);
pcercuei 0:df031b60ca29 147 }
pcercuei 0:df031b60ca29 148
pcercuei 0:df031b60ca29 149 static ssize_t serial_write_dev_attr(const struct iio_device *dev,
pcercuei 0:df031b60ca29 150 const char *attr, const char *src, size_t len, bool is_debug)
pcercuei 0:df031b60ca29 151 {
pcercuei 0:df031b60ca29 152 const struct iio_context *ctx = iio_device_get_context(dev);
pcercuei 0:df031b60ca29 153 struct iio_context_pdata *pdata = ctx->pdata;
pcercuei 0:df031b60ca29 154
pcercuei 0:df031b60ca29 155 return iiod_client_write_attr(pdata->iiod_client, NULL,
pcercuei 0:df031b60ca29 156 dev, NULL, attr, src, len, is_debug);
pcercuei 0:df031b60ca29 157 }
pcercuei 0:df031b60ca29 158
pcercuei 0:df031b60ca29 159 static ssize_t serial_read_chn_attr(const struct iio_channel *chn,
pcercuei 0:df031b60ca29 160 const char *attr, char *dst, size_t len)
pcercuei 0:df031b60ca29 161 {
pcercuei 0:df031b60ca29 162 const struct iio_device *dev = iio_channel_get_device(chn);
pcercuei 0:df031b60ca29 163 const struct iio_context *ctx = iio_device_get_context(dev);
pcercuei 0:df031b60ca29 164 struct iio_context_pdata *pdata = ctx->pdata;
pcercuei 0:df031b60ca29 165
pcercuei 0:df031b60ca29 166 return iiod_client_read_attr(pdata->iiod_client, NULL,
pcercuei 0:df031b60ca29 167 chn->dev, chn, attr, dst, len, false);
pcercuei 0:df031b60ca29 168 }
pcercuei 0:df031b60ca29 169
pcercuei 0:df031b60ca29 170 static ssize_t serial_write_chn_attr(const struct iio_channel *chn,
pcercuei 0:df031b60ca29 171 const char *attr, const char *src, size_t len)
pcercuei 0:df031b60ca29 172 {
pcercuei 0:df031b60ca29 173 const struct iio_device *dev = iio_channel_get_device(chn);
pcercuei 0:df031b60ca29 174 const struct iio_context *ctx = iio_device_get_context(dev);
pcercuei 0:df031b60ca29 175 struct iio_context_pdata *pdata = ctx->pdata;
pcercuei 0:df031b60ca29 176
pcercuei 0:df031b60ca29 177 return iiod_client_write_attr(pdata->iiod_client, NULL,
pcercuei 0:df031b60ca29 178 dev, chn, attr, src, len, false);
pcercuei 0:df031b60ca29 179 }
pcercuei 0:df031b60ca29 180
pcercuei 0:df031b60ca29 181 static int serial_set_kernel_buffers_count(const struct iio_device *dev,
pcercuei 0:df031b60ca29 182 unsigned int nb_blocks)
pcercuei 0:df031b60ca29 183 {
pcercuei 0:df031b60ca29 184 const struct iio_context *ctx = iio_device_get_context(dev);
pcercuei 0:df031b60ca29 185 struct iio_context_pdata *pdata = ctx->pdata;
pcercuei 0:df031b60ca29 186
pcercuei 0:df031b60ca29 187 return iiod_client_set_kernel_buffers_count(pdata->iiod_client, NULL,
pcercuei 0:df031b60ca29 188 dev, nb_blocks);
pcercuei 0:df031b60ca29 189 }
pcercuei 0:df031b60ca29 190
pcercuei 0:df031b60ca29 191 static ssize_t serial_write_data(struct iio_context_pdata *pdata,
pcercuei 0:df031b60ca29 192 void *io_data, const char *data, size_t len)
pcercuei 0:df031b60ca29 193 {
pcercuei 0:df031b60ca29 194 ssize_t ret = (ssize_t) libserialport_to_errno(sp_blocking_write(
pcercuei 0:df031b60ca29 195 pdata->port, data, len, pdata->timeout_ms));
pcercuei 0:df031b60ca29 196
pcercuei 0:df031b60ca29 197 DEBUG("Write returned %li: %s\n", (long) ret, data);
pcercuei 0:df031b60ca29 198 return ret;
pcercuei 0:df031b60ca29 199 }
pcercuei 0:df031b60ca29 200
pcercuei 0:df031b60ca29 201 static ssize_t serial_read_data(struct iio_context_pdata *pdata,
pcercuei 0:df031b60ca29 202 void *io_data, char *buf, size_t len)
pcercuei 0:df031b60ca29 203 {
pcercuei 0:df031b60ca29 204 ssize_t ret = (ssize_t) libserialport_to_errno(sp_blocking_read_next(
pcercuei 0:df031b60ca29 205 pdata->port, buf, len, pdata->timeout_ms));
pcercuei 0:df031b60ca29 206
pcercuei 0:df031b60ca29 207 DEBUG("Read returned %li: %.*s\n", (long) ret, (int) ret, buf);
pcercuei 0:df031b60ca29 208 return ret;
pcercuei 0:df031b60ca29 209 }
pcercuei 0:df031b60ca29 210
pcercuei 0:df031b60ca29 211 static ssize_t serial_read_line(struct iio_context_pdata *pdata,
pcercuei 0:df031b60ca29 212 void *io_data, char *buf, size_t len)
pcercuei 0:df031b60ca29 213 {
pcercuei 0:df031b60ca29 214 size_t i;
pcercuei 0:df031b60ca29 215 bool found = false;
pcercuei 0:df031b60ca29 216 int ret;
pcercuei 0:df031b60ca29 217
pcercuei 0:df031b60ca29 218 DEBUG("Readline size 0x%lx\n", (unsigned long) len);
pcercuei 0:df031b60ca29 219
pcercuei 0:df031b60ca29 220 for (i = 0; i < len - 1; i++) {
pcercuei 0:df031b60ca29 221 ret = libserialport_to_errno(sp_blocking_read_next(
pcercuei 0:df031b60ca29 222 pdata->port, &buf[i], 1,
pcercuei 0:df031b60ca29 223 pdata->timeout_ms));
pcercuei 0:df031b60ca29 224 if (ret < 0) {
pcercuei 0:df031b60ca29 225 ERROR("sp_blocking_read_next returned %i\n", ret);
pcercuei 0:df031b60ca29 226 return (ssize_t) ret;
pcercuei 0:df031b60ca29 227 }
pcercuei 0:df031b60ca29 228
pcercuei 0:df031b60ca29 229 DEBUG("Character: %c\n", buf[i]);
pcercuei 0:df031b60ca29 230
pcercuei 0:df031b60ca29 231 if (buf[i] != '\n')
pcercuei 0:df031b60ca29 232 found = true;
pcercuei 0:df031b60ca29 233 else if (found)
pcercuei 0:df031b60ca29 234 break;
pcercuei 0:df031b60ca29 235 }
pcercuei 0:df031b60ca29 236
pcercuei 0:df031b60ca29 237 /* No \n found? Just garbage data */
pcercuei 0:df031b60ca29 238 if (!found || i == len - 1)
pcercuei 0:df031b60ca29 239 return -EIO;
pcercuei 0:df031b60ca29 240
pcercuei 0:df031b60ca29 241 return (ssize_t) i + 1;
pcercuei 0:df031b60ca29 242 }
pcercuei 0:df031b60ca29 243
pcercuei 0:df031b60ca29 244 static void serial_shutdown(struct iio_context *ctx)
pcercuei 0:df031b60ca29 245 {
pcercuei 0:df031b60ca29 246 struct iio_context_pdata *ctx_pdata = ctx->pdata;
pcercuei 0:df031b60ca29 247 unsigned int i;
pcercuei 0:df031b60ca29 248
pcercuei 0:df031b60ca29 249 iiod_client_destroy(ctx_pdata->iiod_client);
pcercuei 0:df031b60ca29 250 iio_mutex_destroy(ctx_pdata->lock);
pcercuei 0:df031b60ca29 251 sp_close(ctx_pdata->port);
pcercuei 0:df031b60ca29 252 sp_free_port(ctx_pdata->port);
pcercuei 0:df031b60ca29 253
pcercuei 0:df031b60ca29 254 for (i = 0; i < iio_context_get_devices_count(ctx); i++) {
pcercuei 0:df031b60ca29 255 const struct iio_device *dev = iio_context_get_device(ctx, i);
pcercuei 0:df031b60ca29 256 struct iio_device_pdata *pdata = dev->pdata;
pcercuei 0:df031b60ca29 257
pcercuei 0:df031b60ca29 258 free(pdata);
pcercuei 0:df031b60ca29 259 }
pcercuei 0:df031b60ca29 260
pcercuei 0:df031b60ca29 261 free(ctx_pdata);
pcercuei 0:df031b60ca29 262 }
pcercuei 0:df031b60ca29 263
pcercuei 0:df031b60ca29 264 static int serial_set_timeout(struct iio_context *ctx, unsigned int timeout)
pcercuei 0:df031b60ca29 265 {
pcercuei 0:df031b60ca29 266 ctx->pdata->timeout_ms = timeout;
pcercuei 0:df031b60ca29 267 return 0;
pcercuei 0:df031b60ca29 268 }
pcercuei 0:df031b60ca29 269
pcercuei 0:df031b60ca29 270 static const struct iio_backend_ops serial_ops = {
pcercuei 0:df031b60ca29 271 .get_version = serial_get_version,
pcercuei 0:df031b60ca29 272 .open = serial_open,
pcercuei 0:df031b60ca29 273 .close = serial_close,
pcercuei 0:df031b60ca29 274 .read = serial_read,
pcercuei 0:df031b60ca29 275 .write = serial_write,
pcercuei 0:df031b60ca29 276 .read_device_attr = serial_read_dev_attr,
pcercuei 0:df031b60ca29 277 .write_device_attr = serial_write_dev_attr,
pcercuei 0:df031b60ca29 278 .read_channel_attr = serial_read_chn_attr,
pcercuei 0:df031b60ca29 279 .write_channel_attr = serial_write_chn_attr,
pcercuei 0:df031b60ca29 280 .set_kernel_buffers_count = serial_set_kernel_buffers_count,
pcercuei 0:df031b60ca29 281 .shutdown = serial_shutdown,
pcercuei 0:df031b60ca29 282 .set_timeout = serial_set_timeout,
pcercuei 0:df031b60ca29 283 };
pcercuei 0:df031b60ca29 284
pcercuei 0:df031b60ca29 285 static const struct iiod_client_ops serial_iiod_client_ops = {
pcercuei 0:df031b60ca29 286 .write = serial_write_data,
pcercuei 0:df031b60ca29 287 .read = serial_read_data,
pcercuei 0:df031b60ca29 288 .read_line = serial_read_line,
pcercuei 0:df031b60ca29 289 };
pcercuei 0:df031b60ca29 290
pcercuei 0:df031b60ca29 291 static int apply_settings(struct sp_port *port, unsigned int baud_rate,
pcercuei 0:df031b60ca29 292 unsigned int bits, unsigned int stop_bits,
pcercuei 0:df031b60ca29 293 enum sp_parity parity, enum sp_flowcontrol flow)
pcercuei 0:df031b60ca29 294 {
pcercuei 0:df031b60ca29 295 int ret;
pcercuei 0:df031b60ca29 296
pcercuei 0:df031b60ca29 297 ret = libserialport_to_errno(sp_set_baudrate(port, (int) baud_rate));
pcercuei 0:df031b60ca29 298 if (ret)
pcercuei 0:df031b60ca29 299 return ret;
pcercuei 0:df031b60ca29 300
pcercuei 0:df031b60ca29 301 ret = libserialport_to_errno(sp_set_bits(port, (int) bits));
pcercuei 0:df031b60ca29 302 if (ret)
pcercuei 0:df031b60ca29 303 return ret;
pcercuei 0:df031b60ca29 304
pcercuei 0:df031b60ca29 305 ret = libserialport_to_errno(sp_set_stopbits(port, (int) stop_bits));
pcercuei 0:df031b60ca29 306 if (ret)
pcercuei 0:df031b60ca29 307 return ret;
pcercuei 0:df031b60ca29 308
pcercuei 0:df031b60ca29 309 ret = libserialport_to_errno(sp_set_parity(port, parity));
pcercuei 0:df031b60ca29 310 if (ret)
pcercuei 0:df031b60ca29 311 return ret;
pcercuei 0:df031b60ca29 312
pcercuei 0:df031b60ca29 313 return libserialport_to_errno(sp_set_flowcontrol(port, flow));
pcercuei 0:df031b60ca29 314 }
pcercuei 0:df031b60ca29 315
pcercuei 0:df031b60ca29 316 static struct iio_context * serial_create_context(const char *port_name,
pcercuei 0:df031b60ca29 317 unsigned int baud_rate, unsigned int bits,
pcercuei 0:df031b60ca29 318 enum sp_parity parity, enum sp_flowcontrol flow)
pcercuei 0:df031b60ca29 319 {
pcercuei 0:df031b60ca29 320 struct sp_port *port;
pcercuei 0:df031b60ca29 321 struct iio_context_pdata *pdata;
pcercuei 0:df031b60ca29 322 struct iio_context *ctx;
pcercuei 0:df031b60ca29 323 char *name, *desc, *description;
pcercuei 0:df031b60ca29 324 size_t desc_len;
pcercuei 0:df031b60ca29 325 unsigned int i;
pcercuei 0:df031b60ca29 326 int ret;
pcercuei 0:df031b60ca29 327
pcercuei 0:df031b60ca29 328 ret = libserialport_to_errno(sp_get_port_by_name(port_name, &port));
pcercuei 0:df031b60ca29 329 if (ret) {
pcercuei 0:df031b60ca29 330 errno = -ret;
pcercuei 0:df031b60ca29 331 return NULL;
pcercuei 0:df031b60ca29 332 }
pcercuei 0:df031b60ca29 333
pcercuei 0:df031b60ca29 334 ret = libserialport_to_errno(sp_open(port, SP_MODE_READ_WRITE));
pcercuei 0:df031b60ca29 335 if (ret) {
pcercuei 0:df031b60ca29 336 errno = -ret;
pcercuei 0:df031b60ca29 337 goto err_free_port;
pcercuei 0:df031b60ca29 338 }
pcercuei 0:df031b60ca29 339
pcercuei 0:df031b60ca29 340 ret = apply_settings(port, baud_rate, bits, 1, parity, flow);
pcercuei 0:df031b60ca29 341 if (ret) {
pcercuei 0:df031b60ca29 342 errno = -ret;
pcercuei 0:df031b60ca29 343 goto err_close_port;
pcercuei 0:df031b60ca29 344 }
pcercuei 0:df031b60ca29 345
pcercuei 0:df031b60ca29 346 /* Empty the buffers */
pcercuei 0:df031b60ca29 347 sp_flush(port, SP_BUF_BOTH);
pcercuei 0:df031b60ca29 348
pcercuei 0:df031b60ca29 349 name = sp_get_port_name(port);
pcercuei 0:df031b60ca29 350 desc = sp_get_port_description(port);
pcercuei 0:df031b60ca29 351
pcercuei 0:df031b60ca29 352 desc_len = sizeof(": \0") + strlen(name) + strlen(desc);
pcercuei 0:df031b60ca29 353 description = malloc(desc_len);
pcercuei 0:df031b60ca29 354 if (!description) {
pcercuei 0:df031b60ca29 355 errno = ENOMEM;
pcercuei 0:df031b60ca29 356 goto err_close_port;
pcercuei 0:df031b60ca29 357 }
pcercuei 0:df031b60ca29 358
pcercuei 3:d147beabba0e 359 iio_snprintf(description, desc_len, "%s: %s", name, desc);
pcercuei 0:df031b60ca29 360
pcercuei 0:df031b60ca29 361 pdata = zalloc(sizeof(*pdata));
pcercuei 0:df031b60ca29 362 if (!pdata) {
pcercuei 0:df031b60ca29 363 errno = ENOMEM;
pcercuei 0:df031b60ca29 364 goto err_free_description;
pcercuei 0:df031b60ca29 365 }
pcercuei 0:df031b60ca29 366
pcercuei 0:df031b60ca29 367 pdata->port = port;
pcercuei 0:df031b60ca29 368 pdata->timeout_ms = DEFAULT_TIMEOUT_MS;
pcercuei 0:df031b60ca29 369
pcercuei 0:df031b60ca29 370 pdata->lock = iio_mutex_create();
pcercuei 0:df031b60ca29 371 if (!pdata->lock) {
pcercuei 0:df031b60ca29 372 errno = ENOMEM;
pcercuei 0:df031b60ca29 373 goto err_free_pdata;
pcercuei 0:df031b60ca29 374 }
pcercuei 0:df031b60ca29 375
pcercuei 0:df031b60ca29 376 pdata->iiod_client = iiod_client_new(pdata, pdata->lock,
pcercuei 0:df031b60ca29 377 &serial_iiod_client_ops);
pcercuei 0:df031b60ca29 378 if (!pdata->iiod_client)
pcercuei 0:df031b60ca29 379 goto err_destroy_mutex;
pcercuei 0:df031b60ca29 380
pcercuei 0:df031b60ca29 381 ctx = iiod_client_create_context(pdata->iiod_client, NULL);
pcercuei 0:df031b60ca29 382 if (!ctx)
pcercuei 0:df031b60ca29 383 goto err_destroy_iiod_client;
pcercuei 0:df031b60ca29 384
pcercuei 0:df031b60ca29 385 ctx->name = "serial";
pcercuei 0:df031b60ca29 386 ctx->ops = &serial_ops;
pcercuei 0:df031b60ca29 387 ctx->pdata = pdata;
pcercuei 0:df031b60ca29 388 ctx->description = description;
pcercuei 0:df031b60ca29 389
pcercuei 0:df031b60ca29 390 for (i = 0; i < iio_context_get_devices_count(ctx); i++) {
pcercuei 0:df031b60ca29 391 struct iio_device *dev = iio_context_get_device(ctx, i);
pcercuei 0:df031b60ca29 392
pcercuei 0:df031b60ca29 393 dev->pdata = zalloc(sizeof(*dev->pdata));
pcercuei 0:df031b60ca29 394 if (!dev->pdata) {
pcercuei 0:df031b60ca29 395 ret = -ENOMEM;
pcercuei 0:df031b60ca29 396 goto err_context_destroy;
pcercuei 0:df031b60ca29 397 }
pcercuei 0:df031b60ca29 398 }
pcercuei 0:df031b60ca29 399
pcercuei 0:df031b60ca29 400 return ctx;
pcercuei 0:df031b60ca29 401
pcercuei 0:df031b60ca29 402 err_context_destroy:
pcercuei 0:df031b60ca29 403 iio_context_destroy(ctx);
pcercuei 0:df031b60ca29 404 errno = -ret;
pcercuei 0:df031b60ca29 405 return NULL;
pcercuei 0:df031b60ca29 406
pcercuei 0:df031b60ca29 407 err_destroy_iiod_client:
pcercuei 0:df031b60ca29 408 iiod_client_destroy(pdata->iiod_client);
pcercuei 0:df031b60ca29 409 err_destroy_mutex:
pcercuei 0:df031b60ca29 410 iio_mutex_destroy(pdata->lock);
pcercuei 0:df031b60ca29 411 err_free_pdata:
pcercuei 0:df031b60ca29 412 free(pdata);
pcercuei 0:df031b60ca29 413 err_free_description:
pcercuei 0:df031b60ca29 414 free(description);
pcercuei 0:df031b60ca29 415 err_close_port:
pcercuei 0:df031b60ca29 416 sp_close(port);
pcercuei 0:df031b60ca29 417 err_free_port:
pcercuei 0:df031b60ca29 418 sp_free_port(port);
pcercuei 0:df031b60ca29 419 return NULL;
pcercuei 0:df031b60ca29 420 }
pcercuei 0:df031b60ca29 421
pcercuei 0:df031b60ca29 422 static int serial_parse_params(const char *params,
pcercuei 0:df031b60ca29 423 unsigned int *baud_rate, unsigned int *bits,
pcercuei 0:df031b60ca29 424 enum sp_parity *parity, enum sp_flowcontrol *flow)
pcercuei 0:df031b60ca29 425 {
pcercuei 0:df031b60ca29 426 char *end;
pcercuei 0:df031b60ca29 427
pcercuei 0:df031b60ca29 428 *baud_rate = strtoul(params, &end, 10);
pcercuei 0:df031b60ca29 429 if (params == end)
pcercuei 0:df031b60ca29 430 return -EINVAL;
pcercuei 0:df031b60ca29 431
pcercuei 0:df031b60ca29 432 switch (*end) {
pcercuei 0:df031b60ca29 433 case '\0':
pcercuei 0:df031b60ca29 434 /* Default settings */
pcercuei 0:df031b60ca29 435 *bits = 8;
pcercuei 0:df031b60ca29 436 *parity = SP_PARITY_NONE;
pcercuei 0:df031b60ca29 437 *flow = SP_FLOWCONTROL_NONE;
pcercuei 0:df031b60ca29 438 return 0;
pcercuei 0:df031b60ca29 439 case 'n':
pcercuei 0:df031b60ca29 440 *parity = SP_PARITY_NONE;
pcercuei 0:df031b60ca29 441 break;
pcercuei 0:df031b60ca29 442 case 'o':
pcercuei 0:df031b60ca29 443 *parity = SP_PARITY_ODD;
pcercuei 0:df031b60ca29 444 break;
pcercuei 0:df031b60ca29 445 case 'e':
pcercuei 0:df031b60ca29 446 *parity = SP_PARITY_EVEN;
pcercuei 0:df031b60ca29 447 break;
pcercuei 0:df031b60ca29 448 case 'm':
pcercuei 0:df031b60ca29 449 *parity = SP_PARITY_MARK;
pcercuei 0:df031b60ca29 450 break;
pcercuei 0:df031b60ca29 451 case 's':
pcercuei 0:df031b60ca29 452 *parity = SP_PARITY_SPACE;
pcercuei 0:df031b60ca29 453 break;
pcercuei 0:df031b60ca29 454 default:
pcercuei 0:df031b60ca29 455 return -EINVAL;
pcercuei 0:df031b60ca29 456 }
pcercuei 0:df031b60ca29 457
pcercuei 0:df031b60ca29 458 params = (const char *)((uintptr_t) end + 1);
pcercuei 0:df031b60ca29 459
pcercuei 0:df031b60ca29 460 if (!*params) {
pcercuei 0:df031b60ca29 461 *bits = 8;
pcercuei 0:df031b60ca29 462 *flow = SP_FLOWCONTROL_NONE;
pcercuei 0:df031b60ca29 463 return 0;
pcercuei 0:df031b60ca29 464 }
pcercuei 0:df031b60ca29 465
pcercuei 0:df031b60ca29 466 *bits = strtoul(params, &end, 10);
pcercuei 0:df031b60ca29 467 if (params == end)
pcercuei 0:df031b60ca29 468 return -EINVAL;
pcercuei 0:df031b60ca29 469
pcercuei 0:df031b60ca29 470 switch (*end) {
pcercuei 0:df031b60ca29 471 case '\0':
pcercuei 0:df031b60ca29 472 *flow = SP_FLOWCONTROL_NONE;
pcercuei 0:df031b60ca29 473 return 0;
pcercuei 0:df031b60ca29 474 case 'x':
pcercuei 0:df031b60ca29 475 *flow = SP_FLOWCONTROL_XONXOFF;
pcercuei 0:df031b60ca29 476 break;
pcercuei 0:df031b60ca29 477 case 'r':
pcercuei 0:df031b60ca29 478 *flow = SP_FLOWCONTROL_RTSCTS;
pcercuei 0:df031b60ca29 479 break;
pcercuei 0:df031b60ca29 480 case 'd':
pcercuei 0:df031b60ca29 481 *flow = SP_FLOWCONTROL_DTRDSR;
pcercuei 0:df031b60ca29 482 break;
pcercuei 0:df031b60ca29 483 default:
pcercuei 0:df031b60ca29 484 return -EINVAL;
pcercuei 0:df031b60ca29 485 }
pcercuei 0:df031b60ca29 486
pcercuei 0:df031b60ca29 487 /* We should have a '\0' after the flow character */
pcercuei 0:df031b60ca29 488 if (end[1])
pcercuei 0:df031b60ca29 489 return -EINVAL;
pcercuei 0:df031b60ca29 490 else
pcercuei 0:df031b60ca29 491 return 0;
pcercuei 0:df031b60ca29 492 }
pcercuei 0:df031b60ca29 493
pcercuei 0:df031b60ca29 494 struct iio_context * serial_create_context_from_uri(const char *uri)
pcercuei 0:df031b60ca29 495 {
pcercuei 0:df031b60ca29 496 struct iio_context *ctx = NULL;
pcercuei 0:df031b60ca29 497 char *comma, *uri_dup;
pcercuei 0:df031b60ca29 498 unsigned int baud_rate, bits;
pcercuei 0:df031b60ca29 499 enum sp_parity parity;
pcercuei 0:df031b60ca29 500 enum sp_flowcontrol flow;
pcercuei 0:df031b60ca29 501 int ret;
pcercuei 0:df031b60ca29 502
pcercuei 0:df031b60ca29 503 if (strncmp(uri, "serial:", sizeof("serial:") - 1) != 0)
pcercuei 0:df031b60ca29 504 goto err_bad_uri;
pcercuei 0:df031b60ca29 505
pcercuei 0:df031b60ca29 506 uri_dup = iio_strdup((const char *)
pcercuei 0:df031b60ca29 507 ((uintptr_t) uri + sizeof("serial:") - 1));
pcercuei 0:df031b60ca29 508 if (!uri_dup) {
pcercuei 0:df031b60ca29 509 errno = ENOMEM;
pcercuei 0:df031b60ca29 510 return NULL;
pcercuei 0:df031b60ca29 511 }
pcercuei 0:df031b60ca29 512
pcercuei 0:df031b60ca29 513 comma = strchr(uri_dup, ',');
pcercuei 0:df031b60ca29 514 if (!comma)
pcercuei 0:df031b60ca29 515 goto err_free_dup;
pcercuei 0:df031b60ca29 516
pcercuei 0:df031b60ca29 517 *comma = '\0';
pcercuei 0:df031b60ca29 518
pcercuei 0:df031b60ca29 519 ret = serial_parse_params((char *)((uintptr_t) comma + 1),
pcercuei 0:df031b60ca29 520 &baud_rate, &bits, &parity, &flow);
pcercuei 0:df031b60ca29 521 if (ret)
pcercuei 0:df031b60ca29 522 goto err_free_dup;
pcercuei 0:df031b60ca29 523
pcercuei 0:df031b60ca29 524 ctx = serial_create_context(uri_dup, baud_rate, bits, parity, flow);
pcercuei 0:df031b60ca29 525
pcercuei 0:df031b60ca29 526 free(uri_dup);
pcercuei 0:df031b60ca29 527 return ctx;
pcercuei 0:df031b60ca29 528
pcercuei 0:df031b60ca29 529 err_free_dup:
pcercuei 0:df031b60ca29 530 free(uri_dup);
pcercuei 0:df031b60ca29 531 err_bad_uri:
pcercuei 0:df031b60ca29 532 ERROR("Bad URI: \'%s\'\n", uri);
pcercuei 3:d147beabba0e 533 errno = EINVAL;
pcercuei 0:df031b60ca29 534 return NULL;
pcercuei 0:df031b60ca29 535 }
pcercuei 0:df031b60ca29 536