blob: 0e7134c249fd1e1c040bd0dc0ff5be87bad32fd5 [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>
Paul Cercueil9efeb062014-04-29 13:12:45 +02004#include <string.h>
Paul Cercueil66ba1712014-04-01 16:11:48 +02005
Paul Cercueila689cd92014-03-20 16:37:25 +01006struct callback_wrapper_data {
7 ssize_t (*callback)(const struct iio_channel *, void *, size_t, void *);
8 void *data;
9 uint32_t *mask;
10};
11
Paul Cercueil2a74bd72014-04-28 13:18:48 +020012static bool device_is_high_speed(const struct iio_device *dev)
13{
14 /* Little trick: We call the backend's get_buffer() function, which is
15 * for now only implemented in the Local backend, with a NULL pointer.
16 * It will return -ENOSYS if the device is not high speed, and either
17 * -EBADF or -EINVAL otherwise. */
18 const struct iio_backend_ops *ops = dev->ctx->ops;
19 return !!ops->get_buffer &&
20 (ops->get_buffer(dev, NULL, NULL, 0) != -ENOSYS);
21}
22
Paul Cercueila689cd92014-03-20 16:37:25 +010023struct iio_buffer * iio_device_create_buffer(const struct iio_device *dev,
Paul Cercueileb4fb3d2014-04-25 11:33:01 +020024 size_t samples_count)
Paul Cercueila689cd92014-03-20 16:37:25 +010025{
Paul Cercueilde5a3472014-04-01 14:09:56 +020026 struct iio_buffer *buf;
27 unsigned int sample_size = iio_device_get_sample_size(dev);
28 if (!sample_size)
29 return NULL;
30
31 buf = malloc(sizeof(*buf));
Paul Cercueila689cd92014-03-20 16:37:25 +010032 if (!buf)
33 return NULL;
34
Paul Cercueilde5a3472014-04-01 14:09:56 +020035 buf->sample_size = sample_size;
Paul Cercueilf88f8852014-04-01 11:50:59 +020036 buf->length = buf->sample_size * samples_count;
Paul Cercueila689cd92014-03-20 16:37:25 +010037 buf->dev = dev;
Paul Cercueil645ab972014-03-24 14:36:12 +010038 buf->mask = calloc(dev->words, sizeof(*buf->mask));
Paul Cercueila689cd92014-03-20 16:37:25 +010039 if (!buf->mask)
40 goto err_free_buf;
Paul Cercueila689cd92014-03-20 16:37:25 +010041
Paul Cercueil9efeb062014-04-29 13:12:45 +020042 /* Set the default channel mask to the one used by the device.
43 * While input buffers will erase this as soon as the refill function
44 * is used, it is useful for output buffers, as it permits
45 * iio_buffer_foreach_sample to be used. */
46 memcpy(buf->mask, dev->mask, dev->words * sizeof(*buf->mask));
47
Paul Cercueilf17f2dc2014-04-29 15:38:57 +020048 if (iio_device_open(dev, samples_count))
49 goto err_free_mask;
50
Paul Cercueil2a74bd72014-04-28 13:18:48 +020051 buf->dev_is_high_speed = device_is_high_speed(dev);
52 if (buf->dev_is_high_speed) {
Paul Cercueil93f7e1f2014-04-23 16:49:56 +020053 /* We will use the get_buffer backend function is available.
54 * In that case, we don't need our own buffer. */
55 buf->buffer = NULL;
56 } else {
57 buf->buffer = malloc(buf->length);
58 if (!buf->buffer)
Paul Cercueilf17f2dc2014-04-29 15:38:57 +020059 goto err_close_device;
Paul Cercueil93f7e1f2014-04-23 16:49:56 +020060 }
Paul Cercueila689cd92014-03-20 16:37:25 +010061
Paul Cercueileb4fb3d2014-04-25 11:33:01 +020062 buf->data_length = buf->length;
Paul Cercueilf17f2dc2014-04-29 15:38:57 +020063 return buf;
Paul Cercueil66ba1712014-04-01 16:11:48 +020064
Paul Cercueilf17f2dc2014-04-29 15:38:57 +020065err_close_device:
66 iio_device_close(dev);
Paul Cercueilde5a3472014-04-01 14:09:56 +020067err_free_mask:
Paul Cercueila689cd92014-03-20 16:37:25 +010068 free(buf->mask);
69err_free_buf:
70 free(buf);
71 return NULL;
72}
73
74void iio_buffer_destroy(struct iio_buffer *buffer)
75{
Paul Cercueilde5a3472014-04-01 14:09:56 +020076 iio_device_close(buffer->dev);
Paul Cercueil2a74bd72014-04-28 13:18:48 +020077 if (!buffer->dev_is_high_speed)
Paul Cercueil93f7e1f2014-04-23 16:49:56 +020078 free(buffer->buffer);
Paul Cercueila689cd92014-03-20 16:37:25 +010079 free(buffer->mask);
80 free(buffer);
81}
82
Paul Cercueilcbe78562014-04-01 14:42:20 +020083ssize_t iio_buffer_refill(struct iio_buffer *buffer)
Paul Cercueila689cd92014-03-20 16:37:25 +010084{
Paul Cercueil66ba1712014-04-01 16:11:48 +020085 ssize_t read;
Paul Cercueil93f7e1f2014-04-23 16:49:56 +020086 const struct iio_device *dev = buffer->dev;
Paul Cercueil66ba1712014-04-01 16:11:48 +020087
Paul Cercueil2a74bd72014-04-28 13:18:48 +020088 if (buffer->dev_is_high_speed) {
Paul Cercueil93f7e1f2014-04-23 16:49:56 +020089 void *buf;
90 read = dev->ctx->ops->get_buffer(dev, &buf,
91 buffer->mask, dev->words);
92 if (read >= 0)
93 buffer->buffer = buf;
94 } else {
95 read = iio_device_read_raw(dev, buffer->buffer, buffer->length,
96 buffer->mask, dev->words);
97 }
98
Paul Cercueilcbe78562014-04-01 14:42:20 +020099 if (read >= 0)
100 buffer->data_length = read;
101 return read;
Paul Cercueila689cd92014-03-20 16:37:25 +0100102}
103
Paul Cercueilea32b042014-04-11 13:47:12 +0200104ssize_t iio_buffer_push(const struct iio_buffer *buffer)
Paul Cercueilfa2185d2014-04-01 16:13:32 +0200105{
Paul Cercueilfa2185d2014-04-01 16:13:32 +0200106 return iio_device_write_raw(buffer->dev,
Paul Cercueileb4fb3d2014-04-25 11:33:01 +0200107 buffer->buffer, buffer->data_length);
Paul Cercueilfa2185d2014-04-01 16:13:32 +0200108}
109
Paul Cercueila689cd92014-03-20 16:37:25 +0100110static ssize_t callback_wrapper(const struct iio_channel *chn,
111 void *buf, void *d)
112{
113 struct callback_wrapper_data *data = d;
114 if (chn->index >= 0 && TEST_BIT(data->mask, chn->index))
115 return data->callback(chn, buf,
116 chn->format.length / 8, data->data);
117 else
118 return 0;
119}
120
121ssize_t iio_buffer_foreach_sample(struct iio_buffer *buffer,
122 ssize_t (*callback)(const struct iio_channel *,
123 void *, size_t, void *), void *d)
124{
125 struct callback_wrapper_data data = {
126 .callback = callback,
127 .data = d,
Paul Cercueil645ab972014-03-24 14:36:12 +0100128 .mask = buffer->dev->mask,
Paul Cercueila689cd92014-03-20 16:37:25 +0100129 };
130
131 if (buffer->data_length < buffer->sample_size)
132 return 0;
133
134 return iio_device_process_samples(buffer->dev,
Paul Cercueil645ab972014-03-24 14:36:12 +0100135 buffer->mask, buffer->dev->words, buffer->buffer,
Paul Cercueila689cd92014-03-20 16:37:25 +0100136 buffer->data_length, callback_wrapper, &data);
137}
Paul Cercueil95347b92014-03-21 09:50:17 +0100138
Paul Cercueil6d927162014-04-16 15:53:22 +0200139void * iio_buffer_start(const struct iio_buffer *buffer)
140{
141 return buffer->buffer;
142}
143
Paul Cercueil95347b92014-03-21 09:50:17 +0100144void * iio_buffer_first(const struct iio_buffer *buffer,
145 const struct iio_channel *chn)
146{
147 size_t len;
148 unsigned int i;
Paul Cercueil6e7f79e2014-04-04 12:27:24 +0200149 uintptr_t ptr = (uintptr_t) buffer->buffer;
Paul Cercueil95347b92014-03-21 09:50:17 +0100150
Paul Cercueil645ab972014-03-24 14:36:12 +0100151 if (!iio_channel_is_enabled(chn))
Paul Cercueil95347b92014-03-21 09:50:17 +0100152 return iio_buffer_end(buffer);
153
154 for (i = 0; i < buffer->dev->nb_channels; i++) {
155 struct iio_channel *cur = buffer->dev->channels[i];
156 len = cur->format.length / 8;
157
158 /* NOTE: dev->channels are ordered by index */
159 if (cur->index < 0 || cur->index == chn->index)
160 break;
161
Paul Cercueil6e7f79e2014-04-04 12:27:24 +0200162 if (ptr % len)
163 ptr += len - (ptr % len);
Paul Cercueil95347b92014-03-21 09:50:17 +0100164 ptr += len;
165 }
166
167 len = chn->format.length / 8;
Paul Cercueil6e7f79e2014-04-04 12:27:24 +0200168 if (ptr % len)
169 ptr += len - (ptr % len);
170 return (void *) ptr;
Paul Cercueil95347b92014-03-21 09:50:17 +0100171}
172
Paul Cercueil10682b32014-04-04 12:34:37 +0200173ptrdiff_t iio_buffer_step(const struct iio_buffer *buffer)
Paul Cercueil95347b92014-03-21 09:50:17 +0100174{
Paul Cercueil645ab972014-03-24 14:36:12 +0100175 return (ptrdiff_t) iio_device_get_sample_size_mask(buffer->dev,
176 buffer->mask, buffer->dev->words);
Paul Cercueil95347b92014-03-21 09:50:17 +0100177}
178
179void * iio_buffer_end(const struct iio_buffer *buffer)
180{
Paul Cercueil6e7f79e2014-04-04 12:27:24 +0200181 return (void *) ((uintptr_t) buffer->buffer + buffer->data_length);
Paul Cercueil95347b92014-03-21 09:50:17 +0100182}