Skip to content

Commit 8a86dc7

Browse files
committed
wip: multibuffer support
1 parent 26e76f6 commit 8a86dc7

File tree

12 files changed

+805
-113
lines changed

12 files changed

+805
-113
lines changed

attr.c

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
*/
88

99
#include "iio-private.h"
10+
#include "iio/iio-backend.h"
1011
#include "sort.h"
1112

1213
#include <inttypes.h>
@@ -226,6 +227,21 @@ static const char * const attr_type_string[] = {
226227
" buffer",
227228
};
228229

230+
int iio_buffer_add_attr(struct iio_device *dev, unsigned int buf_idx,
231+
const char *name)
232+
{
233+
union iio_pointer p = { .dev = dev, };
234+
int ret;
235+
236+
ret = iio_add_attr(p, &dev->buffers[buf_idx].attrlist, name,
237+
NULL, IIO_ATTR_TYPE_BUFFER);
238+
if (ret < 0)
239+
return ret;
240+
241+
dev_dbg(dev, "Added attr \'%s\'\n", name);
242+
return 0;
243+
}
244+
229245
int iio_device_add_attr(struct iio_device *dev,
230246
const char *name, enum iio_attr_type type)
231247
{
@@ -381,6 +397,15 @@ int iio_attr_get_available(const struct iio_attr *attr, char ***list, size_t *co
381397
if (!attr)
382398
return -EINVAL;
383399

400+
/* As of now there are no available attributes for buffers and the
401+
* below wrongly detects data_available as an available kind of
402+
* attribute. If we start to see more exceptions or buffers with
403+
* valid available attributes, we can think about something like
404+
* a blacklist array.
405+
*/
406+
if (attr->type == IIO_ATTR_TYPE_BUFFER)
407+
return -ENXIO;
408+
384409
if (!string_ends_with(iio_attr_get_name(attr), "available"))
385410
return -ENXIO;
386411

buffer.c

Lines changed: 31 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
#include <errno.h>
1414
#include <iio/iio-debug.h>
1515
#include <iio/iio-lock.h>
16+
#include <stdio.h>
1617
#include <string.h>
1718

1819
void iio_buffer_set_data(struct iio_buffer *buf, void *data)
@@ -48,9 +49,13 @@ static int iio_buffer_set_enabled(const struct iio_buffer *buf, bool enabled)
4849
size_t sample_size, nb_samples = 0;
4950
bool cyclic = false;
5051

52+
printf("iio_buffer_set_enabled: block_size=%zu\n",
53+
buf->block_size);
54+
5155
if (buf->block_size) {
5256
sample_size = iio_device_get_sample_size(buf->dev, buf->mask);
5357
nb_samples = buf->block_size / sample_size;
58+
printf("iio_buffer_set_enabled: sample_size=%zu\n", sample_size);
5459
cyclic = buf->cyclic;
5560
}
5661

@@ -64,6 +69,8 @@ int iio_buffer_enable(struct iio_buffer *buffer)
6469
{
6570
int err;
6671

72+
printf("iio_buffer_enable: nb_blocks=%u\n", buffer->nb_blocks);
73+
6774
if (buffer->nb_blocks == 0) {
6875
dev_err(buffer->dev,
6976
"Cannot enable buffer before creating blocks.\n");
@@ -97,23 +104,37 @@ static int iio_buffer_enqueue_worker(void *_, void *d)
97104
return iio_block_io(d);
98105
}
99106

107+
/*
108+
* \!TODO: Evaluate matching mask with a buffer mask (might be meaningfull for
109+
* multi-buffer devices). Things will error out anyways but the error won't be
110+
* very meaningful for users.
111+
*/
100112
struct iio_buffer *
101113
iio_device_create_buffer(const struct iio_device *dev, unsigned int idx,
102114
const struct iio_channels_mask *mask)
103115
{
104116
const struct iio_backend_ops *ops = dev->ctx->ops;
117+
const struct iio_attr_list *src_attrlist;
105118
struct iio_buffer *buf;
106119
ssize_t sample_size;
107120
size_t attrlist_size;
108121
unsigned int i;
109122
int err;
110123

124+
if (idx >= dev->nb_buffers) {
125+
printf("Requested buffer index %u but device has only %u buffers\n",
126+
idx, dev->nb_buffers);
127+
return iio_ptr(-EINVAL);
128+
}
111129
if (!ops->create_buffer)
112130
return iio_ptr(-ENOSYS);
113131

114132
sample_size = iio_device_get_sample_size(dev, mask);
115-
if (sample_size < 0)
133+
if (sample_size < 0) {
134+
printf("Failed to get sample size for buffer creation %d\n",
135+
(int) sample_size);
116136
return iio_ptr((int) sample_size);
137+
}
117138
if (!sample_size)
118139
return iio_ptr(-EINVAL);
119140

@@ -125,8 +146,14 @@ iio_device_create_buffer(const struct iio_device *dev, unsigned int idx,
125146
buf->idx = idx;
126147

127148
/* Duplicate buffer attributes from the iio_device.
128-
* This ensures that those can contain a pointer to our iio_buffer */
129-
buf->attrlist.num = dev->attrlist[IIO_ATTR_TYPE_BUFFER].num;
149+
* This ensures that those can contain a pointer to our iio_buffer.
150+
* For multi-buffer devices, use per-buffer attrlist; otherwise use legacy. */
151+
if (dev->nb_buffers > 1)
152+
src_attrlist = &dev->buffers[idx].attrlist;
153+
else
154+
src_attrlist = &dev->attrlist[IIO_ATTR_TYPE_BUFFER];
155+
156+
buf->attrlist.num = src_attrlist->num;
130157
attrlist_size = buf->attrlist.num * sizeof(*buf->attrlist.attrs);
131158
buf->attrlist.attrs = malloc(attrlist_size);
132159
if (!buf->attrlist.attrs) {
@@ -135,7 +162,7 @@ iio_device_create_buffer(const struct iio_device *dev, unsigned int idx,
135162
}
136163

137164
memcpy(buf->attrlist.attrs, /* Flawfinder: ignore */
138-
dev->attrlist[IIO_ATTR_TYPE_BUFFER].attrs, attrlist_size);
165+
src_attrlist->attrs, attrlist_size);
139166

140167
for (i = 0; i < buf->attrlist.num; i++)
141168
buf->attrlist.attrs[i].iio.buf = buf;

context.c

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,18 +20,20 @@ static const char xml_header[] = "<?xml version=\"1.0\" encoding=\"utf-8\"?>"
2020
"<!DOCTYPE context ["
2121
"<!ELEMENT context (device | context-attribute)*>"
2222
"<!ELEMENT context-attribute EMPTY>"
23-
"<!ELEMENT device (channel | attribute | debug-attribute | buffer-attribute)*>"
23+
"<!ELEMENT device (channel | attribute | debug-attribute | buffer-attribute | buffer)*>"
2424
"<!ELEMENT channel (scan-element?, attribute*)>"
2525
"<!ELEMENT attribute EMPTY>"
2626
"<!ELEMENT scan-element EMPTY>"
2727
"<!ELEMENT debug-attribute EMPTY>"
28+
"<!ELEMENT buffer (buffer-attribute*, channel+)>"
2829
"<!ELEMENT buffer-attribute EMPTY>"
2930
"<!ATTLIST context name CDATA #REQUIRED version-major CDATA #REQUIRED "
3031
"version-minor CDATA #REQUIRED version-git CDATA #REQUIRED description CDATA #IMPLIED>"
3132
"<!ATTLIST context-attribute name CDATA #REQUIRED value CDATA #REQUIRED>"
3233
"<!ATTLIST device id CDATA #REQUIRED name CDATA #IMPLIED label CDATA #IMPLIED>"
3334
"<!ATTLIST channel id CDATA #REQUIRED type (input|output) #REQUIRED name CDATA #IMPLIED label CDATA #IMPLIED>"
3435
"<!ATTLIST scan-element index CDATA #REQUIRED format CDATA #REQUIRED scale CDATA #IMPLIED>"
36+
"<!ATTLIST buffer index CDATA #REQUIRED>"
3537
"<!ATTLIST attribute name CDATA #REQUIRED filename CDATA #IMPLIED>"
3638
"<!ATTLIST debug-attribute name CDATA #REQUIRED>"
3739
"<!ATTLIST buffer-attribute name CDATA #REQUIRED>"

device.c

Lines changed: 130 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
#include "iio-private.h"
1111
#include "sort.h"
1212

13+
#include <asm-generic/errno-base.h>
1314
#include <iio/iio-debug.h>
1415
#include <inttypes.h>
1516
#include <errno.h>
@@ -93,6 +94,42 @@ ssize_t iio_snprintf_device_xml(char *ptr, ssize_t len,
9394
}
9495
}
9596

97+
for (i = 0; i < dev->nb_buffers; i++) {
98+
const struct iio_buffer_meta *buf = &dev->buffers[i];
99+
unsigned int j;
100+
101+
ret = iio_snprintf(ptr, len, "<buffer index=\"%u\" >", i);
102+
if (ret < 0)
103+
return ret;
104+
105+
iio_update_xml_indexes(ret, &ptr, &len, &alen);
106+
107+
for (j = 0; j < buf->attrlist.num; j++) {
108+
ret = iio_snprintf_xml_attr(&buf->attrlist.attrs[j], ptr, len);
109+
if (ret < 0)
110+
return ret;
111+
112+
iio_update_xml_indexes(ret, &ptr, &len, &alen);
113+
}
114+
115+
for (j = 0; j < buf->nb_scan_elements; j++) {
116+
const struct iio_channel *scan = buf->scan_elements[j];
117+
118+
ret = iio_snprintf(ptr, len, "<channel id=\"%s\" type=\"%s\" />",
119+
scan->id, scan->is_output ? "output" : "input");
120+
if (ret < 0)
121+
return ret;
122+
123+
iio_update_xml_indexes(ret, &ptr, &len, &alen);
124+
}
125+
126+
ret = iio_snprintf(ptr, len, "</buffer>");
127+
if (ret < 0)
128+
return ret;
129+
130+
iio_update_xml_indexes(ret, &ptr, &len, &alen);
131+
}
132+
96133
ret = iio_snprintf(ptr, len, "</device>");
97134
if (ret < 0)
98135
return ret;
@@ -120,6 +157,33 @@ unsigned int iio_device_get_channels_count(const struct iio_device *dev)
120157
return dev->nb_channels;
121158
}
122159

160+
unsigned int iio_device_get_buffers_count(const struct iio_device *dev)
161+
{
162+
return dev->nb_buffers;
163+
}
164+
165+
int iio_device_get_buffer_scans_count(const struct iio_device *dev,
166+
unsigned int buffer_idx, unsigned int *nb_scans)
167+
{
168+
if (buffer_idx >= dev->nb_buffers)
169+
return -EINVAL;
170+
171+
*nb_scans = dev->buffers[buffer_idx].nb_scan_elements;
172+
return 0;
173+
}
174+
175+
const struct iio_channel *
176+
iio_device_get_buffer_scan_element(const struct iio_device *dev,
177+
unsigned int buffer_idx, unsigned int scan_idx)
178+
{
179+
if (buffer_idx >= dev->nb_buffers)
180+
return iio_ptr(-ENOENT);
181+
if (scan_idx >= dev->buffers[buffer_idx].nb_scan_elements)
182+
return iio_ptr(-ENOENT);
183+
184+
return dev->buffers[buffer_idx].scan_elements[scan_idx];
185+
}
186+
123187
struct iio_channel * iio_device_get_channel(const struct iio_device *dev,
124188
unsigned int index)
125189
{
@@ -244,6 +308,13 @@ void free_device(struct iio_device *dev)
244308
for (type = IIO_ATTR_TYPE_DEVICE; type <= IIO_ATTR_TYPE_BUFFER; type++)
245309
iio_free_attrs(&dev->attrlist[type]);
246310

311+
/* Free multi-buffer metadata */
312+
for (i = 0; i < dev->nb_buffers; i++) {
313+
iio_free_attrs(&dev->buffers[i].attrlist);
314+
free(dev->buffers[i].scan_elements);
315+
}
316+
free(dev->buffers);
317+
247318
for (i = 0; i < dev->nb_channels; i++)
248319
free_channel(dev->channels[i]);
249320
free(dev->channels);
@@ -354,6 +425,65 @@ void iio_device_set_pdata(struct iio_device *dev, struct iio_device_pdata *d)
354425
dev->pdata = d;
355426
}
356427

428+
int iio_device_add_scan_element_to_buffer(struct iio_device *dev, struct iio_channel *chn,
429+
unsigned int buf_idx)
430+
{
431+
struct iio_buffer_meta *buf;
432+
struct iio_channel **scans;
433+
unsigned int i;
434+
435+
if (buf_idx >= dev->nb_buffers)
436+
return -EINVAL;
437+
if (!chn->is_scan_element)
438+
return -EINVAL;
439+
440+
buf = &dev->buffers[buf_idx];
441+
printf("Add scan element %s to buffer %u. Existing(%u)\n", chn->id, buf_idx,
442+
buf->nb_scan_elements);
443+
/* Check if the scan element is already in the buffer */
444+
for (i = 0; i < buf->nb_scan_elements; i++) {
445+
if (buf->scan_elements[i] == chn)
446+
return -EEXIST;
447+
}
448+
449+
scans = realloc(buf->scan_elements,
450+
(buf->nb_scan_elements + 1) * sizeof(*buf->scan_elements));
451+
if (!scans)
452+
return -ENOMEM;
453+
454+
buf->scan_elements = scans;
455+
buf->scan_elements[buf->nb_scan_elements++] = chn;
456+
457+
return 0;
458+
}
459+
460+
int iio_device_add_buffer(struct iio_device *dev, unsigned int buf_idx)
461+
{
462+
struct iio_buffer_meta *buf, *bufs;
463+
464+
/* This assumes buffers are added in order */
465+
if (buf_idx != dev->nb_buffers) {
466+
dev_err(dev, "Invalid index(%u) for buffer. Expected %u\n",
467+
buf_idx, dev->nb_buffers);
468+
return -EINVAL;
469+
}
470+
471+
buf = zalloc(sizeof(*buf));
472+
if (!buf)
473+
return -ENOMEM;
474+
475+
bufs = realloc(dev->buffers, (buf_idx + 1) * sizeof(*dev->buffers));
476+
if (!bufs) {
477+
free(buf);
478+
return -ENOMEM;
479+
}
480+
481+
bufs[dev->nb_buffers++] = *buf;
482+
dev->buffers = bufs;
483+
484+
return 0;
485+
}
486+
357487
struct iio_channel * iio_device_add_channel(struct iio_device *dev, long index,
358488
const char *id, const char *name, const char *label,
359489
bool output, bool scan_element,

iio-private.h

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,13 @@ struct iio_attr_list {
7878
unsigned int num;
7979
};
8080

81+
/* Per-buffer metadata (for multi-buffer devices) */
82+
struct iio_buffer_meta {
83+
struct iio_attr_list attrlist;
84+
struct iio_channel **scan_elements;
85+
unsigned int nb_scan_elements;
86+
};
87+
8188
struct iio_context {
8289
struct iio_context_pdata *pdata;
8390
const struct iio_backend_ops *ops;
@@ -130,6 +137,10 @@ struct iio_device {
130137

131138
struct iio_channel **channels;
132139
unsigned int nb_channels;
140+
141+
/* Multi-buffer support: 1 = legacy single-buffer */
142+
unsigned int nb_buffers;
143+
struct iio_buffer_meta *buffers;
133144
};
134145

135146
struct iio_buffer {

iiod/responder.c

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -454,10 +454,13 @@ static void handle_create_buffer(struct parser_pdata *pdata,
454454
for (i = 0; i < nb_channels; i++) {
455455
chn = iio_device_get_channel(dev, i);
456456

457-
if (TEST_BIT(entry->words, i))
457+
if (TEST_BIT(entry->words, i)) {
458+
printf("Enabling channel %s for buffer %u\n",
459+
iio_channel_get_id(chn), entry->idx);
458460
iio_channel_enable(chn, mask);
459-
else
461+
} else {
460462
iio_channel_disable(chn, mask);
463+
}
461464
}
462465

463466
entry->enqueue_task = iio_task_create(buffer_enqueue_block, entry,
@@ -705,6 +708,8 @@ static void handle_create_block(struct parser_pdata *pdata,
705708
goto out_send_response;
706709
}
707710

711+
printf("Creating block of size %llu for buffer %u\n",
712+
(unsigned long long) block_size, cmd->code & 0xffff);
708713
block = iio_buffer_create_block(buf, (size_t) block_size);
709714
ret = iio_err(block);
710715
if (ret)

0 commit comments

Comments
 (0)