• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * libiio - Library for interfacing industrial I/O (IIO) devices
3  *
4  * Copyright (C) 2014-2015 Analog Devices, Inc.
5  * Author: Paul Cercueil <paul.cercueil@analog.com>
6  *
7  * This library is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Lesser General Public
9  * License as published by the Free Software Foundation; either
10  * version 2.1 of the License, or (at your option) any later version.
11  *
12  * This library is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * Lesser General Public License for more details.
16  *
17  * */
18 
19 #include "iio-config.h"
20 #include "iio-private.h"
21 
22 #include <errno.h>
23 #include <string.h>
24 
25 struct callback_wrapper_data {
26 	ssize_t (*callback)(const struct iio_channel *, void *, size_t, void *);
27 	void *data;
28 	uint32_t *mask;
29 };
30 
device_is_high_speed(const struct iio_device * dev)31 static bool device_is_high_speed(const struct iio_device *dev)
32 {
33 	/* Little trick: We call the backend's get_buffer() function, which is
34 	 * for now only implemented in the Local backend, with a NULL pointer.
35 	 * It will return -ENOSYS if the device is not high speed, and either
36 	 * -EBADF or -EINVAL otherwise. */
37 	const struct iio_backend_ops *ops = dev->ctx->ops;
38 	return !!ops->get_buffer &&
39 		(ops->get_buffer(dev, NULL, 0, NULL, 0) != -ENOSYS);
40 }
41 
iio_device_create_buffer(const struct iio_device * dev,size_t samples_count,bool cyclic)42 struct iio_buffer * iio_device_create_buffer(const struct iio_device *dev,
43 		size_t samples_count, bool cyclic)
44 {
45 	int ret = -EINVAL;
46 	struct iio_buffer *buf;
47 	unsigned int sample_size = iio_device_get_sample_size(dev);
48 
49 	if (!sample_size || !samples_count)
50 		goto err_set_errno;
51 
52 	buf = malloc(sizeof(*buf));
53 	if (!buf) {
54 		ret = -ENOMEM;
55 		goto err_set_errno;
56 	}
57 
58 	buf->dev_sample_size = sample_size;
59 	buf->length = sample_size * samples_count;
60 	buf->dev = dev;
61 	buf->mask = calloc(dev->words, sizeof(*buf->mask));
62 	if (!buf->mask) {
63 		ret = -ENOMEM;
64 		goto err_free_buf;
65 	}
66 
67 	/* Set the default channel mask to the one used by the device.
68 	 * While input buffers will erase this as soon as the refill function
69 	 * is used, it is useful for output buffers, as it permits
70 	 * iio_buffer_foreach_sample to be used. */
71 	memcpy(buf->mask, dev->mask, dev->words * sizeof(*buf->mask));
72 
73 	ret = iio_device_open(dev, samples_count, cyclic);
74 	if (ret < 0)
75 		goto err_free_mask;
76 
77 	buf->dev_is_high_speed = device_is_high_speed(dev);
78 	if (buf->dev_is_high_speed) {
79 		/* Dequeue the first buffer, so that buf->buffer is correctly
80 		 * initialized */
81 		buf->buffer = NULL;
82 		if (iio_device_is_tx(dev)) {
83 			ret = dev->ctx->ops->get_buffer(dev, &buf->buffer,
84 					buf->length, buf->mask, dev->words);
85 			if (ret < 0)
86 				goto err_close_device;
87 		}
88 	} else {
89 		buf->buffer = malloc(buf->length);
90 		if (!buf->buffer) {
91 			ret = -ENOMEM;
92 			goto err_close_device;
93 		}
94 	}
95 
96 	buf->sample_size = iio_device_get_sample_size_mask(dev,
97 			buf->mask, dev->words);
98 	buf->data_length = buf->length;
99 	return buf;
100 
101 err_close_device:
102 	iio_device_close(dev);
103 err_free_mask:
104 	free(buf->mask);
105 err_free_buf:
106 	free(buf);
107 err_set_errno:
108 	errno = -ret;
109 	return NULL;
110 }
111 
iio_buffer_destroy(struct iio_buffer * buffer)112 void iio_buffer_destroy(struct iio_buffer *buffer)
113 {
114 	iio_device_close(buffer->dev);
115 	if (!buffer->dev_is_high_speed)
116 		free(buffer->buffer);
117 	free(buffer->mask);
118 	free(buffer);
119 }
120 
iio_buffer_get_poll_fd(struct iio_buffer * buffer)121 int iio_buffer_get_poll_fd(struct iio_buffer *buffer)
122 {
123 	return iio_device_get_poll_fd(buffer->dev);
124 }
125 
iio_buffer_set_blocking_mode(struct iio_buffer * buffer,bool blocking)126 int iio_buffer_set_blocking_mode(struct iio_buffer *buffer, bool blocking)
127 {
128 	return iio_device_set_blocking_mode(buffer->dev, blocking);
129 }
130 
iio_buffer_refill(struct iio_buffer * buffer)131 ssize_t iio_buffer_refill(struct iio_buffer *buffer)
132 {
133 	ssize_t read;
134 	const struct iio_device *dev = buffer->dev;
135 
136 	if (buffer->dev_is_high_speed) {
137 		read = dev->ctx->ops->get_buffer(dev, &buffer->buffer,
138 				buffer->length, buffer->mask, dev->words);
139 	} else {
140 		read = iio_device_read_raw(dev, buffer->buffer, buffer->length,
141 				buffer->mask, dev->words);
142 	}
143 
144 	if (read >= 0) {
145 		buffer->data_length = read;
146 		buffer->sample_size = iio_device_get_sample_size_mask(dev,
147 				buffer->mask, dev->words);
148 	}
149 	return read;
150 }
151 
iio_buffer_push(struct iio_buffer * buffer)152 ssize_t iio_buffer_push(struct iio_buffer *buffer)
153 {
154 	const struct iio_device *dev = buffer->dev;
155 	ssize_t ret;
156 
157 	if (buffer->dev_is_high_speed) {
158 		void *buf;
159 		ret = dev->ctx->ops->get_buffer(dev, &buf,
160 				buffer->data_length, buffer->mask, dev->words);
161 		if (ret >= 0) {
162 			buffer->buffer = buf;
163 			ret = (ssize_t) buffer->data_length;
164 		}
165 	} else {
166 		void *ptr = buffer->buffer;
167 		size_t tmp_len;
168 
169 		/* iio_device_write_raw doesn't guarantee that all bytes are
170 		 * written */
171 		for (tmp_len = buffer->data_length; tmp_len; ) {
172 			ret = iio_device_write_raw(dev, ptr, tmp_len);
173 			if (ret < 0)
174 				goto out_reset_data_length;
175 
176 			tmp_len -= ret;
177 			ptr = (void *) ((uintptr_t) ptr + ret);
178 		}
179 
180 		ret = (ssize_t) buffer->data_length;
181 	}
182 
183 out_reset_data_length:
184 	buffer->data_length = buffer->length;
185 	return ret;
186 }
187 
iio_buffer_push_partial(struct iio_buffer * buffer,size_t samples_count)188 ssize_t iio_buffer_push_partial(struct iio_buffer *buffer, size_t samples_count)
189 {
190 	size_t new_len = samples_count * buffer->dev_sample_size;
191 
192 	if (new_len == 0 || new_len > buffer->length)
193 		return -EINVAL;
194 
195 	buffer->data_length = new_len;
196 	return iio_buffer_push(buffer);
197 }
198 
iio_buffer_foreach_sample(struct iio_buffer * buffer,ssize_t (* callback)(const struct iio_channel *,void *,size_t,void *),void * d)199 ssize_t iio_buffer_foreach_sample(struct iio_buffer *buffer,
200 		ssize_t (*callback)(const struct iio_channel *,
201 			void *, size_t, void *), void *d)
202 {
203 	uintptr_t ptr = (uintptr_t) buffer->buffer,
204 		  start = ptr,
205 		  end = ptr + buffer->data_length;
206 	const struct iio_device *dev = buffer->dev;
207 	ssize_t processed = 0;
208 
209 	if (buffer->sample_size == 0)
210 		return -EINVAL;
211 
212 	if (buffer->data_length < buffer->dev_sample_size)
213 		return 0;
214 
215 	while (end - ptr >= (size_t) buffer->sample_size) {
216 		unsigned int i;
217 
218 		for (i = 0; i < dev->nb_channels; i++) {
219 			const struct iio_channel *chn = dev->channels[i];
220 			unsigned int length = chn->format.length / 8;
221 
222 			if (chn->index < 0)
223 				break;
224 
225 			/* Test if the buffer has samples for this channel */
226 			if (!TEST_BIT(buffer->mask, chn->number))
227 				continue;
228 
229 			if ((ptr - start) % length)
230 				ptr += length - ((ptr - start) % length);
231 
232 			/* Test if the client wants samples from this channel */
233 			if (TEST_BIT(dev->mask, chn->number)) {
234 				ssize_t ret = callback(chn,
235 						(void *) ptr, length, d);
236 				if (ret < 0)
237 					return ret;
238 				else
239 					processed += ret;
240 			}
241 
242 			if (i == dev->nb_channels - 1 || dev->channels[
243 					i + 1]->index != chn->index)
244 				ptr += length * chn->format.repeat;
245 		}
246 	}
247 	return processed;
248 }
249 
iio_buffer_start(const struct iio_buffer * buffer)250 void * iio_buffer_start(const struct iio_buffer *buffer)
251 {
252 	return buffer->buffer;
253 }
254 
iio_buffer_first(const struct iio_buffer * buffer,const struct iio_channel * chn)255 void * iio_buffer_first(const struct iio_buffer *buffer,
256 		const struct iio_channel *chn)
257 {
258 	size_t len;
259 	unsigned int i;
260 	uintptr_t ptr = (uintptr_t) buffer->buffer,
261 		  start = ptr;
262 
263 	if (!iio_channel_is_enabled(chn))
264 		return iio_buffer_end(buffer);
265 
266 	for (i = 0; i < buffer->dev->nb_channels; i++) {
267 		struct iio_channel *cur = buffer->dev->channels[i];
268 		len = cur->format.length / 8 * cur->format.repeat;
269 
270 		/* NOTE: dev->channels are ordered by index */
271 		if (cur->index < 0 || cur->index == chn->index)
272 			break;
273 
274 		/* Test if the buffer has samples for this channel */
275 		if (!TEST_BIT(buffer->mask, cur->number))
276 			continue;
277 
278 		/* Two channels with the same index use the same samples */
279 		if (i > 0 && cur->index == buffer->dev->channels[i - 1]->index)
280 			continue;
281 
282 		if ((ptr - start) % len)
283 			ptr += len - ((ptr - start) % len);
284 		ptr += len;
285 	}
286 
287 	len = chn->format.length / 8;
288 	if ((ptr - start) % len)
289 		ptr += len - ((ptr - start) % len);
290 	return (void *) ptr;
291 }
292 
iio_buffer_step(const struct iio_buffer * buffer)293 ptrdiff_t iio_buffer_step(const struct iio_buffer *buffer)
294 {
295 	return (ptrdiff_t) buffer->sample_size;
296 }
297 
iio_buffer_end(const struct iio_buffer * buffer)298 void * iio_buffer_end(const struct iio_buffer *buffer)
299 {
300 	return (void *) ((uintptr_t) buffer->buffer + buffer->data_length);
301 }
302 
iio_buffer_set_data(struct iio_buffer * buf,void * data)303 void iio_buffer_set_data(struct iio_buffer *buf, void *data)
304 {
305 	buf->userdata = data;
306 }
307 
iio_buffer_get_data(const struct iio_buffer * buf)308 void * iio_buffer_get_data(const struct iio_buffer *buf)
309 {
310 	return buf->userdata;
311 }
312 
iio_buffer_get_device(const struct iio_buffer * buf)313 const struct iio_device * iio_buffer_get_device(const struct iio_buffer *buf)
314 {
315 	return buf->dev;
316 }
317 
iio_buffer_cancel(struct iio_buffer * buf)318 void iio_buffer_cancel(struct iio_buffer *buf)
319 {
320 	const struct iio_backend_ops *ops = buf->dev->ctx->ops;
321 
322 	if (ops->cancel)
323 		ops->cancel(buf->dev);
324 }
325