Lely core libraries 2.3.4
obj.c
Go to the documentation of this file.
1
24#include "co.h"
25#include <lely/co/detail/obj.h>
26#include <lely/co/dev.h>
27#include <lely/co/sdo.h>
28#include <lely/util/cmp.h>
29#include <lely/util/errnum.h>
30
31#include <assert.h>
32#if !LELY_NO_MALLOC
33#include <stdlib.h>
34#endif
35#include <string.h>
36
37#if !LELY_NO_MALLOC
38
43static void co_obj_update(co_obj_t *obj);
44
46static void co_obj_clear(co_obj_t *obj);
47
48void *
49__co_obj_alloc(void)
50{
51 void *ptr = malloc(sizeof(struct __co_obj));
52#if !LELY_NO_ERRNO
53 if (!ptr)
54 set_errc(errno2c(errno));
55#endif
56 return ptr;
57}
58
59void
60__co_obj_free(void *ptr)
61{
62 free(ptr);
63}
64
65#endif // !LELY_NO_MALLOC
66
67struct __co_obj *
68__co_obj_init(struct __co_obj *obj, co_unsigned16_t idx, void *val, size_t size)
69{
70 assert(obj);
71#if !LELY_NO_MALLOC
72 assert(val == NULL);
73 assert(size == 0);
74#endif
75
76 rbnode_init(&obj->node, &obj->idx);
77 obj->dev = NULL;
78 obj->idx = idx;
79
80 rbtree_init(&obj->tree, &uint8_cmp);
81
82#if !LELY_NO_CO_OBJ_NAME
83 obj->name = NULL;
84#endif
85
86 obj->code = CO_OBJECT_VAR;
87
88 obj->val = val;
89 obj->size = size;
90
91 return obj;
92}
93
94void
95__co_obj_fini(struct __co_obj *obj)
96{
97 assert(obj);
98
99 if (obj->dev)
100 co_dev_remove_obj(obj->dev, obj);
101
102#if !LELY_NO_MALLOC
103 co_obj_clear(obj);
104#endif
105
106#if !LELY_NO_MALLOC && !LELY_NO_CO_OBJ_NAME
107 free(obj->name);
108#endif
109}
110
111#if !LELY_NO_MALLOC
112
113co_obj_t *
114co_obj_create(co_unsigned16_t idx)
115{
116 trace("creating object %04X", idx);
117
118 co_obj_t *obj = __co_obj_alloc();
119 if (!obj)
120 return NULL;
121
122 return __co_obj_init(obj, idx, NULL, 0);
123}
124
125void
127{
128 if (obj) {
129 trace("destroying object %04X", obj->idx);
130 __co_obj_fini(obj);
131 __co_obj_free(obj);
132 }
133}
134
135#endif // !LELY_NO_MALLOC
136
137co_obj_t *
139{
140 assert(obj);
141
142 struct rbnode *node = rbnode_prev(&obj->node);
143 return node ? structof(node, co_obj_t, node) : NULL;
144}
145
146co_obj_t *
148{
149 assert(obj);
150
151 struct rbnode *node = rbnode_next(&obj->node);
152 return node ? structof(node, co_obj_t, node) : NULL;
153}
154
155co_dev_t *
157{
158 assert(obj);
159
160 return obj->dev;
161}
162
163co_unsigned16_t
165{
166 assert(obj);
167
168 return obj->idx;
169}
170
171co_unsigned8_t
172co_obj_get_subidx(const co_obj_t *obj, co_unsigned8_t maxidx,
173 co_unsigned8_t *subidx)
174{
175 assert(obj);
176
177 if (!subidx)
178 maxidx = 0;
179
180 if (maxidx) {
181 struct rbnode *node = rbtree_first(&obj->tree);
182 for (size_t i = 0; node && i < maxidx;
183 node = rbnode_next(node), i++)
184 subidx[i] = co_sub_get_subidx(
185 structof(node, co_sub_t, node));
186 }
187
188 return (co_unsigned8_t)rbtree_size(&obj->tree);
189}
190
191int
193{
194 assert(obj);
195 assert(sub);
196
197 if (sub->obj && sub->obj != obj)
198 return -1;
199
200 if (sub->obj == obj)
201 return 0;
202
203 if (rbtree_find(&obj->tree, sub->node.key))
204 return -1;
205
206 sub->obj = obj;
207 rbtree_insert(&sub->obj->tree, &sub->node);
208
209#if !LELY_NO_MALLOC
210 co_obj_update(obj);
211#endif
212
213 return 0;
214}
215
216int
218{
219 assert(obj);
220 assert(sub);
221
222 if (sub->obj != obj)
223 return -1;
224
225 rbtree_remove(&sub->obj->tree, &sub->node);
226 rbnode_init(&sub->node, &sub->subidx);
227 sub->obj = NULL;
228
229#if !LELY_NO_MALLOC
230 co_val_fini(co_sub_get_type(sub), sub->val);
231 sub->val = NULL;
232
233 co_obj_update(obj);
234#endif
235
236 return 0;
237}
238
239co_sub_t *
240co_obj_find_sub(const co_obj_t *obj, co_unsigned8_t subidx)
241{
242 assert(obj);
243
244 struct rbnode *node = rbtree_find(&obj->tree, &subidx);
245 return node ? structof(node, co_sub_t, node) : NULL;
246}
247
248co_sub_t *
250{
251 assert(obj);
252
253 struct rbnode *node = rbtree_first(&obj->tree);
254 return node ? structof(node, co_sub_t, node) : NULL;
255}
256
257co_sub_t *
259{
260 assert(obj);
261
262 struct rbnode *node = rbtree_last(&obj->tree);
263 return node ? structof(node, co_sub_t, node) : NULL;
264}
265
266#if !LELY_NO_CO_OBJ_NAME
267const char *
269{
270 assert(obj);
271
272 return obj->name;
273}
274#endif
275
276#if !LELY_NO_MALLOC && !LELY_NO_CO_OBJ_NAME
277int
278co_obj_set_name(co_obj_t *obj, const char *name)
279{
280 assert(obj);
281
282 if (!name || !*name) {
283 free(obj->name);
284 obj->name = NULL;
285 return 0;
286 }
287
288 void *ptr = realloc(obj->name, strlen(name) + 1);
289 if (!ptr) {
290#if !LELY_NO_ERRNO
291 set_errc(errno2c(errno));
292#endif
293 return -1;
294 }
295 obj->name = ptr;
296 strcpy(obj->name, name);
297
298 return 0;
299}
300#endif // !LELY_NO_MALLOC && !LELY_NO_CO_OBJ_NAME
301
302co_unsigned8_t
304{
305 assert(obj);
306
307 return obj->code;
308}
309
310int
311co_obj_set_code(co_obj_t *obj, co_unsigned8_t code)
312{
313 assert(obj);
314
315 switch (code) {
316 case CO_OBJECT_NULL:
317 case CO_OBJECT_DOMAIN:
320 case CO_OBJECT_VAR:
321 case CO_OBJECT_ARRAY:
322 case CO_OBJECT_RECORD: obj->code = code; return 0;
323 default: set_errnum(ERRNUM_INVAL); return -1;
324 }
325}
326
327void *
329{
330 return obj ? obj->val : NULL;
331}
332
333size_t
335{
336 return obj ? obj->size : 0;
337}
338
339const void *
340co_obj_get_val(const co_obj_t *obj, co_unsigned8_t subidx)
341{
342 co_sub_t *sub = obj ? co_obj_find_sub(obj, subidx) : NULL;
343 return co_sub_get_val(sub);
344}
345
346size_t
347co_obj_set_val(co_obj_t *obj, co_unsigned8_t subidx, const void *ptr, size_t n)
348{
349 assert(obj);
350
351 co_sub_t *sub = co_obj_find_sub(obj, subidx);
352 if (!sub) {
354 return 0;
355 }
356
357 return co_sub_set_val(sub, ptr, n);
358}
359
360#define LELY_CO_DEFINE_TYPE(a, b, c, d) \
361 co_##b##_t co_obj_get_val_##c( \
362 const co_obj_t *obj, co_unsigned8_t subidx) \
363 { \
364 /* clang-format off */ \
365 co_sub_t *sub = obj \
366 ? co_obj_find_sub(obj, subidx) \
367 : NULL; \
368 /* clang-format on */ \
369 return co_sub_get_val_##c(sub); \
370 } \
371\
372 size_t co_obj_set_val_##c( \
373 co_obj_t *obj, co_unsigned8_t subidx, co_##b##_t c) \
374 { \
375 assert(obj); \
376\
377 co_sub_t *sub = co_obj_find_sub(obj, subidx); \
378 if (!sub) { \
379 set_errnum(ERRNUM_INVAL); \
380 return 0; \
381 } \
382\
383 return co_sub_set_val_##c(sub, c); \
384 }
385#include <lely/co/def/basic.def>
386#undef LELY_CO_DEFINE_TYPE
387
388void
390{
391 assert(obj);
392
393 rbtree_foreach (&obj->tree, node)
394 co_sub_set_dn_ind(structof(node, co_sub_t, node), ind, data);
395}
396
397#if !LELY_NO_CO_OBJ_UPLOAD
398void
400{
401 assert(obj);
402
403 rbtree_foreach (&obj->tree, node)
404 co_sub_set_up_ind(structof(node, co_sub_t, node), ind, data);
405}
406#endif
407
408#if !LELY_NO_MALLOC
409
410void *
411__co_sub_alloc(void)
412{
413 void *ptr = malloc(sizeof(struct __co_sub));
414#if !LELY_NO_ERRNO
415 if (!ptr)
416 set_errc(errno2c(errno));
417#endif
418 return ptr;
419}
420
421void
422__co_sub_free(void *ptr)
423{
424 free(ptr);
425}
426
427#endif // !LELY_NO_MALLOC
428
429struct __co_sub *
430__co_sub_init(struct __co_sub *sub, co_unsigned8_t subidx, co_unsigned16_t type,
431 void *val)
432{
433 assert(sub);
434#if !LELY_NO_MALLOC
435 assert(val == NULL);
436#endif
437
438 rbnode_init(&sub->node, &sub->subidx);
439 sub->obj = NULL;
440 sub->subidx = subidx;
441
442#if !LELY_NO_CO_OBJ_NAME
443 sub->name = NULL;
444#endif
445
446 sub->type = type;
447#if !LELY_NO_CO_OBJ_LIMITS
448 if (co_val_init_min(sub->type, &sub->min) == -1)
449 return NULL;
450 if (co_val_init_max(sub->type, &sub->max) == -1)
451 return NULL;
452#endif
453#if !LELY_NO_CO_OBJ_DEFAULT
454 if (co_val_init(sub->type, &sub->def) == -1)
455 return NULL;
456#endif
457 sub->val = val;
458
459 sub->access = CO_ACCESS_RW;
460 sub->pdo_mapping = 0;
461 sub->flags = 0;
462
464 sub->dn_data = NULL;
465#if !LELY_NO_CO_OBJ_UPLOAD
467 sub->up_data = NULL;
468#endif
469
470 return sub;
471}
472
473void
474__co_sub_fini(struct __co_sub *sub)
475{
476 assert(sub);
477
478 if (sub->obj)
479 co_obj_remove_sub(sub->obj, sub);
480
481#if !LELY_NO_CO_OBJ_DEFAULT
482 co_val_fini(sub->type, &sub->def);
483#endif
484#if !LELY_NO_CO_OBJ_LIMITS
485 co_val_fini(sub->type, &sub->max);
486 co_val_fini(sub->type, &sub->min);
487#endif
488
489#if !LELY_NO_MALLOC && !LELY_NO_CO_OBJ_NAME
490 free(sub->name);
491#endif
492}
493
494#if !LELY_NO_MALLOC
495
496co_sub_t *
497co_sub_create(co_unsigned8_t subidx, co_unsigned16_t type)
498{
499 int errc = 0;
500
501 co_sub_t *sub = __co_sub_alloc();
502 if (!sub) {
503 errc = get_errc();
504 goto error_alloc_sub;
505 }
506
507 if (!__co_sub_init(sub, subidx, type, NULL)) {
508 errc = get_errc();
509 goto error_init_sub;
510 }
511
512 return sub;
513
514error_init_sub:
515 __co_sub_free(sub);
516error_alloc_sub:
517 set_errc(errc);
518 return NULL;
519}
520
521void
523{
524 if (sub) {
525 __co_sub_fini(sub);
526 __co_sub_free(sub);
527 }
528}
529
530#endif // !LELY_NO_MALLOC
531
532co_sub_t *
534{
535 assert(sub);
536
537 struct rbnode *node = rbnode_prev(&sub->node);
538 return node ? structof(node, co_sub_t, node) : NULL;
539}
540
541co_sub_t *
543{
544 assert(sub);
545
546 struct rbnode *node = rbnode_next(&sub->node);
547 return node ? structof(node, co_sub_t, node) : NULL;
548}
549
550co_obj_t *
552{
553 assert(sub);
554
555 return sub->obj;
556}
557
558co_unsigned8_t
560{
561 assert(sub);
562
563 return sub->subidx;
564}
565
566#if !LELY_NO_CO_OBJ_NAME
567const char *
569{
570 assert(sub);
571
572 return sub->name;
573}
574#endif
575
576#if !LELY_NO_MALLOC && !LELY_NO_CO_OBJ_NAME
577int
578co_sub_set_name(co_sub_t *sub, const char *name)
579{
580 assert(sub);
581
582 if (!name || !*name) {
583 free(sub->name);
584 sub->name = NULL;
585 return 0;
586 }
587
588 void *ptr = realloc(sub->name, strlen(name) + 1);
589 if (!ptr) {
590#if !LELY_NO_ERRNO
591 set_errc(errno2c(errno));
592#endif
593 return -1;
594 }
595 sub->name = ptr;
596 strcpy(sub->name, name);
597
598 return 0;
599}
600#endif // !LELY_NO_MALLOC && !LELY_NO_CO_OBJ_NAME
601
602co_unsigned16_t
604{
605 assert(sub);
606
607 return sub->type;
608}
609
610#if !LELY_NO_CO_OBJ_LIMITS
611
612const void *
614{
615 return sub ? co_val_addressof(sub->type, &sub->min) : NULL;
616}
617
618size_t
620{
621 return sub ? co_val_sizeof(sub->type, &sub->min) : 0;
622}
623
624const void *
626{
627 return sub ? &sub->min : NULL;
628}
629
630size_t
631co_sub_set_min(co_sub_t *sub, const void *ptr, size_t n)
632{
633 assert(sub);
634
635 co_val_fini(sub->type, &sub->min);
636 return co_val_make(sub->type, &sub->min, ptr, n);
637}
638
639const void *
641{
642 return sub ? co_val_addressof(sub->type, &sub->max) : NULL;
643}
644
645size_t
647{
648 return sub ? co_val_sizeof(sub->type, &sub->max) : 0;
649}
650
651const void *
653{
654 return sub ? &sub->max : NULL;
655}
656
657size_t
658co_sub_set_max(co_sub_t *sub, const void *ptr, size_t n)
659{
660 assert(sub);
661
662 co_val_fini(sub->type, &sub->max);
663 return co_val_make(sub->type, &sub->max, ptr, n);
664}
665
666#endif // !LELY_NO_CO_OBJ_LIMITS
667
668#if !LELY_NO_CO_OBJ_DEFAULT
669
670const void *
672{
673 return sub ? co_val_addressof(sub->type, &sub->def) : NULL;
674}
675
676size_t
678{
679 return sub ? co_val_sizeof(sub->type, &sub->def) : 0;
680}
681
682const void *
684{
685 return sub ? &sub->def : NULL;
686}
687
688size_t
689co_sub_set_def(co_sub_t *sub, const void *ptr, size_t n)
690{
691 assert(sub);
692
693 co_val_fini(sub->type, &sub->def);
694 return co_val_make(sub->type, &sub->def, ptr, n);
695}
696
697#endif // !LELY_NO_CO_OBJ_DEFAULT
698
699const void *
701{
702 return sub ? co_val_addressof(sub->type, sub->val) : NULL;
703}
704
705size_t
707{
708 return sub ? co_val_sizeof(sub->type, sub->val) : 0;
709}
710
711const void *
713{
714 return sub ? sub->val : NULL;
715}
716
717size_t
718co_sub_set_val(co_sub_t *sub, const void *ptr, size_t n)
719{
720 assert(sub);
721
722 co_val_fini(sub->type, sub->val);
723 return co_val_make(sub->type, sub->val, ptr, n);
724}
725
726#define LELY_CO_DEFINE_TYPE(a, b, c, d) \
727 co_##b##_t co_sub_get_val_##c(const co_sub_t *sub) \
728 { \
729 static const co_##b##_t val; \
730\
731 if (!sub || sub->type != CO_DEFTYPE_##a || !sub->val) \
732 return val; \
733 return ((union co_val *)sub->val)->c; \
734 } \
735\
736 size_t co_sub_set_val_##c(co_sub_t *sub, co_##b##_t c) \
737 { \
738 assert(sub); \
739\
740 if (sub->type != CO_DEFTYPE_##a) { \
741 set_errnum(ERRNUM_INVAL); \
742 return 0; \
743 } \
744\
745 return co_sub_set_val(sub, &c, sizeof(c)); \
746 }
747#include <lely/co/def/basic.def>
748#undef LELY_CO_DEFINE_TYPE
749
750#if !LELY_NO_CO_OBJ_LIMITS
751co_unsigned32_t
752co_sub_chk_val(const co_sub_t *sub, co_unsigned16_t type, const void *val)
753{
754 assert(sub);
755
756 // Arrays do not have a minimum or maximum value.
757 if (!co_type_is_basic(sub->type))
758 return 0;
759
760 if (sub->type != type)
761 return CO_SDO_AC_TYPE_LEN;
762
763 assert(val);
764
765 // Check whether the value is within bounds.
766 if (co_val_cmp(sub->type, &sub->min, &sub->max) > 0)
768 if (co_val_cmp(sub->type, val, &sub->max) > 0)
769 return CO_SDO_AC_PARAM_HI;
770 if (co_val_cmp(sub->type, val, &sub->min) < 0)
771 return CO_SDO_AC_PARAM_LO;
772
773 return 0;
774}
775#endif
776
777unsigned int
779{
780 assert(sub);
781
782 return sub->access;
783}
784
785int
786co_sub_set_access(co_sub_t *sub, unsigned int access)
787{
788 assert(sub);
789
790 switch (access) {
791 case CO_ACCESS_RO:
792 case CO_ACCESS_WO:
793 case CO_ACCESS_RW:
794 case CO_ACCESS_RWR:
795 case CO_ACCESS_RWW:
796 case CO_ACCESS_CONST: sub->access = access; return 0;
797 default: set_errnum(ERRNUM_INVAL); return -1;
798 }
799}
800
801int
803{
804 assert(sub);
805
806 return sub->pdo_mapping;
807}
808
809void
810co_sub_set_pdo_mapping(co_sub_t *sub, int pdo_mapping)
811{
812 assert(sub);
813
814 sub->pdo_mapping = !!pdo_mapping;
815}
816
817unsigned int
819{
820 assert(sub);
821
822 return sub->flags;
823}
824
825void
826co_sub_set_flags(co_sub_t *sub, unsigned int flags)
827{
828 assert(sub);
829
830 sub->flags = flags;
831}
832
833#if !LELY_NO_CO_OBJ_FILE
834
835const char *
837{
838 assert(sub);
839
840 if (!(sub->flags & CO_OBJ_FLAGS_UPLOAD_FILE))
841 return NULL;
842
843 assert(sub->type == CO_DEFTYPE_DOMAIN);
844 return co_sub_addressof_val(sub);
845}
846
847int
848co_sub_set_upload_file(co_sub_t *sub, const char *filename)
849{
850 assert(sub);
851 assert(filename);
852
855 return -1;
856 }
857
858 assert(sub->type == CO_DEFTYPE_DOMAIN);
859 return co_sub_set_val(sub, filename, strlen(filename) + 1) ? 0 : -1;
860}
861
862const char *
864{
865 assert(sub);
866
867 if (!(sub->flags & CO_OBJ_FLAGS_DOWNLOAD_FILE))
868 return NULL;
869
870 assert(sub->type == CO_DEFTYPE_DOMAIN);
871 return co_sub_addressof_val(sub);
872}
873
874int
875co_sub_set_download_file(co_sub_t *sub, const char *filename)
876{
877 assert(sub);
878 assert(filename);
879
882 return -1;
883 }
884
885 assert(sub->type == CO_DEFTYPE_DOMAIN);
886 return co_sub_set_val(sub, filename, strlen(filename) + 1) ? 0 : -1;
887}
888
889#endif // !LELY_NO_CO_OBJ_FILE
890
891void
892co_sub_get_dn_ind(const co_sub_t *sub, co_sub_dn_ind_t **pind, void **pdata)
893{
894 assert(sub);
895
896 if (pind)
897 *pind = sub->dn_ind;
898 if (pdata)
899 *pdata = sub->dn_data;
900}
901
902void
904{
905 assert(sub);
906
907 sub->dn_ind = ind ? ind : &co_sub_default_dn_ind;
908 sub->dn_data = ind ? data : NULL;
909}
910
911int
912co_sub_on_dn(co_sub_t *sub, struct co_sdo_req *req, co_unsigned32_t *pac)
913{
914 assert(sub);
915 assert(req);
916
917#if !LELY_NO_CO_OBJ_FILE
918 // clang-format off
921 // clang-format on
922 return co_sdo_req_dn_file(req, co_sub_addressof_val(sub), pac);
923#endif
924
925 // Read the value.
926 co_unsigned16_t type = co_sub_get_type(sub);
927 union co_val val;
928#if LELY_NO_MALLOC
929 struct co_array array = CO_ARRAY_INIT;
930 if (co_type_is_array(type))
931 co_val_init_array(&val, &array);
932#endif
933 if (co_sdo_req_dn_val(req, type, &val, pac) == -1)
934 return -1;
935
936#if !LELY_NO_CO_OBJ_LIMITS
937 // Accept the value if it is within bounds.
938 co_unsigned32_t ac = co_sub_chk_val(sub, type, &val);
939 if (ac) {
940#if !LELY_NO_MALLOC
941 co_val_fini(type, &val);
942#endif
943 if (pac)
944 *pac = ac;
945 return -1;
946 }
947#endif
948
949 co_sub_dn(sub, &val);
950#if !LELY_NO_MALLOC
951 co_val_fini(type, &val);
952#endif
953
954 return 0;
955}
956
957co_unsigned32_t
959{
960 if (!sub)
961 return CO_SDO_AC_NO_SUB;
962
963 if (!(sub->access & CO_ACCESS_WRITE))
964 return CO_SDO_AC_NO_WRITE;
965
966 if (!req)
967 return CO_SDO_AC_ERROR;
968
969 assert(sub->dn_ind);
970 return sub->dn_ind(sub, req, sub->dn_data);
971}
972
973co_unsigned32_t
974co_sub_dn_ind_val(co_sub_t *sub, co_unsigned16_t type, const void *val)
975{
976 if (co_sub_get_type(sub) != type)
977 return CO_SDO_AC_TYPE_LEN;
978
979 struct co_sdo_req req = CO_SDO_REQ_INIT;
980 co_unsigned32_t ac = 0;
981
982 int errc = get_errc();
983
984 if (co_sdo_req_up_val(&req, type, val, &ac) == -1)
985 goto error;
986
987 ac = co_sub_dn_ind(sub, &req);
988
989error:
990 co_sdo_req_fini(&req);
991 set_errc(errc);
992 return ac;
993}
994
995int
996co_sub_dn(co_sub_t *sub, void *val)
997{
998 assert(sub);
999
1000 if (!(sub->flags & CO_OBJ_FLAGS_WRITE)) {
1001#if LELY_NO_MALLOC
1002 if (!co_val_copy(sub->type, sub->val, val))
1003 return -1;
1004#else
1005 co_val_fini(sub->type, sub->val);
1006 if (!co_val_move(sub->type, sub->val, val))
1007 return -1;
1008#endif
1009 }
1010
1011 return 0;
1012}
1013
1014#if !LELY_NO_CO_OBJ_UPLOAD
1015
1016void
1017co_sub_get_up_ind(const co_sub_t *sub, co_sub_up_ind_t **pind, void **pdata)
1018{
1019 assert(sub);
1020
1021 if (pind)
1022 *pind = sub->up_ind;
1023 if (pdata)
1024 *pdata = sub->up_data;
1025}
1026
1027void
1029{
1030 assert(sub);
1031
1032 sub->up_ind = ind ? ind : &co_sub_default_up_ind;
1033 sub->up_data = ind ? data : NULL;
1034}
1035
1036#endif // !LELY_NO_CO_OBJ_UPLOAD
1037
1038int
1039co_sub_on_up(const co_sub_t *sub, struct co_sdo_req *req, co_unsigned32_t *pac)
1040{
1041 assert(sub);
1042 assert(req);
1043
1044#if !LELY_NO_CO_OBJ_FILE
1047 const char *filename = co_sub_addressof_val(sub);
1048 // Ignore an empty UploadFile attribute.
1049 if (!filename || !*filename)
1050 return 0;
1051 return co_sdo_req_up_file(req, filename, pac);
1052 }
1053#endif
1054
1055 const void *val = co_sub_get_val(sub);
1056 if (!val) {
1057 if (pac)
1058 *pac = CO_SDO_AC_NO_DATA;
1059 return -1;
1060 }
1061
1062 return co_sdo_req_up_val(req, co_sub_get_type(sub), val, pac);
1063}
1064
1065co_unsigned32_t
1066co_sub_up_ind(const co_sub_t *sub, struct co_sdo_req *req)
1067{
1068 if (!sub)
1069 return CO_SDO_AC_NO_SUB;
1070
1071 if (!(sub->access & CO_ACCESS_READ))
1072 return CO_SDO_AC_NO_READ;
1073
1074 if (!req)
1075 return CO_SDO_AC_ERROR;
1076
1077#if LELY_NO_CO_OBJ_UPLOAD
1078 return co_sub_default_up_ind(sub, req, NULL);
1079#else
1080 assert(sub->up_ind);
1081 return sub->up_ind(sub, req, sub->up_data);
1082#endif
1083}
1084
1085co_unsigned32_t
1086co_sub_default_dn_ind(co_sub_t *sub, struct co_sdo_req *req, void *data)
1087{
1088 (void)data;
1089
1090 co_unsigned32_t ac = 0;
1091 co_sub_on_dn(sub, req, &ac);
1092 return ac;
1093}
1094
1095co_unsigned32_t
1096co_sub_default_up_ind(const co_sub_t *sub, struct co_sdo_req *req, void *data)
1097{
1098 (void)data;
1099
1100 co_unsigned32_t ac = 0;
1101 co_sub_on_up(sub, req, &ac);
1102 return ac;
1103}
1104
1105#if !LELY_NO_MALLOC
1106
1107static void
1109{
1110 assert(obj);
1111
1112 // Compute the total size and alignment (in bytes) of the object.
1113 size_t align = 1;
1114 size_t size = 0;
1115 rbtree_foreach (&obj->tree, node) {
1116 co_sub_t *sub = structof(node, co_sub_t, node);
1117 co_unsigned16_t type = co_sub_get_type(sub);
1118 align = MAX(align, co_type_alignof(type));
1119 size = ALIGN(size, co_type_alignof(type));
1120 size += co_type_sizeof(type);
1121 }
1122 size = ALIGN(size, align);
1123
1124 void *val = NULL;
1125 if (size) {
1126 val = calloc(1, size);
1127 if (!val) {
1128#if !LELY_NO_ERRNO
1129 set_errc(errno2c(errno));
1130#endif
1131 return;
1132 }
1133 }
1134
1135 // Initialize the values of the sub-objects.
1136 size_t offset = 0;
1137 rbtree_foreach (&obj->tree, node) {
1138 co_sub_t *sub = structof(node, co_sub_t, node);
1139 co_unsigned16_t type = co_sub_get_type(sub);
1140 // Compute the offset of the sub-object.
1142 // Move the old value, if it exists.
1143 void *src = sub->val;
1144 sub->val = (char *)val + offset;
1145 if (src)
1146 co_val_move(type, sub->val, src);
1147 offset += co_type_sizeof(type);
1148 }
1149
1150 free(obj->val);
1151 obj->val = val;
1152 obj->size = size;
1153}
1154
1155static void
1157{
1158 assert(obj);
1159
1160 rbtree_foreach (&obj->tree, node)
1161 co_sub_destroy(structof(node, co_sub_t, node));
1162
1163 free(obj->val);
1164 obj->val = NULL;
1165}
1166
1167#endif // !LELY_NO_MALLOC
This header file is part of the utilities library; it contains the comparison function definitions.
This header file is part of the CANopen library; it contains the device description declarations.
int co_dev_remove_obj(co_dev_t *dev, co_obj_t *obj)
Removes an object from the object dictionary a CANopen device.
Definition dev.c:263
This is the internal header file of the object dictionary.
This header file is part of the utilities library; it contains the native and platform-independent er...
@ 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
int errno2c(int errnum)
Transforms a standard C error number to a native error code.
Definition errnum.c:46
void set_errnum(errnum_t errnum)
Sets the current (thread-specific) platform-independent error number to errnum.
Definition errnum.h:424
This header file is part of the CANopen library; it contains the Service Data Object (SDO) declaratio...
#define CO_SDO_AC_PARAM_LO
SDO abort code: Value of parameter written too low (download only).
Definition sdo.h:141
#define CO_SDO_AC_NO_READ
SDO abort code: Attempt to read a write only object.
Definition sdo.h:87
int co_sdo_req_dn_val(struct co_sdo_req *req, co_unsigned16_t type, void *val, co_unsigned32_t *pac)
Copies the next segment of the specified CANopen SDO download request to the internal buffer and,...
Definition sdo.c:170
#define CO_SDO_REQ_INIT
The static initializer for struct co_sdo_req.
Definition sdo.h:206
int co_sdo_req_up_val(struct co_sdo_req *req, co_unsigned16_t type, const void *val, co_unsigned32_t *pac)
Writes the specified value to a buffer and constructs a CANopen SDO upload request.
Definition sdo.c:287
void co_sdo_req_fini(struct co_sdo_req *req)
Finalizes a CANopen SDO upload/download request.
Definition sdo.c:121
#define CO_SDO_AC_TYPE_LEN
SDO abort code: Data type does not match, length of service parameter does not match.
Definition sdo.h:117
#define CO_SDO_AC_ERROR
SDO abort code: General error.
Definition sdo.h:150
int co_sdo_req_dn_file(struct co_sdo_req *req, const char *filename, co_unsigned32_t *pac)
Copies the next segment of the specified CANopen SDO download request to the internal buffer and,...
Definition sdo.c:212
int co_sdo_req_up_file(struct co_sdo_req *req, const char *filename, co_unsigned32_t *pac)
Loads the specified file into a buffer and constructs a CANopen SDO upload request.
Definition sdo.c:323
#define CO_SDO_AC_PARAM_HI
SDO abort code: Value of parameter written too high (download only).
Definition sdo.h:138
#define CO_SDO_AC_NO_DATA
SDO abort code: No data available.
Definition sdo.h:175
#define CO_SDO_AC_NO_SUB
SDO abort code: Sub-index does not exist.
Definition sdo.h:132
#define CO_SDO_AC_NO_WRITE
SDO abort code: Attempt to write a read only object.
Definition sdo.h:90
#define CO_SDO_AC_PARAM_RANGE
SDO abort code: Maximum value is less than minimum value (download only).
Definition sdo.h:144
#define structof(ptr, type, member)
Obtains the address of a structure from the address of one of its members.
Definition util.h:93
#define ALIGN(x, a)
Rounds x up to the nearest multiple of a.
Definition util.h:41
#define MAX(a, b)
Returns the maximum of a and b.
Definition util.h:65
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
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_sub_t * co_sub_prev(const co_sub_t *sub)
Finds the previous sub-object in a CANopen object.
Definition obj.c:533
co_sub_t * co_obj_first_sub(const co_obj_t *obj)
Finds the first sub-object (with the lowest sub-index) in a CANopen object.
Definition obj.c:249
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
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
co_unsigned32_t co_sub_default_up_ind(const co_sub_t *sub, struct co_sdo_req *req, void *data)
The default upload indication function.
Definition obj.c:1096
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
int co_sub_set_download_file(co_sub_t *sub, const char *filename)
Sets the value of the DownloadFile attribute of a CANopen sub-object.
Definition obj.c:875
co_unsigned32_t co_sub_dn_ind(co_sub_t *sub, struct co_sdo_req *req)
Invokes the download indication function of a CANopen sub-object, registered with co_sub_set_dn_ind()...
Definition obj.c:958
void co_sub_set_up_ind(co_sub_t *sub, co_sub_up_ind_t *ind, void *data)
Sets the upload indication function for a CANopen sub-object.
Definition obj.c:1028
void * co_obj_addressof_val(const co_obj_t *obj)
Returns the address of the value of a CANopen object.
Definition obj.c:328
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
const char * co_sub_get_download_file(const co_sub_t *sub)
Returns a pointer to the value of the DownloadFile attribute of a CANopen sub-object,...
Definition obj.c:863
void co_sub_set_dn_ind(co_sub_t *sub, co_sub_dn_ind_t *ind, void *data)
Sets the download indication function for a CANopen sub-object.
Definition obj.c:903
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
int co_sub_set_upload_file(co_sub_t *sub, const char *filename)
Sets the value of the UploadFile attribute of a CANopen sub-object.
Definition obj.c:848
co_unsigned32_t co_sub_up_ind(const co_sub_t *sub, struct co_sdo_req *req)
Invokes the upload indication function of a CANopen sub-object, registered with co_sub_set_up_ind().
Definition obj.c:1066
static void co_obj_clear(co_obj_t *obj)
Destroys all sub-objects.
Definition obj.c:1156
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
co_unsigned32_t co_sub_dn_ind_val(co_sub_t *sub, co_unsigned16_t type, const void *val)
Invokes the download indication function of a CANopen sub-object, registered with co_sub_set_dn_ind()...
Definition obj.c:974
void co_sub_get_dn_ind(const co_sub_t *sub, co_sub_dn_ind_t **pind, void **pdata)
Retrieves the download indication function for a CANopen sub-object.
Definition obj.c:892
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
size_t co_sub_sizeof_max(const co_sub_t *sub)
Returns size (in bytes) of the upper limit of the value of a CANopen sub-object.
Definition obj.c:646
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
const void * co_sub_addressof_def(const co_sub_t *sub)
Returns the address of the default value of a CANopen sub-object.
Definition obj.c:671
size_t co_sub_sizeof_def(const co_sub_t *sub)
Returns the size (in bytes) of the default value of a CANopen sub-object.
Definition obj.c:677
void co_sub_get_up_ind(const co_sub_t *sub, co_sub_up_ind_t **pind, void **pdata)
Retrieves the upload indication function for a CANopen sub-object.
Definition obj.c:1017
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
const void * co_obj_get_val(const co_obj_t *obj, co_unsigned8_t subidx)
Returns a pointer to the current value of a CANopen sub-object.
Definition obj.c:340
const void * co_sub_addressof_max(const co_sub_t *sub)
Returns the address of the upper limit of the value of a CANopen sub-object.
Definition obj.c:640
int co_sub_dn(co_sub_t *sub, void *val)
Downloads (moves) a value into a CANopen sub-object if the refuse-write-on-download flag (CO_OBJ_FLAG...
Definition obj.c:996
co_sub_t * co_obj_last_sub(const co_obj_t *obj)
Finds the last sub-object (with the highest sub-index) in a CANopen object.
Definition obj.c:258
co_unsigned8_t co_obj_get_code(const co_obj_t *obj)
Returns the object code of a CANopen object.
Definition obj.c:303
const void * co_sub_addressof_val(const co_sub_t *sub)
Returns the address of the current value of a CANopen sub-object.
Definition obj.c:700
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
const char * co_sub_get_upload_file(const co_sub_t *sub)
Returns a pointer to the value of the UploadFile attribute of a CANopen sub-object,...
Definition obj.c:836
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
co_obj_t * co_obj_next(const co_obj_t *obj)
Finds the next object in the object dictionary of a CANopen device.
Definition obj.c:147
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
size_t co_sub_sizeof_val(const co_sub_t *sub)
Returns the size (in bytes) of the current value of a CANopen sub-object.
Definition obj.c:706
static void co_obj_update(co_obj_t *obj)
Updates an object by allocating a new memory region containing the members and moving the old values.
Definition obj.c:1108
const char * co_obj_get_name(const co_obj_t *obj)
Returns the name of a CANopen object.
Definition obj.c:268
int co_obj_remove_sub(co_obj_t *obj, co_sub_t *sub)
Removes a sub-object from a CANopen object.
Definition obj.c:217
int co_sub_on_dn(co_sub_t *sub, struct co_sdo_req *req, co_unsigned32_t *pac)
Implements the default behavior when a download indication is received by a CANopen sub-object.
Definition obj.c:912
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
void co_obj_destroy(co_obj_t *obj)
Destroys a CANopen object, including its sub-objects.
Definition obj.c:126
void co_obj_set_dn_ind(co_obj_t *obj, co_sub_dn_ind_t *ind, void *data)
Sets the download indication function for a CANopen object.
Definition obj.c:389
co_dev_t * co_obj_get_dev(const co_obj_t *obj)
Returns a pointer to the CANopen device containing the specified object.
Definition obj.c:156
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
co_unsigned32_t co_sub_default_dn_ind(co_sub_t *sub, struct co_sdo_req *req, void *data)
The default download indication function.
Definition obj.c:1086
co_obj_t * co_obj_create(co_unsigned16_t idx)
Creates a CANopen object.
Definition obj.c:114
void co_obj_set_up_ind(co_obj_t *obj, co_sub_up_ind_t *ind, void *data)
Sets the upload indication function for a CANopen object.
Definition obj.c:399
co_sub_t * co_sub_next(const co_sub_t *sub)
Finds the next sub-object in a CANopen object.
Definition obj.c:542
co_obj_t * co_sub_get_obj(const co_sub_t *sub)
Returns the a pointer to the CANopen object containing the specified sub-object.
Definition obj.c:551
size_t co_obj_sizeof_val(const co_obj_t *obj)
Returns size (in bytes) of the value of a CANopen object.
Definition obj.c:334
int co_sub_on_up(const co_sub_t *sub, struct co_sdo_req *req, co_unsigned32_t *pac)
Implements the default behavior when an upload indication is received by a CANopen sub-object.
Definition obj.c:1039
unsigned int co_sub_get_access(const co_sub_t *sub)
Returns the access type of a CANopen sub-object.
Definition obj.c:778
const void * co_sub_addressof_min(const co_sub_t *sub)
Returns the address of the lower limit of the value of a CANopen sub-object.
Definition obj.c:613
size_t co_obj_set_val(co_obj_t *obj, co_unsigned8_t subidx, const void *ptr, size_t n)
Sets the current value of a CANopen sub-object.
Definition obj.c:347
co_unsigned8_t co_obj_get_subidx(const co_obj_t *obj, co_unsigned8_t maxidx, co_unsigned8_t *subidx)
Retrieves a list of sub-indices in a CANopen object.
Definition obj.c:172
co_sub_t * co_sub_create(co_unsigned8_t subidx, co_unsigned16_t type)
Creates a CANopen sub-object.
Definition obj.c:497
co_unsigned32_t co_sub_chk_val(const co_sub_t *sub, co_unsigned16_t type, const void *val)
Checks if the specifed value would be a valid value for a CANopen sub-object.
Definition obj.c:752
size_t co_sub_sizeof_min(const co_sub_t *sub)
Returns size (in bytes) of the lower limit of the value of a CANopen sub-object.
Definition obj.c:619
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
co_obj_t * co_obj_prev(const co_obj_t *obj)
Finds the previous object in the object dictionary of a CANopen device.
Definition obj.c:138
#define CO_ACCESS_READ
The object can be read.
Definition obj.h:57
#define CO_OBJ_FLAGS_WRITE
Refuse write on download.
Definition obj.h:90
#define CO_ACCESS_WO
Write-only access.
Definition obj.h:72
#define CO_ACCESS_RO
Read-only access.
Definition obj.h:69
#define CO_OBJECT_DEFSTRUCT
A record type definition.
Definition obj.h:39
#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
#define CO_OBJECT_DEFTYPE
A type definitions.
Definition obj.h:36
#define CO_OBJECT_DOMAIN
A large variable amount of data.
Definition obj.h:33
#define CO_ACCESS_RW
Read or write access.
Definition obj.h:75
co_unsigned32_t co_sub_up_ind_t(const co_sub_t *sub, struct co_sdo_req *req, void *data)
The type of a CANopen sub-object upload indication function, invoked by an SDO upload request or Tran...
Definition obj.h:157
co_unsigned32_t co_sub_dn_ind_t(co_sub_t *sub, struct co_sdo_req *req, void *data)
The type of a CANopen sub-object download indication function, invoked by an SDO download request or ...
Definition obj.h:142
#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
#define CO_OBJECT_NULL
An object with no data fields.
Definition obj.h:30
#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
#define CO_ACCESS_WRITE
The object can be written.
Definition obj.h:60
#define CO_ACCESS_RWW
Read or write on process output.
Definition obj.h:81
#define CO_ACCESS_CONST
Constant value.
Definition obj.h:84
void rbnode_init(struct rbnode *node, const void *key)
Initializes a node in a red-black tree.
Definition rbtree.h:237
struct rbnode * rbtree_last(const struct rbtree *tree)
Returns a pointer to the last (rightmost) node in a red-black tree.
Definition rbtree.c:343
void rbtree_insert(struct rbtree *tree, struct rbnode *node)
Inserts a node into a red-black tree.
Definition rbtree.c:108
struct rbnode * rbtree_find(const struct rbtree *tree, const void *key)
Finds a node in a red-black tree.
Definition rbtree.c:306
struct rbnode * rbtree_first(const struct rbtree *tree)
Returns a pointer to the first (leftmost) node in a red-black tree.
Definition rbtree.c:335
struct rbnode * rbnode_next(const struct rbnode *node)
Returns a pointer to the next (in-order) node in a red-black tree with respect to node.
Definition rbtree.c:91
void rbtree_init(struct rbtree *tree, rbtree_cmp_t *cmp)
Initializes a red-black tree.
Definition rbtree.h:248
struct rbnode * rbnode_prev(const struct rbnode *node)
Returns a pointer to the previous (in-order) node in a red-black tree with respect to node.
Definition rbtree.c:74
size_t rbtree_size(const struct rbtree *tree)
Returns the size (in number of nodes) of a red-black tree.
Definition rbtree.h:265
void rbtree_remove(struct rbtree *tree, struct rbnode *node)
Removes a node from a red-black tree.
Definition rbtree.c:187
#define rbtree_foreach(tree, node)
Iterates over each node in a red-black tree in ascending order.
Definition rbtree.h:234
This is the internal header file of the CANopen library.
This header file is part of the C11 and POSIX compatibility library; it includes <stdlib....
This header file is part of the C11 and POSIX compatibility library; it includes <string....
A CANopen device.
Definition dev.h:30
A CANopen object.
Definition obj.h:31
co_unsigned16_t idx
The object index.
Definition obj.h:37
co_unsigned8_t code
The object code.
Definition obj.h:39
size_t size
The size (in bytes) of the value at val.
Definition obj.h:49
struct rbtree tree
The tree containing all the sub-objects.
Definition obj.h:45
struct rbnode node
The node of this object in the tree of objects.
Definition obj.h:33
co_dev_t * dev
A pointer to the CANopen device containing this object.
Definition obj.h:35
char * name
A pointer to the name of the object.
Definition obj.h:42
void * val
A pointer to the object value.
Definition obj.h:47
A CANopen sub-object.
Definition obj.h:53
uint_least32_t pdo_mapping
A flag indicating if it is possible to map this object into a PDO.
Definition obj.h:81
co_sub_dn_ind_t * dn_ind
A pointer to the download indication function.
Definition obj.h:85
co_unsigned8_t subidx
The object sub-index.
Definition obj.h:59
struct rbnode node
The node of this sub-object in the tree of sub-objects.
Definition obj.h:55
co_obj_t * obj
A pointer to the CANopen object containing this sub-object.
Definition obj.h:57
union co_val def
The default value.
Definition obj.h:74
union co_val min
The lower limit of the object value.
Definition obj.h:68
co_sub_up_ind_t * up_ind
A pointer to the upload indication function.
Definition obj.h:90
union co_val max
The upper limit of the object value.
Definition obj.h:70
uint_least32_t access
The access type.
Definition obj.h:79
char * name
A pointer to the name of the sub-object.
Definition obj.h:64
co_unsigned16_t type
The data type.
Definition obj.h:61
void * val
A pointer to the sub-object value.
Definition obj.h:77
void * dn_data
A pointer to user-specified data for dn_ind.
Definition obj.h:87
void * up_data
A pointer to user-specified data for up_ind.
Definition obj.h:92
uint_least32_t flags
The object flags.
Definition obj.h:83
A CANopen SDO upload/download request.
Definition sdo.h:181
size_t offset
The offset of the bytes at buf.
Definition sdo.h:196
size_t size
The total size (in bytes) of the value to be uploaded/downloaded.
Definition sdo.h:187
A node in a red-black tree.
Definition rbtree.h:53
const void * key
A pointer to the key for this node.
Definition rbtree.h:59
int co_type_is_array(co_unsigned16_t type)
Returns 1 if the specified (static) data type is an array, and 0 if not.
Definition type.c:40
#define CO_DEFTYPE_DOMAIN
The data type (and object index) of an arbitrary large block of data.
Definition type.h:77
size_t co_type_alignof(co_unsigned16_t type)
Returns the alignment requirements (in bytes) of a value of the specified data type,...
Definition type.c:65
size_t co_type_sizeof(co_unsigned16_t type)
Returns the native size (in bytes) of a value of the specified data type, or 1 if it is not a static ...
Definition type.c:52
int co_type_is_basic(co_unsigned16_t type)
Returns 1 if the specified (static) data type is a basic type, and 0 if not.
Definition type.c:28
A union of the CANopen static data types.
Definition val.h:273
int co_val_init(co_unsigned16_t type, void *val)
Initializes a value of the specified data type to zero.
Definition val.c:62
size_t co_val_move(co_unsigned16_t type, void *dst, void *src)
Moves one value to another.
Definition val.c:354
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
size_t co_val_copy(co_unsigned16_t type, void *dst, const void *src)
Copies one value to another.
Definition val.c:318
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
int co_val_cmp(co_unsigned16_t type, const void *v1, const void *v2)
Compares two values of the specified data type.
Definition val.c:369
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
size_t co_val_make(co_unsigned16_t type, void *val, const void *ptr, size_t n)
Constructs a value of the specified data type.
Definition val.c:282
void co_val_fini(co_unsigned16_t type, void *val)
Finalizes a value of the specified data type.
Definition val.c:249
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