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 
43 static void co_obj_update(co_obj_t *obj);
44 
46 static void co_obj_clear(co_obj_t *obj);
47 
48 void *
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 
59 void
60 __co_obj_free(void *ptr)
61 {
62  free(ptr);
63 }
64 
65 #endif // !LELY_NO_MALLOC
66 
67 struct __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 
94 void
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 
113 co_obj_t *
114 co_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 
125 void
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 
137 co_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 
146 co_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 
155 co_dev_t *
157 {
158  assert(obj);
159 
160  return obj->dev;
161 }
162 
163 co_unsigned16_t
165 {
166  assert(obj);
167 
168  return obj->idx;
169 }
170 
171 co_unsigned8_t
172 co_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 
191 int
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 
216 int
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 
239 co_sub_t *
240 co_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 
248 co_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 
257 co_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
267 const char *
269 {
270  assert(obj);
271 
272  return obj->name;
273 }
274 #endif
275 
276 #if !LELY_NO_MALLOC && !LELY_NO_CO_OBJ_NAME
277 int
278 co_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 
302 co_unsigned8_t
304 {
305  assert(obj);
306 
307  return obj->code;
308 }
309 
310 int
311 co_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:
318  case CO_OBJECT_DEFTYPE:
319  case CO_OBJECT_DEFSTRUCT:
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 
327 void *
329 {
330  return obj ? obj->val : NULL;
331 }
332 
333 size_t
335 {
336  return obj ? obj->size : 0;
337 }
338 
339 const void *
340 co_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 
346 size_t
347 co_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 
388 void
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
398 void
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 
410 void *
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 
421 void
422 __co_sub_free(void *ptr)
423 {
424  free(ptr);
425 }
426 
427 #endif // !LELY_NO_MALLOC
428 
429 struct __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 
473 void
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 
496 co_sub_t *
497 co_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 
514 error_init_sub:
515  __co_sub_free(sub);
516 error_alloc_sub:
517  set_errc(errc);
518  return NULL;
519 }
520 
521 void
523 {
524  if (sub) {
525  __co_sub_fini(sub);
526  __co_sub_free(sub);
527  }
528 }
529 
530 #endif // !LELY_NO_MALLOC
531 
532 co_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 
541 co_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 
550 co_obj_t *
552 {
553  assert(sub);
554 
555  return sub->obj;
556 }
557 
558 co_unsigned8_t
560 {
561  assert(sub);
562 
563  return sub->subidx;
564 }
565 
566 #if !LELY_NO_CO_OBJ_NAME
567 const char *
569 {
570  assert(sub);
571 
572  return sub->name;
573 }
574 #endif
575 
576 #if !LELY_NO_MALLOC && !LELY_NO_CO_OBJ_NAME
577 int
578 co_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 
602 co_unsigned16_t
604 {
605  assert(sub);
606 
607  return sub->type;
608 }
609 
610 #if !LELY_NO_CO_OBJ_LIMITS
611 
612 const void *
614 {
615  return sub ? co_val_addressof(sub->type, &sub->min) : NULL;
616 }
617 
618 size_t
620 {
621  return sub ? co_val_sizeof(sub->type, &sub->min) : 0;
622 }
623 
624 const void *
626 {
627  return sub ? &sub->min : NULL;
628 }
629 
630 size_t
631 co_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 
639 const void *
641 {
642  return sub ? co_val_addressof(sub->type, &sub->max) : NULL;
643 }
644 
645 size_t
647 {
648  return sub ? co_val_sizeof(sub->type, &sub->max) : 0;
649 }
650 
651 const void *
653 {
654  return sub ? &sub->max : NULL;
655 }
656 
657 size_t
658 co_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 
670 const void *
672 {
673  return sub ? co_val_addressof(sub->type, &sub->def) : NULL;
674 }
675 
676 size_t
678 {
679  return sub ? co_val_sizeof(sub->type, &sub->def) : 0;
680 }
681 
682 const void *
684 {
685  return sub ? &sub->def : NULL;
686 }
687 
688 size_t
689 co_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 
699 const void *
701 {
702  return sub ? co_val_addressof(sub->type, sub->val) : NULL;
703 }
704 
705 size_t
707 {
708  return sub ? co_val_sizeof(sub->type, sub->val) : 0;
709 }
710 
711 const void *
713 {
714  return sub ? sub->val : NULL;
715 }
716 
717 size_t
718 co_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
751 co_unsigned32_t
752 co_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)
767  return CO_SDO_AC_PARAM_RANGE;
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 
777 unsigned int
779 {
780  assert(sub);
781 
782  return sub->access;
783 }
784 
785 int
786 co_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 
801 int
803 {
804  assert(sub);
805 
806  return sub->pdo_mapping;
807 }
808 
809 void
810 co_sub_set_pdo_mapping(co_sub_t *sub, int pdo_mapping)
811 {
812  assert(sub);
813 
814  sub->pdo_mapping = !!pdo_mapping;
815 }
816 
817 unsigned int
819 {
820  assert(sub);
821 
822  return sub->flags;
823 }
824 
825 void
826 co_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 
835 const 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 
847 int
848 co_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 
862 const 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 
874 int
875 co_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 
891 void
892 co_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 
902 void
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 
911 int
912 co_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 
957 co_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 
973 co_unsigned32_t
974 co_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 
989 error:
990  co_sdo_req_fini(&req);
991  set_errc(errc);
992  return ac;
993 }
994 
995 int
996 co_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 
1016 void
1017 co_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 
1027 void
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 
1038 int
1039 co_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 
1065 co_unsigned32_t
1066 co_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 
1085 co_unsigned32_t
1086 co_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 
1095 co_unsigned32_t
1096 co_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 
1107 static 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.
1141  offset = ALIGN(offset, co_type_alignof(type));
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 
1155 static 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_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
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
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
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
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
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
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
co_sub_t * co_sub_next(const co_sub_t *sub)
Finds the next sub-object in a CANopen object.
Definition: obj.c:542
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
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
co_sub_t * co_sub_create(co_unsigned8_t subidx, co_unsigned16_t type)
Creates a CANopen sub-object.
Definition: obj.c:497
co_unsigned16_t co_obj_get_idx(const co_obj_t *obj)
Returns the index of a CANopen object.
Definition: obj.c:164
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
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
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
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_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
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_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
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
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
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
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
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_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
void * co_obj_addressof_val(const co_obj_t *obj)
Returns the address of the value of a CANopen object.
Definition: obj.c:328
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
co_sub_t * co_sub_prev(const co_sub_t *sub)
Finds the previous sub-object in a CANopen object.
Definition: obj.c:533
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
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_unsigned8_t co_obj_get_code(const co_obj_t *obj)
Returns the object code of a CANopen object.
Definition: obj.c:303
size_t co_sub_set_max(co_sub_t *sub, const void *ptr, size_t n)
Sets the upper limit of a value of a CANopen sub-object.
Definition: obj.c:658
unsigned int co_sub_get_flags(const co_sub_t *sub)
Returns the object flags of a CANopen sub-object.
Definition: obj.c:818
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
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
int co_obj_set_name(co_obj_t *obj, const char *name)
Sets the name of a CANopen object.
Definition: obj.c:278
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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_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
#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 * 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:343
void rbtree_init(struct rbtree *tree, rbtree_cmp_t *cmp)
Initializes a red-black tree.
Definition: rbtree.h:248
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
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
#define rbtree_foreach(tree, node)
Iterates over each node in a red-black tree in ascending order.
Definition: rbtree.h:234
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 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