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