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 
38 struct __co_dev {
40  co_unsigned8_t netid;
42  co_unsigned8_t id;
44  struct rbtree tree;
46  char *name;
48  char *vendor_name;
50  co_unsigned32_t vendor_id;
52  char *product_name;
54  co_unsigned32_t product_code;
56  co_unsigned32_t revision;
58  char *order_code;
60  unsigned baud : 10;
62  co_unsigned16_t rate;
64  int lss;
66  co_unsigned32_t dummy;
67 };
68 
69 static void co_obj_set_id(
70  co_obj_t *obj, co_unsigned8_t new_id, co_unsigned8_t old_id);
71 static void co_sub_set_id(
72  co_sub_t *sub, co_unsigned8_t new_id, co_unsigned8_t old_id);
73 static void co_val_set_id(co_unsigned16_t type, void *val,
74  co_unsigned8_t new_id, co_unsigned8_t old_id);
75 
76 void *
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 
85 void
86 __co_dev_free(void *ptr)
87 {
88  free(ptr);
89 }
90 
91 struct __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 
125 void
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 
140 co_dev_t *
141 co_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 
158 error_init_dev:
159  __co_dev_free(dev);
160 error_alloc_dev:
161  set_errc(errc);
162  return NULL;
163 }
164 
165 void
167 {
168  if (dev) {
169  __co_dev_fini(dev);
170  __co_dev_free(dev);
171  }
172 }
173 
174 co_unsigned8_t
176 {
177  assert(dev);
178 
179  return dev->netid;
180 }
181 
182 int
183 co_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 
197 co_unsigned8_t
199 {
200  assert(dev);
201 
202  return dev->id;
203 }
204 
205 int
206 co_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 
223 co_unsigned16_t
224 co_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 
242 int
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 
263 int
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 
278 co_obj_t *
279 co_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 
289 co_sub_t *
290 co_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 
296 const char *
298 {
299  assert(dev);
300 
301  return dev->name;
302 }
303 
304 int
305 co_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 
326 const char *
328 {
329  assert(dev);
330 
331  return dev->vendor_name;
332 }
333 
334 int
335 co_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 
356 co_unsigned32_t
358 {
359  assert(dev);
360 
361  return dev->vendor_id;
362 }
363 
364 void
365 co_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 
372 const char *
374 {
375  assert(dev);
376 
377  return dev->product_name;
378 }
379 
380 int
381 co_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 
402 co_unsigned32_t
404 {
405  assert(dev);
406 
407  return dev->product_code;
408 }
409 
410 void
411 co_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 
418 co_unsigned32_t
420 {
421  assert(dev);
422 
423  return dev->revision;
424 }
425 
426 void
427 co_dev_set_revision(co_dev_t *dev, co_unsigned32_t revision)
428 {
429  assert(dev);
430 
431  dev->revision = revision;
432 }
433 
434 const char *
436 {
437  assert(dev);
438 
439  return dev->order_code;
440 }
441 
442 int
443 co_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 
464 unsigned int
466 {
467  assert(dev);
468 
469  return dev->baud;
470 }
471 
472 void
473 co_dev_set_baud(co_dev_t *dev, unsigned int baud)
474 {
475  assert(dev);
476 
477  dev->baud = baud;
478 }
479 
480 co_unsigned16_t
482 {
483  assert(dev);
484 
485  return dev->rate;
486 }
487 
488 void
489 co_dev_set_rate(co_dev_t *dev, co_unsigned16_t rate)
490 {
491  assert(dev);
492 
493  dev->rate = rate;
494 }
495 
496 int
498 {
499  assert(dev);
500 
501  return dev->lss;
502 }
503 
504 void
505 co_dev_set_lss(co_dev_t *dev, int lss)
506 {
507  assert(dev);
508 
509  dev->lss = !!lss;
510 }
511 
512 co_unsigned32_t
514 {
515  assert(dev);
516 
517  return dev->dummy;
518 }
519 
520 void
521 co_dev_set_dummy(co_dev_t *dev, co_unsigned32_t dummy)
522 {
523  assert(dev);
524 
525  dev->dummy = dummy;
526 }
527 
528 const void *
529 co_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 
538 size_t
539 co_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 
579 size_t
580 co_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 
637 size_t
638 co_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 
681 int
682 co_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
724 int
725 co_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 
763 error_read_dcf:
764 error_read:
766 error_init_dom:
767 error_get_size:
768  frbuf_destroy(buf);
769 error_create_buf:
770  set_errc(errc);
771  return -1;
772 }
773 #endif
774 
775 int
776 co_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 
842 error_init_dom:
843  free(idx);
844 error_malloc_idx:
845  set_errc(errc);
846  return -1;
847 }
848 
849 #ifndef LELY_NO_CO_DCF
850 int
851 co_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 
884 error_commit:
885 error_write:
886  fwbuf_destroy(buf);
887 error_create_buf:
889 error_write_dcf:
890  set_errc(errc);
891  return -1;
892 }
893 #endif
894 
895 static void
896 co_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 
904 static void
905 co_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 
923 static void
924 co_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 }
int lss
A flag specifying whether LSS is supported (1) or not (0).
Definition: dev.c:64
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
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
#define CO_NUM_NETWORKS
The maximum number of CANopen networks.
Definition: dev.h:53
const void * key
A pointer to the key for this node.
Definition: rbtree.h:58
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
A CANopen sub-object.
Definition: obj.h:54
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
#define CO_UNSIGNED16_MAX
The maximum value of a 16-bit unsigned integer.
Definition: val.h:64
#define CO_DEFTYPE_DOMAIN
The data type (and object index) of an arbitrary large block of data.
Definition: type.h:77
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
char * order_code
A pointer to the order code.
Definition: dev.c:58
This header file is part of the utilities library; it contains the comparison function definitions...
co_unsigned32_t revision
The revision number.
Definition: dev.c:56
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 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
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
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
A union of the CANopen static data types.
Definition: val.h:163
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
#define MIN(a, b)
Returns the minimum of a and b.
Definition: util.h:57
void co_dev_set_lss(co_dev_t *dev, int lss)
Sets the LSS support flag.
Definition: dev.c:505
#define CO_UNSIGNED16_MIN
The minimum value of a 16-bit unsigned integer.
Definition: val.h:61
union co_val max
The upper limit of the object value.
Definition: obj.h:71
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 is the internal header file of the object dictionary.
unsigned baud
The supported bit rates.
Definition: dev.c:60
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
char * name
A pointer to the name of the device.
Definition: dev.c:46
struct rbtree tree
The tree containing the object dictionary.
Definition: dev.c:44
void set_errc(int errc)
Sets the current (thread-specific) native error code to errc.
Definition: errnum.c:957
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
union co_val def
The default value.
Definition: obj.h:74
#define CO_DEFTYPE_UNSIGNED32
The data type (and object index) of a 32-bit unsigned integer.
Definition: type.h:50
co_unsigned8_t netid
The network-ID.
Definition: dev.c:40
co_unsigned32_t vendor_id
The vendor ID.
Definition: dev.c:50
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 rbtree_foreach(tree, node)
Iterates over each node in a red-black tree in ascending order.
Definition: rbtree.h:226
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
void fwbuf_destroy(fwbuf_t *buf)
Destroys a write file buffer.
Definition: fwbuf.c:326
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, CO_BAUD_800, CO_BAUD_500, CO_BAUD_250, CO_BAUD_125, CO_BAUD_50, CO_BAUD_20, CO_BAUD_10 and CO_BAUD_AUTO).
Definition: dev.c:465
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 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
A red-black tree.
Definition: rbtree.h:90
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
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
struct rbnode node
The node of this object in the tree of objects.
Definition: obj.h:34
#define CO_DEFTYPE_UNSIGNED16
The data type (and object index) of a 16-bit unsigned integer.
Definition: type.h:47
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
frbuf_t * frbuf_create(const char *filename)
Creates a new read file buffer.
Definition: frbuf.c:133
const char * co_dev_get_name(const co_dev_t *dev)
Returns the name of a CANopen device.
Definition: dev.c:297
This is the internal header file of the CANopen library.
fwbuf_t * fwbuf_create(const char *filename)
Creates a new (atomic) write file buffer.
Definition: fwbuf.c:301
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, and writes them to a memory buffer, in the concise DCF format.
Definition: dev.c:776
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
void co_dev_destroy(co_dev_t *dev)
Destroys a CANopen device, including all objects in its object dictionary.
Definition: dev.c:166
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
char * product_name
A pointer to the product name.
Definition: dev.c:52
int co_dev_get_lss(const co_dev_t *dev)
Returns 1 if LSS is supported and 0 if not.
Definition: dev.c:497
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 get_errc(void)
Returns the last (thread-specific) native error code set by a system call or library function...
Definition: errnum.c:947
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
#define MAX(a, b)
Returns the maximum of a and b.
Definition: util.h:65
#define CO_DEFTYPE_UNSIGNED8
The data type (and object index) of an 8-bit unsigned integer.
Definition: type.h:44
co_dev_t * co_dev_create(co_unsigned8_t id)
Creates a new CANopen device.
Definition: dev.c:141
An read file buffer struct.
Definition: frbuf.c:49
#define CO_NUM_NODES
The maximum number of nodes in a CANopen network.
Definition: dev.h:56
struct rbnode * rbtree_find(const struct rbtree *tree, const void *key)
Finds a node in a red-black tree.
Definition: rbtree.c:308
void frbuf_destroy(frbuf_t *buf)
Destroys a read file buffer.
Definition: frbuf.c:158
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
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
co_unsigned32_t dummy
The data types supported for mapping dummy entries in PDOs.
Definition: dev.c:66
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
Invalid argument.
Definition: errnum.h:129
void rbtree_remove(struct rbtree *tree, struct rbnode *node)
Removes a node from a red-black tree.
Definition: rbtree.c:188
unsigned int co_sub_get_flags(const co_sub_t *sub)
Returns the object flags of a CANopen sub-object.
Definition: obj.c:722
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
int errno2c(int errnum)
Transforms a standard C error number to a native error code.
Definition: errnum.c:43
#define __unlikely(x)
Indicates to the compiler that the expression is most-likely false.
Definition: features.h:286
#define CO_OBJ_FLAGS_VAL_NODEID
The current object value is of the form $NODEID { "+" number }.
Definition: obj.h:114
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
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
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
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
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, and writes them to a file, in the concise DCF format.
Definition: dev.c:851
A CANopen device.
Definition: dev.c:38
An (atomic) write file buffer struct.
Definition: fwbuf.c:56
int co_dev_set_name(co_dev_t *dev, const char *name)
Sets the name of a CANopen device.
Definition: dev.c:305
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, and stores them in the object dictionary of a CANopen device.
Definition: dev.c:682
void co_obj_destroy(co_obj_t *obj)
Destroys a CANopen object, including its sub-objects.
Definition: obj.c:118
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_unsigned8_t id
The node-ID.
Definition: dev.c:42
co_unsigned32_t product_code
The product code.
Definition: dev.c:54
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_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
void co_val_fini(co_unsigned16_t type, void *val)
Finalizes a value of the specified data type.
Definition: val.c:273
char * vendor_name
A pointer to the vendor name.
Definition: dev.c:48
This header file is part of the utilities library; it contains the read file buffer declarations...
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_revision(const co_dev_t *dev)
Returns the revision number of a CANopen device.
Definition: dev.c:419
void rbtree_init(struct rbtree *tree, rbtree_cmp_t *cmp)
Initializes a red-black tree.
Definition: rbtree.h:238
#define CO_OBJ_FLAGS_DEF_NODEID
The default object value is of the form $NODEID { "+" number }.
Definition: obj.h:111
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
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
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 rbtree_insert(struct rbtree *tree, struct rbnode *node)
Inserts a node into a red-black tree.
Definition: rbtree.c:108
This header file is part of the utilities library; it contains the (atomic) write file buffer declara...
co_unsigned8_t co_dev_get_id(const co_dev_t *dev)
Returns the node-ID of a CANopen device.
Definition: dev.c:198
This header file is part of the C11 and POSIX compatibility library; it includes <stdlib.h> and defines any missing functionality.
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
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
co_unsigned16_t co_obj_get_idx(const co_obj_t *obj)
Returns the index of a CANopen object.
Definition: obj.c:136
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
#define CO_OBJ_FLAGS_MAX_NODEID
The upper limit of the object value is of the form $NODEID { "+" number }.
Definition: obj.h:108
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
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
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
A CANopen object.
Definition: obj.h:32
#define CO_OBJ_FLAGS_MIN_NODEID
The lower limit of the object value is of the form $NODEID { "+" number }.
Definition: obj.h:105
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
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_unsigned16_t rate
The (pending) baudrate (in kbit/s).
Definition: dev.c:62
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
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
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
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
A node in a red-black tree.
Definition: rbtree.h:52