blob: 0f6ed66754a67e5130fb2472c214fa027a4d7c42 [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 Cercueilf88f8852014-04-01 11:50:59 +020031 buf->buffer = malloc(buf->length);
Paul Cercueilde5a3472014-04-01 14:09:56 +020032 if (!buf->buffer)
33 goto err_free_mask;
Paul Cercueila689cd92014-03-20 16:37:25 +010034
Paul Cercueil66ba1712014-04-01 16:11:48 +020035 if (is_output)
36 buf->data_length = buf->length;
37 else
38 buf->data_length = 0;
39
Paul Cercueil93f17052014-04-02 13:56:27 +020040 if (!iio_device_open(dev, samples_count))
Paul Cercueilde5a3472014-04-01 14:09:56 +020041 return buf;
Paul Cercueil93f17052014-04-02 13:56:27 +020042
43 free(buf->buffer);
Paul Cercueilde5a3472014-04-01 14:09:56 +020044err_free_mask:
Paul Cercueila689cd92014-03-20 16:37:25 +010045 free(buf->mask);
46err_free_buf:
47 free(buf);
48 return NULL;
49}
50
51void iio_buffer_destroy(struct iio_buffer *buffer)
52{
Paul Cercueilde5a3472014-04-01 14:09:56 +020053 iio_device_close(buffer->dev);
Paul Cercueila689cd92014-03-20 16:37:25 +010054 free(buffer->buffer);
Paul Cercueila689cd92014-03-20 16:37:25 +010055 free(buffer->mask);
56 free(buffer);
57}
58
Paul Cercueilcbe78562014-04-01 14:42:20 +020059ssize_t iio_buffer_refill(struct iio_buffer *buffer)
Paul Cercueila689cd92014-03-20 16:37:25 +010060{
Paul Cercueil66ba1712014-04-01 16:11:48 +020061 ssize_t read;
62
63 if (buffer->is_output)
64 return -EINVAL;
65
66 read = iio_device_read_raw(buffer->dev,
Paul Cercueila689cd92014-03-20 16:37:25 +010067 buffer->buffer, buffer->length,
Paul Cercueil645ab972014-03-24 14:36:12 +010068 buffer->mask, buffer->dev->words);
Paul Cercueilcbe78562014-04-01 14:42:20 +020069 if (read >= 0)
70 buffer->data_length = read;
71 return read;
Paul Cercueila689cd92014-03-20 16:37:25 +010072}
73
Paul Cercueilfa2185d2014-04-01 16:13:32 +020074int iio_buffer_push(const struct iio_buffer *buffer)
75{
76 if (!buffer->is_output)
77 return -EINVAL;
78
79 return iio_device_write_raw(buffer->dev,
80 buffer->buffer, buffer->length);
81}
82
Paul Cercueila689cd92014-03-20 16:37:25 +010083static ssize_t callback_wrapper(const struct iio_channel *chn,
84 void *buf, void *d)
85{
86 struct callback_wrapper_data *data = d;
87 if (chn->index >= 0 && TEST_BIT(data->mask, chn->index))
88 return data->callback(chn, buf,
89 chn->format.length / 8, data->data);
90 else
91 return 0;
92}
93
94ssize_t iio_buffer_foreach_sample(struct iio_buffer *buffer,
95 ssize_t (*callback)(const struct iio_channel *,
96 void *, size_t, void *), void *d)
97{
98 struct callback_wrapper_data data = {
99 .callback = callback,
100 .data = d,
Paul Cercueil645ab972014-03-24 14:36:12 +0100101 .mask = buffer->dev->mask,
Paul Cercueila689cd92014-03-20 16:37:25 +0100102 };
103
104 if (buffer->data_length < buffer->sample_size)
105 return 0;
106
107 return iio_device_process_samples(buffer->dev,
Paul Cercueil645ab972014-03-24 14:36:12 +0100108 buffer->mask, buffer->dev->words, buffer->buffer,
Paul Cercueila689cd92014-03-20 16:37:25 +0100109 buffer->data_length, callback_wrapper, &data);
110}
Paul Cercueil95347b92014-03-21 09:50:17 +0100111
112void * iio_buffer_first(const struct iio_buffer *buffer,
113 const struct iio_channel *chn)
114{
115 size_t len;
116 unsigned int i;
117 void *ptr = buffer->buffer;
118
Paul Cercueil645ab972014-03-24 14:36:12 +0100119 if (!iio_channel_is_enabled(chn))
Paul Cercueil95347b92014-03-21 09:50:17 +0100120 return iio_buffer_end(buffer);
121
122 for (i = 0; i < buffer->dev->nb_channels; i++) {
123 struct iio_channel *cur = buffer->dev->channels[i];
124 len = cur->format.length / 8;
125
126 /* NOTE: dev->channels are ordered by index */
127 if (cur->index < 0 || cur->index == chn->index)
128 break;
129
130 if ((uintptr_t) ptr % len)
131 ptr += len - ((uintptr_t) ptr % len);
132 ptr += len;
133 }
134
135 len = chn->format.length / 8;
136 if ((uintptr_t) ptr % len)
137 ptr += len - ((uintptr_t) ptr % len);
138 return ptr;
139}
140
141ptrdiff_t iio_buffer_step(const struct iio_buffer *buffer,
142 const struct iio_channel *chn)
143{
Paul Cercueil645ab972014-03-24 14:36:12 +0100144 return (ptrdiff_t) iio_device_get_sample_size_mask(buffer->dev,
145 buffer->mask, buffer->dev->words);
Paul Cercueil95347b92014-03-21 09:50:17 +0100146}
147
148void * iio_buffer_end(const struct iio_buffer *buffer)
149{
150 return buffer->buffer + buffer->data_length;
151}