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