blob: 3777d9522f10d384ab3adde5b9d18fbe74a68025 [file] [log] [blame]
Paul Cercueila689cd92014-03-20 16:37:25 +01001#include "iio-private.h"
2
Paul Cercueil66ba1712014-04-01 16:11:48 +02003#include <errno.h>
4
Paul Cercueila689cd92014-03-20 16:37:25 +01005struct callback_wrapper_data {
6 ssize_t (*callback)(const struct iio_channel *, void *, size_t, void *);
7 void *data;
8 uint32_t *mask;
9};
10
Paul Cercueil2a74bd72014-04-28 13:18:48 +020011static bool device_is_high_speed(const struct iio_device *dev)
12{
13 /* Little trick: We call the backend's get_buffer() function, which is
14 * for now only implemented in the Local backend, with a NULL pointer.
15 * It will return -ENOSYS if the device is not high speed, and either
16 * -EBADF or -EINVAL otherwise. */
17 const struct iio_backend_ops *ops = dev->ctx->ops;
18 return !!ops->get_buffer &&
19 (ops->get_buffer(dev, NULL, NULL, 0) != -ENOSYS);
20}
21
Paul Cercueila689cd92014-03-20 16:37:25 +010022struct iio_buffer * iio_device_create_buffer(const struct iio_device *dev,
Paul Cercueileb4fb3d2014-04-25 11:33:01 +020023 size_t samples_count)
Paul Cercueila689cd92014-03-20 16:37:25 +010024{
Paul Cercueilde5a3472014-04-01 14:09:56 +020025 struct iio_buffer *buf;
26 unsigned int sample_size = iio_device_get_sample_size(dev);
27 if (!sample_size)
28 return NULL;
29
30 buf = malloc(sizeof(*buf));
Paul Cercueila689cd92014-03-20 16:37:25 +010031 if (!buf)
32 return NULL;
33
Paul Cercueilde5a3472014-04-01 14:09:56 +020034 buf->sample_size = sample_size;
Paul Cercueilf88f8852014-04-01 11:50:59 +020035 buf->length = buf->sample_size * samples_count;
Paul Cercueila689cd92014-03-20 16:37:25 +010036 buf->dev = dev;
Paul Cercueil645ab972014-03-24 14:36:12 +010037 buf->mask = calloc(dev->words, sizeof(*buf->mask));
Paul Cercueila689cd92014-03-20 16:37:25 +010038 if (!buf->mask)
39 goto err_free_buf;
Paul Cercueila689cd92014-03-20 16:37:25 +010040
Paul Cercueil2a74bd72014-04-28 13:18:48 +020041 buf->dev_is_high_speed = device_is_high_speed(dev);
42 if (buf->dev_is_high_speed) {
Paul Cercueil93f7e1f2014-04-23 16:49:56 +020043 /* We will use the get_buffer backend function is available.
44 * In that case, we don't need our own buffer. */
45 buf->buffer = NULL;
46 } else {
47 buf->buffer = malloc(buf->length);
48 if (!buf->buffer)
49 goto err_free_mask;
50 }
Paul Cercueila689cd92014-03-20 16:37:25 +010051
Paul Cercueileb4fb3d2014-04-25 11:33:01 +020052 buf->data_length = buf->length;
Paul Cercueil66ba1712014-04-01 16:11:48 +020053
Paul Cercueil93f17052014-04-02 13:56:27 +020054 if (!iio_device_open(dev, samples_count))
Paul Cercueilde5a3472014-04-01 14:09:56 +020055 return buf;
Paul Cercueil93f17052014-04-02 13:56:27 +020056
Paul Cercueil2a74bd72014-04-28 13:18:48 +020057 if (!buf->dev_is_high_speed)
Paul Cercueil93f7e1f2014-04-23 16:49:56 +020058 free(buf->buffer);
Paul Cercueilde5a3472014-04-01 14:09:56 +020059err_free_mask:
Paul Cercueila689cd92014-03-20 16:37:25 +010060 free(buf->mask);
61err_free_buf:
62 free(buf);
63 return NULL;
64}
65
66void iio_buffer_destroy(struct iio_buffer *buffer)
67{
Paul Cercueilde5a3472014-04-01 14:09:56 +020068 iio_device_close(buffer->dev);
Paul Cercueil2a74bd72014-04-28 13:18:48 +020069 if (!buffer->dev_is_high_speed)
Paul Cercueil93f7e1f2014-04-23 16:49:56 +020070 free(buffer->buffer);
Paul Cercueila689cd92014-03-20 16:37:25 +010071 free(buffer->mask);
72 free(buffer);
73}
74
Paul Cercueilcbe78562014-04-01 14:42:20 +020075ssize_t iio_buffer_refill(struct iio_buffer *buffer)
Paul Cercueila689cd92014-03-20 16:37:25 +010076{
Paul Cercueil66ba1712014-04-01 16:11:48 +020077 ssize_t read;
Paul Cercueil93f7e1f2014-04-23 16:49:56 +020078 const struct iio_device *dev = buffer->dev;
Paul Cercueil66ba1712014-04-01 16:11:48 +020079
Paul Cercueil2a74bd72014-04-28 13:18:48 +020080 if (buffer->dev_is_high_speed) {
Paul Cercueil93f7e1f2014-04-23 16:49:56 +020081 void *buf;
82 read = dev->ctx->ops->get_buffer(dev, &buf,
83 buffer->mask, dev->words);
84 if (read >= 0)
85 buffer->buffer = buf;
86 } else {
87 read = iio_device_read_raw(dev, buffer->buffer, buffer->length,
88 buffer->mask, dev->words);
89 }
90
Paul Cercueilcbe78562014-04-01 14:42:20 +020091 if (read >= 0)
92 buffer->data_length = read;
93 return read;
Paul Cercueila689cd92014-03-20 16:37:25 +010094}
95
Paul Cercueilea32b042014-04-11 13:47:12 +020096ssize_t iio_buffer_push(const struct iio_buffer *buffer)
Paul Cercueilfa2185d2014-04-01 16:13:32 +020097{
Paul Cercueilfa2185d2014-04-01 16:13:32 +020098 return iio_device_write_raw(buffer->dev,
Paul Cercueileb4fb3d2014-04-25 11:33:01 +020099 buffer->buffer, buffer->data_length);
Paul Cercueilfa2185d2014-04-01 16:13:32 +0200100}
101
Paul Cercueila689cd92014-03-20 16:37:25 +0100102static ssize_t callback_wrapper(const struct iio_channel *chn,
103 void *buf, void *d)
104{
105 struct callback_wrapper_data *data = d;
106 if (chn->index >= 0 && TEST_BIT(data->mask, chn->index))
107 return data->callback(chn, buf,
108 chn->format.length / 8, data->data);
109 else
110 return 0;
111}
112
113ssize_t iio_buffer_foreach_sample(struct iio_buffer *buffer,
114 ssize_t (*callback)(const struct iio_channel *,
115 void *, size_t, void *), void *d)
116{
117 struct callback_wrapper_data data = {
118 .callback = callback,
119 .data = d,
Paul Cercueil645ab972014-03-24 14:36:12 +0100120 .mask = buffer->dev->mask,
Paul Cercueila689cd92014-03-20 16:37:25 +0100121 };
122
123 if (buffer->data_length < buffer->sample_size)
124 return 0;
125
126 return iio_device_process_samples(buffer->dev,
Paul Cercueil645ab972014-03-24 14:36:12 +0100127 buffer->mask, buffer->dev->words, buffer->buffer,
Paul Cercueila689cd92014-03-20 16:37:25 +0100128 buffer->data_length, callback_wrapper, &data);
129}
Paul Cercueil95347b92014-03-21 09:50:17 +0100130
Paul Cercueil6d927162014-04-16 15:53:22 +0200131void * iio_buffer_start(const struct iio_buffer *buffer)
132{
133 return buffer->buffer;
134}
135
Paul Cercueil95347b92014-03-21 09:50:17 +0100136void * iio_buffer_first(const struct iio_buffer *buffer,
137 const struct iio_channel *chn)
138{
139 size_t len;
140 unsigned int i;
Paul Cercueil6e7f79e2014-04-04 12:27:24 +0200141 uintptr_t ptr = (uintptr_t) buffer->buffer;
Paul Cercueil95347b92014-03-21 09:50:17 +0100142
Paul Cercueil645ab972014-03-24 14:36:12 +0100143 if (!iio_channel_is_enabled(chn))
Paul Cercueil95347b92014-03-21 09:50:17 +0100144 return iio_buffer_end(buffer);
145
146 for (i = 0; i < buffer->dev->nb_channels; i++) {
147 struct iio_channel *cur = buffer->dev->channels[i];
148 len = cur->format.length / 8;
149
150 /* NOTE: dev->channels are ordered by index */
151 if (cur->index < 0 || cur->index == chn->index)
152 break;
153
Paul Cercueil6e7f79e2014-04-04 12:27:24 +0200154 if (ptr % len)
155 ptr += len - (ptr % len);
Paul Cercueil95347b92014-03-21 09:50:17 +0100156 ptr += len;
157 }
158
159 len = chn->format.length / 8;
Paul Cercueil6e7f79e2014-04-04 12:27:24 +0200160 if (ptr % len)
161 ptr += len - (ptr % len);
162 return (void *) ptr;
Paul Cercueil95347b92014-03-21 09:50:17 +0100163}
164
Paul Cercueil10682b32014-04-04 12:34:37 +0200165ptrdiff_t iio_buffer_step(const struct iio_buffer *buffer)
Paul Cercueil95347b92014-03-21 09:50:17 +0100166{
Paul Cercueil645ab972014-03-24 14:36:12 +0100167 return (ptrdiff_t) iio_device_get_sample_size_mask(buffer->dev,
168 buffer->mask, buffer->dev->words);
Paul Cercueil95347b92014-03-21 09:50:17 +0100169}
170
171void * iio_buffer_end(const struct iio_buffer *buffer)
172{
Paul Cercueil6e7f79e2014-04-04 12:27:24 +0200173 return (void *) ((uintptr_t) buffer->buffer + buffer->data_length);
Paul Cercueil95347b92014-03-21 09:50:17 +0100174}