Dawn Framework 1.0
Universal data acquisition framework for embedded systems
nxscope.cxx
1// dawn/src/proto/nxscope/nxscope.cxx
2//
3// SPDX-License-Identifier: Apache-2.0
4//
5
6#include "dawn/proto/nxscope/nxscope.hxx"
7
8#include <cstring>
9
10#include "dawn/io/common.hxx"
11#include "dawn/io/ddata.hxx"
12
13using namespace dawn;
14
15#if defined(CONFIG_DAWN_PROTO_NXSCOPE_SAMPLE_THREAD) + defined(CONFIG_DAWN_IO_NOTIFY) != 1
16# error one sampling method can be supported
17#endif
18
19// Interval for recv thread in us
20
21#define NXSCOPE_RECV_INTERVAL (10000)
22
23// Interval in us for sample thread
24
25#define NXSCOPE_SAMPLE_INTERVAL (1000000)
26
27static inline uint16_t nxscopeU16Le(const uint8_t *p)
28{
29 return (uint16_t)p[0] | ((uint16_t)p[1] << 8);
30}
31
32static inline uint32_t nxscopeU32Le(const uint8_t *p)
33{
34 return (uint32_t)p[0] | ((uint32_t)p[1] << 8) | ((uint32_t)p[2] << 16) | ((uint32_t)p[3] << 24);
35}
36
37#ifdef CONFIG_DAWN_IO_NOTIFY
38int CProtoNxscope::ioNotifierCb(void *priv, io_ddata_t *data)
39{
40 SProtoNxscopeIochan *chan = (SProtoNxscopeIochan *)priv;
41
42 if (!chan || !chan->obj || !data || !chan->put)
43 {
44 return -EINVAL;
45 }
46
47 return chan->put(&chan->obj->nxs, chan->chan, data->getDataPtr(), data->getItems());
48}
49#endif
50
51int CProtoNxscope::sendAck(int ret)
52{
53 size_t len;
54
55 if (nxs.proto_cmd == nullptr || nxs.intf_cmd == nullptr)
56 {
57 return -EINVAL;
58 }
59
60 if (nxs.proto_cmd->ops == nullptr || nxs.intf_cmd->ops == nullptr)
61 {
62 return -EINVAL;
63 }
64
65 if (nxs.proto_cmd->ops->frame_final == nullptr || nxs.intf_cmd->ops->send == nullptr)
66 {
67 return -EINVAL;
68 }
69
70 if (nxs.txbuf == nullptr)
71 {
72 return -EINVAL;
73 }
74
75 if (nxs.txbuf_len < nxs.proto_cmd->hdrlen + sizeof(ret) + nxs.proto_cmd->footlen)
76 {
77 return -ENOBUFS;
78 }
79
80 len = nxs.proto_cmd->hdrlen;
81 std::memcpy(&nxs.txbuf[len], &ret, sizeof(ret));
82 len += sizeof(ret);
83
84 ret = nxs.proto_cmd->ops->frame_final(nxs.proto_cmd, NXSCOPE_HDRID_ACK, nxs.txbuf, &len);
85 if (ret < 0)
86 {
87 return ret;
88 }
89
90 return nxs.intf_cmd->ops->send(nxs.intf_cmd, nxs.txbuf, (int)len);
91}
92
93int CProtoNxscope::userIdCb(void *priv, uint8_t id, uint8_t *buff)
94{
95 CProtoNxscope *obj;
96 int ret;
97 bool handled;
98
99 obj = static_cast<CProtoNxscope *>(priv);
100 if (obj == nullptr || buff == nullptr)
101 {
102 return -EINVAL;
103 }
104
105 handled = (id == NXSCOPE_USER_SET_IO || id == NXSCOPE_USER_SET_IO_SEEK);
106 if (!handled)
107 {
108 /* Ignore non-extension IDs routed through userid callback.
109 * In particular, ACK frames may be seen here and must not be ACKed again.
110 */
111 return OK;
112 }
113
114 ret = obj->handleUserCommand(id, buff);
115
116#ifdef CONFIG_LOGGING_NXSCOPE_ACKFRAMES
117 {
118 int ack;
119
120 ack = obj->sendAck(ret);
121 if (ack < 0)
122 {
123 DAWNERR("nxscope user ack failed: %d\n", ack);
124 return ack;
125 }
126 }
127#endif
128
129 return ret;
130}
131
132int CProtoNxscope::handleUserCommand(uint8_t id, uint8_t *buff)
133{
134 switch (id)
135 {
136 case NXSCOPE_USER_SET_IO:
137 {
138 return userSetIO(buff);
139 }
140
141 case NXSCOPE_USER_SET_IO_SEEK:
142 {
143 return userSetIOSeek(buff);
144 }
145
146 default:
147 {
148 return -ENOTSUP;
149 }
150 }
151}
152
153CProtoNxscope::SProtoNxscopeIochan *CProtoNxscope::findIochan(SObjectId::ObjectId objid)
154{
155 for (auto &iochan : vio)
156 {
157 if (iochan.io != nullptr && iochan.io->getIdV() == objid)
158 {
159 return &iochan;
160 }
161 }
162
163 return nullptr;
164}
165
166int CProtoNxscope::userSetIO(uint8_t *buff)
167{
169 uint16_t size;
170 SProtoNxscopeIochan *iochan;
171 CIOCommon *io;
172 io_ddata_t *iodata;
173 size_t oldSize;
174 int ret;
175
176 objid = nxscopeU32Le(buff);
177 size = nxscopeU16Le(&buff[4]);
178
179 iochan = findIochan(objid);
180 if (iochan == nullptr || iochan->io == nullptr)
181 {
182 return -ENOENT;
183 }
184
185 io = iochan->io;
186 if (!io->isWrite())
187 {
188 return -EPERM;
189 }
190
191 iodata = iochan->setData;
192 if (iodata == nullptr)
193 {
194 return -ENOMEM;
195 }
196
197 if (!io->isSeekable())
198 {
199 if (size != io->getDataSize())
200 {
201 return -EINVAL;
202 }
203
204 std::memcpy(iodata->getDataPtr(), &buff[6], size);
205 ret = io->setData(*iodata);
206 }
207 else
208 {
209 if (size > iodata->getDataSize())
210 {
211 return -EINVAL;
212 }
213
214 std::memcpy(iodata->getDataPtr(), &buff[6], size);
215
216 oldSize = iodata->N;
217 iodata->N = size;
218 ret = io->setData(*iodata);
219 iodata->N = oldSize;
220 }
221
222 return ret;
223}
224
225int CProtoNxscope::userSetIOSeek(uint8_t *buff)
226{
228 size_t offset;
229 uint16_t size;
230 SProtoNxscopeIochan *iochan;
231 CIOCommon *io;
232 io_ddata_t *iodata;
233 size_t oldSize;
234 int ret;
235
236 objid = nxscopeU32Le(buff);
237 offset = nxscopeU32Le(&buff[4]);
238 size = nxscopeU16Le(&buff[8]);
239
240 iochan = findIochan(objid);
241 if (iochan == nullptr || iochan->io == nullptr)
242 {
243 return -ENOENT;
244 }
245
246 io = iochan->io;
247 if (!io->isWrite())
248 {
249 return -EPERM;
250 }
251
252 if (!io->isSeekable())
253 {
254 return -ENOTSUP;
255 }
256
257 iodata = iochan->setData;
258 if (iodata == nullptr)
259 {
260 return -ENOMEM;
261 }
262
263 if (size > iodata->getDataSize())
264 {
265 return -EINVAL;
266 }
267
268 std::memcpy(iodata->getDataPtr(), &buff[10], size);
269
270 oldSize = iodata->N;
271 iodata->N = size;
272 ret = io->setData(*iodata, offset);
273 iodata->N = oldSize;
274
275 return ret;
276}
277
278int CProtoNxscope::configureNxscope()
279{
280 int ret;
281
282 // Default serial protocol implementation
283
284 ret = nxscope_proto_ser_init(&nxsProto, nullptr);
285 if (ret != OK)
286 {
287 DAWNERR("nxscope_proto_ser_init failed: %d\n", ret);
288 return ret;
289 }
290
291 // Connect callbacks
292
293 nxsCbs.userid_priv = this;
294 nxsCbs.userid = userIdCb;
295 nxsCbs.start_priv = nullptr;
296 nxsCbs.start = nullptr;
297
298 // Initialize nxscope
299
300 nxsCfg.streambuf_len = CONFIG_DAWN_PROTO_NXSCOPE_STREAMBUF_LEN;
301 nxsCfg.rxbuf_len = CONFIG_DAWN_PROTO_NXSCOPE_RXBUF_LEN;
302 nxsCfg.rx_padding = CONFIG_DAWN_PROTO_NXSCOPE_RX_PADDING;
303#ifdef CONFIG_LOGGING_NXSCOPE_CRICHANNELS
304 nxsCfg.cribuf_len = CONFIG_DAWN_PROTO_NXSCOPE_CRIBUF_LEN;
305#endif
306
307 nxsCfg.intf_cmd = &nxsIntf;
308 nxsCfg.intf_stream = &nxsIntf;
309 nxsCfg.proto_cmd = &nxsProto;
310 nxsCfg.proto_stream = &nxsProto;
311 nxsCfg.callbacks = &nxsCbs;
312 nxsCfg.channels = vchannels.size();
313
314 ret = nxscope_init(&nxs, &nxsCfg);
315 if (ret != OK)
316 {
317 DAWNERR("nxscope_init failed: %d\n", ret);
318 return ret;
319 }
320
321 return OK;
322}
323
324int CProtoNxscope::allocObject(SProtoNxscopeIOBind *alloc)
325{
326 DAWNINFO("allocate object 0x%" PRIx32 "\n", alloc->objid.v);
327
328 // Allocate object in map
329
330 setObjectMapItem(alloc->objid.v, nullptr);
331
332 // Store reference to chanel configuration
333
334 vchannels.push_back(alloc);
335
336 return OK;
337};
338
339int CProtoNxscope::allocNames(size_t j, SProtoNxscopeNames *alloc)
340{
341 DAWNINFO("channel %zu with name %s\n", j, alloc->name);
342
343 // Store reference to chanel configuration
344
345 vnames.push_back(alloc);
346
347 return OK;
348};
349
350uint8_t CProtoNxscope::getChannelDim(const CIOCommon &io)
351{
352 return io.getDataDim();
353}
354
355uint8_t CProtoNxscope::getChannelDtype(const CIOCommon &io)
356{
357 uint8_t dtype = io.getDtype();
358
359 switch (dtype)
360 {
361#ifdef CONFIG_DAWN_DTYPE_INT32
363 {
364 return NXSCOPE_TYPE_INT32;
365 }
366#endif
367
368#ifdef CONFIG_DAWN_DTYPE_UINT32
370 {
371 return NXSCOPE_TYPE_UINT32;
372 }
373#endif
374
375#ifdef CONFIG_DAWN_DTYPE_UINT64
377 {
378 return NXSCOPE_TYPE_UINT64;
379 }
380#endif
381
382#ifdef CONFIG_DAWN_DTYPE_FLOAT
384 {
385 return NXSCOPE_TYPE_FLOAT;
386 }
387#endif
388
389#ifdef CONFIG_DAWN_DTYPE_B16
391 {
392 return NXSCOPE_TYPE_B16;
393 }
394#endif
395
396#ifdef CONFIG_DAWN_DTYPE_UB16
398 {
399 return NXSCOPE_TYPE_UB16;
400 }
401#endif
402
403#ifdef CONFIG_DAWN_DTYPE_CHAR
405 {
406 return NXSCOPE_TYPE_CHAR;
407 }
408#endif
409
410 default:
411 {
412 DAWNERR("unsuported nxscope type %d\n", dtype);
413 return NXSCOPE_TYPE_NONE;
414 }
415 }
416}
417
418int CProtoNxscope::nxscopeChannelsCreate()
419{
420 union nxscope_chinfo_type_u u;
421 const SProtoNxscopeIOBind *alloc;
422 size_t bindidx;
423 int chanid = 0;
424 int ret;
425
426 hasStreamChannels = false;
427
428 for (bindidx = 0; bindidx < vchannels.size(); bindidx++)
429 {
430 alloc = vchannels[bindidx];
431 const CIOCommon *io = getIO(alloc->objid.v);
432
433 if (io != nullptr)
434 {
435 SProtoNxscopeIochan iochan;
436 const char *name;
437
438 if (bindidx < vnames.size())
439 {
440 name = vnames[bindidx]->name;
441 }
442 else
443 {
444 name = "no-name";
445 }
446
447 DAWNINFO("nxscope channel %s %p 0x%x\n", name, io, alloc->objid.v);
448
449 // Store IO to nxscope chan map
450
451 iochan.chan = chanid;
452 iochan.dim = getChannelDim(*io);
453 iochan.stream = io->isRead();
454 iochan.io = (CIOCommon *)io;
455 iochan.obj = this;
456 iochan.setData = nullptr;
457#ifdef CONFIG_DAWN_IO_NOTIFY
458 iochan.put = nullptr;
459#endif
460#ifdef CONFIG_DAWN_PROTO_NXSCOPE_SAMPLE_THREAD
461 iochan.sample = nullptr;
462 iochan.data = nullptr;
463#endif
464
465 if (io->isRead() == false && io->isWrite() == false)
466 {
467 DAWNERR("IO 0x%" PRIx32 " has neither read nor write support\n", alloc->objid.v);
468 return -EPERM;
469 }
470
471 if (iochan.io->isWrite())
472 {
473 if (iochan.io->isSeekable())
474 {
475 iochan.setData = iochan.io->ddata_alloc(1, CONFIG_DAWN_PROTO_NXSCOPE_RXBUF_LEN);
476 }
477 else
478 {
479 iochan.setData = iochan.io->ddata_alloc(1);
480 }
481
482 if (iochan.setData == nullptr)
483 {
484 DAWNERR("failed to allocate set buffer for objid=0x%" PRIx32 "\n",
485 alloc->objid.v);
486#ifdef CONFIG_DAWN_PROTO_NXSCOPE_SAMPLE_THREAD
487 delete iochan.data;
488 iochan.data = nullptr;
489#endif
490 return -ENOMEM;
491 }
492 }
493
494 if (iochan.stream)
495 {
496 ret = bindChannelCallbacks(iochan, io->getDtype());
497 if (ret < 0)
498 {
499 if (iochan.io->isWrite())
500 {
501 DAWNINFO("set-only nxscope channel for objid=0x%" PRIx32 "\n",
502 alloc->objid.v);
503 iochan.stream = false;
504 }
505 else
506 {
507 DAWNERR("Unsupported data type %d for objid=0x%" PRIx32 "\n",
508 io->getDtype(),
509 alloc->objid.v);
510#ifdef CONFIG_DAWN_PROTO_NXSCOPE_SAMPLE_THREAD
511 delete iochan.data;
512 iochan.data = nullptr;
513#endif
514 delete iochan.setData;
515 iochan.setData = nullptr;
516 return ret;
517 }
518 }
519 }
520
521#ifdef CONFIG_DAWN_IO_NOTIFY
522 if (iochan.stream && iochan.io->isNotify() == false)
523 {
524 if (iochan.io->isWrite())
525 {
526 DAWNINFO("set-only nxscope channel (no notify) for "
527 "objid=0x%" PRIx32 "\n",
528 alloc->objid.v);
529 iochan.stream = false;
530 }
531 else
532 {
533 DAWNERR("notify not supported for objid=0x%" PRIx32 "\n", alloc->objid.v);
534 delete iochan.setData;
535 iochan.setData = nullptr;
536 return -ENOTSUP;
537 }
538 }
539#endif
540
541#ifdef CONFIG_DAWN_PROTO_NXSCOPE_SAMPLE_THREAD
542 if (iochan.stream && iochan.io->isSeekable())
543 {
544 if (iochan.io->isWrite())
545 {
546 DAWNINFO("set-only nxscope channel (seekable) for "
547 "objid=0x%" PRIx32 "\n",
548 alloc->objid.v);
549 iochan.stream = false;
550 }
551 else
552 {
553 DAWNERR("seekable IO not supported by NXScope "
554 "(objid=0x%08" PRIx32 ")\n",
555 iochan.io->getIdV());
556 delete iochan.setData;
557 iochan.setData = nullptr;
558 return -ENOTSUP;
559 }
560 }
561
562 if (iochan.stream)
563 {
564 iochan.data = iochan.io->ddata_alloc(1);
565 if (iochan.data == nullptr)
566 {
567 DAWNERR("failed to allocate sample buffer for objid=0x%" PRIx32 "\n",
568 alloc->objid.v);
569 delete iochan.setData;
570 iochan.setData = nullptr;
571 return -ENOMEM;
572 }
573 }
574#endif
575
576 if (iochan.stream)
577 {
578 // Initialize nxscope stream channel
579 u.s.dtype = getChannelDtype(*io);
580 u.s._res = 0;
581 u.s.cri = 0;
582 // NOTE: nxscope_chan_init declares name as char* (non-const)
583 // but never modifies it. The char* in the struct is only
584 // stored and compared, so casting away const is safe here.
585 nxscope_chan_init(&nxs, chanid, const_cast<char *>(name), u.u8, iochan.dim, 0);
586 iochan.chan = chanid;
587 chanid += 1;
588 hasStreamChannels = true;
589 }
590 else
591 {
592 iochan.chan = 0;
593 }
594
595 vio.push_back(iochan);
596 }
597 else
598 {
599 DAWNERR("IO not found for objid=0x%" PRIx32 "\n", alloc->objid.v);
600 return -EIO;
601 }
602 }
603
604 return OK;
605};
606
607#ifdef CONFIG_DAWN_IO_NOTIFY
608int CProtoNxscope::putInt32(struct nxscope_s *nxs, uint8_t chan, void *data, uint8_t dim)
609{
610 return nxscope_put_vint32(nxs, chan, static_cast<int32_t *>(data), dim);
611}
612
613int CProtoNxscope::putUint32(struct nxscope_s *nxs, uint8_t chan, void *data, uint8_t dim)
614{
615 return nxscope_put_vuint32(nxs, chan, static_cast<uint32_t *>(data), dim);
616}
617
618int CProtoNxscope::putUint64(struct nxscope_s *nxs, uint8_t chan, void *data, uint8_t dim)
619{
620 return nxscope_put_vuint64(nxs, chan, static_cast<uint64_t *>(data), dim);
621}
622
623int CProtoNxscope::putFloat(struct nxscope_s *nxs, uint8_t chan, void *data, uint8_t dim)
624{
625 return nxscope_put_vfloat(nxs, chan, static_cast<float *>(data), dim);
626}
627#endif
628
629#ifdef CONFIG_DAWN_PROTO_NXSCOPE_SAMPLE_THREAD
630int CProtoNxscope::sampleInt32(CProtoNxscope *obj, SProtoNxscopeIochan *iochan)
631{
632 int ret;
633
634 if (!iochan || !iochan->data)
635 {
636 return -EINVAL;
637 }
638
639 ret = iochan->io->getData(*iochan->data, 1);
640 if (ret == OK)
641 {
642 ret = nxscope_put_vint32(
643 &obj->nxs, iochan->chan, static_cast<int32_t *>(iochan->data->getDataPtr()), iochan->dim);
644 }
645
646 return ret;
647}
648
649int CProtoNxscope::sampleUint32(CProtoNxscope *obj, SProtoNxscopeIochan *iochan)
650{
651 int ret;
652
653 if (!iochan || !iochan->data)
654 {
655 return -EINVAL;
656 }
657
658 ret = iochan->io->getData(*iochan->data, 1);
659 if (ret == OK)
660 {
661 ret = nxscope_put_vuint32(
662 &obj->nxs, iochan->chan, static_cast<uint32_t *>(iochan->data->getDataPtr()), iochan->dim);
663 }
664
665 return ret;
666}
667
668int CProtoNxscope::sampleUint64(CProtoNxscope *obj, SProtoNxscopeIochan *iochan)
669{
670 int ret;
671
672 if (!iochan || !iochan->data)
673 {
674 return -EINVAL;
675 }
676
677 ret = iochan->io->getData(*iochan->data, 1);
678 if (ret == OK)
679 {
680 ret = nxscope_put_vuint64(
681 &obj->nxs, iochan->chan, static_cast<uint64_t *>(iochan->data->getDataPtr()), iochan->dim);
682 }
683
684 return ret;
685}
686
687int CProtoNxscope::sampleFloat(CProtoNxscope *obj, SProtoNxscopeIochan *iochan)
688{
689 int ret;
690
691 if (!iochan || !iochan->data)
692 {
693 return -EINVAL;
694 }
695
696 ret = iochan->io->getData(*iochan->data, 1);
697 if (ret == OK)
698 {
699 ret = nxscope_put_vfloat(
700 &obj->nxs, iochan->chan, static_cast<float *>(iochan->data->getDataPtr()), iochan->dim);
701 }
702
703 return ret;
704}
705#endif
706
707int CProtoNxscope::bindChannelCallbacks(SProtoNxscopeIochan &iochan, uint8_t dtype)
708{
709 switch (dtype)
710 {
711#ifdef CONFIG_DAWN_DTYPE_INT32
713 {
714# ifdef CONFIG_DAWN_IO_NOTIFY
715 iochan.put = &putInt32;
716# endif
717# ifdef CONFIG_DAWN_PROTO_NXSCOPE_SAMPLE_THREAD
718 iochan.sample = &sampleInt32;
719# endif
720 break;
721 }
722#endif
723
724#ifdef CONFIG_DAWN_DTYPE_UINT32
726 {
727# ifdef CONFIG_DAWN_IO_NOTIFY
728 iochan.put = &putUint32;
729# endif
730# ifdef CONFIG_DAWN_PROTO_NXSCOPE_SAMPLE_THREAD
731 iochan.sample = &sampleUint32;
732# endif
733 break;
734 }
735#endif
736
737#ifdef CONFIG_DAWN_DTYPE_UINT64
739 {
740# ifdef CONFIG_DAWN_IO_NOTIFY
741 iochan.put = &putUint64;
742# endif
743# ifdef CONFIG_DAWN_PROTO_NXSCOPE_SAMPLE_THREAD
744 iochan.sample = &sampleUint64;
745# endif
746 break;
747 }
748#endif
749
750#ifdef CONFIG_DAWN_DTYPE_FLOAT
752 {
753# ifdef CONFIG_DAWN_IO_NOTIFY
754 iochan.put = &putFloat;
755# endif
756# ifdef CONFIG_DAWN_PROTO_NXSCOPE_SAMPLE_THREAD
757 iochan.sample = &sampleFloat;
758# endif
759 break;
760 }
761#endif
762
763 default:
764 {
765 return -ENOTSUP;
766 }
767 }
768
769 return OK;
770}
771
772#ifdef CONFIG_DAWN_PROTO_NXSCOPE_SAMPLE_THREAD
773void CProtoNxscope::getAndPut(SProtoNxscopeIochan *iochan)
774{
775 int ret;
776
777 if (!iochan || !iochan->sample)
778 {
779 return;
780 }
781
782 ret = iochan->sample(this, iochan);
783 if (ret < 0 && ret != -EAGAIN)
784 {
785 DAWNERR("sampling failed for chan=%d ret=%d\n", iochan->chan, ret);
786 }
787}
788#endif
789
790void CProtoNxscope::threadRecv()
791{
792 // Loop until stop called
793
794 do
795 {
796 int ret;
797
798 /* Flush stream data */
799
800 if (hasStreamChannels)
801 {
802 ret = nxscope_stream(&nxs);
803 if (ret < 0)
804 {
805 DAWNERR("ERROR: nxscope_stream failed %d\n", ret);
806 }
807 }
808
809 /* Handle recv data */
810
811 ret = nxscope_recv(&nxs);
812 if (ret < 0)
813 {
814 DAWNERR("ERROR: nxscope_recv failed %d\n", ret);
815 }
816
817#if NXSCOPE_RECV_NONBLOCK == 1
818 // Sleep if read is non-blocking
819
820 usleep(NXSCOPE_RECV_INTERVAL);
821#endif
822 }
823 while (!threadRecvMember.shouldQuit());
824
825 // Mark thread quit done
826
827 threadRecvMember.markThreadFinished();
828}
829
830#ifdef CONFIG_DAWN_PROTO_NXSCOPE_SAMPLE_THREAD
831void CProtoNxscope::threadSample()
832{
833 // Loop until stop called
834
835 do
836 {
837 for (auto &io : vio)
838 {
839 if (!io.stream)
840 {
841 continue;
842 }
843 getAndPut(&io);
844 }
845
846 usleep(NXSCOPE_SAMPLE_INTERVAL);
847 }
848 while (!threadSampleMember.shouldQuit());
849
850 // Mark thread quit done
851
852 threadSampleMember.markThreadFinished();
853}
854
855#endif // CONFIG_DAWN_PROTO_NXSCOPE_SAMPLE_THREAD
856
857CProtoNxscope::~CProtoNxscope()
858{
859 for (auto &io : vio)
860 {
861#ifdef CONFIG_DAWN_PROTO_NXSCOPE_SAMPLE_THREAD
862 delete io.data;
863 io.data = nullptr;
864#endif
865 delete io.setData;
866 io.setData = nullptr;
867 }
868
869 vchannels.clear();
870 vnames.clear();
871 vio.clear();
872
873 // Deinit nxscope
874
875 nxscope_deinit(&nxs);
876}
877
879{
880 int ret;
881
882 ret = initPriv();
883 if (ret != OK)
884 {
885 return ret;
886 }
887
888 return OK;
889}
890
892{
893 // Allocated objects are mapped after handler bind, so create channels here
894 return nxscopeChannelsCreate();
895}
896
898{
899 int ret;
900
901 ret = deinitPriv();
902 if (ret != OK)
903 {
904 return ret;
905 }
906
907 return OK;
908}
909
911{
912 int ret;
913
914 ret = startPriv();
915 if (ret != OK)
916 {
917 return ret;
918 }
919
920 // Start recv thread
921
922 threadRecvMember.setThreadFunc([this]() { threadRecv(); });
923 ret = threadRecvMember.threadStart();
924 if (ret < 0)
925 {
926 return ret;
927 }
928
929#ifdef CONFIG_DAWN_PROTO_NXSCOPE_SAMPLE_THREAD
930 // Start sample thread
931
932 threadSampleMember.setThreadFunc([this]() { threadSample(); });
933 ret = threadSampleMember.threadStart();
934 if (ret < 0)
935 {
936 return ret;
937 }
938
939#else
940 // Register notifications
941
942 for (auto &io : vio)
943 {
944 if (!io.stream)
945 {
946 continue;
947 }
948 ret = io.io->setNotifier(ioNotifierCb, 0, (void *)&io);
949 if (ret < 0)
950 {
951 if (io.io->isWrite())
952 {
953 DAWNINFO("set notifier failed for writable objId = 0x%" PRIx32
954 ", fallback to set-only (%d)\n",
955 io.io->getIdV(),
956 ret);
957 io.stream = false;
958 continue;
959 }
960
961 DAWNERR("set notifier failed for objId = 0x%" PRIx32 "\n", io.io->getIdV());
962 return ret;
963 }
964 }
965#endif
966
967 return OK;
968};
969
971{
972 int ret;
973
974 // Stop transport first to unblock recv path before thread joins
975
976 ret = stopPriv();
977
978 // Stop recv thread
979
980 threadRecvMember.threadStop();
981
982#ifdef CONFIG_DAWN_PROTO_NXSCOPE_SAMPLE_THREAD
983 // Stop sample thread
984
985 threadSampleMember.threadStop();
986#endif
987
988 return ret;
989};
990
992{
993#ifdef CONFIG_DAWN_PROTO_NXSCOPE_SAMPLE_THREAD
994 return !(threadRecvMember.isStopped() & threadSampleMember.isStopped());
995#else
996 return !threadRecvMember.isStopped();
997#endif
998}
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
Base class for all I/O objects.
Definition common.hxx:27
virtual bool isWrite() const =0
Check if IO supports write operations.
int setData(IODataCmn &data, size_t offset=0)
Set data for I/O (public interface with stats tracking).
Definition common.hxx:392
virtual bool isSeekable() const
Check if IO supports partial (seekable) access.
Definition common.hxx:502
virtual size_t getDataDim() const =0
Get data vector dimension.
virtual size_t getDataSize() const =0
Get data size in bytes.
virtual bool isRead() const =0
Check if IO supports read operations.
SObjectId::ObjectId getIdV() const
Get object identifier as raw 32-bit value.
Definition object.cxx:155
uint8_t getDtype() const
Get data type field.
Definition object.cxx:175
Real-time data visualization protocol (base class).
Definition nxscope.hxx:37
int doStop()
Stop implementation hook.
Definition nxscope.cxx:970
bool hasThread() const
Check if a background thread is active.
Definition nxscope.cxx:991
struct nxscope_intf_s nxsIntf
NXScope interface structure (from logging library).
Definition nxscope.hxx:79
int configure()
Configure object from descriptor data.
Definition nxscope.cxx:878
int doStart()
Start implementation hook.
Definition nxscope.cxx:910
int init()
One-time initialize object after bindings are resolved.
Definition nxscope.cxx:891
int deinit()
De-initialize object.
Definition nxscope.cxx:897
int threadStop()
Stop the worker thread.
Definition thread.cxx:240
int threadStart()
Start the worker thread.
Definition thread.cxx:166
void setThreadFunc(Func &&func)
Assign the function executed by threadStart().
Definition thread.hxx:100
Out-of-tree user-extension hooks for Dawn.
Definition bindable.hxx:13
@ DTYPE_FLOAT
IEEE 754 single-precision floating point (32-bit).
Definition objectid.hxx:112
@ DTYPE_INT32
Signed 32-bit integer (-2147483648 to 2147483647).
Definition objectid.hxx:92
@ DTYPE_UINT64
Unsigned 64-bit integer.
Definition objectid.hxx:104
@ DTYPE_UB16
Unsigned 16.16 fixed-point (32-bit).
Definition objectid.hxx:132
@ DTYPE_CHAR
Character/string type (null-terminated, 4-byte aligned).
Definition objectid.hxx:144
@ DTYPE_UINT32
Unsigned 32-bit integer (0 to 4294967295).
Definition objectid.hxx:96
@ DTYPE_B16
Signed 16.16 fixed-point (32-bit).
Definition objectid.hxx:128
uint32_t ObjectId
ObjectID type - single 32-bit value.
Definition objectid.hxx:44
Heap-allocated dynamic I/O data buffer.
Definition ddata.hxx:21
size_t getDataSize()
Get data size in bytes.
Definition ddata.hxx:153
void * getDataPtr(size_t batch=0)
Get pointer to data only (skips timestamp if present).
Definition ddata.hxx:180
size_t getItems()
Get number of items per batch.
Definition ddata.hxx:128