diff --git a/iiod/responder.c b/iiod/responder.c index 4fa83e1c7..91d5fbf7f 100644 --- a/iiod/responder.c +++ b/iiod/responder.c @@ -835,6 +835,33 @@ static void handle_retry_dequeue_block(struct parser_pdata *pdata, iiod_io_send_response_code(block_entry->io, ret); } +void iiod_set_event(struct iio_event_stream *stream, + const struct iio_event *event, + int err_code_or_zero) +{ + struct evstream_entry *elm, *entry = NULL; + struct iiod_buf buf = { + .ptr = (void *)event, + .size = sizeof(*event), + }; + + iio_mutex_lock(evlist_lock); + + SLIST_FOREACH(elm, &evlist, entry) { + if (elm->stream == stream) { + entry = elm; + break; + } + } + + iio_mutex_unlock(evlist_lock); + + if (err_code_or_zero) + iiod_io_send_response_code(entry->io, err_code_or_zero); + else + iiod_io_send_response(entry->io, sizeof(*event), &buf, 1); +} + static int evstream_read(void *priv, void *d) { struct evstream_entry *entry = priv; @@ -846,6 +873,12 @@ static int evstream_read(void *priv, void *d) int ret; ret = iio_event_stream_read(entry->stream, &event, false); + if (ret == -EAGAIN) { + /* If iio_event_stream_read() returned -EAGAIN for a blocking + * read, trust that the application will call iiod_set_event(). */ + return 0; + } + if (ret < 0) return iiod_io_send_response_code(entry->io, ret); diff --git a/tinyiiod/tinyiiod.h b/tinyiiod/tinyiiod.h index 06152bd5e..a4a8d37a8 100644 --- a/tinyiiod/tinyiiod.h +++ b/tinyiiod/tinyiiod.h @@ -37,4 +37,12 @@ int iiod_interpreter(struct iio_context *ctx, ssize_t (*write_cb)(struct iiod_pdata *, const void *, size_t), const void *xml, size_t xml_len); +/* When a blocking iio_backend_ops.read_ev() is called, and there is no event, + * the callback is expected to return -EAGAIN; only then, when/if an event + * eventually occurs, the application should call iiod_set_event() once to + * answer. */ +void iiod_set_event(struct iio_event_stream *stream, + const struct iio_event *event, + int err_code_or_zero); + #endif /* __LIBTINYIIOD_H__ */