Lely core libraries 1.9.2
obj.c
Go to the documentation of this file.
1
24#include "obj.h"
25#include "co.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#include <stdlib.h>
33#include <string.h>
34
39static void co_obj_update(co_obj_t *obj);
40
42static void co_obj_clear(co_obj_t *obj);
43
45static co_unsigned32_t default_sub_dn_ind(
46 co_sub_t *sub, struct co_sdo_req *req, void *data);
47
49static co_unsigned32_t default_sub_up_ind(
50 const co_sub_t *sub, struct co_sdo_req *req, void *data);
51
52void *
53__co_obj_alloc(void)
54{
55 void *ptr = malloc(sizeof(struct __co_obj));
56 if (__unlikely(!ptr))
57 set_errc(errno2c(errno));
58 return ptr;
59}
60
61void
62__co_obj_free(void *ptr)
63{
64 free(ptr);
65}
66
67struct __co_obj *
68__co_obj_init(struct __co_obj *obj, co_unsigned16_t idx)
69{
70 assert(obj);
71
72 obj->node.key = &obj->idx;
73 obj->dev = NULL;
74 obj->idx = idx;
75
76 rbtree_init(&obj->tree, &uint8_cmp);
77
78#ifndef LELY_NO_CO_OBJ_NAME
79 obj->name = NULL;
80#endif
81
82 obj->code = CO_OBJECT_VAR;
83
84 obj->val = NULL;
85 obj->size = 0;
86
87 return obj;
88}
89
90void
91__co_obj_fini(struct __co_obj *obj)
92{
93 assert(obj);
94
95 if (obj->dev)
96 co_dev_remove_obj(obj->dev, obj);
97
98 co_obj_clear(obj);
99
100#ifndef LELY_NO_CO_OBJ_NAME
101 free(obj->name);
102#endif
103}
104
105co_obj_t *
106co_obj_create(co_unsigned16_t idx)
107{
108 trace("creating object %04X", idx);
109
110 co_obj_t *obj = __co_obj_alloc();
111 if (__unlikely(!obj))
112 return NULL;
113
114 return __co_obj_init(obj, idx);
115}
116
117void
119{
120 if (obj) {
121 trace("destroying object %04X", obj->idx);
122 __co_obj_fini(obj);
123 __co_obj_free(obj);
124 }
125}
126
127co_dev_t *
129{
130 assert(obj);
131
132 return obj->dev;
133}
134
135co_unsigned16_t
137{
138 assert(obj);
139
140 return obj->idx;
141}
142
143co_unsigned8_t
144co_obj_get_subidx(const co_obj_t *obj, co_unsigned8_t maxidx,
145 co_unsigned8_t *subidx)
146{
147 assert(obj);
148
149 if (!subidx)
150 maxidx = 0;
151
152 if (maxidx) {
153 struct rbnode *node = rbtree_first(&obj->tree);
154 for (size_t i = 0; node && i < maxidx;
155 node = rbnode_next(node), i++)
156 subidx[i] = co_sub_get_subidx(
157 structof(node, co_sub_t, node));
158 }
159
160 return (co_unsigned8_t)rbtree_size(&obj->tree);
161}
162
163int
165{
166 assert(obj);
167 assert(sub);
168
169 if (__unlikely(sub->obj && sub->obj != obj))
170 return -1;
171
172 if (__unlikely(sub->obj == obj))
173 return 0;
174
175 if (__unlikely(rbtree_find(&obj->tree, sub->node.key)))
176 return -1;
177
178 sub->obj = obj;
179 rbtree_insert(&sub->obj->tree, &sub->node);
180
181 co_obj_update(obj);
182
183 return 0;
184}
185
186int
188{
189 assert(obj);
190 assert(sub);
191
192 if (__unlikely(sub->obj != obj))
193 return -1;
194
195 rbtree_remove(&sub->obj->tree, &sub->node);
196 sub->obj = NULL;
197
198 co_val_fini(co_sub_get_type(sub), sub->val);
199 sub->val = NULL;
200
201 co_obj_update(obj);
202
203 return 0;
204}
205
206co_sub_t *
207co_obj_find_sub(const co_obj_t *obj, co_unsigned8_t subidx)
208{
209 assert(obj);
210
211 struct rbnode *node = rbtree_find(&obj->tree, &subidx);
212 return __likely(node) ? structof(node, co_sub_t, node) : NULL;
213}
214
215#ifndef LELY_NO_CO_OBJ_NAME
216
217const char *
219{
220 assert(obj);
221
222 return obj->name;
223}
224
225int
226co_obj_set_name(co_obj_t *obj, const char *name)
227{
228 assert(obj);
229
230 if (!name || !*name) {
231 free(obj->name);
232 obj->name = NULL;
233 return 0;
234 }
235
236 void *ptr = realloc(obj->name, strlen(name) + 1);
237 if (__unlikely(!ptr)) {
238 set_errc(errno2c(errno));
239 return -1;
240 }
241 obj->name = ptr;
242 strcpy(obj->name, name);
243
244 return 0;
245}
246
247#endif // LELY_NO_CO_OBJ_NAME
248
249co_unsigned8_t
251{
252 assert(obj);
253
254 return obj->code;
255}
256
257int
258co_obj_set_code(co_obj_t *obj, co_unsigned8_t code)
259{
260 assert(obj);
261
262 switch (code) {
263 case CO_OBJECT_NULL:
264 case CO_OBJECT_DOMAIN:
267 case CO_OBJECT_VAR:
268 case CO_OBJECT_ARRAY:
269 case CO_OBJECT_RECORD: obj->code = code; return 0;
270 default: set_errnum(ERRNUM_INVAL); return -1;
271 }
272}
273
274void *
276{
277 return __likely(obj) ? obj->val : NULL;
278}
279
280size_t
282{
283 return __likely(obj) ? obj->size : 0;
284}
285
286const void *
287co_obj_get_val(const co_obj_t *obj, co_unsigned8_t subidx)
288{
289 co_sub_t *sub = __likely(obj) ? co_obj_find_sub(obj, subidx) : NULL;
290 return co_sub_get_val(sub);
291}
292
293size_t
294co_obj_set_val(co_obj_t *obj, co_unsigned8_t subidx, const void *ptr, size_t n)
295{
296 assert(obj);
297
298 co_sub_t *sub = co_obj_find_sub(obj, subidx);
299 if (__unlikely(!sub)) {
301 return 0;
302 }
303
304 return co_sub_set_val(sub, ptr, n);
305}
306
307#define LELY_CO_DEFINE_TYPE(a, b, c, d) \
308 co_##b##_t co_obj_get_val_##c( \
309 const co_obj_t *obj, co_unsigned8_t subidx) \
310 { \
311 /* clang-format off */ \
312 co_sub_t *sub = __likely(obj) \
313 ? co_obj_find_sub(obj, subidx) \
314 : NULL; \
315 /* clang-format on */ \
316 return co_sub_get_val_##c(sub); \
317 } \
318\
319 size_t co_obj_set_val_##c( \
320 co_obj_t *obj, co_unsigned8_t subidx, co_##b##_t c) \
321 { \
322 assert(obj); \
323\
324 co_sub_t *sub = co_obj_find_sub(obj, subidx); \
325 if (__unlikely(!sub)) { \
326 set_errnum(ERRNUM_INVAL); \
327 return 0; \
328 } \
329\
330 return co_sub_set_val_##c(sub, c); \
331 }
332#include <lely/co/def/basic.def>
333#undef LELY_CO_DEFINE_TYPE
334
335void
337{
338 assert(obj);
339
340 rbtree_foreach (&obj->tree, node)
341 co_sub_set_dn_ind(structof(node, co_sub_t, node), ind, data);
342}
343
344void
346{
347 assert(obj);
348
349 rbtree_foreach (&obj->tree, node)
350 co_sub_set_up_ind(structof(node, co_sub_t, node), ind, data);
351}
352
353void *
354__co_sub_alloc(void)
355{
356 void *ptr = malloc(sizeof(struct __co_sub));
357 if (__unlikely(!ptr))
358 set_errc(errno2c(errno));
359 return ptr;
360}
361
362void
363__co_sub_free(void *ptr)
364{
365 free(ptr);
366}
367
368struct __co_sub *
369__co_sub_init(struct __co_sub *sub, co_unsigned8_t subidx, co_unsigned16_t type)
370{
371 assert(sub);
372
373 sub->node.key = &sub->subidx;
374 sub->obj = NULL;
375 sub->subidx = subidx;
376
377#ifndef LELY_NO_CO_OBJ_NAME
378 sub->name = NULL;
379#endif
380
381 sub->type = type;
382#ifndef LELY_NO_CO_OBJ_LIMITS
383 if (__unlikely(co_val_init_min(sub->type, &sub->min) == -1))
384 return NULL;
385 if (__unlikely(co_val_init_max(sub->type, &sub->max) == -1))
386 return NULL;
387#endif
388 if (__unlikely(co_val_init(sub->type, &sub->def) == -1))
389 return NULL;
390 sub->val = NULL;
391
392 sub->access = CO_ACCESS_RW;
393 sub->pdo_mapping = 0;
394 sub->flags = 0;
395
397 sub->dn_data = NULL;
399 sub->up_data = NULL;
400
401 return sub;
402}
403
404void
405__co_sub_fini(struct __co_sub *sub)
406{
407 assert(sub);
408
409 if (sub->obj)
410 co_obj_remove_sub(sub->obj, sub);
411
412 co_val_fini(sub->type, &sub->def);
413#ifndef LELY_NO_CO_OBJ_LIMITS
414 co_val_fini(sub->type, &sub->max);
415 co_val_fini(sub->type, &sub->min);
416#endif
417
418#ifndef LELY_NO_CO_OBJ_NAME
419 free(sub->name);
420#endif
421}
422
423co_sub_t *
424co_sub_create(co_unsigned8_t subidx, co_unsigned16_t type)
425{
426 int errc = 0;
427
428 co_sub_t *sub = __co_sub_alloc();
429 if (__unlikely(!sub)) {
430 errc = get_errc();
431 goto error_alloc_sub;
432 }
433
434 if (__unlikely(!__co_sub_init(sub, subidx, type))) {
435 errc = get_errc();
436 goto error_init_sub;
437 }
438
439 return sub;
440
441error_init_sub:
442 __co_sub_free(sub);
443error_alloc_sub:
444 set_errc(errc);
445 return NULL;
446}
447
448void
450{
451 if (sub) {
452 __co_sub_fini(sub);
453 __co_sub_free(sub);
454 }
455}
456
457co_obj_t *
459{
460 assert(sub);
461
462 return sub->obj;
463}
464
465co_unsigned8_t
467{
468 assert(sub);
469
470 return sub->subidx;
471}
472
473#ifndef LELY_NO_CO_OBJ_NAME
474
475const char *
477{
478 assert(sub);
479
480 return sub->name;
481}
482
483int
484co_sub_set_name(co_sub_t *sub, const char *name)
485{
486 assert(sub);
487
488 if (!name || !*name) {
489 free(sub->name);
490 sub->name = NULL;
491 return 0;
492 }
493
494 void *ptr = realloc(sub->name, strlen(name) + 1);
495 if (__unlikely(!ptr)) {
496 set_errc(errno2c(errno));
497 return -1;
498 }
499 sub->name = ptr;
500 strcpy(sub->name, name);
501
502 return 0;
503}
504
505#endif // LELY_NO_CO_OBJ_NAME
506
507co_unsigned16_t
509{
510 assert(sub);
511
512 return sub->type;
513}
514
515#ifndef LELY_NO_CO_OBJ_LIMITS
516
517const void *
519{
520 return __likely(sub) ? co_val_addressof(sub->type, &sub->min) : NULL;
521}
522
523size_t
525{
526 return __likely(sub) ? co_val_sizeof(sub->type, &sub->min) : 0;
527}
528
529const void *
531{
532 return __likely(sub) ? &sub->min : NULL;
533}
534
535size_t
536co_sub_set_min(co_sub_t *sub, const void *ptr, size_t n)
537{
538 assert(sub);
539
540 co_val_fini(sub->type, &sub->min);
541 return co_val_make(sub->type, &sub->min, ptr, n);
542}
543
544const void *
546{
547 return __likely(sub) ? co_val_addressof(sub->type, &sub->max) : NULL;
548}
549
550size_t
552{
553 return __likely(sub) ? co_val_sizeof(sub->type, &sub->max) : 0;
554}
555
556const void *
558{
559 return __likely(sub) ? &sub->max : NULL;
560}
561
562size_t
563co_sub_set_max(co_sub_t *sub, const void *ptr, size_t n)
564{
565 assert(sub);
566
567 co_val_fini(sub->type, &sub->max);
568 return co_val_make(sub->type, &sub->max, ptr, n);
569}
570
571#endif // LELY_NO_CO_OBJ_LIMITS
572
573const void *
575{
576 return __likely(sub) ? co_val_addressof(sub->type, &sub->def) : NULL;
577}
578
579size_t
581{
582 return __likely(sub) ? co_val_sizeof(sub->type, &sub->def) : 0;
583}
584
585const void *
587{
588 return __likely(sub) ? &sub->def : NULL;
589}
590
591size_t
592co_sub_set_def(co_sub_t *sub, const void *ptr, size_t n)
593{
594 assert(sub);
595
596 co_val_fini(sub->type, &sub->def);
597 return co_val_make(sub->type, &sub->def, ptr, n);
598}
599
600const void *
602{
603 return __likely(sub) ? co_val_addressof(sub->type, sub->val) : NULL;
604}
605
606size_t
608{
609 return __likely(sub) ? co_val_sizeof(sub->type, sub->val) : 0;
610}
611
612const void *
614{
615 return __likely(sub) ? sub->val : NULL;
616}
617
618size_t
619co_sub_set_val(co_sub_t *sub, const void *ptr, size_t n)
620{
621 assert(sub);
622
623 co_val_fini(sub->type, sub->val);
624 return co_val_make(sub->type, sub->val, ptr, n);
625}
626
627#define LELY_CO_DEFINE_TYPE(a, b, c, d) \
628 co_##b##_t co_sub_get_val_##c(const co_sub_t *sub) \
629 { \
630 static const co_##b##_t val; \
631\
632 /* clang-format off */ \
633 if (__unlikely(!sub || sub->type != CO_DEFTYPE_##a \
634 || !sub->val)) \
635 /* clang-format on */ \
636 return val; \
637 return ((union co_val *)sub->val)->c; \
638 } \
639\
640 size_t co_sub_set_val_##c(co_sub_t *sub, co_##b##_t c) \
641 { \
642 assert(sub); \
643\
644 if (__unlikely(sub->type != CO_DEFTYPE_##a)) { \
645 set_errnum(ERRNUM_INVAL); \
646 return 0; \
647 } \
648\
649 return co_sub_set_val(sub, &c, sizeof(c)); \
650 }
651#include <lely/co/def/basic.def>
652#undef LELY_CO_DEFINE_TYPE
653
654#ifndef LELY_NO_CO_OBJ_LIMITS
655co_unsigned32_t
656co_sub_chk_val(const co_sub_t *sub, co_unsigned16_t type, const void *val)
657{
658 assert(sub);
659
660 // Arrays do not have a minimum or maximum value.
661 if (!co_type_is_basic(sub->type))
662 return 0;
663
664 if (__unlikely(sub->type != type))
665 return CO_SDO_AC_TYPE_LEN;
666
667 assert(val);
668
669 // Check whether the value is within bounds.
670 if (__unlikely(co_val_cmp(sub->type, &sub->min, &sub->max) > 0))
672 if (__unlikely(co_val_cmp(sub->type, val, &sub->max) > 0))
673 return CO_SDO_AC_PARAM_HI;
674 if (__unlikely(co_val_cmp(sub->type, val, &sub->min) < 0))
675 return CO_SDO_AC_PARAM_LO;
676
677 return 0;
678}
679#endif
680
681unsigned int
683{
684 assert(sub);
685
686 return sub->access;
687}
688
689int
691{
692 assert(sub);
693
694 switch (access) {
695 case CO_ACCESS_RO:
696 case CO_ACCESS_WO:
697 case CO_ACCESS_RW:
698 case CO_ACCESS_RWR:
699 case CO_ACCESS_RWW:
700 case CO_ACCESS_CONST: sub->access = access; return 0;
701 default: set_errnum(ERRNUM_INVAL); return -1;
702 }
703}
704
705int
707{
708 assert(sub);
709
710 return sub->pdo_mapping;
711}
712
713void
715{
716 assert(sub);
717
718 sub->pdo_mapping = !!pdo_mapping;
719}
720
721unsigned int
723{
724 assert(sub);
725
726 return sub->flags;
727}
728
729void
730co_sub_set_flags(co_sub_t *sub, unsigned int flags)
731{
732 assert(sub);
733
734 sub->flags = flags;
735}
736
737void
738co_sub_get_dn_ind(const co_sub_t *sub, co_sub_dn_ind_t **pind, void **pdata)
739{
740 assert(sub);
741
742 if (pind)
743 *pind = sub->dn_ind;
744 if (pdata)
745 *pdata = sub->dn_data;
746}
747
748void
750{
751 assert(sub);
752
753 sub->dn_ind = ind ? ind : &default_sub_dn_ind;
754 sub->dn_data = ind ? data : NULL;
755}
756
757co_unsigned32_t
759{
760 assert(sub);
761 assert(req);
762
763 co_unsigned32_t ac = 0;
764
765#ifndef LELY_NO_CO_OBJ_FILE
766 // clang-format off
769 // clang-format on
771 return ac;
772 }
773#endif
774
775 // Read the value.
776 co_unsigned16_t type = co_sub_get_type(sub);
777 union co_val val;
778 if (__unlikely(co_sdo_req_dn_val(req, type, &val, &ac) == -1))
779 goto error_req;
780
781#ifndef LELY_NO_CO_OBJ_LIMITS
782 // Accept the value if it is within bounds.
783 ac = co_sub_chk_val(sub, type, &val);
784#endif
785 if (__likely(!ac))
786 co_sub_dn(sub, &val);
787
788 co_val_fini(type, &val);
789error_req:
790 return ac;
791}
792
793co_unsigned32_t
795{
796 if (__unlikely(!sub))
797 return CO_SDO_AC_NO_SUB;
798
799 if (__unlikely(!(sub->access & CO_ACCESS_WRITE)))
800 return CO_SDO_AC_NO_WRITE;
801
802 if (__unlikely(!req))
803 return CO_SDO_AC_ERROR;
804
805 assert(sub->dn_ind);
806 return sub->dn_ind(sub, req, sub->dn_data);
807}
808
809co_unsigned32_t
810co_sub_dn_ind_val(co_sub_t *sub, co_unsigned16_t type, const void *val)
811{
812 if (__unlikely(co_sub_get_type(sub) != type))
813 return CO_SDO_AC_TYPE_LEN;
814
815 struct co_sdo_req req = CO_SDO_REQ_INIT;
816 co_unsigned32_t ac = 0;
817
818 int errc = get_errc();
819
820 if (__unlikely(co_sdo_req_up_val(&req, type, val, &ac) == -1))
821 goto error;
822
823 ac = co_sub_dn_ind(sub, &req);
824
825error:
826 co_sdo_req_fini(&req);
827 set_errc(errc);
828 return ac;
829}
830
831int
832co_sub_dn(co_sub_t *sub, void *val)
833{
834 assert(sub);
835
836 if (!(sub->flags & CO_OBJ_FLAGS_WRITE)) {
837 co_val_fini(sub->type, sub->val);
838 if (__unlikely(!co_val_move(sub->type, sub->val, val)))
839 return -1;
840 }
841
842 return 0;
843}
844
845void
846co_sub_get_up_ind(const co_sub_t *sub, co_sub_up_ind_t **pind, void **pdata)
847{
848 assert(sub);
849
850 if (pind)
851 *pind = sub->up_ind;
852 if (pdata)
853 *pdata = sub->up_data;
854}
855
856void
858{
859 assert(sub);
860
861 sub->up_ind = ind ? ind : &default_sub_up_ind;
862 sub->up_data = ind ? data : NULL;
863}
864
865co_unsigned32_t
866co_sub_on_up(const co_sub_t *sub, struct co_sdo_req *req)
867{
868 assert(sub);
869 assert(req);
870
871 co_unsigned32_t ac = 0;
872
873#ifndef LELY_NO_CO_OBJ_FILE
877 return ac;
878 }
879#endif
880
881 const void *val = co_sub_get_val(sub);
882 if (__unlikely(!val))
883 return CO_SDO_AC_NO_DATA;
884
885 co_sdo_req_up_val(req, co_sub_get_type(sub), val, &ac);
886 return ac;
887}
888
889co_unsigned32_t
890co_sub_up_ind(const co_sub_t *sub, struct co_sdo_req *req)
891{
892 if (__unlikely(!sub))
893 return CO_SDO_AC_NO_SUB;
894
895 if (__unlikely(!(sub->access & CO_ACCESS_READ)))
896 return CO_SDO_AC_NO_READ;
897
898 if (__unlikely(!req))
899 return CO_SDO_AC_ERROR;
900
901 assert(sub->up_ind);
902 return sub->up_ind(sub, req, sub->up_data);
903}
904
905static void
907{
908 assert(obj);
909
910 // Compute the total size (in bytes) of the object.
911 size_t size = 0;
912 rbtree_foreach (&obj->tree, node) {
913 co_sub_t *sub = structof(node, co_sub_t, node);
914 co_unsigned16_t type = co_sub_get_type(sub);
915 size = ALIGN(size, co_type_alignof(type));
916 size += co_type_sizeof(type);
917 }
918
919 void *val = NULL;
920 if (size) {
921 val = calloc(1, size);
922 if (__unlikely(!val)) {
923 set_errc(errno2c(errno));
924 return;
925 }
926 }
927
928 // Initialize the values of the sub-objects.
929 size = 0;
930 rbtree_foreach (&obj->tree, node) {
931 co_sub_t *sub = structof(node, co_sub_t, node);
932 co_unsigned16_t type = co_sub_get_type(sub);
933 // Compute the offset of the sub-object.
934 size = ALIGN(size, co_type_alignof(type));
935 // Move the old value, if it exists.
936 void *src = sub->val;
937 sub->val = (char *)val + size;
938 if (src)
939 co_val_move(type, sub->val, src);
940 size += co_type_sizeof(type);
941 }
942
943 free(obj->val);
944 obj->val = val;
945 obj->size = size;
946}
947
948static void
950{
951 assert(obj);
952
953 rbtree_foreach (&obj->tree, node)
954 co_sub_destroy(structof(node, co_sub_t, node));
955
956 free(obj->val);
957 obj->val = NULL;
958}
959
960static co_unsigned32_t
961default_sub_dn_ind(co_sub_t *sub, struct co_sdo_req *req, void *data)
962{
963 (void)data;
964
965 return co_sub_on_dn(sub, req);
966}
967
968static co_unsigned32_t
969default_sub_up_ind(const co_sub_t *sub, struct co_sdo_req *req, void *data)
970{
971 (void)data;
972
973 return co_sub_on_up(sub, req);
974}
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:264
This header file is part of the utilities library; it contains the native and platform-independent er...
@ 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
int errno2c(int errnum)
Transforms a standard C error number to a native error code.
Definition: errnum.c:43
void set_errnum(errnum_t errnum)
Sets the current (thread-specific) platform-independent error number to errnum.
Definition: errnum.h:375
#define __unlikely(x)
Indicates to the compiler that the expression is most-likely false.
Definition: features.h:286
#define __likely(x)
Indicates to the compiler that the expression is most-likely true.
Definition: features.h:273
#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.
Definition: obj.h:150
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:135
#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
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:165
#define CO_SDO_REQ_INIT
The static initializer for struct co_sdo_req.
Definition: sdo.h:203
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:278
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:206
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:312
#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
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
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
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
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_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:794
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:857
void * co_obj_addressof_val(const co_obj_t *obj)
Returns the address of the value of a CANopen object.
Definition: obj.c:275
co_unsigned16_t co_obj_get_idx(const co_obj_t *obj)
Returns the index of a CANopen object.
Definition: obj.c:136
static co_unsigned32_t default_sub_dn_ind(co_sub_t *sub, struct co_sdo_req *req, void *data)
The default download indication function.
Definition: obj.c:961
const char * co_sub_get_name(const co_sub_t *sub)
Returns the name of a CANopen sub-object.
Definition: obj.c:476
static co_unsigned32_t default_sub_up_ind(const co_sub_t *sub, struct co_sdo_req *req, void *data)
The default upload indication function.
Definition: obj.c:969
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
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:749
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
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:890
static void co_obj_clear(co_obj_t *obj)
Destroys all sub-objects.
Definition: obj.c:949
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
co_unsigned32_t co_sub_on_dn(co_sub_t *sub, struct co_sdo_req *req)
Implements the default behavior when a download indication is received by a CANopen sub-object.
Definition: obj.c:758
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:810
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:738
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
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:551
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
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:574
size_t co_sub_sizeof_def(const co_sub_t *sub)
Returns size (in bytes) of the default value of a CANopen sub-object.
Definition: obj.c:580
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:846
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
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:287
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:545
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:832
co_unsigned8_t co_obj_get_code(const co_obj_t *obj)
Returns the object code of a CANopen object.
Definition: obj.c:250
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:601
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
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
size_t co_sub_sizeof_val(const co_sub_t *sub)
Returns size (in bytes) of the current value of a CANopen sub-object.
Definition: obj.c:607
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:906
const char * co_obj_get_name(const co_obj_t *obj)
Returns the name of a CANopen object.
Definition: obj.c:218
int co_obj_remove_sub(co_obj_t *obj, co_sub_t *sub)
Removes a sub-object from a CANopen object.
Definition: obj.c:187
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
void co_obj_destroy(co_obj_t *obj)
Destroys a CANopen object, including its sub-objects.
Definition: obj.c:118
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:336
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:128
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
co_obj_t * co_obj_create(co_unsigned16_t idx)
Creates a CANopen object.
Definition: obj.c:106
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:345
co_unsigned32_t co_sub_on_up(const co_sub_t *sub, struct co_sdo_req *req)
Implements the default behavior when an upload indication is received by a CANopen sub-object.
Definition: obj.c:866
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:458
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:281
unsigned int co_sub_get_access(const co_sub_t *sub)
Returns the access type of a CANopen sub-object.
Definition: obj.c:682
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:518
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:294
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:144
co_sub_t * co_sub_create(co_unsigned8_t subidx, co_unsigned16_t type)
Creates a CANopen sub-object.
Definition: obj.c:424
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:656
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:524
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
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:308
struct rbnode * rbtree_first(const struct rbtree *tree)
Returns a pointer to the first (leftmost) node in a red-black tree.
Definition: rbtree.c:324
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:238
size_t rbtree_size(const struct rbtree *tree)
Returns the size (in number of nodes) of a red-black tree.
Definition: rbtree.h:252
void rbtree_remove(struct rbtree *tree, struct rbnode *node)
Removes a node from a red-black tree.
Definition: rbtree.c:188
#define rbtree_foreach(tree, node)
Iterates over each node in a red-black tree in ascending order.
Definition: rbtree.h:226
This is the internal header file of the CANopen library.
This is the internal header file of the object dictionary.
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.c:38
A CANopen object.
Definition: obj.h:32
co_unsigned16_t idx
The object index.
Definition: obj.h:38
co_unsigned8_t code
The object code.
Definition: obj.h:40
size_t size
The size (in bytes) of the value at val.
Definition: obj.h:50
struct rbtree tree
The tree containing all the sub-objects.
Definition: obj.h:46
struct rbnode node
The node of this object in the tree of objects.
Definition: obj.h:34
co_dev_t * dev
A pointer to the CANopen device containing this object.
Definition: obj.h:36
char * name
A pointer to the name of the object.
Definition: obj.h:43
void * val
A pointer to the object value.
Definition: obj.h:48
A CANopen sub-object.
Definition: obj.h:54
unsigned access
The access type.
Definition: obj.h:78
co_sub_dn_ind_t * dn_ind
A pointer to the download indication function.
Definition: obj.h:84
unsigned flags
The object flags.
Definition: obj.h:82
co_unsigned8_t subidx
The object sub-index.
Definition: obj.h:60
struct rbnode node
The node of this sub-object in the tree of sub-objects.
Definition: obj.h:56
co_obj_t * obj
A pointer to the CANopen object containing this sub-object.
Definition: obj.h:58
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:69
co_sub_up_ind_t * up_ind
A pointer to the upload indication function.
Definition: obj.h:88
union co_val max
The upper limit of the object value.
Definition: obj.h:71
unsigned pdo_mapping
A flag indicating if it is possible to map this object into a PDO.
Definition: obj.h:80
char * name
A pointer to the name of the sub-object.
Definition: obj.h:65
co_unsigned16_t type
The data type.
Definition: obj.h:62
void * val
A pointer to the sub-object value.
Definition: obj.h:76
void * dn_data
A pointer to user-specified data for dn_ind.
Definition: obj.h:86
void * up_data
A pointer to user-specified data for up_ind.
Definition: obj.h:90
A CANopen SDO upload/download request.
Definition: sdo.h:178
size_t size
The total size (in bytes) of the value to be uploaded/downloaded.
Definition: sdo.h:184
A node in a red-black tree.
Definition: rbtree.h:52
const void * key
A pointer to the key for this node.
Definition: rbtree.h:58
#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 0 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:163
int co_val_init(co_unsigned16_t type, void *val)
Initializes a value of the specified data type to zero.
Definition: val.c:120
size_t co_val_move(co_unsigned16_t type, void *dst, void *src)
Moves one value to another.
Definition: val.c:371
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
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
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:386
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
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:306
void co_val_fini(co_unsigned16_t type, void *val)
Finalizes a value of the specified data type.
Definition: val.c:273
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