Dawn Framework 1.0
Universal data acquisition framework for embedded systems
dummy_notify.cxx
1// dawn/src/io/dummy_notify.cxx
2//
3// SPDX-License-Identifier: Apache-2.0
4//
5
6#include <cstring>
7#include <errno.h>
8#include <inttypes.h>
9#include <new>
10#include <sys/timerfd.h>
11
12#include "dawn/io/dummy_notify.hxx"
13
14using namespace dawn;
15
16static size_t dummyNotifyInitvalWordsPerValue(size_t tlen)
17{
18 if (tlen == sizeof(uint64_t))
19 {
20 return 2;
21 }
22
23 return 1;
24}
25
26int CIODummyNotify::configureDesc(const CDescObject &desc)
27{
28 const SObjectCfg::SObjectCfgItem *item = nullptr;
29 size_t parsed_dim = 1;
30 bool parsed_dim_set = false;
31 size_t parsed_init_len = 1;
32 size_t offset = 0;
33 size_t i = 0;
34
35 for (i = 0; i < desc.getSize(); i++)
36 {
37 item = desc.objectCfgItemAtOffset(offset);
38
39 switch (item->cfgid.s.cls)
40 {
42 {
43 offset += cfgCmnOffset(item);
44 break;
45 }
46
48 {
49 switch (item->cfgid.s.id)
50 {
51 case IO_DUMMY_NOTIFY_CFG_INITVAL:
52 {
53 size_t word_count = item->cfgid.s.size;
54 size_t word_step = dummyNotifyInitvalWordsPerValue(getDtypeSize());
55 size_t init_len;
56
57 if (word_count == 0)
58 {
59 DAWNERR("Dummy notify IO init value "
60 "dimension must be > 0\n");
61 return -EINVAL;
62 }
63
64 if (word_count % word_step != 0)
65 {
66 DAWNERR("Dummy notify IO init value word count "
67 "%zu is invalid for element size %zu\n",
68 word_count,
69 getDtypeSize());
70 return -EINVAL;
71 }
72
73 init_len = word_count / word_step;
74 cfgval = &item->data[0];
75 parsed_init_len = init_len;
76
77 offset += 1 + word_count;
78 break;
79 }
80
81 case IO_DUMMY_NOTIFY_CFG_INTERVAL:
82 {
83 const uint32_t *tmp = &item->data[0];
84
85 timfd_interval(*tmp);
86 offset += 1 + item->cfgid.s.size;
87 break;
88 }
89
90 case IO_DUMMY_NOTIFY_CFG_DIM:
91 {
92 uint32_t dim = item->data[0];
93
94 if (dim == 0)
95 {
96 DAWNERR("Dummy notify IO dimension must be > 0\n");
97 return -EINVAL;
98 }
99
100 parsed_dim = dim;
101 parsed_dim_set = true;
102 offset += 1 + item->cfgid.s.size;
103 break;
104 }
105
106 case IO_DUMMY_NOTIFY_CFG_NOTIFY_ON_WRITE:
107 {
108 notifyOnWrite = item->data[0] != 0;
109 offset += 1 + item->cfgid.s.size;
110 break;
111 }
112
113 default:
114 {
115 DAWNERR("unsupported dummy_notify objectCfg "
116 "0x%" PRIx32 "\n",
117 item->cfgid.v);
118 return -EINVAL;
119 }
120 }
121
122 break;
123 }
124
125 default:
126 {
127 DAWNERR("unsupported dummy_notify cfg 0x08%" PRIx32 "\n", item->cfgid.v);
128 return -EINVAL;
129 }
130 }
131 }
132
133 if (!parsed_dim_set && cfgval != nullptr)
134 {
135 parsed_dim = parsed_init_len;
136 }
137
138 if (cfgval != nullptr && parsed_init_len < parsed_dim)
139 {
140 DAWNERR("Dummy notify IO init value dimension %zu is smaller than "
141 "data dimension %zu\n",
142 parsed_init_len,
143 parsed_dim);
144 return -EINVAL;
145 }
146
147 dlen = parsed_dim;
148 cfglen = parsed_init_len;
149
150 return OK;
151}
152
153int CIODummyNotify::setVal(const void *v, size_t d)
154{
155 DAWNASSERT(dlen * tlen == d, "invalid input");
156 DAWNASSERT(val != nullptr, "buffer not initialized");
157
158 mutex.lock();
159
160 std::memcpy(val, v, d);
161
162#ifdef CONFIG_DAWN_IO_TIMESTAMP
163 if (isTimestamp())
164 {
165 ts = getTimestamp();
166 }
167#endif
168
169 mutex.unlock();
170
171 return OK;
172}
173
174int CIODummyNotify::applyInitval()
175{
176 size_t i = 0;
177 size_t word_step;
178
179 if (cfgval == nullptr)
180 {
181 return OK;
182 }
183
184 DAWNASSERT(val != nullptr, "buffer not initialized");
185
186 word_step = dummyNotifyInitvalWordsPerValue(tlen);
187
188 for (i = 0; i < dlen; i++)
189 {
190 std::memcpy(static_cast<uint8_t *>(val) + (i * tlen), &cfgval[i * word_step], tlen);
191 }
192
193 return OK;
194}
195
196CIODummyNotify::~CIODummyNotify()
197{
198 deinit();
199}
200
202{
203 dlen = 1;
204 cfglen = 1;
205 cfgval = nullptr;
206 notifyOnWrite = false;
207#ifdef CONFIG_DAWN_IO_NOTIFY
208 interval = 0;
209#endif
210
211 return configureDesc(getDesc());
212}
213
215{
216 int ret;
217
218 val = new (std::nothrow) uint8_t[dlen * tlen]();
219 if (!val)
220 {
221 DAWNERR("new failed\n");
222 return -ENOMEM;
223 }
224
225 ret = applyInitval();
226 if (ret != OK)
227 {
228 delete[] static_cast<uint8_t *>(val);
229 val = nullptr;
230 return ret;
231 }
232
233 writeData = new (std::nothrow) io_ddata_t(tlen, dlen, 1, getDtype(), isTimestamp());
234 if (writeData == nullptr || !writeData->isAllocated())
235 {
236 delete writeData;
237 writeData = nullptr;
238 delete[] static_cast<uint8_t *>(val);
239 val = nullptr;
240 return -ENOMEM;
241 }
242
243#ifdef CONFIG_DAWN_IO_NOTIFY
244 if (interval == 0)
245 {
246 DAWNERR("dummy_notify requires interval > 0\n");
247 delete writeData;
248 writeData = nullptr;
249 delete[] static_cast<uint8_t *>(val);
250 val = nullptr;
251 return -EINVAL;
252 }
253#endif
254
255 ret = timfd_init();
256 if (ret != OK)
257 {
258 delete writeData;
259 writeData = nullptr;
260 delete[] static_cast<uint8_t *>(val);
261 val = nullptr;
262 return ret;
263 }
264
265 return OK;
266}
267
269{
270 stop();
271
272 if (val)
273 {
274 delete[] static_cast<uint8_t *>(val);
275 val = nullptr;
276 }
277
278 delete writeData;
279 writeData = nullptr;
280
281 return OK;
282}
283
285{
286 size_t i;
287
288 for (i = 0; i < len; i++)
289 {
290 mutex.lock();
291
292#ifdef CONFIG_DAWN_IO_TIMESTAMP
293 data.getTs(i) = ts;
294#endif
295 std::memcpy(data.getDataPtr(i), val, dlen * tlen);
296
297 mutex.unlock();
298 }
299
300 timfd_ack();
301 return OK;
302}
303
305{
306 int ret = setVal(data.getDataPtr(), dlen * tlen);
307
308#ifdef CONFIG_DAWN_IO_NOTIFY
309 if (ret == OK && notifyOnWrite && writeData != nullptr)
310 {
311 mutex.lock();
312
313# ifdef CONFIG_DAWN_IO_TIMESTAMP
314 if (isTimestamp())
315 {
316 writeData->getTs(0) = ts;
317 }
318# endif
319
320 std::memcpy(writeData->getDataPtr(), val, dlen * tlen);
321
322 mutex.unlock();
323
324 (void)notifyData(writeData);
325 }
326#endif
327
328 return ret;
329}
330
331#ifdef CONFIG_DAWN_IO_NOTIFY
332int CIODummyNotify::getFd() const
333{
334 return timfd_fd();
335}
336
337int CIODummyNotify::notify()
338{
339 struct itimerspec tms;
340 int ret;
341
342 if (timfd_fd() < 0)
343 {
344 return -EINVAL;
345 }
346
347 tms.it_value.tv_sec = 0;
348 tms.it_value.tv_nsec = 1;
349 tms.it_interval.tv_sec = 0;
350 tms.it_interval.tv_nsec = 0;
351
352 ret = timerfd_settime(timfd_fd(), 0, &tms, NULL);
353 if (ret != OK)
354 {
355 DAWNERR("timerfd_settime notify failed\n");
356 }
357
358 return ret;
359}
360#endif
361
363{
364 return timfd_start();
365}
366
368{
369 return timfd_stop();
370}
371
373{
374 return dlen * tlen;
375}
376
378{
379 return dlen;
380}
Descriptor wrapper for individual object configuration.
size_t getSize() const
Get number of configuration items for this object.
SObjectCfg::SObjectCfgItem * objectCfgItemAtOffset(size_t offset) const
Get configuration item at specified offset.
virtual int getFd() const
Get file descriptor for notifications.
Definition common.hxx:425
uint64_t getTimestamp()
Get current timestamp.
Definition common.cxx:194
bool isTimestamp() const
Check if I/O supports timestamp.
Definition common.cxx:189
size_t cfgCmnOffset(const SObjectCfg::SObjectCfgItem *cfg)
Get offset of configuration item in descriptor.
Definition common.cxx:144
@ IO_CLASS_ANY
Any I/O class.
Definition common.hxx:86
@ IO_CLASS_DUMMY_NOTIFY
Timer-driven dummy IO.
Definition common.hxx:105
int init()
One-time initialize object after bindings are resolved.
int deinit()
De-initialize object.
int configure()
Configure object from descriptor data.
int doStart()
Start implementation hook.
size_t getDataSize() const
Get data size in bytes.
int setDataImpl(IODataCmn &data)
Set data implementation (override in derived classes).
int doStop()
Stop implementation hook.
size_t getDataDim() const
Get data vector dimension.
int getDataImpl(IODataCmn &data, size_t len)
Get data implementation (override in derived classes).
int stop()
Stop object.
Definition object.hxx:145
CDescObject & getDesc()
Get descriptor object for this object.
Definition object.cxx:190
size_t getDtypeSize() const
Get size of this object's data type.
Definition object.cxx:195
uint8_t getDtype() const
Get data type field.
Definition object.cxx:175
Out-of-tree user-extension hooks for Dawn.
Definition bindable.hxx:13
Base interface for I/O data buffers (static and dynamic).
Definition idata.hxx:21
virtual void * getDataPtr(size_t batch=0)=0
Get pointer to data only (skips timestamp if present).
virtual uint64_t & getTs(size_t batch=0)=0
Get timestamp reference for batch.
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).
Heap-allocated dynamic I/O data buffer.
Definition ddata.hxx:21
void * getDataPtr(size_t batch=0)
Get pointer to data only (skips timestamp if present).
Definition ddata.hxx:180
io_ts_t & getTs(size_t batch=0)
Get timestamp reference for batch.
Definition ddata.hxx:203
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.