Lely core libraries 1.9.2
dev.c
Go to the documentation of this file.
1
24#include "co.h"
25#include <lely/util/cmp.h>
26#include <lely/util/errnum.h>
27#ifndef LELY_NO_CO_DCF
28#include <lely/util/frbuf.h>
29#include <lely/util/fwbuf.h>
30#endif
31#include "obj.h"
32#include <lely/co/dev.h>
33
34#include <assert.h>
35#include <stdlib.h>
36
38struct __co_dev {
40 co_unsigned8_t netid;
42 co_unsigned8_t id;
44 struct rbtree tree;
46 char *name;
50 co_unsigned32_t vendor_id;
54 co_unsigned32_t product_code;
56 co_unsigned32_t revision;
60 unsigned baud : 10;
62 co_unsigned16_t rate;
64 int lss;
66 co_unsigned32_t dummy;
67};
68
69static void co_obj_set_id(
70 co_obj_t *obj, co_unsigned8_t new_id, co_unsigned8_t old_id);
71static void co_sub_set_id(
72 co_sub_t *sub, co_unsigned8_t new_id, co_unsigned8_t old_id);
73static void co_val_set_id(co_unsigned16_t type, void *val,
74 co_unsigned8_t new_id, co_unsigned8_t old_id);
75
76void *
77__co_dev_alloc(void)
78{
79 void *ptr = malloc(sizeof(struct __co_dev));
80 if (__unlikely(!ptr))
81 set_errc(errno2c(errno));
82 return ptr;
83}
84
85void
86__co_dev_free(void *ptr)
87{
88 free(ptr);
89}
90
91struct __co_dev *
92__co_dev_init(struct __co_dev *dev, co_unsigned8_t id)
93{
94 assert(dev);
95
96 dev->netid = 0;
97
98 if (__unlikely(!id || (id > CO_NUM_NODES && id != 0xff))) {
100 return NULL;
101 }
102 dev->id = id;
103
104 rbtree_init(&dev->tree, &uint16_cmp);
105
106 dev->name = NULL;
107
108 dev->vendor_name = NULL;
109 dev->vendor_id = 0;
110 dev->product_name = NULL;
111 dev->product_code = 0;
112 dev->revision = 0;
113 dev->order_code = NULL;
114
115 dev->baud = 0;
116 dev->rate = 0;
117
118 dev->lss = 0;
119
120 dev->dummy = 0;
121
122 return dev;
123}
124
125void
126__co_dev_fini(struct __co_dev *dev)
127{
128 assert(dev);
129
130 rbtree_foreach (&dev->tree, node)
131 co_obj_destroy(structof(node, co_obj_t, node));
132
133 free(dev->vendor_name);
134 free(dev->product_name);
135 free(dev->order_code);
136
137 free(dev->name);
138}
139
140co_dev_t *
141co_dev_create(co_unsigned8_t id)
142{
143 int errc = 0;
144
145 co_dev_t *dev = __co_dev_alloc();
146 if (__unlikely(!dev)) {
147 errc = get_errc();
148 goto error_alloc_dev;
149 }
150
151 if (__unlikely(!__co_dev_init(dev, id))) {
152 errc = get_errc();
153 goto error_init_dev;
154 }
155
156 return dev;
157
158error_init_dev:
159 __co_dev_free(dev);
160error_alloc_dev:
161 set_errc(errc);
162 return NULL;
163}
164
165void
167{
168 if (dev) {
169 __co_dev_fini(dev);
170 __co_dev_free(dev);
171 }
172}
173
174co_unsigned8_t
176{
177 assert(dev);
178
179 return dev->netid;
180}
181
182int
183co_dev_set_netid(co_dev_t *dev, co_unsigned8_t id)
184{
185 assert(dev);
186
187 if (__unlikely(id > CO_NUM_NETWORKS && id != 0xff)) {
189 return -1;
190 }
191
192 dev->netid = id;
193
194 return 0;
195}
196
197co_unsigned8_t
199{
200 assert(dev);
201
202 return dev->id;
203}
204
205int
206co_dev_set_id(co_dev_t *dev, co_unsigned8_t id)
207{
208 assert(dev);
209
210 if (__unlikely(!id || (id > CO_NUM_NODES && id != 0xff))) {
212 return -1;
213 }
214
215 rbtree_foreach (&dev->tree, node)
216 co_obj_set_id(structof(node, co_obj_t, node), id, dev->id);
217
218 dev->id = id;
219
220 return 0;
221}
222
223co_unsigned16_t
224co_dev_get_idx(const co_dev_t *dev, co_unsigned16_t maxidx,
225 co_unsigned16_t *idx)
226{
227 assert(dev);
228
229 if (!idx)
230 maxidx = 0;
231
232 if (maxidx) {
233 struct rbnode *node = rbtree_first(&dev->tree);
234 for (size_t i = 0; node && i < maxidx;
235 node = rbnode_next(node), i++)
236 idx[i] = co_obj_get_idx(structof(node, co_obj_t, node));
237 }
238
239 return (co_unsigned16_t)rbtree_size(&dev->tree);
240}
241
242int
244{
245 assert(dev);
246 assert(obj);
247
248 if (__unlikely(obj->dev && obj->dev != dev))
249 return -1;
250
251 if (__unlikely(obj->dev == dev))
252 return 0;
253
254 if (__unlikely(rbtree_find(&dev->tree, obj->node.key)))
255 return -1;
256
257 obj->dev = dev;
258 rbtree_insert(&obj->dev->tree, &obj->node);
259
260 return 0;
261}
262
263int
265{
266 assert(dev);
267 assert(obj);
268
269 if (__unlikely(obj->dev != dev))
270 return -1;
271
272 rbtree_remove(&obj->dev->tree, &obj->node);
273 obj->dev = NULL;
274
275 return 0;
276}
277
278co_obj_t *
279co_dev_find_obj(const co_dev_t *dev, co_unsigned16_t idx)
280{
281 assert(dev);
282
283 struct rbnode *node = rbtree_find(&dev->tree, &idx);
284 if (!node)
285 return NULL;
286 return structof(node, co_obj_t, node);
287}
288
289co_sub_t *
290co_dev_find_sub(const co_dev_t *dev, co_unsigned16_t idx, co_unsigned8_t subidx)
291{
292 co_obj_t *obj = co_dev_find_obj(dev, idx);
293 return __likely(obj) ? co_obj_find_sub(obj, subidx) : NULL;
294}
295
296const char *
298{
299 assert(dev);
300
301 return dev->name;
302}
303
304int
305co_dev_set_name(co_dev_t *dev, const char *name)
306{
307 assert(dev);
308
309 if (!name || !*name) {
310 free(dev->name);
311 dev->name = NULL;
312 return 0;
313 }
314
315 void *ptr = realloc(dev->name, strlen(name) + 1);
316 if (__unlikely(!ptr)) {
317 set_errc(errno2c(errno));
318 return -1;
319 }
320 dev->name = ptr;
321 strcpy(dev->name, name);
322
323 return 0;
324}
325
326const char *
328{
329 assert(dev);
330
331 return dev->vendor_name;
332}
333
334int
335co_dev_set_vendor_name(co_dev_t *dev, const char *vendor_name)
336{
337 assert(dev);
338
339 if (!vendor_name || !*vendor_name) {
340 free(dev->vendor_name);
341 dev->vendor_name = NULL;
342 return 0;
343 }
344
345 void *ptr = realloc(dev->vendor_name, strlen(vendor_name) + 1);
346 if (__unlikely(!ptr)) {
347 set_errc(errno2c(errno));
348 return -1;
349 }
350 dev->vendor_name = ptr;
351 strcpy(dev->vendor_name, vendor_name);
352
353 return 0;
354}
355
356co_unsigned32_t
358{
359 assert(dev);
360
361 return dev->vendor_id;
362}
363
364void
365co_dev_set_vendor_id(co_dev_t *dev, co_unsigned32_t vendor_id)
366{
367 assert(dev);
368
369 dev->vendor_id = vendor_id;
370}
371
372const char *
374{
375 assert(dev);
376
377 return dev->product_name;
378}
379
380int
381co_dev_set_product_name(co_dev_t *dev, const char *product_name)
382{
383 assert(dev);
384
385 if (!product_name || !*product_name) {
386 free(dev->product_name);
387 dev->product_name = NULL;
388 return 0;
389 }
390
391 void *ptr = realloc(dev->product_name, strlen(product_name) + 1);
392 if (__unlikely(!ptr)) {
393 set_errc(errno2c(errno));
394 return -1;
395 }
396 dev->product_name = ptr;
397 strcpy(dev->product_name, product_name);
398
399 return 0;
400}
401
402co_unsigned32_t
404{
405 assert(dev);
406
407 return dev->product_code;
408}
409
410void
411co_dev_set_product_code(co_dev_t *dev, co_unsigned32_t product_code)
412{
413 assert(dev);
414
415 dev->product_code = product_code;
416}
417
418co_unsigned32_t
420{
421 assert(dev);
422
423 return dev->revision;
424}
425
426void
427co_dev_set_revision(co_dev_t *dev, co_unsigned32_t revision)
428{
429 assert(dev);
430
431 dev->revision = revision;
432}
433
434const char *
436{
437 assert(dev);
438
439 return dev->order_code;
440}
441
442int
443co_dev_set_order_code(co_dev_t *dev, const char *order_code)
444{
445 assert(dev);
446
447 if (!order_code || !*order_code) {
448 free(dev->order_code);
449 dev->order_code = NULL;
450 return 0;
451 }
452
453 void *ptr = realloc(dev->order_code, strlen(order_code) + 1);
454 if (__unlikely(!ptr)) {
455 set_errc(errno2c(errno));
456 return -1;
457 }
458 dev->order_code = ptr;
459 strcpy(dev->order_code, order_code);
460
461 return 0;
462}
463
464unsigned int
466{
467 assert(dev);
468
469 return dev->baud;
470}
471
472void
473co_dev_set_baud(co_dev_t *dev, unsigned int baud)
474{
475 assert(dev);
476
477 dev->baud = baud;
478}
479
480co_unsigned16_t
482{
483 assert(dev);
484
485 return dev->rate;
486}
487
488void
489co_dev_set_rate(co_dev_t *dev, co_unsigned16_t rate)
490{
491 assert(dev);
492
493 dev->rate = rate;
494}
495
496int
498{
499 assert(dev);
500
501 return dev->lss;
502}
503
504void
506{
507 assert(dev);
508
509 dev->lss = !!lss;
510}
511
512co_unsigned32_t
514{
515 assert(dev);
516
517 return dev->dummy;
518}
519
520void
521co_dev_set_dummy(co_dev_t *dev, co_unsigned32_t dummy)
522{
523 assert(dev);
524
525 dev->dummy = dummy;
526}
527
528const void *
529co_dev_get_val(const co_dev_t *dev, co_unsigned16_t idx, co_unsigned8_t subidx)
530{
531 // clang-format off
532 co_sub_t *sub = __likely(dev)
533 ? co_dev_find_sub(dev, idx, subidx) : NULL;
534 // clang-format on
535 return co_sub_get_val(sub);
536}
537
538size_t
539co_dev_set_val(co_dev_t *dev, co_unsigned16_t idx, co_unsigned8_t subidx,
540 const void *ptr, size_t n)
541{
542 assert(dev);
543
544 co_sub_t *sub = co_dev_find_sub(dev, idx, subidx);
545 if (__unlikely(!sub)) {
547 return 0;
548 }
549
550 return co_sub_set_val(sub, ptr, n);
551}
552
553#define LELY_CO_DEFINE_TYPE(a, b, c, d) \
554 co_##b##_t co_dev_get_val_##c(const co_dev_t *dev, \
555 co_unsigned16_t idx, co_unsigned8_t subidx) \
556 { \
557 co_sub_t *sub = __likely(dev) \
558 ? co_dev_find_sub(dev, idx, subidx) \
559 : NULL; \
560 return co_sub_get_val_##c(sub); \
561 } \
562\
563 size_t co_dev_set_val_##c(co_dev_t *dev, co_unsigned16_t idx, \
564 co_unsigned8_t subidx, co_##b##_t c) \
565 { \
566 assert(dev); \
567\
568 co_sub_t *sub = co_dev_find_sub(dev, idx, subidx); \
569 if (__unlikely(!sub)) { \
570 set_errnum(ERRNUM_INVAL); \
571 return 0; \
572 } \
573\
574 return co_sub_set_val_##c(sub, c); \
575 }
576#include <lely/co/def/basic.def>
577#undef LELY_CO_DEFINE_TYPE
578
579size_t
580co_dev_read_sub(co_dev_t *dev, co_unsigned16_t *pidx, co_unsigned8_t *psubidx,
581 const uint8_t *begin, const uint8_t *end)
582{
583 if (__unlikely(!begin || !end || end - begin < 2 + 1 + 4))
584 return 0;
585
586 // Read the object index.
587 co_unsigned16_t idx;
588 // clang-format off
589 if (__unlikely(co_val_read(CO_DEFTYPE_UNSIGNED16, &idx, begin, end)
590 != 2))
591 // clang-format on
592 return 0;
593 begin += 2;
594 // Read the object sub-index.
595 co_unsigned8_t subidx;
596 // clang-format off
597 if (__unlikely(co_val_read(CO_DEFTYPE_UNSIGNED8, &subidx, begin, end)
598 != 1))
599 // clang-format on
600 return 0;
601 begin += 1;
602 // Read the value size (in bytes).
603 co_unsigned32_t size;
604 // clang-format off
605 if (__unlikely(co_val_read(CO_DEFTYPE_UNSIGNED32, &size, begin, end)
606 != 4))
607 // clang-format on
608 return 0;
609 begin += 4;
610
611 if (__unlikely(end - begin < (ptrdiff_t)size))
612 return 0;
613
614 // Read the value into the sub-object, if it exists.
615 co_sub_t *sub = co_dev_find_sub(dev, idx, subidx);
616 if (sub) {
617 co_unsigned16_t type = co_sub_get_type(sub);
618 union co_val val;
619 co_val_init(type, &val);
620 // clang-format off
621 if (__likely(co_val_read(type, &val, begin, begin + size)
622 == size))
623 // clang-format on
624 co_sub_set_val(sub, co_val_addressof(type, &val),
625 co_val_sizeof(type, &val));
626 co_val_fini(type, &val);
627 }
628
629 if (pidx)
630 *pidx = idx;
631 if (psubidx)
632 *psubidx = subidx;
633
634 return 2 + 1 + 4 + size;
635}
636
637size_t
638co_dev_write_sub(const co_dev_t *dev, co_unsigned16_t idx,
639 co_unsigned8_t subidx, uint8_t *begin, uint8_t *end)
640{
641 co_sub_t *sub = co_dev_find_sub(dev, idx, subidx);
642 if (__unlikely(!sub))
643 return 0;
644 co_unsigned16_t type = co_sub_get_type(sub);
645 const void *val = co_sub_get_val(sub);
646
647 co_unsigned32_t size = co_val_write(type, val, NULL, NULL);
648 if (__unlikely(!size && co_val_sizeof(type, val)))
649 return 0;
650
651 if (begin && (!end || end - begin >= (ptrdiff_t)(2 + 1 + 4 + size))) {
652 // Write the object index.
653 // clang-format off
655 end) != 2))
656 // clang-format on
657 return 0;
658 begin += 2;
659 // Write the object sub-index.
660 // clang-format off
662 begin, end) != 1))
663 // clang-format on
664 return 0;
665 begin += 1;
666 // Write the value size (in bytes).
667 // clang-format off
669 end) != 4))
670 // clang-format on
671 return 0;
672 begin += 4;
673 // Write the value.
674 if (__unlikely(co_val_write(type, val, begin, end) != size))
675 return 0;
676 }
677
678 return 2 + 1 + 4 + size;
679}
680
681int
682co_dev_read_dcf(co_dev_t *dev, co_unsigned16_t *pmin, co_unsigned16_t *pmax,
683 void *const *ptr)
684{
685 assert(dev);
686 assert(ptr);
687
688 co_unsigned16_t min = CO_UNSIGNED16_MAX;
689 co_unsigned16_t max = CO_UNSIGNED16_MIN;
690
691 size_t size = co_val_sizeof(CO_DEFTYPE_DOMAIN, ptr);
692 const uint8_t *begin = *ptr;
693 const uint8_t *end = begin + size;
694
695 // Read the total number of sub-indices.
696 co_unsigned32_t n;
697 size = co_val_read(CO_DEFTYPE_UNSIGNED32, &n, begin, end);
698 if (__unlikely(size != 4))
699 return 0;
700 begin += size;
701
702 for (size_t i = 0; i < n; i++) {
703 // Read the value of the sub-object.
704 co_unsigned16_t idx;
705 size = co_dev_read_sub(dev, &idx, NULL, begin, end);
706 if (__unlikely(!size))
707 return 0;
708 begin += size;
709
710 // Keep track of the index range.
711 min = MIN(min, idx);
712 max = MAX(max, idx);
713 }
714
715 if (pmin)
716 *pmin = min;
717 if (pmax)
718 *pmax = max;
719
720 return 0;
721}
722
723#ifndef LELY_NO_CO_DCF
724int
725co_dev_read_dcf_file(co_dev_t *dev, co_unsigned16_t *pmin,
726 co_unsigned16_t *pmax, const char *filename)
727{
728 int errc = 0;
729
730 frbuf_t *buf = frbuf_create(filename);
731 if (__unlikely(!buf)) {
732 errc = get_errc();
733 goto error_create_buf;
734 }
735
736 int64_t size = frbuf_get_size(buf);
737 if (size == -1) {
738 errc = get_errc();
739 goto error_get_size;
740 }
741
742 void *dom = NULL;
743 if (__unlikely(co_val_init_dom(&dom, NULL, size) == -1)) {
744 errc = get_errc();
745 goto error_init_dom;
746 }
747
748 if (__unlikely(frbuf_read(buf, dom, size) != size)) {
749 errc = get_errc();
750 goto error_read;
751 }
752
753 if (co_dev_read_dcf(dev, pmin, pmax, &dom) == -1) {
754 errc = get_errc();
755 goto error_read_dcf;
756 }
757
759 frbuf_destroy(buf);
760
761 return 0;
762
763error_read_dcf:
764error_read:
766error_init_dom:
767error_get_size:
768 frbuf_destroy(buf);
769error_create_buf:
770 set_errc(errc);
771 return -1;
772}
773#endif
774
775int
776co_dev_write_dcf(const co_dev_t *dev, co_unsigned16_t min, co_unsigned16_t max,
777 void **ptr)
778{
779 assert(dev);
780 assert(ptr);
781
782 int errc = 0;
783
784 // Get the list of object indices.
785 co_unsigned16_t maxidx = co_dev_get_idx(dev, 0, NULL);
786 co_unsigned16_t *idx = calloc(maxidx, sizeof(co_unsigned16_t));
787 if (__unlikely(!idx)) {
788 errc = errno2c(errno);
789 goto error_malloc_idx;
790 }
791 maxidx = co_dev_get_idx(dev, maxidx, idx);
792
793 size_t size = 4;
794 co_unsigned32_t n = 0;
795
796 for (size_t i = 0; i < maxidx; i++) {
797 if (idx[i] < min || idx[i] > max)
798 continue;
799
800 // Get the list of object sub-indices.
801 co_obj_t *obj = co_dev_find_obj(dev, idx[i]);
802 co_unsigned8_t subidx[0xff];
803 co_unsigned8_t maxsubidx = co_obj_get_subidx(obj, 0xff, subidx);
804
805 // Count the number of sub-objects and compute the size (in
806 // bytes).
807 for (size_t j = 0; j < maxsubidx; j++, n++)
808 size += co_dev_write_sub(
809 dev, idx[i], subidx[j], NULL, NULL);
810 }
811
812 // Create a DOMAIN for the concise DCF.
813 if (__unlikely(co_val_init_dom(ptr, NULL, size) == -1)) {
814 errc = get_errc();
815 goto error_init_dom;
816 }
817 uint8_t *begin = *ptr;
818 uint8_t *end = begin + size;
819
820 // Write the total number of sub-indices.
821 begin += co_val_write(CO_DEFTYPE_UNSIGNED32, &n, begin, end);
822
823 for (size_t i = 0; i < maxidx; i++) {
824 if (idx[i] < min || idx[i] > max)
825 continue;
826
827 // Get the list of object sub-indices.
828 co_obj_t *obj = co_dev_find_obj(dev, idx[i]);
829 co_unsigned8_t subidx[0xff];
830 co_unsigned8_t maxsubidx = co_obj_get_subidx(obj, 0xff, subidx);
831
832 // Write the value of the sub-object.
833 for (size_t j = 0; j < maxsubidx; j++, n++)
834 begin += co_dev_write_sub(
835 dev, idx[i], subidx[j], begin, end);
836 }
837
838 free(idx);
839
840 return 0;
841
842error_init_dom:
843 free(idx);
844error_malloc_idx:
845 set_errc(errc);
846 return -1;
847}
848
849#ifndef LELY_NO_CO_DCF
850int
851co_dev_write_dcf_file(const co_dev_t *dev, co_unsigned16_t min,
852 co_unsigned16_t max, const char *filename)
853{
854 int errc = 0;
855
856 void *dom = NULL;
857 if (__unlikely(co_dev_write_dcf(dev, min, max, &dom) == -1)) {
858 errc = get_errc();
859 goto error_write_dcf;
860 }
861
862 fwbuf_t *buf = fwbuf_create(filename);
863 if (__unlikely(!buf)) {
864 errc = get_errc();
865 goto error_create_buf;
866 }
867
868 size_t nbyte = co_val_sizeof(CO_DEFTYPE_DOMAIN, &dom);
869 if (__unlikely(fwbuf_write(buf, dom, nbyte) != (ssize_t)nbyte)) {
870 errc = get_errc();
871 goto error_write;
872 }
873
874 if (__unlikely(fwbuf_commit(buf) == -1)) {
875 errc = get_errc();
876 goto error_commit;
877 }
878
879 fwbuf_destroy(buf);
881
882 return 0;
883
884error_commit:
885error_write:
886 fwbuf_destroy(buf);
887error_create_buf:
889error_write_dcf:
890 set_errc(errc);
891 return -1;
892}
893#endif
894
895static void
896co_obj_set_id(co_obj_t *obj, co_unsigned8_t new_id, co_unsigned8_t old_id)
897{
898 assert(obj);
899
900 rbtree_foreach (&obj->tree, node)
901 co_sub_set_id(structof(node, co_sub_t, node), new_id, old_id);
902}
903
904static void
905co_sub_set_id(co_sub_t *sub, co_unsigned8_t new_id, co_unsigned8_t old_id)
906{
907 assert(sub);
908
909 unsigned int flags = co_sub_get_flags(sub);
910 co_unsigned16_t type = co_sub_get_type(sub);
911#ifndef LELY_NO_CO_OBJ_LIMITS
912 if (flags & CO_OBJ_FLAGS_MIN_NODEID)
913 co_val_set_id(type, &sub->min, new_id, old_id);
914 if (flags & CO_OBJ_FLAGS_MAX_NODEID)
915 co_val_set_id(type, &sub->max, new_id, old_id);
916#endif
917 if (flags & CO_OBJ_FLAGS_DEF_NODEID)
918 co_val_set_id(type, &sub->def, new_id, old_id);
919 if (flags & CO_OBJ_FLAGS_VAL_NODEID)
920 co_val_set_id(type, sub->val, new_id, old_id);
921}
922
923static void
924co_val_set_id(co_unsigned16_t type, void *val, co_unsigned8_t new_id,
925 co_unsigned8_t old_id)
926{
927 assert(val);
928
929 union co_val *u = val;
930 switch (type) {
931#define LELY_CO_DEFINE_TYPE(a, b, c, d) \
932 case CO_DEFTYPE_##a: \
933 u->c += new_id - old_id; \
934 break;
935#include <lely/co/def/basic.def>
936#undef LELY_CO_DEFINE_TYPE
937 }
938}
This header file is part of the utilities library; it contains the comparison function definitions.
co_obj_t * co_dev_find_obj(const co_dev_t *dev, co_unsigned16_t idx)
Finds an object in the object dictionary of a CANopen device.
Definition: dev.c:279
co_unsigned16_t co_dev_get_idx(const co_dev_t *dev, co_unsigned16_t maxidx, co_unsigned16_t *idx)
Retrieves a list of object indices in the object dictionary of a CANopen device.
Definition: dev.c:224
int co_dev_read_dcf(co_dev_t *dev, co_unsigned16_t *pmin, co_unsigned16_t *pmax, void *const *ptr)
Reads the values of a range of objects from a memory buffer, in the concise DCF format,...
Definition: dev.c:682
co_unsigned8_t co_dev_get_id(const co_dev_t *dev)
Returns the node-ID of a CANopen device.
Definition: dev.c:198
int co_dev_set_vendor_name(co_dev_t *dev, const char *vendor_name)
Sets the vendor name of a CANopen device.
Definition: dev.c:335
void co_dev_set_product_code(co_dev_t *dev, co_unsigned32_t product_code)
Sets the product code of a CANopen device.
Definition: dev.c:411
void co_dev_set_dummy(co_dev_t *dev, co_unsigned32_t dummy)
Sets the data types supported by a CANopen device for mapping dummy entries in PDOs.
Definition: dev.c:521
int co_dev_insert_obj(co_dev_t *dev, co_obj_t *obj)
Inserts an object into the object dictionary of a CANopen device.
Definition: dev.c:243
const char * co_dev_get_product_name(const co_dev_t *dev)
Returns a pointer to the product name of a CANopen device.
Definition: dev.c:373
void co_dev_set_vendor_id(co_dev_t *dev, co_unsigned32_t vendor_id)
Sets the vendor ID of a CANopen device.
Definition: dev.c:365
size_t co_dev_read_sub(co_dev_t *dev, co_unsigned16_t *pidx, co_unsigned8_t *psubidx, const uint8_t *begin, const uint8_t *end)
Reads a value from a memory buffer, in the concise DCF format, and stores it in a sub-object in the o...
Definition: dev.c:580
int co_dev_set_id(co_dev_t *dev, co_unsigned8_t id)
Sets the node-ID of a CANopen device.
Definition: dev.c:206
int co_dev_set_netid(co_dev_t *dev, co_unsigned8_t id)
Sets the network-ID of a CANopen device.
Definition: dev.c:183
const char * co_dev_get_vendor_name(const co_dev_t *dev)
Returns a pointer to the vendor name of a CANopen device.
Definition: dev.c:327
void co_dev_set_revision(co_dev_t *dev, co_unsigned32_t revision)
Sets the revision number of a CANopen device.
Definition: dev.c:427
co_sub_t * co_dev_find_sub(const co_dev_t *dev, co_unsigned16_t idx, co_unsigned8_t subidx)
Finds a sub-object in the object dictionary of a CANopen device.
Definition: dev.c:290
co_unsigned16_t co_dev_get_rate(const co_dev_t *dev)
Returns the (pending) baudrate of a CANopen device (in kbit/s).
Definition: dev.c:481
size_t co_dev_write_sub(const co_dev_t *dev, co_unsigned16_t idx, co_unsigned8_t subidx, uint8_t *begin, uint8_t *end)
Loads the value of a sub-object from the object dictionary of a CANopen device, and writes it to a me...
Definition: dev.c:638
int co_dev_write_dcf(const co_dev_t *dev, co_unsigned16_t min, co_unsigned16_t max, void **ptr)
Loads the values of a range of objects in the object dictionary of a CANopen device,...
Definition: dev.c:776
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
int co_dev_get_lss(const co_dev_t *dev)
Returns 1 if LSS is supported and 0 if not.
Definition: dev.c:497
co_unsigned8_t co_dev_get_netid(const co_dev_t *dev)
Returns the network-ID of a CANopen device.
Definition: dev.c:175
co_unsigned32_t co_dev_get_vendor_id(const co_dev_t *dev)
Returns the vendor ID of a CANopen device.
Definition: dev.c:357
void co_dev_set_lss(co_dev_t *dev, int lss)
Sets the LSS support flag.
Definition: dev.c:505
int co_dev_set_order_code(co_dev_t *dev, const char *order_code)
Sets the order code of a CANopen device.
Definition: dev.c:443
co_unsigned32_t co_dev_get_dummy(const co_dev_t *dev)
Returns the data types supported by a CANopen device for mapping dummy entries in PDOs (one bit for e...
Definition: dev.c:513
const char * co_dev_get_name(const co_dev_t *dev)
Returns the name of a CANopen device.
Definition: dev.c:297
int co_dev_write_dcf_file(const co_dev_t *dev, co_unsigned16_t min, co_unsigned16_t max, const char *filename)
Loads the values of a range of objects in the object dictionary of a CANopen device,...
Definition: dev.c:851
void co_dev_destroy(co_dev_t *dev)
Destroys a CANopen device, including all objects in its object dictionary.
Definition: dev.c:166
void co_dev_set_rate(co_dev_t *dev, co_unsigned16_t rate)
Sets the (pending) baudrate of a CANopen device.
Definition: dev.c:489
size_t co_dev_set_val(co_dev_t *dev, co_unsigned16_t idx, co_unsigned8_t subidx, const void *ptr, size_t n)
Sets the current value of a CANopen sub-object.
Definition: dev.c:539
unsigned int co_dev_get_baud(const co_dev_t *dev)
Returns the supported bit rates of a CANopen device (any combination of CO_BAUD_1000,...
Definition: dev.c:465
co_unsigned32_t co_dev_get_product_code(const co_dev_t *dev)
Returns the product code of a CANopen device.
Definition: dev.c:403
const void * co_dev_get_val(const co_dev_t *dev, co_unsigned16_t idx, co_unsigned8_t subidx)
Returns a pointer to the current value of a CANopen sub-object.
Definition: dev.c:529
int co_dev_set_product_name(co_dev_t *dev, const char *product_name)
Sets the product name of a CANopen device.
Definition: dev.c:381
void co_dev_set_baud(co_dev_t *dev, unsigned int baud)
Sets the supported bit rates of a CANopen device.
Definition: dev.c:473
int co_dev_read_dcf_file(co_dev_t *dev, co_unsigned16_t *pmin, co_unsigned16_t *pmax, const char *filename)
Reads the values of a range of objects from a file, in the concise DCF format, and stores them in the...
Definition: dev.c:725
co_dev_t * co_dev_create(co_unsigned8_t id)
Creates a new CANopen device.
Definition: dev.c:141
const char * co_dev_get_order_code(const co_dev_t *dev)
Returns a pointer to the order code of a CANopen device.
Definition: dev.c:435
int co_dev_set_name(co_dev_t *dev, const char *name)
Sets the name of a CANopen device.
Definition: dev.c:305
co_unsigned32_t co_dev_get_revision(const co_dev_t *dev)
Returns the revision number of a CANopen device.
Definition: dev.c:419
This header file is part of the CANopen library; it contains the device description declarations.
#define CO_NUM_NODES
The maximum number of nodes in a CANopen network.
Definition: dev.h:56
#define CO_NUM_NETWORKS
The maximum number of CANopen networks.
Definition: dev.h:53
This header file is part of the utilities library; it contains the native and platform-independent er...
@ ERRNUM_INVAL
Invalid argument.
Definition: errnum.h:129
int get_errc(void)
Returns the last (thread-specific) native error code set by a system call or library function.
Definition: errnum.c:947
void set_errc(int errc)
Sets the current (thread-specific) native error code to errc.
Definition: errnum.c:957
int errno2c(int errnum)
Transforms a standard C error number to a native error code.
Definition: errnum.c:43
void set_errnum(errnum_t errnum)
Sets the current (thread-specific) platform-independent error number to errnum.
Definition: errnum.h:375
#define __unlikely(x)
Indicates to the compiler that the expression is most-likely false.
Definition: features.h:286
#define __likely(x)
Indicates to the compiler that the expression is most-likely true.
Definition: features.h:273
This header file is part of the utilities library; it contains the read file buffer declarations.
intmax_t frbuf_get_size(frbuf_t *buf)
Returns the size (in bytes) of the a read file buffer, or -1 on error.
Definition: frbuf.c:167
void frbuf_destroy(frbuf_t *buf)
Destroys a read file buffer.
Definition: frbuf.c:158
frbuf_t * frbuf_create(const char *filename)
Creates a new read file buffer.
Definition: frbuf.c:133
ssize_t frbuf_read(frbuf_t *buf, void *ptr, size_t size)
Reads bytes from the current position in a read file buffer.
Definition: frbuf.c:270
This header file is part of the utilities library; it contains the (atomic) write file buffer declara...
ssize_t fwbuf_write(fwbuf_t *buf, const void *ptr, size_t size)
Writes bytes to the current position in a write file buffer.
Definition: fwbuf.c:485
void fwbuf_destroy(fwbuf_t *buf)
Destroys a write file buffer.
Definition: fwbuf.c:326
int fwbuf_commit(fwbuf_t *buf)
Commits all changes to a write file buffer to disk if all previous file operations were successful,...
Definition: fwbuf.c:974
fwbuf_t * fwbuf_create(const char *filename)
Creates a new (atomic) write file buffer.
Definition: fwbuf.c:301
co_unsigned8_t co_obj_get_subidx(const co_obj_t *obj, co_unsigned8_t maxsubidx, co_unsigned8_t *subidx)
Retrieves a list of sub-indices in a CANopen object.
Definition: obj.c:144
#define CO_OBJ_FLAGS_MAX_NODEID
The upper limit of the object value is of the form $NODEID { "+" number }.
Definition: obj.h:108
co_unsigned16_t co_obj_get_idx(const co_obj_t *obj)
Returns the index of a CANopen object.
Definition: obj.c:136
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
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
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_OBJ_FLAGS_DEF_NODEID
The default object value is of the form $NODEID { "+" number }.
Definition: obj.h:111
unsigned int co_sub_get_flags(const co_sub_t *sub)
Returns the object flags of a CANopen sub-object.
Definition: obj.c:722
#define CO_OBJ_FLAGS_MIN_NODEID
The lower limit of the object value is of the form $NODEID { "+" number }.
Definition: obj.h:105
#define CO_OBJ_FLAGS_VAL_NODEID
The current object value is of the form $NODEID { "+" number }.
Definition: obj.h:114
void co_obj_destroy(co_obj_t *obj)
Destroys a CANopen object, including its sub-objects.
Definition: obj.c:118
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
#define structof(ptr, type, member)
Obtains the address of a structure from the address of one of its members.
Definition: util.h:93
#define MIN(a, b)
Returns the minimum of a and b.
Definition: util.h:57
#define MAX(a, b)
Returns the maximum of a and b.
Definition: util.h:65
void rbtree_insert(struct rbtree *tree, struct rbnode *node)
Inserts a node into a red-black tree.
Definition: rbtree.c:108
struct rbnode * rbtree_find(const struct rbtree *tree, const void *key)
Finds a node in a red-black tree.
Definition: rbtree.c:308
struct rbnode * rbtree_first(const struct rbtree *tree)
Returns a pointer to the first (leftmost) node in a red-black tree.
Definition: rbtree.c:324
struct rbnode * rbnode_next(const struct rbnode *node)
Returns a pointer to the next (in-order) node in a red-black tree with respect to node.
Definition: rbtree.c:91
void rbtree_init(struct rbtree *tree, rbtree_cmp_t *cmp)
Initializes a red-black tree.
Definition: rbtree.h:238
size_t rbtree_size(const struct rbtree *tree)
Returns the size (in number of nodes) of a red-black tree.
Definition: rbtree.h:252
void rbtree_remove(struct rbtree *tree, struct rbnode *node)
Removes a node from a red-black tree.
Definition: rbtree.c:188
#define rbtree_foreach(tree, node)
Iterates over each node in a red-black tree in ascending order.
Definition: rbtree.h:226
This is the internal header file of the CANopen library.
This is the internal header file of the object dictionary.
This header file is part of the C11 and POSIX compatibility library; it includes <stdlib....
A CANopen device.
Definition: dev.c:38
struct rbtree tree
The tree containing the object dictionary.
Definition: dev.c:44
co_unsigned32_t product_code
The product code.
Definition: dev.c:54
char * product_name
A pointer to the product name.
Definition: dev.c:52
co_unsigned16_t rate
The (pending) baudrate (in kbit/s).
Definition: dev.c:62
char * vendor_name
A pointer to the vendor name.
Definition: dev.c:48
char * order_code
A pointer to the order code.
Definition: dev.c:58
co_unsigned8_t netid
The network-ID.
Definition: dev.c:40
co_unsigned8_t id
The node-ID.
Definition: dev.c:42
unsigned baud
The supported bit rates.
Definition: dev.c:60
int lss
A flag specifying whether LSS is supported (1) or not (0).
Definition: dev.c:64
co_unsigned32_t vendor_id
The vendor ID.
Definition: dev.c:50
co_unsigned32_t revision
The revision number.
Definition: dev.c:56
co_unsigned32_t dummy
The data types supported for mapping dummy entries in PDOs.
Definition: dev.c:66
char * name
A pointer to the name of the device.
Definition: dev.c:46
A CANopen object.
Definition: obj.h:32
struct rbtree tree
The tree containing all the sub-objects.
Definition: obj.h:46
struct rbnode node
The node of this object in the tree of objects.
Definition: obj.h:34
co_dev_t * dev
A pointer to the CANopen device containing this object.
Definition: obj.h:36
A CANopen sub-object.
Definition: obj.h:54
union co_val def
The default value.
Definition: obj.h:74
union co_val min
The lower limit of the object value.
Definition: obj.h:69
union co_val max
The upper limit of the object value.
Definition: obj.h:71
void * val
A pointer to the sub-object value.
Definition: obj.h:76
An read file buffer struct.
Definition: frbuf.c:49
An (atomic) write file buffer struct.
Definition: fwbuf.c:56
A node in a red-black tree.
Definition: rbtree.h:52
const void * key
A pointer to the key for this node.
Definition: rbtree.h:58
A red-black tree.
Definition: rbtree.h:90
#define CO_DEFTYPE_UNSIGNED16
The data type (and object index) of a 16-bit unsigned integer.
Definition: type.h:47
#define CO_DEFTYPE_DOMAIN
The data type (and object index) of an arbitrary large block of data.
Definition: type.h:77
#define CO_DEFTYPE_UNSIGNED8
The data type (and object index) of an 8-bit unsigned integer.
Definition: type.h:44
#define CO_DEFTYPE_UNSIGNED32
The data type (and object index) of a 32-bit unsigned integer.
Definition: type.h:50
ptrdiff_t ssize_t
Used for a count of bytes or an error indication.
Definition: types.h:43
A union of the CANopen static data types.
Definition: val.h:163
size_t co_val_write(co_unsigned16_t type, const void *val, uint8_t *begin, uint8_t *end)
Writes a value of the specified data type to a memory buffer.
Definition: val.c:718
int co_val_init(co_unsigned16_t type, void *val)
Initializes a value of the specified data type to zero.
Definition: val.c:120
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
#define CO_UNSIGNED16_MIN
The minimum value of a 16-bit unsigned integer.
Definition: val.h:61
int co_val_init_dom(void **val, const void *dom, size_t n)
Initializes an arbitrary large block of data (CO_DEFTYPE_DOMAIN).
Definition: val.c:254
size_t co_val_read(co_unsigned16_t type, void *val, const uint8_t *begin, const uint8_t *end)
Reads a value of the specified data type from a memory buffer.
Definition: val.c:470
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
void co_val_fini(co_unsigned16_t type, void *val)
Finalizes a value of the specified data type.
Definition: val.c:273
#define CO_UNSIGNED16_MAX
The maximum value of a 16-bit unsigned integer.
Definition: val.h:64