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 }
co_dev_remove_obj
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
default_sub_up_ind
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
co_obj_get_name
const char * co_obj_get_name(const co_obj_t *obj)
Returns the name of a CANopen object.
Definition: obj.c:254
__co_sub::obj
co_obj_t * obj
A pointer to the CANopen object containing this sub-object.
Definition: obj.h:58
__co_obj::size
size_t size
The size (in bytes) of the value at val.
Definition: obj.h:50
rbtree_insert
void rbtree_insert(struct rbtree *tree, struct rbnode *node)
Inserts a node into a red-black tree.
Definition: rbtree.c:108
CO_ACCESS_RW
#define CO_ACCESS_RW
Read or write access.
Definition: obj.h:75
__co_obj::idx
co_unsigned16_t idx
The object index.
Definition: obj.h:38
co_sub_sizeof_max
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
co_obj_remove_sub
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
co_sub_get_access
unsigned int co_sub_get_access(const co_sub_t *sub)
Returns the access type of a CANopen sub-object.
Definition: obj.c:745
co_sub_set_min
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
rbtree_foreach
#define rbtree_foreach(tree, node)
Iterates over each node in a red-black tree in ascending order.
Definition: rbtree.h:226
rbnode_next
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
co_obj_get_code
co_unsigned8_t co_obj_get_code(const co_obj_t *obj)
Returns the object code of a CANopen object.
Definition: obj.c:286
co_val_init_max
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
CO_OBJ_FLAGS_DOWNLOAD_FILE
#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
co_obj_update
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
cmp.h
co_obj_insert_sub
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
dev.h
rbtree_first
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
co_sub_dn_ind_val
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
__co_obj::val
void * val
A pointer to the object value.
Definition: obj.h:48
rbtree_find
struct rbnode * rbtree_find(const struct rbtree *tree, const void *key)
Finds a node in a red-black tree.
Definition: rbtree.c:306
__co_sub::def
union co_val def
The default value.
Definition: obj.h:75
co_val_fini
void co_val_fini(co_unsigned16_t type, void *val)
Finalizes a value of the specified data type.
Definition: val.c:275
co_obj_find_sub
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
CO_ACCESS_RWW
#define CO_ACCESS_RWW
Read or write on process output.
Definition: obj.h:81
__co_obj::code
co_unsigned8_t code
The object code.
Definition: obj.h:40
__co_sub::val
void * val
A pointer to the sub-object value.
Definition: obj.h:78
co_sub_prev
co_sub_t * co_sub_prev(const co_sub_t *sub)
Finds the previous sub-object in a CANopen object.
Definition: obj.c:502
string.h
co_val_init_min
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
__co_sub::dn_data
void * dn_data
A pointer to user-specified data for dn_ind.
Definition: obj.h:88
co_sub_set_access
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
CO_SDO_AC_PARAM_RANGE
#define CO_SDO_AC_PARAM_RANGE
SDO abort code: Maximum value is less than minimum value (download only).
Definition: sdo.h:144
co_obj_set_dn_ind
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
co_sub_set_def
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
co_sub_get_max
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
co_sdo_req_up_val
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
CO_OBJ_FLAGS_WRITE
#define CO_OBJ_FLAGS_WRITE
Refuse write on download.
Definition: obj.h:90
co_val_addressof
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
co_obj_addressof_val
void * co_obj_addressof_val(const co_obj_t *obj)
Returns the address of the value of a CANopen object.
Definition: obj.c:311
rbtree_last
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
co_sub_on_up
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
__co_sub::access
unsigned long access
The access type.
Definition: obj.h:80
co_val_move
size_t co_val_move(co_unsigned16_t type, void *dst, void *src)
Moves one value to another.
Definition: val.c:382
__co_sub::type
co_unsigned16_t type
The data type.
Definition: obj.h:62
co_sub_set_max
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
co_sub_get_val
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
co_type_is_basic
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
co_obj_set_up_ind
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
__co_sub::max
union co_val max
The upper limit of the object value.
Definition: obj.h:71
co_obj_set_val
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
default_sub_dn_ind
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
co_sub_sizeof_def
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
get_errc
int get_errc(void)
Returns the last (thread-specific) native error code set by a system call or library function.
Definition: errnum.c:947
co_sub_addressof_def
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
co_obj_clear
static void co_obj_clear(co_obj_t *obj)
Destroys all sub-objects.
Definition: obj.c:1082
errno2c
int errno2c(int errnum)
Transforms a standard C error number to a native error code.
Definition: errnum.c:43
co_obj_last_sub
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
CO_DEFTYPE_DOMAIN
#define CO_DEFTYPE_DOMAIN
The data type (and object index) of an arbitrary large block of data.
Definition: type.h:77
co.h
co_sub_up_ind_t
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_sub_sizeof_min
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_sdo_req_up_file
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
sdo.h
co_obj_destroy
void co_obj_destroy(co_obj_t *obj)
Destroys a CANopen object, including its sub-objects.
Definition: obj.c:118
co_type_alignof
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
__co_sub::dn_ind
co_sub_dn_ind_t * dn_ind
A pointer to the download indication function.
Definition: obj.h:86
__co_sub::name
char * name
A pointer to the name of the sub-object.
Definition: obj.h:65
CO_OBJECT_DOMAIN
#define CO_OBJECT_DOMAIN
A large variable amount of data.
Definition: obj.h:33
CO_OBJECT_DEFTYPE
#define CO_OBJECT_DEFTYPE
A type definitions.
Definition: obj.h:36
co_sub_set_val
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
CO_SDO_AC_TYPE_LEN
#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
CO_SDO_AC_PARAM_HI
#define CO_SDO_AC_PARAM_HI
SDO abort code: Value of parameter written too high (download only).
Definition: sdo.h:138
co_sub_addressof_min
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
__co_sub::min
union co_val min
The lower limit of the object value.
Definition: obj.h:69
CO_ACCESS_READ
#define CO_ACCESS_READ
The object can be read.
Definition: obj.h:57
__co_sub::up_ind
co_sub_up_ind_t * up_ind
A pointer to the upload indication function.
Definition: obj.h:91
co_sub_get_download_file
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_ACCESS_RWR
#define CO_ACCESS_RWR
Read or write on process input.
Definition: obj.h:78
co_obj_get_val
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
__co_obj::name
char * name
A pointer to the name of the object.
Definition: obj.h:43
CO_SDO_AC_PARAM_LO
#define CO_SDO_AC_PARAM_LO
SDO abort code: Value of parameter written too low (download only).
Definition: sdo.h:141
co_obj_get_subidx
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_type_sizeof
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
set_errnum
void set_errnum(errnum_t errnum)
Sets the current (thread-specific) platform-independent error number to errnum.
Definition: errnum.h:375
co_obj_sizeof_val
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
set_errc
void set_errc(int errc)
Sets the current (thread-specific) native error code to errc.
Definition: errnum.c:957
co_obj_get_dev
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
__co_sub::pdo_mapping
unsigned long pdo_mapping
A flag indicating if it is possible to map this object into a PDO.
Definition: obj.h:82
CO_SDO_AC_NO_SUB
#define CO_SDO_AC_NO_SUB
SDO abort code: Sub-index does not exist.
Definition: sdo.h:132
co_sub_set_dn_ind
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
co_sub_next
co_sub_t * co_sub_next(const co_sub_t *sub)
Finds the next sub-object in a CANopen object.
Definition: obj.c:511
__co_obj::dev
co_dev_t * dev
A pointer to the CANopen device containing this object.
Definition: obj.h:36
co_sdo_req
A CANopen SDO upload/download request.
Definition: sdo.h:178
co_obj_prev
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
errnum.h
__co_sub::node
struct rbnode node
The node of this sub-object in the tree of sub-objects.
Definition: obj.h:56
__co_obj::tree
struct rbtree tree
The tree containing all the sub-objects.
Definition: obj.h:46
co_obj_set_name
int co_obj_set_name(co_obj_t *obj, const char *name)
Sets the name of a CANopen object.
Definition: obj.c:262
co_sub_get_obj
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
ALIGN
#define ALIGN(x, a)
Rounds x up to the nearest multiple of a.
Definition: util.h:41
co_val_sizeof
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
co_obj_first_sub
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
co_sub_get_min
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
CO_SDO_AC_ERROR
#define CO_SDO_AC_ERROR
SDO abort code: General error.
Definition: sdo.h:150
co_sub_on_dn
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
co_obj_get_idx
co_unsigned16_t co_obj_get_idx(const co_obj_t *obj)
Returns the index of a CANopen object.
Definition: obj.c:154
ERRNUM_INVAL
@ ERRNUM_INVAL
Invalid argument.
Definition: errnum.h:129
co_obj_next
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_sdo_req::size
size_t size
The total size (in bytes) of the value to be uploaded/downloaded.
Definition: sdo.h:184
co_sub_get_def
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
co_val_make
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
co_sub_set_name
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_sub_dn_ind_t
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
CO_SDO_REQ_INIT
#define CO_SDO_REQ_INIT
The static initializer for struct co_sdo_req.
Definition: sdo.h:203
CO_SDO_AC_NO_DATA
#define CO_SDO_AC_NO_DATA
SDO abort code: No data available.
Definition: sdo.h:175
CO_OBJECT_ARRAY
#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
co_sub_chk_val
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
rbnode
A node in a red-black tree.
Definition: rbtree.h:52
co_sub_up_ind
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
CO_SDO_AC_NO_WRITE
#define CO_SDO_AC_NO_WRITE
SDO abort code: Attempt to write a read only object.
Definition: sdo.h:90
CO_OBJECT_DEFSTRUCT
#define CO_OBJECT_DEFSTRUCT
A record type definition.
Definition: obj.h:39
co_sub_set_flags
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_OBJECT_NULL
#define CO_OBJECT_NULL
An object with no data fields.
Definition: obj.h:30
co_sub_set_upload_file
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
obj.h
co_val_cmp
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
co_val
A union of the CANopen static data types.
Definition: val.h:163
rbtree_init
void rbtree_init(struct rbtree *tree, rbtree_cmp_t *cmp)
Initializes a red-black tree.
Definition: rbtree.h:238
co_sdo_req_dn_val
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
__co_obj
A CANopen object.
Definition: obj.h:32
co_sub_create
co_sub_t * co_sub_create(co_unsigned8_t subidx, co_unsigned16_t type)
Creates a CANopen sub-object.
Definition: obj.c:468
co_sub_get_pdo_mapping
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
co_sub_get_name
const char * co_sub_get_name(const co_sub_t *sub)
Returns the name of a CANopen sub-object.
Definition: obj.c:538
__co_dev
A CANopen device.
Definition: dev.c:41
co_sub_get_dn_ind
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_get_subidx
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
__co_obj::node
struct rbnode node
The node of this object in the tree of objects.
Definition: obj.h:34
rbtree_remove
void rbtree_remove(struct rbtree *tree, struct rbnode *node)
Removes a node from a red-black tree.
Definition: rbtree.c:187
co_sub_set_up_ind
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
co_obj_set_code
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
co_val_init
int co_val_init(co_unsigned16_t type, void *val)
Initializes a value of the specified data type to zero.
Definition: val.c:122
co_sub_get_flags
unsigned int co_sub_get_flags(const co_sub_t *sub)
Returns the object flags of a CANopen sub-object.
Definition: obj.c:785
structof
#define structof(ptr, type, member)
Obtains the address of a structure from the address of one of its members.
Definition: util.h:93
CO_OBJECT_RECORD
#define CO_OBJECT_RECORD
A multiple data field object where the data fields may be any combination of simple variables.
Definition: obj.h:54
rbnode::key
const void * key
A pointer to the key for this node.
Definition: rbtree.h:58
co_sub_get_up_ind
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_ACCESS_WRITE
#define CO_ACCESS_WRITE
The object can be written.
Definition: obj.h:60
CO_ACCESS_WO
#define CO_ACCESS_WO
Write-only access.
Definition: obj.h:72
co_sub_dn
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
rbtree_size
size_t rbtree_size(const struct rbtree *tree)
Returns the size (in number of nodes) of a red-black tree.
Definition: rbtree.h:252
co_sub_sizeof_val
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
CO_ACCESS_CONST
#define CO_ACCESS_CONST
Constant value.
Definition: obj.h:84
co_sub_destroy
void co_sub_destroy(co_sub_t *sub)
Destroys a CANopen sub-object.
Definition: obj.c:493
co_sub_addressof_max
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_SDO_AC_NO_READ
#define CO_SDO_AC_NO_READ
SDO abort code: Attempt to read a write only object.
Definition: sdo.h:87
co_obj_create
co_obj_t * co_obj_create(co_unsigned16_t idx)
Creates a CANopen object.
Definition: obj.c:106
co_sub_dn_ind
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_addressof_val
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
co_sub_get_upload_file
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
co_sdo_req_fini
void co_sdo_req_fini(struct co_sdo_req *req)
Finalizes a CANopen SDO upload/download request.
Definition: sdo.c:121
co_sdo_req_dn_file
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
stdlib.h
__co_sub
A CANopen sub-object.
Definition: obj.h:54
__co_sub::up_data
void * up_data
A pointer to user-specified data for up_ind.
Definition: obj.h:93
CO_OBJ_FLAGS_UPLOAD_FILE
#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
co_sub_set_pdo_mapping
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_ACCESS_RO
#define CO_ACCESS_RO
Read-only access.
Definition: obj.h:69
co_sub_get_type
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
CO_OBJECT_VAR
#define CO_OBJECT_VAR
A single value.
Definition: obj.h:42
co_sub_set_download_file
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_sub::subidx
co_unsigned8_t subidx
The object sub-index.
Definition: obj.h:60
rbnode_prev
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
__co_sub::flags
unsigned long flags
The object flags.
Definition: obj.h:84