Lely core libraries 2.3.4
sdev.c
Go to the documentation of this file.
1
24#include "co.h"
25
26#if !LELY_NO_CO_SDEV
27
28#include <lely/co/sdev.h>
29#include <lely/libc/stdio.h>
30#include <lely/util/errnum.h>
31#if !LELY_NO_STDIO
32#include <lely/util/lex.h>
33#include <lely/util/print.h>
34#endif
35
36#include <assert.h>
37#if !LELY_NO_STDIO
38// Include inttypes.h after stdio.h to enforce declarations of format specifiers
39// in Newlib.
40#include <inttypes.h>
41#include <stdlib.h>
42#endif
43
44static int co_sdev_load(const struct co_sdev *sdev, co_dev_t *dev);
45static int co_sobj_load(const struct co_sobj *sobj, co_obj_t *obj);
46static int co_ssub_load(const struct co_ssub *ssub, co_sub_t *sub);
47
48#if !LELY_NO_STDIO
49static int snprintf_c99_sobj(char *s, size_t n, const co_obj_t *obj);
50static int snprintf_c99_ssub(char *s, size_t n, const co_sub_t *sub);
51static int snprintf_c99_sval(
52 char *s, size_t n, co_unsigned16_t type, const void *val);
53static int snprintf_c99_esc(char *s, size_t n, const char *esc);
54#endif
55
56struct __co_dev *
57__co_dev_init_from_sdev(struct __co_dev *dev, const struct co_sdev *sdev)
58{
59 assert(dev);
60
61 int errc = 0;
62
63 if (!sdev) {
64 errc = errnum2c(ERRNUM_INVAL);
65 goto error_param;
66 }
67
68 if (!__co_dev_init(dev, sdev->id)) {
69 errc = get_errc();
70 goto error_init_dev;
71 }
72
73 if (co_sdev_load(sdev, dev) == -1) {
74 errc = get_errc();
75 goto error_load_sdev;
76 }
77
78 return dev;
79
80error_load_sdev:
81 __co_dev_fini(dev);
82error_init_dev:
83error_param:
84 set_errc(errc);
85 return NULL;
86}
87
90{
91 int errc = 0;
92
93 co_dev_t *dev = __co_dev_alloc();
94 if (!dev) {
95 errc = get_errc();
96 goto error_alloc_dev;
97 }
98
99 if (!__co_dev_init_from_sdev(dev, sdev)) {
100 errc = get_errc();
101 goto error_init_dev;
102 }
103
104 return dev;
105
106error_init_dev:
107 __co_dev_free(dev);
108error_alloc_dev:
109 set_errc(errc);
110 return NULL;
111}
112
113#if !LELY_NO_STDIO
114
115int
116snprintf_c99_sdev(char *s, size_t n, const co_dev_t *dev)
117{
118 if (!s)
119 n = 0;
120
121 if (!dev)
122 return 0;
123
124 int errsv = 0;
125
126 int r, t = 0;
127 const char *name;
128
129 // cppcheck-suppress nullPointer symbolName=s
130 r = snprintf(s, n, "{\n\t.id = 0x%02x,\n", co_dev_get_id(dev));
131 if (r < 0) {
132 errsv = errno;
133 goto error_print_dev;
134 }
135 t += r;
136 r = MIN((size_t)r, n);
137 s += r;
138 n -= r;
139
140 name = co_dev_get_name(dev);
141 if (name) {
142 r = snprintf(s, n, "\t.name = CO_SDEV_STRING(\"");
143 if (r < 0) {
144 errsv = errno;
145 goto error_print_dev;
146 }
147 t += r;
148 r = MIN((size_t)r, n);
149 s += r;
150 n -= r;
151 r = snprintf_c99_esc(s, n, name);
152 if (r < 0) {
153 errsv = errno;
154 goto error_print_dev;
155 }
156 t += r;
157 r = MIN((size_t)r, n);
158 s += r;
159 n -= r;
160 r = snprintf(s, n, "\"),\n");
161 } else {
162 r = snprintf(s, n, "\t.name = NULL,\n");
163 }
164 if (r < 0) {
165 errsv = errno;
166 goto error_print_dev;
167 }
168 t += r;
169 r = MIN((size_t)r, n);
170 s += r;
171 n -= r;
172
174 if (name) {
175 r = snprintf(s, n, "\t.vendor_name = CO_SDEV_STRING(\"");
176 if (r < 0) {
177 errsv = errno;
178 goto error_print_dev;
179 }
180 t += r;
181 r = MIN((size_t)r, n);
182 s += r;
183 n -= r;
184 r = snprintf_c99_esc(s, n, name);
185 if (r < 0) {
186 errsv = errno;
187 goto error_print_dev;
188 }
189 t += r;
190 r = MIN((size_t)r, n);
191 s += r;
192 n -= r;
193 r = snprintf(s, n, "\"),\n");
194 } else {
195 r = snprintf(s, n, "\t.vendor_name = NULL,\n");
196 }
197 if (r < 0) {
198 errsv = errno;
199 goto error_print_dev;
200 }
201 t += r;
202 r = MIN((size_t)r, n);
203 s += r;
204 n -= r;
205
206 r = snprintf(s, n, "\t.vendor_id = 0x%08" PRIx32 ",\n",
208 if (r < 0) {
209 errsv = errno;
210 goto error_print_dev;
211 }
212 t += r;
213 r = MIN((size_t)r, n);
214 s += r;
215 n -= r;
216
218 if (name) {
219 r = snprintf(s, n, "\t.product_name = CO_SDEV_STRING(\"");
220 if (r < 0) {
221 errsv = errno;
222 goto error_print_dev;
223 }
224 t += r;
225 r = MIN((size_t)r, n);
226 s += r;
227 n -= r;
228 r = snprintf_c99_esc(s, n, name);
229 if (r < 0) {
230 errsv = errno;
231 goto error_print_dev;
232 }
233 t += r;
234 r = MIN((size_t)r, n);
235 s += r;
236 n -= r;
237 r = snprintf(s, n, "\"),\n");
238 } else {
239 r = snprintf(s, n, "\t.product_name = NULL,\n");
240 }
241 if (r < 0) {
242 errsv = errno;
243 goto error_print_dev;
244 }
245 t += r;
246 r = MIN((size_t)r, n);
247 s += r;
248 n -= r;
249
250 r = snprintf(s, n,
251 "\t.product_code = 0x%08" PRIx32
252 ",\n\t.revision = 0x%08" PRIx32 ",\n",
254 if (r < 0) {
255 errsv = errno;
256 goto error_print_dev;
257 }
258 t += r;
259 r = MIN((size_t)r, n);
260 s += r;
261 n -= r;
262
264 if (name) {
265 r = snprintf(s, n, "\t.order_code = CO_SDEV_STRING(\"");
266 if (r < 0) {
267 errsv = errno;
268 goto error_print_dev;
269 }
270 t += r;
271 r = MIN((size_t)r, n);
272 s += r;
273 n -= r;
274 r = snprintf_c99_esc(s, n, name);
275 if (r < 0) {
276 errsv = errno;
277 goto error_print_dev;
278 }
279 t += r;
280 r = MIN((size_t)r, n);
281 s += r;
282 n -= r;
283 r = snprintf(s, n, "\"),\n");
284 } else {
285 r = snprintf(s, n, "\t.order_code = NULL,\n");
286 }
287 if (r < 0) {
288 errsv = errno;
289 goto error_print_dev;
290 }
291 t += r;
292 r = MIN((size_t)r, n);
293 s += r;
294 n -= r;
295
296 r = snprintf(s, n, "\t.baud = 0");
297 if (r < 0) {
298 errsv = errno;
299 goto error_print_dev;
300 }
301 t += r;
302 r = MIN((size_t)r, n);
303 s += r;
304 n -= r;
305 unsigned int baud = co_dev_get_baud(dev);
306#define LELY_CO_DEFINE_BAUD(x) \
307 if (baud & CO_BAUD_##x) { \
308 r = snprintf(s, n, "\n\t\t| CO_BAUD_" #x); \
309 if (r < 0) { \
310 errsv = errno; \
311 goto error_print_dev; \
312 } \
313 t += r; \
314 r = MIN((size_t)r, n); \
315 s += r; \
316 n -= r; \
317 }
318
319 LELY_CO_DEFINE_BAUD(1000)
320 LELY_CO_DEFINE_BAUD(800)
321 LELY_CO_DEFINE_BAUD(500)
322 LELY_CO_DEFINE_BAUD(250)
323 LELY_CO_DEFINE_BAUD(125)
324 LELY_CO_DEFINE_BAUD(50)
325 LELY_CO_DEFINE_BAUD(20)
326 LELY_CO_DEFINE_BAUD(10)
327 LELY_CO_DEFINE_BAUD(AUTO)
328
329#undef LELY_CO_DEFINE_BAUD
330
331 r = snprintf(s, n,
332 ",\n\t.rate = %d,\n\t.lss = %d,\n\t.dummy = 0x%08" PRIx32
333 ",\n",
335 co_dev_get_dummy(dev));
336 if (r < 0) {
337 errsv = errno;
338 goto error_print_dev;
339 }
340 t += r;
341 r = MIN((size_t)r, n);
342 s += r;
343 n -= r;
344
345 co_unsigned16_t maxidx = co_dev_get_idx(dev, 0, NULL);
346 co_unsigned16_t *idx = malloc(maxidx * sizeof(co_unsigned16_t));
347 if (!idx) {
348 errsv = errno;
349 goto error_malloc_idx;
350 }
351 co_dev_get_idx(dev, maxidx, idx);
352
353 r = snprintf(s, n, "\t.nobj = %d,\n\t.objs = (const struct co_sobj[]){",
354 maxidx);
355 if (r < 0) {
356 errsv = errno;
357 goto error_print_obj;
358 }
359 t += r;
360 r = MIN((size_t)r, n);
361 s += r;
362 n -= r;
363
364 for (size_t i = 0; i < maxidx; i++) {
365 r = snprintf(s, n, i ? ", {\n" : "{\n");
366 if (r < 0) {
367 errsv = errno;
368 goto error_print_obj;
369 }
370 t += r;
371 r = MIN((size_t)r, n);
372 s += r;
373 n -= r;
374 r = snprintf_c99_sobj(s, n, co_dev_find_obj(dev, idx[i]));
375 if (r < 0) {
376 errsv = errno;
377 goto error_print_obj;
378 }
379 t += r;
380 r = MIN((size_t)r, n);
381 s += r;
382 n -= r;
383 r = snprintf(s, n, "\t}");
384 if (r < 0) {
385 errsv = errno;
386 goto error_print_obj;
387 }
388 t += r;
389 r = MIN((size_t)r, n);
390 s += r;
391 n -= r;
392 }
393
394 r = snprintf(s, n, "}\n}");
395 if (r < 0) {
396 errsv = errno;
397 goto error_print_obj;
398 }
399 t += r;
400
401 free(idx);
402
403 return t;
404
405error_print_obj:
406 free(idx);
407error_malloc_idx:
408error_print_dev:
409 errno = errsv;
410 return r;
411}
412
413int
414asprintf_c99_sdev(char **ps, const co_dev_t *dev)
415{
416 int n = snprintf_c99_sdev(NULL, 0, dev);
417 if (n < 0)
418 return n;
419
420 char *s = malloc(n + 1);
421 if (!s)
422 return -1;
423
424 n = snprintf_c99_sdev(s, n + 1, dev);
425 if (n < 0) {
426 int errsv = errno;
427 free(s);
428 errno = errsv;
429 return n;
430 }
431
432 *ps = s;
433 return n;
434}
435
436#endif // !LELY_NO_STDIO
437
438static int
439co_sdev_load(const struct co_sdev *sdev, co_dev_t *dev)
440{
441 assert(sdev);
442 assert(dev);
443
444#if !LELY_NO_CO_OBJ_NAME
445 if (co_dev_set_name(dev, sdev->name) == -1)
446 return -1;
447
448 if (co_dev_set_vendor_name(dev, sdev->vendor_name) == -1)
449 return -1;
450#endif
451
453
454#if !LELY_NO_CO_OBJ_NAME
455 if (co_dev_set_product_name(dev, sdev->product_name) == -1)
456 return -1;
457#endif
458
460 co_dev_set_revision(dev, sdev->revision);
461
462#if !LELY_NO_CO_OBJ_NAME
463 if (co_dev_set_order_code(dev, sdev->order_code) == -1)
464 return -1;
465#endif
466
467 co_dev_set_baud(dev, sdev->baud);
468 co_dev_set_rate(dev, sdev->rate);
469
470 co_dev_set_lss(dev, sdev->lss);
471
472 co_dev_set_dummy(dev, sdev->dummy);
473
474 for (size_t i = 0; i < sdev->nobj; i++) {
475 const struct co_sobj *sobj = &sdev->objs[i];
476 co_obj_t *obj = co_obj_create(sobj->idx);
477 if (!obj)
478 return -1;
479 if (co_dev_insert_obj(dev, obj) == -1) {
480 int errc = get_errc();
481 co_obj_destroy(obj);
482 set_errc(errc);
483 return -1;
484 }
485 if (co_sobj_load(sobj, obj) == -1)
486 return -1;
487 }
488
489 return 0;
490}
491
492static int
493co_sobj_load(const struct co_sobj *sobj, co_obj_t *obj)
494{
495 assert(sobj);
496 assert(obj);
497
498#if !LELY_NO_CO_OBJ_NAME
499 if (co_obj_set_name(obj, sobj->name) == -1)
500 return -1;
501#endif
502
503 if (co_obj_set_code(obj, sobj->code) == -1)
504 return -1;
505
506 for (size_t i = 0; i < sobj->nsub; i++) {
507 const struct co_ssub *ssub = &sobj->subs[i];
508 co_sub_t *sub = co_sub_create(ssub->subidx, ssub->type);
509 if (!sub)
510 return -1;
511 if (co_obj_insert_sub(obj, sub) == -1) {
512 int errc = get_errc();
513 co_sub_destroy(sub);
514 set_errc(errc);
515 return -1;
516 }
517 if (co_ssub_load(ssub, sub) == -1)
518 return -1;
519 }
520
521 return 0;
522}
523
524static int
525co_ssub_load(const struct co_ssub *ssub, co_sub_t *sub)
526{
527 assert(ssub);
528 assert(sub);
529
530#if !LELY_NO_CO_OBJ_NAME
531 if (co_sub_set_name(sub, ssub->name) == -1)
532 return -1;
533#endif
534
535 if (co_sub_set_access(sub, ssub->access) == -1)
536 return -1;
537
538 const void *ptr;
539 size_t n;
540
541#if !LELY_NO_CO_OBJ_LIMITS
542 ptr = co_val_addressof(ssub->type, &ssub->min);
543 n = co_val_sizeof(ssub->type, &ssub->min);
544 if (n && !co_sub_set_min(sub, ptr, n))
545 return -1;
546
547 ptr = co_val_addressof(ssub->type, &ssub->max);
548 n = co_val_sizeof(ssub->type, &ssub->max);
549 if (n && !co_sub_set_max(sub, ptr, n))
550 return -1;
551#endif
552
553#if !LELY_NO_CO_OBJ_DEFAULT
554 ptr = co_val_addressof(ssub->type, &ssub->def);
555 n = co_val_sizeof(ssub->type, &ssub->def);
556 if (n && !co_sub_set_def(sub, ptr, n))
557 return -1;
558#endif
559
560 ptr = co_val_addressof(ssub->type, &ssub->val);
561 n = co_val_sizeof(ssub->type, &ssub->val);
562 if (n && !co_sub_set_val(sub, ptr, n))
563 return -1;
564
566 co_sub_set_flags(sub, ssub->flags);
567
568 return 0;
569}
570
571#if !LELY_NO_STDIO
572
573static int
574snprintf_c99_sobj(char *s, size_t n, const co_obj_t *obj)
575{
576 if (!s)
577 n = 0;
578
579 if (!obj)
580 return 0;
581
582 int r, t = 0;
583
584#if !LELY_NO_CO_OBJ_NAME
585 const char *name = co_obj_get_name(obj);
586 if (name) {
587 r = snprintf(s, n,
588 "#if !LELY_NO_CO_OBJ_NAME\n\t\t.name = CO_SDEV_STRING(\"");
589 if (r < 0)
590 return r;
591 t += r;
592 r = MIN((size_t)r, n);
593 s += r;
594 n -= r;
595 r = snprintf_c99_esc(s, n, name);
596 if (r < 0)
597 return r;
598 t += r;
599 r = MIN((size_t)r, n);
600 s += r;
601 n -= r;
602 r = snprintf(s, n, "\"),\n");
603 } else {
604#endif
605 r = snprintf(s, n,
606 "#if !LELY_NO_CO_OBJ_NAME\n\t\t.name = NULL,\n");
607#if !LELY_NO_CO_OBJ_NAME
608 }
609#endif
610 if (r < 0)
611 return r;
612 t += r;
613 r = MIN((size_t)r, n);
614 s += r;
615 n -= r;
616
617 r = snprintf(s, n, "#endif\n\t\t.idx = 0x%04x,\n\t\t.code = ",
618 co_obj_get_idx(obj));
619 if (r < 0)
620 return r;
621 t += r;
622 r = MIN((size_t)r, n);
623 s += r;
624 n -= r;
625
626 co_unsigned8_t code = co_obj_get_code(obj);
627 switch (code) {
628 case CO_OBJECT_NULL: r = snprintf(s, n, "CO_OBJECT_NULL,\n"); break;
629 case CO_OBJECT_DOMAIN: r = snprintf(s, n, "CO_OBJECT_DOMAIN,\n"); break;
631 r = snprintf(s, n, "CO_OBJECT_DEFTYPE,\n");
632 break;
634 r = snprintf(s, n, "CO_OBJECT_DEFSTRUCT,\n");
635 break;
636 case CO_OBJECT_VAR: r = snprintf(s, n, "CO_OBJECT_VAR,\n"); break;
637 case CO_OBJECT_ARRAY: r = snprintf(s, n, "CO_OBJECT_ARRAY,\n"); break;
638 case CO_OBJECT_RECORD: r = snprintf(s, n, "CO_OBJECT_RECORD,\n"); break;
639 default: r = snprintf(s, n, "0x%02x,\n", code); break;
640 }
641 if (r < 0)
642 return r;
643 t += r;
644 r = MIN((size_t)r, n);
645 s += r;
646 n -= r;
647
648 co_unsigned8_t subidx[0xff];
649 co_unsigned8_t maxsubidx = co_obj_get_subidx(obj, 0xff, subidx);
650
651 r = snprintf(s, n,
652 "\t\t.nsub = %d,\n\t\t.subs = (const struct co_ssub[]){",
653 maxsubidx);
654 if (r < 0)
655 return r;
656 t += r;
657 r = MIN((size_t)r, n);
658 s += r;
659 n -= r;
660
661 for (size_t i = 0; i < maxsubidx; i++) {
662 r = snprintf(s, n, i ? ", {\n" : "{\n");
663 if (r < 0)
664 return r;
665 t += r;
666 r = MIN((size_t)r, n);
667 s += r;
668 n -= r;
669 r = snprintf_c99_ssub(s, n, co_obj_find_sub(obj, subidx[i]));
670 if (r < 0)
671 return r;
672 t += r;
673 r = MIN((size_t)r, n);
674 s += r;
675 n -= r;
676 r = snprintf(s, n, "\t\t}");
677 if (r < 0)
678 return r;
679 t += r;
680 r = MIN((size_t)r, n);
681 s += r;
682 n -= r;
683 }
684
685 r = snprintf(s, n, "}\n");
686 if (r < 0)
687 return r;
688 t += r;
689
690 return t;
691}
692
693static int
694snprintf_c99_ssub(char *s, size_t n, const co_sub_t *sub)
695{
696 if (!s)
697 n = 0;
698
699 if (!sub)
700 return 0;
701
702 int r, t = 0;
703
704#if !LELY_NO_CO_OBJ_NAME
705 const char *name = co_sub_get_name(sub);
706 if (name) {
707 r = snprintf(s, n,
708 "#if !LELY_NO_CO_OBJ_NAME\n\t\t\t.name = CO_SDEV_STRING(\"");
709 if (r < 0)
710 return r;
711 t += r;
712 r = MIN((size_t)r, n);
713 s += r;
714 n -= r;
715 r = snprintf_c99_esc(s, n, name);
716 if (r < 0)
717 return r;
718 t += r;
719 r = MIN((size_t)r, n);
720 s += r;
721 n -= r;
722 r = snprintf(s, n, "\"),\n");
723 } else {
724#endif
725 r = snprintf(s, n,
726 "#if !LELY_NO_CO_OBJ_NAME\n\t\t\t.name = NULL,\n");
727#if !LELY_NO_CO_OBJ_NAME
728 }
729#endif
730 if (r < 0)
731 return r;
732 t += r;
733 r = MIN((size_t)r, n);
734 s += r;
735 n -= r;
736
737 r = snprintf(s, n, "#endif\n\t\t\t.subidx = 0x%02x,\n\t\t\t.type = ",
738 co_sub_get_subidx(sub));
739 if (r < 0)
740 return r;
741 t += r;
742 r = MIN((size_t)r, n);
743 s += r;
744 n -= r;
745
746 co_unsigned16_t type = co_sub_get_type(sub);
747 switch (type) {
748#define LELY_CO_DEFINE_TYPE(a, b, c, d) \
749 case CO_DEFTYPE_##a: \
750 r = snprintf(s, n, "CO_DEFTYPE_" #a ",\n"); \
751 break;
752#include <lely/co/def/type.def>
753#undef LELY_CO_DEFINE_TYPE
754 default: r = snprintf(s, n, "0x%04x,\n", type); break;
755 }
756 if (r < 0)
757 return r;
758 t += r;
759 r = MIN((size_t)r, n);
760 s += r;
761 n -= r;
762
763 r = snprintf(s, n, "#if !LELY_NO_CO_OBJ_LIMITS\n\t\t\t.min = ");
764 if (r < 0)
765 return r;
766 t += r;
767 r = MIN((size_t)r, n);
768 s += r;
769 n -= r;
770#if !LELY_NO_CO_OBJ_LIMITS
771 r = snprintf_c99_sval(s, n, type, co_sub_get_min(sub));
772#else
773 union co_val min;
774 co_val_init_min(type, &min);
775 r = snprintf_c99_sval(s, n, type, &min);
776 co_val_fini(type, &min);
777#endif
778 if (r < 0)
779 return r;
780 t += r;
781 r = MIN((size_t)r, n);
782 s += r;
783 n -= r;
784
785 r = snprintf(s, n, ",\n\t\t\t.max = ");
786 if (r < 0)
787 return r;
788 t += r;
789 r = MIN((size_t)r, n);
790 s += r;
791 n -= r;
792#if !LELY_NO_CO_OBJ_LIMITS
793 r = snprintf_c99_sval(s, n, type, co_sub_get_max(sub));
794#else
795 union co_val max;
796 co_val_init_max(type, &max);
797 r = snprintf_c99_sval(s, n, type, &max);
798 co_val_fini(type, &max);
799#endif
800 if (r < 0)
801 return r;
802 t += r;
803 r = MIN((size_t)r, n);
804 s += r;
805 n -= r;
806
807 r = snprintf(s, n,
808 ",\n#endif\n#if !LELY_NO_CO_OBJ_DEFAULT\n\t\t\t.def = ");
809 if (r < 0)
810 return r;
811 t += r;
812 r = MIN((size_t)r, n);
813 s += r;
814 n -= r;
815#if !LELY_NO_CO_OBJ_DEFAULT
816 r = snprintf_c99_sval(s, n, type, co_sub_get_def(sub));
817#else
818 union co_val def;
819 co_val_init_min(type, &def);
820 r = snprintf_c99_sval(s, n, type, &def);
821 co_val_fini(type, &def);
822#endif
823 if (r < 0)
824 return r;
825 t += r;
826 r = MIN((size_t)r, n);
827 s += r;
828 n -= r;
829
830 r = snprintf(s, n, ",\n#endif\n\t\t\t.val = ");
831 if (r < 0)
832 return r;
833 t += r;
834 r = MIN((size_t)r, n);
835 s += r;
836 n -= r;
837#if !LELY_NO_CO_OBJ_FILE
838 // clang-format off
839 if (type == CO_DEFTYPE_DOMAIN
841 || (co_sub_get_flags(sub)
843 // clang-format on
844 r = snprintf_c99_sval(s, n, CO_DEFTYPE_VISIBLE_STRING,
845 co_sub_get_val(sub));
846 else
847#endif
848 r = snprintf_c99_sval(s, n, type, co_sub_get_val(sub));
849 if (r < 0)
850 return r;
851 t += r;
852 r = MIN((size_t)r, n);
853 s += r;
854 n -= r;
855
856 r = snprintf(s, n, ",\n\t\t\t.access = ");
857 if (r < 0)
858 return r;
859 t += r;
860 r = MIN((size_t)r, n);
861 s += r;
862 n -= r;
863 unsigned int access = co_sub_get_access(sub);
864 switch (access) {
865 case CO_ACCESS_RO: r = snprintf(s, n, "CO_ACCESS_RO,\n"); break;
866 case CO_ACCESS_WO: r = snprintf(s, n, "CO_ACCESS_WO,\n"); break;
867 case CO_ACCESS_RW: r = snprintf(s, n, "CO_ACCESS_RW,\n"); break;
868 case CO_ACCESS_RWR: r = snprintf(s, n, "CO_ACCESS_RWR,\n"); break;
869 case CO_ACCESS_RWW: r = snprintf(s, n, "CO_ACCESS_RWW,\n"); break;
870 case CO_ACCESS_CONST: r = snprintf(s, n, "CO_ACCESS_CONST,\n"); break;
871 default: r = snprintf(s, n, "0x%x,\n", access); break;
872 }
873 if (r < 0)
874 return r;
875 t += r;
876 r = MIN((size_t)r, n);
877 s += r;
878 n -= r;
879
880 r = snprintf(s, n, "\t\t\t.pdo_mapping = %d,\n",
882 if (r < 0)
883 return r;
884 t += r;
885 r = MIN((size_t)r, n);
886 s += r;
887 n -= r;
888
889 r = snprintf(s, n, "\t\t\t.flags = 0\n");
890 if (r < 0)
891 return r;
892 t += r;
893 r = MIN((size_t)r, n);
894 s += r;
895 n -= r;
896 unsigned int flags = co_sub_get_flags(sub);
897#define LELY_CO_DEFINE_FLAGS(x) \
898 if (flags & CO_OBJ_FLAGS_##x) { \
899 r = snprintf(s, n, "\t\t\t\t| CO_OBJ_FLAGS_" #x "\n"); \
900 if (r < 0) \
901 return r; \
902 t += r; \
903 r = MIN((size_t)r, n); \
904 s += r; \
905 n -= r; \
906 }
907
908 LELY_CO_DEFINE_FLAGS(READ)
909 LELY_CO_DEFINE_FLAGS(WRITE)
910#if !LELY_NO_CO_OBJ_FILE
911 LELY_CO_DEFINE_FLAGS(UPLOAD_FILE)
912 LELY_CO_DEFINE_FLAGS(DOWNLOAD_FILE)
913#endif
914 LELY_CO_DEFINE_FLAGS(MIN_NODEID)
915 LELY_CO_DEFINE_FLAGS(MAX_NODEID)
916 LELY_CO_DEFINE_FLAGS(DEF_NODEID)
917 LELY_CO_DEFINE_FLAGS(VAL_NODEID)
918 // cppcheck-suppress uselessAssignmentArg
919 // cppcheck-suppress uselessAssignmentPtrArg
920 LELY_CO_DEFINE_FLAGS(PARAMETER_VALUE)
921
922#undef LELY_CO_DEFINE_FLAGS
923
924 return t;
925}
926
927static int
928snprintf_c99_sval(char *s, size_t n, co_unsigned16_t type, const void *val)
929{
930 if (!s)
931 n = 0;
932
933 if (!val)
934 return 0;
935
936 int r, t = 0;
937
938 const union co_val *u = val;
939 switch (type) {
941 r = snprintf(s, n, "{ .b = %d }", !!u->b);
942 break;
944 if (u->i8 == CO_INTEGER8_MIN) {
945 r = snprintf(s, n, "{ .i8 = CO_INTEGER8_MIN }");
946 } else if (u->i8 == CO_INTEGER8_MAX) {
947 r = snprintf(s, n, "{ .i8 = CO_INTEGER8_MAX }");
948 } else {
949 r = snprintf(s, n, "{ .i8 = %" PRIi8 " }", u->i8);
950 }
951 break;
953 if (u->i16 == CO_INTEGER16_MIN) {
954 r = snprintf(s, n, "{ .i16 = CO_INTEGER16_MIN }");
955 } else if (u->i16 == CO_INTEGER16_MAX) {
956 r = snprintf(s, n, "{ .i16 = CO_INTEGER16_MAX }");
957 } else {
958 r = snprintf(s, n, "{ .i16 = %" PRIi16 " }", u->i16);
959 }
960 break;
962 if (u->i32 == CO_INTEGER32_MIN) {
963 r = snprintf(s, n, "{ .i32 = CO_INTEGER32_MIN }");
964 } else if (u->i32 == CO_INTEGER32_MAX) {
965 r = snprintf(s, n, "{ .i32 = CO_INTEGER32_MAX }");
966 } else {
967 r = snprintf(s, n, "{ .i32 = %" PRIi32 "l }", u->i32);
968 }
969 break;
971 if (u->u8 == CO_UNSIGNED8_MIN) {
972 r = snprintf(s, n, "{ .u8 = CO_UNSIGNED8_MIN }");
973 } else if (u->u8 == CO_UNSIGNED8_MAX) {
974 r = snprintf(s, n, "{ .u8 = CO_UNSIGNED8_MAX }");
975 } else {
976 r = snprintf(s, n, "{ .u8 = 0x%02" PRIx8 " }", u->u8);
977 }
978 break;
980 if (u->u16 == CO_UNSIGNED16_MIN) {
981 r = snprintf(s, n, "{ .u16 = CO_UNSIGNED16_MIN }");
982 } else if (u->u16 == CO_UNSIGNED16_MAX) {
983 r = snprintf(s, n, "{ .u16 = CO_UNSIGNED16_MAX }");
984 } else {
985 r = snprintf(s, n, "{ .u16 = 0x%04" PRIx16 "u }",
986 u->u16);
987 }
988 break;
990 if (u->u32 == CO_UNSIGNED32_MIN) {
991 r = snprintf(s, n, "{ .u32 = CO_UNSIGNED32_MIN }");
992 } else if (u->u32 == CO_UNSIGNED32_MAX) {
993 r = snprintf(s, n, "{ .u32 = CO_UNSIGNED32_MAX }");
994 } else {
995 r = snprintf(s, n, "{ .u32 = 0x%08" PRIx32 "lu }",
996 u->u32);
997 }
998 break;
1000 if (u->r32 == CO_REAL32_MIN) {
1001 r = snprintf(s, n, "{ .r32 = CO_REAL32_MIN }");
1002 } else if (u->r32 == CO_REAL32_MAX) {
1003 r = snprintf(s, n, "{ .r32 = CO_REAL32_MAX }");
1004 } else {
1005 r = snprintf(s, n, "{ .r32 = %.*g }", DECIMAL_DIG,
1006 (double)u->r32);
1007 }
1008 break;
1010 if (u->vs) {
1011 r = snprintf(s, n, "{ .vs = CO_VISIBLE_STRING_C(\"");
1012 if (r < 0)
1013 return r;
1014 t += r;
1015 r = MIN((size_t)r, n);
1016 s += r;
1017 n -= r;
1018 r = snprintf_c99_esc(s, n, u->vs);
1019 if (r < 0)
1020 return r;
1021 t += r;
1022 r = MIN((size_t)r, n);
1023 s += r;
1024 n -= r;
1025 r = snprintf(s, n, "\") }");
1026 } else {
1027 r = snprintf(s, n, "{ .vs = NULL }");
1028 }
1029 break;
1031 if (u->os) {
1032 r = snprintf(s, n,
1033 "{ .os = CO_OCTET_STRING_C(\n\t\t\t\t\"");
1034 if (r < 0)
1035 return r;
1036 t += r;
1037 r = MIN((size_t)r, n);
1038 s += r;
1039 n -= r;
1040 size_t size = co_val_sizeof(type, val);
1041 for (size_t i = 0; i < size; i++) {
1042 // clang-format off
1043 r = snprintf(s, n, i && !(i % 8)
1044 ? "\"\n\t\t\t\t\"\\x%02x"
1045 : "\\x%02x",
1046 u->os[i]);
1047 // clang-format on
1048 if (r < 0)
1049 return r;
1050 t += r;
1051 r = MIN((size_t)r, n);
1052 s += r;
1053 n -= r;
1054 }
1055 r = snprintf(s, n, "\"\n\t\t\t) }");
1056 } else {
1057 r = snprintf(s, n, "{ .vs = NULL }");
1058 }
1059 break;
1061 if (u->us) {
1062 r = snprintf(s, n,
1063 "{ .us = CO_UNICODE_STRING_C({\n\t\t\t\t");
1064 if (r < 0)
1065 return r;
1066 t += r;
1067 r = MIN((size_t)r, n);
1068 s += r;
1069 n -= r;
1070 size_t size = co_val_sizeof(type, val) / 2 + 1;
1071 for (size_t i = 0; i < size; i++) {
1072 // clang-format off
1073 r = snprintf(s, n, i && !(i % 4)
1074 ? ",\n\t\t\t\t0x%04x"
1075 : (i ? ", 0x%04x" : "0x%04x"),
1076 u->us[i]);
1077 // clang-format on
1078 if (r < 0)
1079 return r;
1080 t += r;
1081 r = MIN((size_t)r, n);
1082 s += r;
1083 n -= r;
1084 }
1085 r = snprintf(s, n, "\n\t\t\t}) }");
1086 } else {
1087 r = snprintf(s, n, "{ .us = NULL }");
1088 }
1089 break;
1091 r = snprintf(s, n,
1092 "{ .t = { "
1093 ".ms = 0x%08" PRIx32 ", "
1094 ".days = 0x%04" PRIx16 " "
1095 "} }",
1096 u->t.ms, u->t.days);
1097 break;
1099 r = snprintf(s, n,
1100 "{ .t = { "
1101 ".ms = 0x%08" PRIx32 ", "
1102 ".days = 0x%04" PRIx16 " "
1103 "} }",
1104 u->td.ms, u->td.days);
1105 break;
1106 case CO_DEFTYPE_DOMAIN:
1107 if (u->dom) {
1108 r = snprintf(s, n,
1109 "{ .dom = CO_DOMAIN_C(co_unsigned8_t, {\n\t\t\t\t");
1110 if (r < 0)
1111 return r;
1112 t += r;
1113 r = MIN((size_t)r, n);
1114 s += r;
1115 n -= r;
1116 const co_unsigned8_t *bp = u->dom;
1117 size_t size = co_val_sizeof(type, val);
1118 for (size_t i = 0; i < size; i++) {
1119 // clang-format off
1120 r = snprintf(s, n, i && !(i % 8)
1121 ? ",\n\t\t\t\t0x%02x"
1122 : (i ? ", 0x%02x" : "0x%02x"),
1123 bp[i]);
1124 // clang-format on
1125 if (r < 0)
1126 return r;
1127 t += r;
1128 r = MIN((size_t)r, n);
1129 s += r;
1130 n -= r;
1131 }
1132 r = snprintf(s, n, "\n\t\t\t}) }");
1133 } else {
1134 r = snprintf(s, n, "{ .dom = NULL }");
1135 }
1136 break;
1138 if (u->i24 == CO_INTEGER24_MIN) {
1139 r = snprintf(s, n, "{ .i24 = CO_INTEGER24_MIN }");
1140 } else if (u->i24 == CO_INTEGER24_MAX) {
1141 r = snprintf(s, n, "{ .i24 = CO_INTEGER24_MAX }");
1142 } else {
1143 r = snprintf(s, n, "{ .i24 = %" PRIi32 "l }", u->i24);
1144 }
1145 break;
1146 case CO_DEFTYPE_REAL64:
1147 if (u->r64 == CO_REAL64_MIN) {
1148 r = snprintf(s, n, "{ .r64 = CO_REAL64_MIN }");
1149 } else if (u->r64 == CO_REAL64_MAX) {
1150 r = snprintf(s, n, "{ .r64 = CO_REAL64_MAX }");
1151 } else {
1152 r = snprintf(s, n, "{ .r64 = %.*g }", DECIMAL_DIG,
1153 u->r64);
1154 }
1155 break;
1157 if (u->i40 == CO_INTEGER40_MIN) {
1158 r = snprintf(s, n, "{ CO_INTEGER40_MIN }");
1159 } else if (u->i40 == CO_INTEGER40_MAX) {
1160 r = snprintf(s, n, "{ CO_INTEGER40_MAX }");
1161 } else {
1162 r = snprintf(s, n, "{ .i40 = %" PRIi64 "ll }", u->i40);
1163 }
1164 break;
1166 if (u->i48 == CO_INTEGER48_MIN) {
1167 r = snprintf(s, n, "{ .i48 = CO_INTEGER48_MIN }");
1168 } else if (u->i48 == CO_INTEGER48_MAX) {
1169 r = snprintf(s, n, "{ .i48 = CO_INTEGER48_MAX }");
1170 } else {
1171 r = snprintf(s, n, "{ .i48 = %" PRIi64 "ll }", u->i48);
1172 }
1173 break;
1175 if (u->i56 == CO_INTEGER56_MIN) {
1176 r = snprintf(s, n, "{ .i56 = CO_INTEGER56_MIN }");
1177 } else if (u->i56 == CO_INTEGER56_MAX) {
1178 r = snprintf(s, n, "{ .i56 = CO_INTEGER56_MAX }");
1179 } else {
1180 r = snprintf(s, n, "{ .i56 = %" PRIi64 "ll }", u->i56);
1181 }
1182 break;
1184 if (u->i64 == CO_INTEGER64_MIN) {
1185 r = snprintf(s, n, "{ .i64 = CO_INTEGER64_MIN }");
1186 } else if (u->i64 == CO_INTEGER64_MAX) {
1187 r = snprintf(s, n, "{ .i64 = CO_INTEGER64_MAX }");
1188 } else {
1189 r = snprintf(s, n, "{ .i64 = %" PRIi64 "ll }", u->i64);
1190 }
1191 break;
1193 if (u->u24 == CO_UNSIGNED24_MIN) {
1194 r = snprintf(s, n, "{ .u24 = CO_UNSIGNED24_MIN }");
1195 } else if (u->u24 == CO_UNSIGNED24_MAX) {
1196 r = snprintf(s, n, "{ .u24 = CO_UNSIGNED24_MAX }");
1197 } else {
1198 r = snprintf(s, n, "{ .u24 = 0x%06" PRIx32 "lu }",
1199 u->u24);
1200 }
1201 break;
1203 if (u->u40 == CO_UNSIGNED40_MIN) {
1204 r = snprintf(s, n, "{ .u40 = CO_UNSIGNED40_MIN }");
1205 } else if (u->u40 == CO_UNSIGNED40_MAX) {
1206 r = snprintf(s, n, "{ .u40 = CO_UNSIGNED40_MAX }");
1207 } else {
1208 r = snprintf(s, n, "{ .u40 = 0x%010" PRIx64 "llu }",
1209 u->u40);
1210 }
1211 break;
1213 if (u->u48 == CO_UNSIGNED48_MIN) {
1214 r = snprintf(s, n, "{ .u48 = CO_UNSIGNED48_MIN }");
1215 } else if (u->u48 == CO_UNSIGNED48_MAX) {
1216 r = snprintf(s, n, "{ .u48 = CO_UNSIGNED48_MAX }");
1217 } else {
1218 r = snprintf(s, n, "{ .u48 = 0x%012" PRIx64 "llu }",
1219 u->u48);
1220 }
1221 break;
1223 if (u->u56 == CO_UNSIGNED56_MIN) {
1224 r = snprintf(s, n, "{ .u56 = CO_UNSIGNED56_MIN }");
1225 } else if (u->u56 == CO_UNSIGNED56_MAX) {
1226 r = snprintf(s, n, "{ .u56 = CO_UNSIGNED56_MAX }");
1227 } else {
1228 r = snprintf(s, n, "{ .u56 = 0x%014" PRIx64 "llu }",
1229 u->u56);
1230 }
1231 break;
1233 if (u->u64 == CO_UNSIGNED64_MIN) {
1234 r = snprintf(s, n, "{ .u64 = CO_UNSIGNED64_MIN }");
1235 } else if (u->u64 == CO_UNSIGNED64_MAX) {
1236 r = snprintf(s, n, "{ .u64 = CO_UNSIGNED64_MAX }");
1237 } else {
1238 r = snprintf(s, n, "{ .u64 = 0x%016" PRIx64 "llu }",
1239 u->u64);
1240 }
1241 break;
1242 default: r = 0; break;
1243 }
1244 if (r < 0)
1245 return r;
1246 t += r;
1247
1248 return t;
1249}
1250
1251static int
1252snprintf_c99_esc(char *s, size_t n, const char *esc)
1253{
1254 if (!s)
1255 n = 0;
1256
1257 if (!esc)
1258 return 0;
1259
1260 int t = 0;
1261
1262 for (;;) {
1263 // Read the next UTF-8 encoded Unicode character.
1264 char32_t c32;
1265 size_t chars = lex_utf8(esc, NULL, NULL, &c32);
1266 if (!chars || !c32)
1267 break;
1268 esc += chars;
1269 // Print the C99 escape sequence to a temporary buffer.
1270 char buf[12] = { '\0' };
1271 char *cp = buf;
1272 print_c99_esc(&cp, buf + sizeof(buf), c32);
1273 // Print the character to the string.
1274 int r = snprintf(s, n, "%s", buf);
1275 if (r < 0)
1276 return r;
1277 t += r;
1278 r = MIN((size_t)r, n);
1279 s += r;
1280 n -= r;
1281 }
1282
1283 return t;
1284}
1285
1286#endif // !LELY_NO_STDIO
1287
1288#endif // !LELY_NO_CO_SDEV
co_obj_t * co_dev_find_obj(const co_dev_t *dev, co_unsigned16_t idx)
Finds an object in the object dictionary of a CANopen device.
Definition: dev.c:279
co_unsigned16_t co_dev_get_idx(const co_dev_t *dev, co_unsigned16_t maxidx, co_unsigned16_t *idx)
Retrieves a list of object indices in the object dictionary of a CANopen device.
Definition: dev.c:223
co_unsigned8_t co_dev_get_id(const co_dev_t *dev)
Returns the node-ID of a CANopen device.
Definition: dev.c:197
int co_dev_set_vendor_name(co_dev_t *dev, const char *vendor_name)
Sets the vendor name of a CANopen device.
Definition: dev.c:357
void co_dev_set_product_code(co_dev_t *dev, co_unsigned32_t product_code)
Sets the product code of a CANopen device.
Definition: dev.c:443
void co_dev_set_dummy(co_dev_t *dev, co_unsigned32_t dummy)
Sets the data types supported by a CANopen device for mapping dummy entries in PDOs.
Definition: dev.c:559
int co_dev_insert_obj(co_dev_t *dev, co_obj_t *obj)
Inserts an object into the object dictionary of a CANopen device.
Definition: dev.c:242
const char * co_dev_get_product_name(const co_dev_t *dev)
Returns a pointer to the product name of a CANopen device.
Definition: dev.c:401
void co_dev_set_vendor_id(co_dev_t *dev, co_unsigned32_t vendor_id)
Sets the vendor ID of a CANopen device.
Definition: dev.c:391
const char * co_dev_get_vendor_name(const co_dev_t *dev)
Returns a pointer to the vendor name of a CANopen device.
Definition: dev.c:349
void co_dev_set_revision(co_dev_t *dev, co_unsigned32_t revision)
Sets the revision number of a CANopen device.
Definition: dev.c:459
co_unsigned16_t co_dev_get_rate(const co_dev_t *dev)
Returns the (pending) baudrate of a CANopen device (in kbit/s).
Definition: dev.c:519
int co_dev_get_lss(const co_dev_t *dev)
Returns 1 if LSS is supported and 0 if not.
Definition: dev.c:535
co_unsigned32_t co_dev_get_vendor_id(const co_dev_t *dev)
Returns the vendor ID of a CANopen device.
Definition: dev.c:383
void co_dev_set_lss(co_dev_t *dev, int lss)
Sets the LSS support flag.
Definition: dev.c:543
int co_dev_set_order_code(co_dev_t *dev, const char *order_code)
Sets the order code of a CANopen device.
Definition: dev.c:477
co_unsigned32_t co_dev_get_dummy(const co_dev_t *dev)
Returns the data types supported by a CANopen device for mapping dummy entries in PDOs (one bit for e...
Definition: dev.c:551
const char * co_dev_get_name(const co_dev_t *dev)
Returns the name of a CANopen device.
Definition: dev.c:317
void co_dev_set_rate(co_dev_t *dev, co_unsigned16_t rate)
Sets the (pending) baudrate of a CANopen device.
Definition: dev.c:527
unsigned int co_dev_get_baud(const co_dev_t *dev)
Returns the supported bit rates of a CANopen device (any combination of CO_BAUD_1000,...
Definition: dev.c:503
co_unsigned32_t co_dev_get_product_code(const co_dev_t *dev)
Returns the product code of a CANopen device.
Definition: dev.c:435
int co_dev_set_product_name(co_dev_t *dev, const char *product_name)
Sets the product name of a CANopen device.
Definition: dev.c:409
void co_dev_set_baud(co_dev_t *dev, unsigned int baud)
Sets the supported bit rates of a CANopen device.
Definition: dev.c:511
const char * co_dev_get_order_code(const co_dev_t *dev)
Returns a pointer to the order code of a CANopen device.
Definition: dev.c:469
int co_dev_set_name(co_dev_t *dev, const char *name)
Sets the name of a CANopen device.
Definition: dev.c:325
co_unsigned32_t co_dev_get_revision(const co_dev_t *dev)
Returns the revision number of a CANopen device.
Definition: dev.c:451
This header file is part of the utilities library; it contains the native and platform-independent er...
int errnum2c(errnum_t errnum)
Transforms a platform-independent error number to a native error code.
Definition: errnum.c:810
@ ERRNUM_INVAL
Invalid argument.
Definition: errnum.h:132
int get_errc(void)
Returns the last (thread-specific) native error code set by a system call or library function.
Definition: errnum.c:932
void set_errc(int errc)
Sets the current (thread-specific) native error code to errc.
Definition: errnum.c:944
#define MIN(a, b)
Returns the minimum of a and b.
Definition: util.h:57
This header file is part of the utilities library; it contains the lexer function declarations.
size_t lex_utf8(const char *begin, const char *end, struct floc *at, char32_t *pc32)
Lexes a UTF-8 encoded Unicode character from a memory buffer.
Definition: lex.c:86
int co_sub_set_access(co_sub_t *sub, unsigned int access)
Sets the access type of a CANopen sub-object.
Definition: obj.c:786
co_unsigned8_t co_obj_get_subidx(const co_obj_t *obj, co_unsigned8_t maxsubidx, co_unsigned8_t *subidx)
Retrieves a list of sub-indices in a CANopen object.
Definition: obj.c:172
int co_sub_set_name(co_sub_t *sub, const char *name)
Sets the name of a CANopen sub-object.
Definition: obj.c:578
co_unsigned8_t co_sub_get_subidx(const co_sub_t *sub)
Returns the sub-index of a CANopen sub-object.
Definition: obj.c:559
void co_sub_destroy(co_sub_t *sub)
Destroys a CANopen sub-object.
Definition: obj.c:522
#define CO_ACCESS_WO
Write-only access.
Definition: obj.h:72
size_t co_sub_set_def(co_sub_t *sub, const void *ptr, size_t n)
Sets the default value of a CANopen sub-object.
Definition: obj.c:689
#define CO_ACCESS_RO
Read-only access.
Definition: obj.h:69
const void * co_sub_get_min(const co_sub_t *sub)
Returns a pointer to the lower limit of the value of a CANopen sub-object.
Definition: obj.c:625
co_unsigned16_t co_obj_get_idx(const co_obj_t *obj)
Returns the index of a CANopen object.
Definition: obj.c:164
const char * co_sub_get_name(const co_sub_t *sub)
Returns the name of a CANopen sub-object.
Definition: obj.c:568
const void * co_sub_get_def(const co_sub_t *sub)
Returns a pointer to the default value of a CANopen sub-object.
Definition: obj.c:683
const void * co_sub_get_val(const co_sub_t *sub)
Returns a pointer to the current value of a CANopen sub-object.
Definition: obj.c:712
#define CO_OBJECT_DEFSTRUCT
A record type definition.
Definition: obj.h:39
int co_obj_set_code(co_obj_t *obj, co_unsigned8_t code)
Sets the code (type) of a CANopen object.
Definition: obj.c:311
void co_sub_set_flags(co_sub_t *sub, unsigned int flags)
Sets the object flags of a CANopen sub-object.
Definition: obj.c:826
int co_sub_get_pdo_mapping(const co_sub_t *sub)
Returns 1 if it is possible to map the specified CANopen sub-object into a PDO, and 0 if not.
Definition: obj.c:802
co_sub_t * co_obj_find_sub(const co_obj_t *obj, co_unsigned8_t subidx)
Finds a sub-object in a CANopen object.
Definition: obj.c:240
size_t co_sub_set_val(co_sub_t *sub, const void *ptr, size_t n)
Sets the current value of a CANopen sub-object.
Definition: obj.c:718
co_unsigned8_t co_obj_get_code(const co_obj_t *obj)
Returns the object code of a CANopen object.
Definition: obj.c:303
size_t co_sub_set_max(co_sub_t *sub, const void *ptr, size_t n)
Sets the upper limit of a value of a CANopen sub-object.
Definition: obj.c:658
unsigned int co_sub_get_flags(const co_sub_t *sub)
Returns the object flags of a CANopen sub-object.
Definition: obj.c:818
#define CO_OBJECT_ARRAY
A multiple data field object where each data field is a simple variable of the same basic data type.
Definition: obj.h:48
#define CO_OBJECT_RECORD
A multiple data field object where the data fields may be any combination of simple variables.
Definition: obj.h:54
int co_obj_set_name(co_obj_t *obj, const char *name)
Sets the name of a CANopen object.
Definition: obj.c:278
const void * co_sub_get_max(const co_sub_t *sub)
Returns a pointer to the upper limit of the value of a CANopen sub-object.
Definition: obj.c:652
size_t co_sub_set_min(co_sub_t *sub, const void *ptr, size_t n)
Sets the lower limit of a value of a CANopen sub-object.
Definition: obj.c:631
#define CO_OBJECT_DEFTYPE
A type definitions.
Definition: obj.h:36
const char * co_obj_get_name(const co_obj_t *obj)
Returns the name of a CANopen object.
Definition: obj.c:268
void co_sub_set_pdo_mapping(co_sub_t *sub, int pdo_mapping)
Enables or disables PDO mapping a CANopen sub-object.
Definition: obj.c:810
#define CO_OBJECT_DOMAIN
A large variable amount of data.
Definition: obj.h:33
void co_obj_destroy(co_obj_t *obj)
Destroys a CANopen object, including its sub-objects.
Definition: obj.c:126
#define CO_ACCESS_RW
Read or write access.
Definition: obj.h:75
#define CO_OBJECT_VAR
A single value.
Definition: obj.h:42
#define CO_ACCESS_RWR
Read or write on process input.
Definition: obj.h:78
#define CO_OBJ_FLAGS_DOWNLOAD_FILE
If a write access is performed for the object, the data is stored in a file.
Definition: obj.h:102
int co_obj_insert_sub(co_obj_t *obj, co_sub_t *sub)
Inserts a sub-object into a CANopen object.
Definition: obj.c:192
#define CO_OBJECT_NULL
An object with no data fields.
Definition: obj.h:30
co_obj_t * co_obj_create(co_unsigned16_t idx)
Creates a CANopen object.
Definition: obj.c:114
#define CO_OBJ_FLAGS_UPLOAD_FILE
If a read access is performed for the object, the data is stored in a file.
Definition: obj.h:96
unsigned int co_sub_get_access(const co_sub_t *sub)
Returns the access type of a CANopen sub-object.
Definition: obj.c:778
#define CO_ACCESS_RWW
Read or write on process output.
Definition: obj.h:81
co_sub_t * co_sub_create(co_unsigned8_t subidx, co_unsigned16_t type)
Creates a CANopen sub-object.
Definition: obj.c:497
co_unsigned16_t co_sub_get_type(const co_sub_t *sub)
Returns the data type of a CANopen sub-object.
Definition: obj.c:603
#define CO_ACCESS_CONST
Constant value.
Definition: obj.h:84
This header file is part of the utilities library; it contains the printing function declarations.
size_t print_c99_esc(char **pbegin, char *end, char32_t c32)
Prints a UTF-8 encoded Unicode character to a memory buffer.
Definition: print.c:109
co_dev_t * co_dev_create_from_sdev(const struct co_sdev *sdev)
Creates a CANopen device from a static device description.
Definition: sdev.c:89
int snprintf_c99_sdev(char *s, size_t n, const co_dev_t *dev)
Prints a C99 static initializer code fragment for a static device description (struct co_sdev) to a s...
Definition: sdev.c:116
int asprintf_c99_sdev(char **ps, const co_dev_t *dev)
Equivalent to snprintf_c99_sdev(), except that it allocates a string large enough to hold the output,...
Definition: sdev.c:414
This header file is part of the CANopen library; it contains the static device description declaratio...
This is the internal header file of the CANopen library.
This header file is part of the C11 and POSIX compatibility library; it includes <stdio....
This header file is part of the C11 and POSIX compatibility library; it includes <stdlib....
A CANopen device.
Definition: dev.h:30
unsigned baud
The supported bit rates.
Definition: dev.h:58
char * name
A pointer to the name of the device.
Definition: dev.h:39
A CANopen object.
Definition: obj.h:31
A CANopen sub-object.
Definition: obj.h:53
A static CANopen device.
Definition: sdev.h:30
co_unsigned8_t id
The node-ID.
Definition: sdev.h:32
co_unsigned16_t nobj
The number of objects in objs.
Definition: sdev.h:56
int lss
A flag specifying whether LSS is supported (1) or not (0).
Definition: sdev.h:52
const char * product_name
A pointer to the product name.
Definition: sdev.h:40
const char * vendor_name
A pointer to the vendor name.
Definition: sdev.h:36
co_unsigned32_t dummy
The data types supported for mapping dummy entries in PDOs.
Definition: sdev.h:54
co_unsigned16_t rate
The (pending) baudrate (in kbit/s).
Definition: sdev.h:50
unsigned baud
The supported bit rates.
Definition: sdev.h:48
co_unsigned32_t product_code
The product code.
Definition: sdev.h:42
co_unsigned32_t vendor_id
The vendor ID.
Definition: sdev.h:38
const char * name
A pointer to the name of the device.
Definition: sdev.h:34
const char * order_code
A pointer to the order code.
Definition: sdev.h:46
co_unsigned32_t revision
The revision number.
Definition: sdev.h:44
const struct co_sobj * objs
An array of objects.
Definition: sdev.h:58
A static CANopen object.
Definition: sdev.h:62
const struct co_ssub * subs
An array of sub-objects.
Definition: sdev.h:74
const char * name
A pointer to the name of the object.
Definition: sdev.h:65
co_unsigned16_t idx
The object index.
Definition: sdev.h:68
co_unsigned8_t nsub
The number of sub-objects in subs.
Definition: sdev.h:72
co_unsigned8_t code
The object code.
Definition: sdev.h:70
A static CANopen sub-object.
Definition: sdev.h:78
union co_val min
The lower limit of val.
Definition: sdev.h:89
union co_val def
The default value of val.
Definition: sdev.h:95
co_unsigned8_t subidx
The object sub-index.
Definition: sdev.h:84
uint_least32_t flags
The object flags.
Definition: sdev.h:104
const char * name
A pointer to the name of the sub-object.
Definition: sdev.h:81
union co_val val
The sub-object value.
Definition: sdev.h:98
uint_least32_t pdo_mapping
A flag indicating if it is possible to map this object into a PDO.
Definition: sdev.h:102
uint_least32_t access
The access type.
Definition: sdev.h:100
co_unsigned16_t type
The data type.
Definition: sdev.h:86
union co_val max
The upper limit of val.
Definition: sdev.h:91
#define CO_DEFTYPE_UNICODE_STRING
The data type (and object index) of an array of (16-bit) Unicode characters.
Definition: type.h:62
#define CO_DEFTYPE_UNSIGNED16
The data type (and object index) of a 16-bit unsigned integer.
Definition: type.h:47
#define CO_DEFTYPE_INTEGER24
The data type (and object index) of a 24-bit signed integer.
Definition: type.h:80
#define CO_DEFTYPE_UNSIGNED48
The data type (and object index) of a 48-bit unsigned integer.
Definition: type.h:104
#define CO_DEFTYPE_INTEGER48
The data type (and object index) of a 48-bit signed integer.
Definition: type.h:89
#define CO_DEFTYPE_VISIBLE_STRING
The data type (and object index) of an array of visible characters.
Definition: type.h:56
#define CO_DEFTYPE_UNSIGNED40
The data type (and object index) of a 40-bit unsigned integer.
Definition: type.h:101
#define CO_DEFTYPE_INTEGER56
The data type (and object index) of a 56-bit signed integer.
Definition: type.h:92
#define CO_DEFTYPE_UNSIGNED64
The data type (and object index) of a 64-bit unsigned integer.
Definition: type.h:110
#define CO_DEFTYPE_INTEGER8
The data type (and object index) of an 8-bit signed integer.
Definition: type.h:35
#define CO_DEFTYPE_DOMAIN
The data type (and object index) of an arbitrary large block of data.
Definition: type.h:77
#define CO_DEFTYPE_UNSIGNED24
The data type (and object index) of a 24-bit unsigned integer.
Definition: type.h:98
#define CO_DEFTYPE_UNSIGNED8
The data type (and object index) of an 8-bit unsigned integer.
Definition: type.h:44
#define CO_DEFTYPE_REAL64
The data type (and object index) of a 64-bit IEEE-754 floating-point number.
Definition: type.h:83
#define CO_DEFTYPE_BOOLEAN
The data type (and object index) of a boolean truth value.
Definition: type.h:32
#define CO_DEFTYPE_INTEGER40
The data type (and object index) of a 40-bit signed integer.
Definition: type.h:86
#define CO_DEFTYPE_TIME_OF_DAY
The data type (and object index) of a 48-bit structure representing the absolute time.
Definition: type.h:68
#define CO_DEFTYPE_INTEGER32
The data type (and object index) of a 32-bit signed integer.
Definition: type.h:41
#define CO_DEFTYPE_INTEGER64
The data type (and object index) of a 64-bit signed integer.
Definition: type.h:95
#define CO_DEFTYPE_UNSIGNED56
The data type (and object index) of a 56-bit unsigned integer.
Definition: type.h:107
#define CO_DEFTYPE_UNSIGNED32
The data type (and object index) of a 32-bit unsigned integer.
Definition: type.h:50
#define CO_DEFTYPE_INTEGER16
The data type (and object index) of a 16-bit signed integer.
Definition: type.h:38
#define CO_DEFTYPE_OCTET_STRING
The data type (and object index) of an array of octets.
Definition: type.h:59
#define CO_DEFTYPE_REAL32
The data type (and object index) of a 32-bit IEEE-754 floating-point number.
Definition: type.h:53
#define CO_DEFTYPE_TIME_DIFF
The data type (and object index) of a 48-bit structure representing a time difference.
Definition: type.h:74
A union of the CANopen static data types.
Definition: val.h:273
#define CO_REAL32_MIN
The minimum value of a 32-bit IEEE-754 floating-point number.
Definition: val.h:105
#define CO_INTEGER8_MIN
The minimum value of an 8-bit signed integer.
Definition: val.h:51
#define CO_INTEGER64_MAX
The maximum value of a 64-bit signed integer.
Definition: val.h:225
#define CO_UNSIGNED64_MIN
The minimum value of a 64-bit unsigned integer.
Definition: val.h:267
#define CO_INTEGER32_MAX
The maximum value of a 32-bit signed integer.
Definition: val.h:72
#define CO_INTEGER24_MAX
The maximum value of a 24-bit signed integer (encoded as an int32_t).
Definition: val.h:180
#define CO_UNSIGNED40_MIN
The minimum value of a 40-bit unsigned integer (encoded as a uint64_t).
Definition: val.h:240
#define CO_UNSIGNED8_MAX
The maximum value of an 8-bit unsigned integer.
Definition: val.h:81
#define CO_INTEGER16_MAX
The maximum value of a 16-bit signed integer.
Definition: val.h:63
#define CO_UNSIGNED32_MAX
The maximum value of a 32-bit unsigned integer.
Definition: val.h:99
#define CO_UNSIGNED48_MIN
The minimum value of a 48-bit unsigned integer (encoded as a uint64_t).
Definition: val.h:249
#define CO_INTEGER48_MAX
The maximum value of a 48-bit signed integer (encoded as an int64_t).
Definition: val.h:207
#define CO_INTEGER24_MIN
The minimum value of a 24-bit signed integer (encoded as an int32_t).
Definition: val.h:177
const void * co_val_addressof(co_unsigned16_t type, const void *val)
Returns the address of the first byte in a value of the specified data type.
Definition: val.c:260
#define CO_UNSIGNED64_MAX
The maximum value of a 64-bit unsigned integer.
Definition: val.h:270
#define CO_INTEGER32_MIN
The minimum value of a 32-bit signed integer.
Definition: val.h:69
#define CO_UNSIGNED16_MIN
The minimum value of a 16-bit unsigned integer.
Definition: val.h:87
#define CO_INTEGER40_MAX
The maximum value of a 40-bit signed integer (encoded as an int64_t).
Definition: val.h:198
#define CO_UNSIGNED40_MAX
The maximum value of a 40-bit unsigned integer (encoded as a uint64_t).
Definition: val.h:243
#define CO_INTEGER64_MIN
The minimum value of a 64-bit signed integer.
Definition: val.h:222
#define CO_UNSIGNED56_MIN
The minimum value of a 56-bit unsigned integer (encoded as a uint64_t).
Definition: val.h:258
#define CO_UNSIGNED56_MAX
The maximum value of a 56-bit unsigned integer (encoded as a uint64_t).
Definition: val.h:261
size_t co_val_sizeof(co_unsigned16_t type, const void *val)
Returns the size (in bytes) of a value of the specified data type.
Definition: val.c:269
#define CO_UNSIGNED8_MIN
The minimum value of an 8-bit unsigned integer.
Definition: val.h:78
#define CO_INTEGER48_MIN
The minimum value of a 48-bit signed integer (encoded as an int64_t).
Definition: val.h:204
#define CO_UNSIGNED48_MAX
The maximum value of a 48-bit unsigned integer (encoded as a uint64_t).
Definition: val.h:252
#define CO_UNSIGNED32_MIN
The minimum value of a 32-bit unsigned integer.
Definition: val.h:96
#define CO_INTEGER56_MAX
The maximum value of a 56-bit signed integer (encoded as an int64_t).
Definition: val.h:216
#define CO_INTEGER40_MIN
The minimum value of a 40-bit signed integer (encoded as an int64_t).
Definition: val.h:195
#define CO_REAL32_MAX
The maximum value of a 32-bit IEEE-754 floating-point number.
Definition: val.h:108
#define CO_UNSIGNED24_MAX
The maximum value of a 24-bit unsigned integer (encoded as a uint32_t).
Definition: val.h:234
#define CO_REAL64_MIN
The minimum value of a 64-bit IEEE-754 floating-point number.
Definition: val.h:186
int co_val_init_min(co_unsigned16_t type, void *val)
Initializes a value of the specified data type with its lower limit.
Definition: val.c:90
#define CO_UNSIGNED24_MIN
The minimum value of a 24-bit unsigned integer (encoded as a uint32_t).
Definition: val.h:231
#define CO_REAL64_MAX
The maximum value of a 64-bit IEEE-754 floating-point number.
Definition: val.h:189
#define CO_INTEGER16_MIN
The minimum value of a 16-bit signed integer.
Definition: val.h:60
void co_val_fini(co_unsigned16_t type, void *val)
Finalizes a value of the specified data type.
Definition: val.c:249
#define CO_INTEGER56_MIN
The minimum value of a 56-bit signed integer (encoded as an int64_t).
Definition: val.h:213
int co_val_init_max(co_unsigned16_t type, void *val)
Initializes a value of the specified data type with its upper limit.
Definition: val.c:118
#define CO_UNSIGNED16_MAX
The maximum value of a 16-bit unsigned integer.
Definition: val.h:90
#define CO_INTEGER8_MAX
The maximum value of an 8-bit signed integer.
Definition: val.h:54