Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Serial backend fixes #1092

Merged
merged 6 commits into from
Dec 5, 2023
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions compat.c
Original file line number Diff line number Diff line change
Expand Up @@ -410,6 +410,14 @@ struct iio_context * iio_context_clone(const struct iio_context *old_ctx)
uri = IIO_CALL(iio_attr_get_static_value)(attr);
params = IIO_CALL(iio_context_get_params)(old_ctx);

if (strncmp(uri, "local:", sizeof("local:") - 1)
&& strncmp(uri, "ip:", sizeof("ip:") - 1)) {
/* The .clone callback was only implemented by the local
* and network backends in Libiio <= v0.25. */
err = -ENOSYS;
goto err_set_errno;
}

ctx = IIO_CALL(iio_create_context)(params, uri);
err = iio_err(ctx);
if (err)
Expand Down
16 changes: 15 additions & 1 deletion iiod-responder.c
Original file line number Diff line number Diff line change
Expand Up @@ -240,12 +240,14 @@ static int iiod_responder_reader_thrd(void *d)
{
struct iiod_responder *priv = d;
struct iiod_command cmd;
struct iiod_buf cmd_buf;
struct iiod_buf cmd_buf, ok_buf;
struct iiod_io *io;
ssize_t ret = 0;

cmd_buf.ptr = &cmd;
cmd_buf.size = sizeof(cmd);
ok_buf.ptr = "0\r\n";
ok_buf.size = 3;

iio_mutex_lock(priv->lock);

Expand All @@ -254,6 +256,18 @@ static int iiod_responder_reader_thrd(void *d)

ret = iiod_rw_all(priv, NULL, &cmd_buf, 1, sizeof(cmd), true);

if (!strncmp((char *)&cmd, "BINARY\r\n", 8)) {
/* If we receive again the "BINARY\r\n" string, send a
* return code of zero and continue as usual.
* This can happen with the serial backend when the
* client disconnects and a new client appears.
* Conveniently, the string is exactly 8 bytes, which is
* the size of a iio_command. */

iiod_rw_all(priv, NULL, &ok_buf, 1, ok_buf.size, false);
continue;
}

iio_mutex_lock(priv->lock);
if (ret <= 0)
break;
Expand Down
61 changes: 54 additions & 7 deletions serial.c
Original file line number Diff line number Diff line change
Expand Up @@ -13,18 +13,25 @@
#include <iio/iio-lock.h>
#include <iio/iiod-client.h>

#include <ctype.h>
#include <errno.h>
#include <libserialport.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#ifdef _WIN32
#include <Windows.h>
#else
#include <time.h>
#endif

struct iio_context_pdata {
struct sp_port *port;
struct iiod_client *iiod_client;

struct iio_context_params params;

bool shutdown;
};

struct iio_buffer_pdata {
Expand Down Expand Up @@ -145,21 +152,44 @@ static ssize_t serial_write_data(struct iiod_client_pdata *io_data,
return ret;
}

void sleep_one_ms(void)
{
#ifdef _WIN32
Sleep(1);
#else
const struct timespec ts = {
/* One millisecond */
.tv_nsec = 1 * 1000 * 1000,
};

nanosleep(&ts, NULL);
#endif
}

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should this be in utils.c rather than here? (I guess it's a single use case?)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

utils.c is for the high-level API, we'd have to export it as a public symbol (as the serial backend can be a module) and I prefer to avoid that as much as possible.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

makes sense.

static ssize_t serial_read_data(struct iiod_client_pdata *io_data,
char *buf, size_t len, unsigned int timeout_ms)
{
struct iio_context_pdata *pdata = (struct iio_context_pdata *) io_data;
long long time_left_ms = (long long)timeout_ms;
enum sp_return sp_ret;
ssize_t ret;
ssize_t ret = 0;

sp_ret = sp_blocking_read_next(pdata->port, buf, len, timeout_ms);
ret = (ssize_t) libserialport_to_errno(sp_ret);
while (true) {
if (timeout_ms && time_left_ms <= 0)
break;

sp_ret = sp_nonblocking_read(pdata->port, buf, len);
ret = (ssize_t) libserialport_to_errno(sp_ret);
if (ret || pdata->shutdown)
break;

prm_dbg(&pdata->params, "Read returned %li: %.*s\n",
(long) ret, (int) ret, buf);
sleep_one_ms();
time_left_ms--;
}

if (ret == 0) {
prm_err(&pdata->params, "sp_blocking_read_next has timed out\n");
if (!pdata->shutdown)
prm_err(&pdata->params, "serial_read_data has timed out\n");
return -ETIMEDOUT;
}

Expand All @@ -170,6 +200,8 @@ static void serial_shutdown(struct iio_context *ctx)
{
struct iio_context_pdata *ctx_pdata = iio_context_get_pdata(ctx);

ctx_pdata->shutdown = true;

iiod_client_destroy(ctx_pdata->iiod_client);
sp_close(ctx_pdata->port);
sp_free_port(ctx_pdata->port);
Expand Down Expand Up @@ -230,6 +262,18 @@ static int serial_enable_buffer(struct iio_buffer_pdata *buf,
return iiod_client_enable_buffer(buf->pdata, nb_samples, enable);
}

static ssize_t
serial_readbuf(struct iio_buffer_pdata *buf, void *dst, size_t len)
{
return iiod_client_readbuf(buf->pdata, dst, len);
}

static ssize_t
serial_writebuf(struct iio_buffer_pdata *buf, const void *src, size_t len)
{
return iiod_client_writebuf(buf->pdata, src, len);
}

static struct iio_block_pdata *
serial_create_block(struct iio_buffer_pdata *buf, size_t size, void **data)
{
Expand Down Expand Up @@ -257,6 +301,9 @@ static const struct iio_backend_ops serial_ops = {
.free_buffer = serial_free_buffer,
.enable_buffer = serial_enable_buffer,

.readbuf = serial_readbuf,
.writebuf = serial_writebuf,

.create_block = serial_create_block,
.free_block = iiod_client_free_block,
.enqueue_block = iiod_client_enqueue_block,
Expand Down