blob: b3ea9393f7956f1c8d6a9341bcf3ebe663451655 [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
11struct iio_buffer * iio_device_create_buffer(const struct iio_device *dev,
Paul Cercueil66ba1712014-04-01 16:11:48 +020012 size_t samples_count, bool is_output)
Paul Cercueila689cd92014-03-20 16:37:25 +010013{
Paul Cercueilde5a3472014-04-01 14:09:56 +020014 struct iio_buffer *buf;
15 unsigned int sample_size = iio_device_get_sample_size(dev);
16 if (!sample_size)
17 return NULL;
18
19 buf = malloc(sizeof(*buf));
Paul Cercueila689cd92014-03-20 16:37:25 +010020 if (!buf)
21 return NULL;
22
Paul Cercueil66ba1712014-04-01 16:11:48 +020023 buf->is_output = is_output;
Paul Cercueilde5a3472014-04-01 14:09:56 +020024 buf->sample_size = sample_size;
Paul Cercueilf88f8852014-04-01 11:50:59 +020025 buf->length = buf->sample_size * samples_count;
Paul Cercueila689cd92014-03-20 16:37:25 +010026 buf->dev = dev;
Paul Cercueil645ab972014-03-24 14:36:12 +010027 buf->mask = calloc(dev->words, sizeof(*buf->mask));
Paul Cercueila689cd92014-03-20 16:37:25 +010028 if (!buf->mask)
29 goto err_free_buf;
Paul Cercueila689cd92014-03-20 16:37:25 +010030
Paul Cercueil93f7e1f2014-04-23 16:49:56 +020031 if (dev->ctx->ops->get_buffer) {
32 /* We will use the get_buffer backend function is available.
33 * In that case, we don't need our own buffer. */
34 buf->buffer = NULL;
35 } else {
36 buf->buffer = malloc(buf->length);
37 if (!buf->buffer)
38 goto err_free_mask;
39 }
Paul Cercueila689cd92014-03-20 16:37:25 +010040
Paul Cercueil66ba1712014-04-01 16:11:48 +020041 if (is_output)
42 buf->data_length = buf->length;
43 else
44 buf->data_length = 0;
45
Paul Cercueil93f17052014-04-02 13:56:27 +020046 if (!iio_device_open(dev, samples_count))
Paul Cercueilde5a3472014-04-01 14:09:56 +020047 return buf;
Paul Cercueil93f17052014-04-02 13:56:27 +020048
Paul Cercueil93f7e1f2014-04-23 16:49:56 +020049 if (!dev->ctx->ops->get_buffer)
50 free(buf->buffer);
Paul Cercueilde5a3472014-04-01 14:09:56 +020051err_free_mask:
Paul Cercueila689cd92014-03-20 16:37:25 +010052 free(buf->mask);
53err_free_buf:
54 free(buf);
55 return NULL;
56}
57
58void iio_buffer_destroy(struct iio_buffer *buffer)
59{
Paul Cercueilde5a3472014-04-01 14:09:56 +020060 iio_device_close(buffer->dev);
Paul Cercueil93f7e1f2014-04-23 16:49:56 +020061 if (!buffer->dev->ctx->ops->get_buffer)
62 free(buffer->buffer);
Paul Cercueila689cd92014-03-20 16:37:25 +010063 free(buffer->mask);
64 free(buffer);
65}
66
Paul Cercueilcbe78562014-04-01 14:42:20 +020067ssize_t iio_buffer_refill(struct iio_buffer *buffer)
Paul Cercueila689cd92014-03-20 16:37:25 +010068{
Paul Cercueil66ba1712014-04-01 16:11:48 +020069 ssize_t read;
Paul Cercueil93f7e1f2014-04-23 16:49:56 +020070 const struct iio_device *dev = buffer->dev;
Paul Cercueil66ba1712014-04-01 16:11:48 +020071
72 if (buffer->is_output)
73 return -EINVAL;
74
Paul Cercueil93f7e1f2014-04-23 16:49:56 +020075 if (dev->ctx->ops->get_buffer) {
76 void *buf;
77 read = dev->ctx->ops->get_buffer(dev, &buf,
78 buffer->mask, dev->words);
79 if (read >= 0)
80 buffer->buffer = buf;
81 } else {
82 read = iio_device_read_raw(dev, buffer->buffer, buffer->length,
83 buffer->mask, dev->words);
84 }
85
Paul Cercueilcbe78562014-04-01 14:42:20 +020086 if (read >= 0)
87 buffer->data_length = read;
88 return read;
Paul Cercueila689cd92014-03-20 16:37:25 +010089}
90
Paul Cercueilea32b042014-04-11 13:47:12 +020091ssize_t iio_buffer_push(const struct iio_buffer *buffer)
Paul Cercueilfa2185d2014-04-01 16:13:32 +020092{
93 if (!buffer->is_output)
94 return -EINVAL;
95
96 return iio_device_write_raw(buffer->dev,
97 buffer->buffer, buffer->length);
98}
99
Paul Cercueila689cd92014-03-20 16:37:25 +0100100static ssize_t callback_wrapper(const struct iio_channel *chn,
101 void *buf, void *d)
102{
103 struct callback_wrapper_data *data = d;
104 if (chn->index >= 0 && TEST_BIT(data->mask, chn->index))
105 return data->callback(chn, buf,
106 chn->format.length / 8, data->data);
107 else
108 return 0;
109}
110
111ssize_t iio_buffer_foreach_sample(struct iio_buffer *buffer,
112 ssize_t (*callback)(const struct iio_channel *,
113 void *, size_t, void *), void *d)
114{
115 struct callback_wrapper_data data = {
116 .callback = callback,
117 .data = d,
Paul Cercueil645ab972014-03-24 14:36:12 +0100118 .mask = buffer->dev->mask,
Paul Cercueila689cd92014-03-20 16:37:25 +0100119 };
120
121 if (buffer->data_length < buffer->sample_size)
122 return 0;
123
124 return iio_device_process_samples(buffer->dev,
Paul Cercueil645ab972014-03-24 14:36:12 +0100125 buffer->mask, buffer->dev->words, buffer->buffer,
Paul Cercueila689cd92014-03-20 16:37:25 +0100126 buffer->data_length, callback_wrapper, &data);
127}
Paul Cercueil95347b92014-03-21 09:50:17 +0100128
Paul Cercueil6d927162014-04-16 15:53:22 +0200129void * iio_buffer_start(const struct iio_buffer *buffer)
130{
131 return buffer->buffer;
132}
133
Paul Cercueil95347b92014-03-21 09:50:17 +0100134void * iio_buffer_first(const struct iio_buffer *buffer,
135 const struct iio_channel *chn)
136{
137 size_t len;
138 unsigned int i;
Paul Cercueil6e7f79e2014-04-04 12:27:24 +0200139 uintptr_t ptr = (uintptr_t) buffer->buffer;
Paul Cercueil95347b92014-03-21 09:50:17 +0100140
Paul Cercueil645ab972014-03-24 14:36:12 +0100141 if (!iio_channel_is_enabled(chn))
Paul Cercueil95347b92014-03-21 09:50:17 +0100142 return iio_buffer_end(buffer);
143
144 for (i = 0; i < buffer->dev->nb_channels; i++) {
145 struct iio_channel *cur = buffer->dev->channels[i];
146 len = cur->format.length / 8;
147
148 /* NOTE: dev->channels are ordered by index */
149 if (cur->index < 0 || cur->index == chn->index)
150 break;
151
Paul Cercueil6e7f79e2014-04-04 12:27:24 +0200152 if (ptr % len)
153 ptr += len - (ptr % len);
Paul Cercueil95347b92014-03-21 09:50:17 +0100154 ptr += len;
155 }
156
157 len = chn->format.length / 8;
Paul Cercueil6e7f79e2014-04-04 12:27:24 +0200158 if (ptr % len)
159 ptr += len - (ptr % len);
160 return (void *) ptr;
Paul Cercueil95347b92014-03-21 09:50:17 +0100161}
162
Paul Cercueil10682b32014-04-04 12:34:37 +0200163ptrdiff_t iio_buffer_step(const struct iio_buffer *buffer)
Paul Cercueil95347b92014-03-21 09:50:17 +0100164{
Paul Cercueil645ab972014-03-24 14:36:12 +0100165 return (ptrdiff_t) iio_device_get_sample_size_mask(buffer->dev,
166 buffer->mask, buffer->dev->words);
Paul Cercueil95347b92014-03-21 09:50:17 +0100167}
168
169void * iio_buffer_end(const struct iio_buffer *buffer)
170{
Paul Cercueil6e7f79e2014-04-04 12:27:24 +0200171 return (void *) ((uintptr_t) buffer->buffer + buffer->data_length);
Paul Cercueil95347b92014-03-21 09:50:17 +0100172}