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