Dawn Framework 1.0
Universal data acquisition framework for embedded systems
onetomany.cxx
1// dawn/src/prog/onetomany.cxx
2//
3// SPDX-License-Identifier: Apache-2.0
4//
5
6#include "dawn/prog/onetomany.hxx"
7
8#include "dawn/debug.hxx"
9#include "dawn/io/common.hxx"
10
11using namespace dawn;
12
13CProgOneToMany::CProgOneToMany(CDescObject &desc)
14 : CProgCommon(desc)
15 , input(nullptr)
16 , inputId(0)
17 , dataBuf(nullptr)
18 , active(false)
19 , registered(false)
20{
21}
22
23CProgOneToMany::~CProgOneToMany()
24{
25 deinit();
26}
27
28int CProgOneToMany::allocOutput(SObjectId::ObjectId ioId)
29{
30 outputIds.push_back(ioId);
31 outputs.push_back(nullptr);
32 setObjectMapItem(ioId, nullptr);
33 return OK;
34}
35
36int CProgOneToMany::configureDesc(const CDescObject &desc)
37{
39 const SObjectId::UObjectId *ids;
40 size_t offset = 0;
41
42 for (size_t i = 0; i < desc.getSize(); i++)
43 {
44 item = desc.objectCfgItemNext(offset);
45
46 if (item->cfgid.s.cls != CProgCommon::PROG_CLASS_ONETOMANY)
47 {
48 DAWNERR("onetomany: unsupported cfg class 0x%" PRIx32 "\n", item->cfgid.v);
49 return -EINVAL;
50 }
51
52 switch (item->cfgid.s.id)
53 {
54 case PROG_ONETOMANY_CFG_INPUT:
55 {
56 if (item->cfgid.s.size != 1)
57 {
58 DAWNERR("onetomany: INPUT must have one item\n");
59 return -EINVAL;
60 }
61 ids = reinterpret_cast<const SObjectId::UObjectId *>(item->data);
62 inputId = ids[0].v;
63 setObjectMapItem(inputId, nullptr);
64 break;
65 }
66
67 case PROG_ONETOMANY_CFG_OUTPUTS:
68 {
69 if (item->cfgid.s.size == 0)
70 {
71 DAWNERR("onetomany: OUTPUTS must not be empty\n");
72 return -EINVAL;
73 }
74 ids = reinterpret_cast<const SObjectId::UObjectId *>(item->data);
75 for (size_t j = 0; j < item->cfgid.s.size; j++)
76 {
77 int ret = allocOutput(ids[j].v);
78 if (ret != OK)
79 {
80 return ret;
81 }
82 }
83 break;
84 }
85
86 default:
87 DAWNERR("onetomany: unsupported cfg id %u\n", item->cfgid.s.id);
88 return -EINVAL;
89 }
90 }
91
92 if (inputId == 0 || outputs.empty())
93 {
94 DAWNERR("onetomany: input and outputs are required\n");
95 return -EINVAL;
96 }
97
98 return OK;
99}
100
102{
103 return configureDesc(getDesc());
104}
105
106int CProgOneToMany::validateShape(CIOCommon *io) const
107{
108 if (io == nullptr || input == nullptr)
109 {
110 return -EIO;
111 }
112
113 if (io->getDtype() != input->getDtype() || io->getDataDim() != input->getDataDim() ||
114 io->isTimestamp() != input->isTimestamp() || io->getDataSize() != input->getDataSize())
115 {
116 return -EINVAL;
117 }
118
119 return OK;
120}
121
123{
124 input = getIO(inputId);
125 if (input == nullptr || !input->isRead() || !input->isNotify())
126 {
127 DAWNERR("onetomany: input 0x%" PRIx32 " is not readable notify IO\n", inputId);
128 return -EINVAL;
129 }
130
131 for (size_t i = 0; i < outputIds.size(); i++)
132 {
133 outputs[i] = getIO(outputIds[i]);
134 if (outputs[i] == nullptr)
135 {
136 DAWNERR("onetomany: output IO 0x%" PRIx32 " not found\n", outputIds[i]);
137 return -EIO;
138 }
139
140 int ret = prepareWritableTarget(outputs[i], input->getDataDim(), true);
141 if (ret != OK)
142 {
143 DAWNERR("onetomany: output prepare failed %d\n", ret);
144 return ret;
145 }
146
147 ret = validateShape(outputs[i]);
148 if (ret != OK)
149 {
150 DAWNERR("onetomany: output 0x%" PRIx32 " incompatible\n", outputIds[i]);
151 return ret;
152 }
153 }
154
155 dataBuf = input->ddata_alloc(1);
156 if (dataBuf == nullptr)
157 {
158 DAWNERR("onetomany: data allocation failed\n");
159 return -ENOMEM;
160 }
161
162 return OK;
163}
164
166{
167 doStop();
168 delete dataBuf;
169 dataBuf = nullptr;
170 input = nullptr;
171 inputId = 0;
172 outputs.clear();
173 outputIds.clear();
174 return OK;
175}
176
177int CProgOneToMany::ioNotifierCb(void *priv, io_ddata_t *data)
178{
179 CProgOneToMany *self = static_cast<CProgOneToMany *>(priv);
180
181 if (self == nullptr || !self->active || data == nullptr)
182 {
183 return OK;
184 }
185
186 self->writeOutputs(data);
187 return OK;
188}
189
191{
192 if (!registered)
193 {
194 int ret = input->setNotifier(ioNotifierCb, 0, this);
195 if (ret != OK)
196 {
197 DAWNERR("onetomany: setNotifier failed %d\n", ret);
198 return ret;
199 }
200 registered = true;
201 }
202
203 active = true;
204 if (input->getData(*dataBuf, 1) == OK)
205 {
206 writeOutputs(dataBuf);
207 }
208 return OK;
209}
210
212{
213 if (registered && input != nullptr)
214 {
215 input->setNotifier(nullptr, 0, nullptr);
216 registered = false;
217 }
218
219 active = false;
220 return OK;
221}
222
224{
225 return false;
226}
227
228void CProgOneToMany::writeOutputs(io_ddata_t *data)
229{
230 for (auto output : outputs)
231 {
232 int ret = output->setData(*data);
233 if (ret != OK)
234 {
235 DAWNERR("onetomany: output setData failed %d\n", ret);
236 }
237 }
238}
CIOCommon * getIO(SObjectId::ObjectId id)
Get an I/O object by ID.
Definition bindable.cxx:41
void setObjectMapItem(SObjectId::ObjectId id, CObject *obj)
Set an item in the object map.
Definition bindable.cxx:23
Descriptor wrapper for individual object configuration.
size_t getSize() const
Get number of configuration items for this object.
SObjectCfg::SObjectCfgItem * objectCfgItemNext(size_t &offset) const
Get config item at current offset and advance past it.
Base class for all I/O objects.
Definition common.hxx:27
int getData(IODataCmn &data, size_t len, size_t offset=0)
Get data from I/O (public interface with stats tracking).
Definition common.hxx:353
virtual bool isNotify() const =0
Check if IO supports notifications.
bool isTimestamp() const
Check if I/O supports timestamp.
Definition common.cxx:189
virtual size_t getDataDim() const =0
Get data vector dimension.
io_ddata_t * ddata_alloc(size_t batch, size_t chunk_size=0)
Allocate data buffer for this I/O.
Definition common.cxx:247
virtual size_t getDataSize() const =0
Get data size in bytes.
virtual bool isRead() const =0
Check if IO supports read operations.
CDescObject & getDesc()
Get descriptor object for this object.
Definition object.cxx:190
uint8_t getDtype() const
Get data type field.
Definition object.cxx:175
Base class for all PROG (processing) objects.
Definition common.hxx:27
One-to-many bridge: forwards one input to many outputs.
Definition onetomany.hxx:22
int init()
One-time initialize object after bindings are resolved.
int configure()
Configure object from descriptor data.
bool hasThread() const
Check if a background thread is active.
int deinit()
De-initialize object.
int doStop()
Stop implementation hook.
int doStart()
Start implementation hook.
Out-of-tree user-extension hooks for Dawn.
Definition bindable.hxx:13
Single configuration item within object.
ObjectCfgData_t data[]
Configuration data array (flexible, size from cfgid.s.size).
UObjectCfgId cfgid
Configuration ID header (type, class, id, size, rw, dtype).
uint32_t ObjectId
ObjectID type - single 32-bit value.
Definition objectid.hxx:44
Heap-allocated dynamic I/O data buffer.
Definition ddata.hxx:21
ObjectCfgId v
Raw 32-bit ConfigID value (for storage, comparison).
Definition objectcfg.hxx:82
uint32_t cls
Object class (bits 21-29, max 511).
uint32_t id
Configuration identifier (bits 0-4, max 31).
Definition objectcfg.hxx:94
uint32_t size
Configuration data size in 32-bit words (bits 5-14, max 1023).
struct dawn::SObjectCfg::UObjectCfgId::@10 s
Bit-field structure for named member access.
32-bit encoded object identifier (union with bit field).
Definition objectid.hxx:218
ObjectId v
Raw 32-bit ObjectID value (for comparison, hashing, storage).
Definition objectid.hxx:221