Lely core libraries  2.2.5
sdev.c
Go to the documentation of this file.
1 
24 #include "co.h"
25 
26 #ifndef LELY_NO_CO_SDEV
27 
28 #include <lely/co/sdev.h>
29 #include <lely/libc/stdio.h>
30 #include <lely/util/errnum.h>
31 #include <lely/util/lex.h>
32 #include <lely/util/print.h>
33 
34 #include <assert.h>
35 // Include inttypes.h after stdio.h to enforce declarations of format specifiers
36 // in Newlib.
37 #include <inttypes.h>
38 #include <stdlib.h>
39 
40 static int co_sdev_load(const struct co_sdev *sdev, co_dev_t *dev);
41 static int co_sobj_load(const struct co_sobj *sobj, co_obj_t *obj);
42 static int co_ssub_load(const struct co_ssub *ssub, co_sub_t *sub);
43 
44 static int snprintf_c99_sobj(char *s, size_t n, const co_obj_t *obj);
45 static int snprintf_c99_ssub(char *s, size_t n, const co_sub_t *sub);
46 static int snprintf_c99_sval(
47  char *s, size_t n, co_unsigned16_t type, const void *val);
48 static int snprintf_c99_esc(char *s, size_t n, const char *esc);
49 
50 struct __co_dev *
51 __co_dev_init_from_sdev(struct __co_dev *dev, const struct co_sdev *sdev)
52 {
53  assert(dev);
54 
55  int errc = 0;
56 
57  if (!sdev) {
58  errc = errnum2c(ERRNUM_INVAL);
59  goto error_param;
60  }
61 
62  if (!__co_dev_init(dev, sdev->id)) {
63  errc = get_errc();
64  goto error_init_dev;
65  }
66 
67  if (co_sdev_load(sdev, dev) == -1) {
68  errc = get_errc();
69  goto error_load_sdev;
70  }
71 
72  return dev;
73 
74 error_load_sdev:
75  __co_dev_fini(dev);
76 error_init_dev:
77 error_param:
78  set_errc(errc);
79  return NULL;
80 }
81 
82 co_dev_t *
83 co_dev_create_from_sdev(const struct co_sdev *sdev)
84 {
85  int errc = 0;
86 
87  co_dev_t *dev = __co_dev_alloc();
88  if (!dev) {
89  errc = get_errc();
90  goto error_alloc_dev;
91  }
92 
93  if (!__co_dev_init_from_sdev(dev, sdev)) {
94  errc = get_errc();
95  goto error_init_dev;
96  }
97 
98  return dev;
99 
100 error_init_dev:
101  __co_dev_free(dev);
102 error_alloc_dev:
103  set_errc(errc);
104  return NULL;
105 }
106 
107 int
108 snprintf_c99_sdev(char *s, size_t n, const co_dev_t *dev)
109 {
110  if (!s)
111  n = 0;
112 
113  if (!dev)
114  return 0;
115 
116  int errsv = 0;
117 
118  int r, t = 0;
119  const char *name;
120 
121  // cppcheck-suppress nullPointerRedundantCheck symbolName=s
122  r = snprintf(s, n, "{\n\t.id = 0x%02x,\n", co_dev_get_id(dev));
123  if (r < 0) {
124  errsv = errno;
125  goto error_print_dev;
126  }
127  t += r;
128  r = MIN((size_t)r, n);
129  s += r;
130  n -= r;
131 
132  name = co_dev_get_name(dev);
133  if (name) {
134  r = snprintf(s, n, "\t.name = CO_SDEV_STRING(\"");
135  if (r < 0) {
136  errsv = errno;
137  goto error_print_dev;
138  }
139  t += r;
140  r = MIN((size_t)r, n);
141  s += r;
142  n -= r;
143  r = snprintf_c99_esc(s, n, name);
144  if (r < 0) {
145  errsv = errno;
146  goto error_print_dev;
147  }
148  t += r;
149  r = MIN((size_t)r, n);
150  s += r;
151  n -= r;
152  r = snprintf(s, n, "\"),\n");
153  } else {
154  r = snprintf(s, n, "\t.name = NULL,\n");
155  }
156  if (r < 0) {
157  errsv = errno;
158  goto error_print_dev;
159  }
160  t += r;
161  r = MIN((size_t)r, n);
162  s += r;
163  n -= r;
164 
166  if (name) {
167  r = snprintf(s, n, "\t.vendor_name = CO_SDEV_STRING(\"");
168  if (r < 0) {
169  errsv = errno;
170  goto error_print_dev;
171  }
172  t += r;
173  r = MIN((size_t)r, n);
174  s += r;
175  n -= r;
176  r = snprintf_c99_esc(s, n, name);
177  if (r < 0) {
178  errsv = errno;
179  goto error_print_dev;
180  }
181  t += r;
182  r = MIN((size_t)r, n);
183  s += r;
184  n -= r;
185  r = snprintf(s, n, "\"),\n");
186  } else {
187  r = snprintf(s, n, "\t.vendor_name = NULL,\n");
188  }
189  if (r < 0) {
190  errsv = errno;
191  goto error_print_dev;
192  }
193  t += r;
194  r = MIN((size_t)r, n);
195  s += r;
196  n -= r;
197 
198  r = snprintf(s, n, "\t.vendor_id = 0x%08" PRIx32 ",\n",
199  co_dev_get_vendor_id(dev));
200  if (r < 0) {
201  errsv = errno;
202  goto error_print_dev;
203  }
204  t += r;
205  r = MIN((size_t)r, n);
206  s += r;
207  n -= r;
208 
210  if (name) {
211  r = snprintf(s, n, "\t.product_name = CO_SDEV_STRING(\"");
212  if (r < 0) {
213  errsv = errno;
214  goto error_print_dev;
215  }
216  t += r;
217  r = MIN((size_t)r, n);
218  s += r;
219  n -= r;
220  r = snprintf_c99_esc(s, n, name);
221  if (r < 0) {
222  errsv = errno;
223  goto error_print_dev;
224  }
225  t += r;
226  r = MIN((size_t)r, n);
227  s += r;
228  n -= r;
229  r = snprintf(s, n, "\"),\n");
230  } else {
231  r = snprintf(s, n, "\t.product_name = NULL,\n");
232  }
233  if (r < 0) {
234  errsv = errno;
235  goto error_print_dev;
236  }
237  t += r;
238  r = MIN((size_t)r, n);
239  s += r;
240  n -= r;
241 
242  r = snprintf(s, n,
243  "\t.product_code = 0x%08" PRIx32
244  ",\n\t.revision = 0x%08" PRIx32 ",\n",
246  if (r < 0) {
247  errsv = errno;
248  goto error_print_dev;
249  }
250  t += r;
251  r = MIN((size_t)r, n);
252  s += r;
253  n -= r;
254 
256  if (name) {
257  r = snprintf(s, n, "\t.order_code = CO_SDEV_STRING(\"");
258  if (r < 0) {
259  errsv = errno;
260  goto error_print_dev;
261  }
262  t += r;
263  r = MIN((size_t)r, n);
264  s += r;
265  n -= r;
266  r = snprintf_c99_esc(s, n, name);
267  if (r < 0) {
268  errsv = errno;
269  goto error_print_dev;
270  }
271  t += r;
272  r = MIN((size_t)r, n);
273  s += r;
274  n -= r;
275  r = snprintf(s, n, "\"),\n");
276  } else {
277  r = snprintf(s, n, "\t.order_code = NULL,\n");
278  }
279  if (r < 0) {
280  errsv = errno;
281  goto error_print_dev;
282  }
283  t += r;
284  r = MIN((size_t)r, n);
285  s += r;
286  n -= r;
287 
288  r = snprintf(s, n, "\t.baud = 0");
289  if (r < 0) {
290  errsv = errno;
291  goto error_print_dev;
292  }
293  t += r;
294  r = MIN((size_t)r, n);
295  s += r;
296  n -= r;
297  unsigned int baud = co_dev_get_baud(dev);
298 #define LELY_CO_DEFINE_BAUD(x) \
299  if (baud & CO_BAUD_##x) { \
300  r = snprintf(s, n, "\n\t\t| CO_BAUD_" #x); \
301  if (r < 0) { \
302  errsv = errno; \
303  goto error_print_dev; \
304  } \
305  t += r; \
306  r = MIN((size_t)r, n); \
307  s += r; \
308  n -= r; \
309  }
310 
311  LELY_CO_DEFINE_BAUD(1000)
312  LELY_CO_DEFINE_BAUD(800)
313  LELY_CO_DEFINE_BAUD(500)
314  LELY_CO_DEFINE_BAUD(250)
315  LELY_CO_DEFINE_BAUD(125)
316  LELY_CO_DEFINE_BAUD(50)
317  LELY_CO_DEFINE_BAUD(20)
318  LELY_CO_DEFINE_BAUD(10)
319  LELY_CO_DEFINE_BAUD(AUTO)
320 
321 #undef LELY_CO_DEFINE_BAUD
322 
323  r = snprintf(s, n,
324  ",\n\t.rate = %d,\n\t.lss = %d,\n\t.dummy = 0x%08" PRIx32
325  ",\n",
326  co_dev_get_rate(dev), co_dev_get_lss(dev),
327  co_dev_get_dummy(dev));
328  if (r < 0) {
329  errsv = errno;
330  goto error_print_dev;
331  }
332  t += r;
333  r = MIN((size_t)r, n);
334  s += r;
335  n -= r;
336 
337  co_unsigned16_t maxidx = co_dev_get_idx(dev, 0, NULL);
338  co_unsigned16_t *idx = malloc(maxidx * sizeof(co_unsigned16_t));
339  if (!idx) {
340  errsv = errno;
341  goto error_malloc_idx;
342  }
343  co_dev_get_idx(dev, maxidx, idx);
344 
345  r = snprintf(s, n, "\t.nobj = %d,\n\t.objs = (const struct co_sobj[]){",
346  maxidx);
347  if (r < 0) {
348  errsv = errno;
349  goto error_print_obj;
350  }
351  t += r;
352  r = MIN((size_t)r, n);
353  s += r;
354  n -= r;
355 
356  for (size_t i = 0; i < maxidx; i++) {
357  r = snprintf(s, n, i ? ", {\n" : "{\n");
358  if (r < 0) {
359  errsv = errno;
360  goto error_print_obj;
361  }
362  t += r;
363  r = MIN((size_t)r, n);
364  s += r;
365  n -= r;
366  r = snprintf_c99_sobj(s, n, co_dev_find_obj(dev, idx[i]));
367  if (r < 0) {
368  errsv = errno;
369  goto error_print_obj;
370  }
371  t += r;
372  r = MIN((size_t)r, n);
373  s += r;
374  n -= r;
375  r = snprintf(s, n, "\t}");
376  if (r < 0) {
377  errsv = errno;
378  goto error_print_obj;
379  }
380  t += r;
381  r = MIN((size_t)r, n);
382  s += r;
383  n -= r;
384  }
385 
386  r = snprintf(s, n, "}\n}");
387  if (r < 0) {
388  errsv = errno;
389  goto error_print_obj;
390  }
391  t += r;
392 
393  free(idx);
394 
395  return t;
396 
397 error_print_obj:
398  free(idx);
399 error_malloc_idx:
400 error_print_dev:
401  errno = errsv;
402  return r;
403 }
404 
405 int
406 asprintf_c99_sdev(char **ps, const co_dev_t *dev)
407 {
408  int n = snprintf_c99_sdev(NULL, 0, dev);
409  if (n < 0)
410  return n;
411 
412  char *s = malloc(n + 1);
413  if (!s)
414  return -1;
415 
416  n = snprintf_c99_sdev(s, n + 1, dev);
417  if (n < 0) {
418  int errsv = errno;
419  free(s);
420  errno = errsv;
421  return n;
422  }
423 
424  *ps = s;
425  return n;
426 }
427 
428 static int
429 co_sdev_load(const struct co_sdev *sdev, co_dev_t *dev)
430 {
431  assert(sdev);
432  assert(dev);
433 
434  if (co_dev_set_name(dev, sdev->name) == -1)
435  return -1;
436 
437  if (co_dev_set_vendor_name(dev, sdev->vendor_name) == -1)
438  return -1;
439 
440  co_dev_set_vendor_id(dev, sdev->vendor_id);
441 
442  if (co_dev_set_product_name(dev, sdev->product_name) == -1)
443  return -1;
444 
446  co_dev_set_revision(dev, sdev->revision);
447 
448  if (co_dev_set_order_code(dev, sdev->order_code) == -1)
449  return -1;
450 
451  co_dev_set_baud(dev, sdev->baud);
452  co_dev_set_rate(dev, sdev->rate);
453 
454  co_dev_set_lss(dev, sdev->lss);
455 
456  co_dev_set_dummy(dev, sdev->dummy);
457 
458  for (size_t i = 0; i < sdev->nobj; i++) {
459  const struct co_sobj *sobj = &sdev->objs[i];
460  co_obj_t *obj = co_obj_create(sobj->idx);
461  if (!obj)
462  return -1;
463  if (co_dev_insert_obj(dev, obj) == -1) {
464  int errc = get_errc();
465  co_obj_destroy(obj);
466  set_errc(errc);
467  return -1;
468  }
469  if (co_sobj_load(sobj, obj) == -1)
470  return -1;
471  }
472 
473  return 0;
474 }
475 
476 static int
477 co_sobj_load(const struct co_sobj *sobj, co_obj_t *obj)
478 {
479  assert(sobj);
480  assert(obj);
481 
482 #ifndef LELY_NO_CO_OBJ_NAME
483  if (co_obj_set_name(obj, sobj->name) == -1)
484  return -1;
485 #endif
486 
487  if (co_obj_set_code(obj, sobj->code) == -1)
488  return -1;
489 
490  for (size_t i = 0; i < sobj->nsub; i++) {
491  const struct co_ssub *ssub = &sobj->subs[i];
492  co_sub_t *sub = co_sub_create(ssub->subidx, ssub->type);
493  if (!sub)
494  return -1;
495  if (co_obj_insert_sub(obj, sub) == -1) {
496  int errc = get_errc();
497  co_sub_destroy(sub);
498  set_errc(errc);
499  return -1;
500  }
501  if (co_ssub_load(ssub, sub) == -1)
502  return -1;
503  }
504 
505  return 0;
506 }
507 
508 static int
509 co_ssub_load(const struct co_ssub *ssub, co_sub_t *sub)
510 {
511  assert(ssub);
512  assert(sub);
513 
514 #ifndef LELY_NO_CO_OBJ_NAME
515  if (co_sub_set_name(sub, ssub->name) == -1)
516  return -1;
517 #endif
518 
519  if (co_sub_set_access(sub, ssub->access) == -1)
520  return -1;
521 
522  const void *ptr;
523  size_t n;
524 
525 #ifndef LELY_NO_CO_OBJ_LIMITS
526  ptr = co_val_addressof(ssub->type, &ssub->min);
527  n = co_val_sizeof(ssub->type, &ssub->min);
528  if (n && !co_sub_set_min(sub, ptr, n))
529  return -1;
530 
531  ptr = co_val_addressof(ssub->type, &ssub->max);
532  n = co_val_sizeof(ssub->type, &ssub->max);
533  if (n && !co_sub_set_max(sub, ptr, n))
534  return -1;
535 #endif
536 
537 #ifndef LELY_NO_CO_OBJ_DEFAULT
538  ptr = co_val_addressof(ssub->type, &ssub->def);
539  n = co_val_sizeof(ssub->type, &ssub->def);
540  if (n && !co_sub_set_def(sub, ptr, n))
541  return -1;
542 #endif
543 
544  ptr = co_val_addressof(ssub->type, &ssub->val);
545  n = co_val_sizeof(ssub->type, &ssub->val);
546  if (n && !co_sub_set_val(sub, ptr, n))
547  return -1;
548 
550  co_sub_set_flags(sub, ssub->flags);
551 
552  return 0;
553 }
554 
555 static int
556 snprintf_c99_sobj(char *s, size_t n, const co_obj_t *obj)
557 {
558  if (!s)
559  n = 0;
560 
561  if (!obj)
562  return 0;
563 
564  int r, t = 0;
565 
566 #ifndef LELY_NO_CO_OBJ_NAME
567  const char *name = co_obj_get_name(obj);
568  if (name) {
569  r = snprintf(s, n,
570  "#if !LELY_NO_CO_OBJ_NAME\n\t\t.name = CO_SDEV_STRING(\"");
571  if (r < 0)
572  return r;
573  t += r;
574  r = MIN((size_t)r, n);
575  s += r;
576  n -= r;
577  r = snprintf_c99_esc(s, n, name);
578  if (r < 0)
579  return r;
580  t += r;
581  r = MIN((size_t)r, n);
582  s += r;
583  n -= r;
584  r = snprintf(s, n, "\"),\n");
585  } else {
586 #endif
587  r = snprintf(s, n,
588  "#if !LELY_NO_CO_OBJ_NAME\n\t\t.name = NULL,\n");
589 #ifndef LELY_NO_CO_OBJ_NAME
590  }
591 #endif
592  if (r < 0)
593  return r;
594  t += r;
595  r = MIN((size_t)r, n);
596  s += r;
597  n -= r;
598 
599  r = snprintf(s, n, "#endif\n\t\t.idx = 0x%04x,\n\t\t.code = ",
600  co_obj_get_idx(obj));
601  if (r < 0)
602  return r;
603  t += r;
604  r = MIN((size_t)r, n);
605  s += r;
606  n -= r;
607 
608  co_unsigned8_t code = co_obj_get_code(obj);
609  switch (code) {
610  case CO_OBJECT_NULL: r = snprintf(s, n, "CO_OBJECT_NULL,\n"); break;
611  case CO_OBJECT_DOMAIN: r = snprintf(s, n, "CO_OBJECT_DOMAIN,\n"); break;
612  case CO_OBJECT_DEFTYPE:
613  r = snprintf(s, n, "CO_OBJECT_DEFTYPE,\n");
614  break;
615  case CO_OBJECT_DEFSTRUCT:
616  r = snprintf(s, n, "CO_OBJECT_DEFSTRUCT,\n");
617  break;
618  case CO_OBJECT_VAR: r = snprintf(s, n, "CO_OBJECT_VAR,\n"); break;
619  case CO_OBJECT_ARRAY: r = snprintf(s, n, "CO_OBJECT_ARRAY,\n"); break;
620  case CO_OBJECT_RECORD: r = snprintf(s, n, "CO_OBJECT_RECORD,\n"); break;
621  default: r = snprintf(s, n, "0x%02x,\n", code); break;
622  }
623  if (r < 0)
624  return r;
625  t += r;
626  r = MIN((size_t)r, n);
627  s += r;
628  n -= r;
629 
630  co_unsigned8_t subidx[0xff];
631  co_unsigned8_t maxsubidx = co_obj_get_subidx(obj, 0xff, subidx);
632 
633  r = snprintf(s, n,
634  "\t\t.nsub = %d,\n\t\t.subs = (const struct co_ssub[]){",
635  maxsubidx);
636  if (r < 0)
637  return r;
638  t += r;
639  r = MIN((size_t)r, n);
640  s += r;
641  n -= r;
642 
643  for (size_t i = 0; i < maxsubidx; i++) {
644  r = snprintf(s, n, i ? ", {\n" : "{\n");
645  if (r < 0)
646  return r;
647  t += r;
648  r = MIN((size_t)r, n);
649  s += r;
650  n -= r;
651  r = snprintf_c99_ssub(s, n, co_obj_find_sub(obj, subidx[i]));
652  if (r < 0)
653  return r;
654  t += r;
655  r = MIN((size_t)r, n);
656  s += r;
657  n -= r;
658  r = snprintf(s, n, "\t\t}");
659  if (r < 0)
660  return r;
661  t += r;
662  r = MIN((size_t)r, n);
663  s += r;
664  n -= r;
665  }
666 
667  r = snprintf(s, n, "}\n");
668  if (r < 0)
669  return r;
670  t += r;
671 
672  return t;
673 }
674 
675 static int
676 snprintf_c99_ssub(char *s, size_t n, const co_sub_t *sub)
677 {
678  if (!s)
679  n = 0;
680 
681  if (!sub)
682  return 0;
683 
684  int r, t = 0;
685 
686 #ifndef LELY_NO_CO_OBJ_NAME
687  const char *name = co_sub_get_name(sub);
688  if (name) {
689  r = snprintf(s, n,
690  "#if !LELY_NO_CO_OBJ_NAME\n\t\t\t.name = CO_SDEV_STRING(\"");
691  if (r < 0)
692  return r;
693  t += r;
694  r = MIN((size_t)r, n);
695  s += r;
696  n -= r;
697  r = snprintf_c99_esc(s, n, name);
698  if (r < 0)
699  return r;
700  t += r;
701  r = MIN((size_t)r, n);
702  s += r;
703  n -= r;
704  r = snprintf(s, n, "\"),\n");
705  } else {
706 #endif
707  r = snprintf(s, n,
708  "#if !LELY_NO_CO_OBJ_NAME\n\t\t\t.name = NULL,\n");
709 #ifndef LELY_NO_CO_OBJ_NAME
710  }
711 #endif
712  if (r < 0)
713  return r;
714  t += r;
715  r = MIN((size_t)r, n);
716  s += r;
717  n -= r;
718 
719  r = snprintf(s, n, "#endif\n\t\t\t.subidx = 0x%02x,\n\t\t\t.type = ",
720  co_sub_get_subidx(sub));
721  if (r < 0)
722  return r;
723  t += r;
724  r = MIN((size_t)r, n);
725  s += r;
726  n -= r;
727 
728  co_unsigned16_t type = co_sub_get_type(sub);
729  switch (type) {
730 #define LELY_CO_DEFINE_TYPE(a, b, c, d) \
731  case CO_DEFTYPE_##a: \
732  r = snprintf(s, n, "CO_DEFTYPE_" #a ",\n"); \
733  break;
734 #include <lely/co/def/type.def>
735 #undef LELY_CO_DEFINE_TYPE
736  default: r = snprintf(s, n, "0x%04x,\n", type); break;
737  }
738  if (r < 0)
739  return r;
740  t += r;
741  r = MIN((size_t)r, n);
742  s += r;
743  n -= r;
744 
745  r = snprintf(s, n, "#if !LELY_NO_CO_OBJ_LIMITS\n\t\t\t.min = ");
746  if (r < 0)
747  return r;
748  t += r;
749  r = MIN((size_t)r, n);
750  s += r;
751  n -= r;
752 #ifndef LELY_NO_CO_OBJ_LIMITS
753  r = snprintf_c99_sval(s, n, type, co_sub_get_min(sub));
754 #else
755  union co_val min;
756  co_val_init_min(type, &min);
757  r = snprintf_c99_sval(s, n, type, &min);
758  co_val_fini(type, &min);
759 #endif
760  if (r < 0)
761  return r;
762  t += r;
763  r = MIN((size_t)r, n);
764  s += r;
765  n -= r;
766 
767  r = snprintf(s, n, ",\n\t\t\t.max = ");
768  if (r < 0)
769  return r;
770  t += r;
771  r = MIN((size_t)r, n);
772  s += r;
773  n -= r;
774 #ifndef LELY_NO_CO_OBJ_LIMITS
775  r = snprintf_c99_sval(s, n, type, co_sub_get_max(sub));
776 #else
777  union co_val max;
778  co_val_init_max(type, &max);
779  r = snprintf_c99_sval(s, n, type, &max);
780  co_val_fini(type, &max);
781 #endif
782  if (r < 0)
783  return r;
784  t += r;
785  r = MIN((size_t)r, n);
786  s += r;
787  n -= r;
788 
789  r = snprintf(s, n,
790  ",\n#endif\n#if !LELY_NO_CO_OBJ_DEFAULT\n\t\t\t.def = ");
791  if (r < 0)
792  return r;
793  t += r;
794  r = MIN((size_t)r, n);
795  s += r;
796  n -= r;
797 #ifndef LELY_NO_CO_OBJ_DEFAULT
798  r = snprintf_c99_sval(s, n, type, co_sub_get_def(sub));
799 #else
800  union co_val def;
801  co_val_init_min(type, &def);
802  r = snprintf_c99_sval(s, n, type, &def);
803  co_val_fini(type, &def);
804 #endif
805  if (r < 0)
806  return r;
807  t += r;
808  r = MIN((size_t)r, n);
809  s += r;
810  n -= r;
811 
812  r = snprintf(s, n, ",\n#endif\n\t\t\t.val = ");
813  if (r < 0)
814  return r;
815  t += r;
816  r = MIN((size_t)r, n);
817  s += r;
818  n -= r;
819 #ifndef LELY_NO_CO_OBJ_FILE
820  // clang-format off
821  if (type == CO_DEFTYPE_DOMAIN
823  || (co_sub_get_flags(sub)
825  // clang-format on
826  r = snprintf_c99_sval(s, n, CO_DEFTYPE_VISIBLE_STRING,
827  co_sub_get_val(sub));
828  else
829 #endif
830  r = snprintf_c99_sval(s, n, type, co_sub_get_val(sub));
831  if (r < 0)
832  return r;
833  t += r;
834  r = MIN((size_t)r, n);
835  s += r;
836  n -= r;
837 
838  r = snprintf(s, n, ",\n\t\t\t.access = ");
839  if (r < 0)
840  return r;
841  t += r;
842  r = MIN((size_t)r, n);
843  s += r;
844  n -= r;
845  unsigned int access = co_sub_get_access(sub);
846  switch (access) {
847  case CO_ACCESS_RO: r = snprintf(s, n, "CO_ACCESS_RO,\n"); break;
848  case CO_ACCESS_WO: r = snprintf(s, n, "CO_ACCESS_WO,\n"); break;
849  case CO_ACCESS_RW: r = snprintf(s, n, "CO_ACCESS_RW,\n"); break;
850  case CO_ACCESS_RWR: r = snprintf(s, n, "CO_ACCESS_RWR,\n"); break;
851  case CO_ACCESS_RWW: r = snprintf(s, n, "CO_ACCESS_RWW,\n"); break;
852  case CO_ACCESS_CONST: r = snprintf(s, n, "CO_ACCESS_CONST,\n"); break;
853  default: r = snprintf(s, n, "0x%x,\n", access); break;
854  }
855  if (r < 0)
856  return r;
857  t += r;
858  r = MIN((size_t)r, n);
859  s += r;
860  n -= r;
861 
862  r = snprintf(s, n, "\t\t\t.pdo_mapping = %d,\n",
864  if (r < 0)
865  return r;
866  t += r;
867  r = MIN((size_t)r, n);
868  s += r;
869  n -= r;
870 
871  r = snprintf(s, n, "\t\t\t.flags = 0\n");
872  if (r < 0)
873  return r;
874  t += r;
875  r = MIN((size_t)r, n);
876  s += r;
877  n -= r;
878  unsigned int flags = co_sub_get_flags(sub);
879 #define LELY_CO_DEFINE_FLAGS(x) \
880  if (flags & CO_OBJ_FLAGS_##x) { \
881  r = snprintf(s, n, "\t\t\t\t| CO_OBJ_FLAGS_" #x "\n"); \
882  if (r < 0) \
883  return r; \
884  t += r; \
885  r = MIN((size_t)r, n); \
886  s += r; \
887  n -= r; \
888  }
889 
890  LELY_CO_DEFINE_FLAGS(READ)
891  LELY_CO_DEFINE_FLAGS(WRITE)
892 #ifndef LELY_NO_CO_OBJ_FILE
893  LELY_CO_DEFINE_FLAGS(UPLOAD_FILE)
894  LELY_CO_DEFINE_FLAGS(DOWNLOAD_FILE)
895 #endif
896  LELY_CO_DEFINE_FLAGS(MIN_NODEID)
897  LELY_CO_DEFINE_FLAGS(MAX_NODEID)
898  LELY_CO_DEFINE_FLAGS(DEF_NODEID)
899  // cppcheck-suppress uselessAssignmentArg
900  // cppcheck-suppress uselessAssignmentPtrArg
901  LELY_CO_DEFINE_FLAGS(VAL_NODEID)
902 
903 #undef LELY_CO_DEFINE_FLAGS
904 
905  return t;
906 }
907 
908 static int
909 snprintf_c99_sval(char *s, size_t n, co_unsigned16_t type, const void *val)
910 {
911  if (!s)
912  n = 0;
913 
914  if (!val)
915  return 0;
916 
917  int r, t = 0;
918 
919  const union co_val *u = val;
920  switch (type) {
921  case CO_DEFTYPE_BOOLEAN:
922  r = snprintf(s, n, "{ .b = %d }", !!u->b);
923  break;
924  case CO_DEFTYPE_INTEGER8:
925  if (u->i8 == CO_INTEGER8_MIN) {
926  r = snprintf(s, n, "{ .i8 = CO_INTEGER8_MIN }");
927  } else if (u->i8 == CO_INTEGER8_MAX) {
928  r = snprintf(s, n, "{ .i8 = CO_INTEGER8_MAX }");
929  } else {
930  r = snprintf(s, n, "{ .i8 = %" PRIi8 " }", u->i8);
931  }
932  break;
934  if (u->i16 == CO_INTEGER16_MIN) {
935  r = snprintf(s, n, "{ .i16 = CO_INTEGER16_MIN }");
936  } else if (u->i16 == CO_INTEGER16_MAX) {
937  r = snprintf(s, n, "{ .i16 = CO_INTEGER16_MAX }");
938  } else {
939  r = snprintf(s, n, "{ .i16 = %" PRIi16 " }", u->i16);
940  }
941  break;
943  if (u->i32 == CO_INTEGER32_MIN) {
944  r = snprintf(s, n, "{ .i32 = CO_INTEGER32_MIN }");
945  } else if (u->i32 == CO_INTEGER32_MAX) {
946  r = snprintf(s, n, "{ .i32 = CO_INTEGER32_MAX }");
947  } else {
948  r = snprintf(s, n, "{ .i32 = %" PRIi32 "l }", u->i32);
949  }
950  break;
952  if (u->u8 == CO_UNSIGNED8_MIN) {
953  r = snprintf(s, n, "{ .u8 = CO_UNSIGNED8_MIN }");
954  } else if (u->u8 == CO_UNSIGNED8_MAX) {
955  r = snprintf(s, n, "{ .u8 = CO_UNSIGNED8_MAX }");
956  } else {
957  r = snprintf(s, n, "{ .u8 = 0x%02" PRIx8 " }", u->u8);
958  }
959  break;
961  if (u->u16 == CO_UNSIGNED16_MIN) {
962  r = snprintf(s, n, "{ .u16 = CO_UNSIGNED16_MIN }");
963  } else if (u->u16 == CO_UNSIGNED16_MAX) {
964  r = snprintf(s, n, "{ .u16 = CO_UNSIGNED16_MAX }");
965  } else {
966  r = snprintf(s, n, "{ .u16 = 0x%04" PRIx16 "u }",
967  u->u16);
968  }
969  break;
971  if (u->u32 == CO_UNSIGNED32_MIN) {
972  r = snprintf(s, n, "{ .u32 = CO_UNSIGNED32_MIN }");
973  } else if (u->u32 == CO_UNSIGNED32_MAX) {
974  r = snprintf(s, n, "{ .u32 = CO_UNSIGNED32_MAX }");
975  } else {
976  r = snprintf(s, n, "{ .u32 = 0x%08" PRIx32 "lu }",
977  u->u32);
978  }
979  break;
980  case CO_DEFTYPE_REAL32:
981  if (u->r32 == CO_REAL32_MIN) {
982  r = snprintf(s, n, "{ .r32 = CO_REAL32_MIN }");
983  } else if (u->r32 == CO_REAL32_MAX) {
984  r = snprintf(s, n, "{ .r32 = CO_REAL32_MAX }");
985  } else {
986  r = snprintf(s, n, "{ .r32 = %.*g }", DECIMAL_DIG,
987  (double)u->r32);
988  }
989  break;
991  if (u->vs) {
992  r = snprintf(s, n, "{ .vs = CO_VISIBLE_STRING_C(\"");
993  if (r < 0)
994  return r;
995  t += r;
996  r = MIN((size_t)r, n);
997  s += r;
998  n -= r;
999  r = snprintf_c99_esc(s, n, u->vs);
1000  if (r < 0)
1001  return r;
1002  t += r;
1003  r = MIN((size_t)r, n);
1004  s += r;
1005  n -= r;
1006  r = snprintf(s, n, "\") }");
1007  } else {
1008  r = snprintf(s, n, "{ .vs = NULL }");
1009  }
1010  break;
1012  if (u->os) {
1013  r = snprintf(s, n,
1014  "{ .os = CO_OCTET_STRING_C(\n\t\t\t\t\"");
1015  if (r < 0)
1016  return r;
1017  t += r;
1018  r = MIN((size_t)r, n);
1019  s += r;
1020  n -= r;
1021  size_t size = co_val_sizeof(type, val);
1022  for (size_t i = 0; i < size; i++) {
1023  // clang-format off
1024  r = snprintf(s, n, i && !(i % 8)
1025  ? "\"\n\t\t\t\t\"\\x%02x"
1026  : "\\x%02x",
1027  u->os[i]);
1028  // clang-format on
1029  if (r < 0)
1030  return r;
1031  t += r;
1032  r = MIN((size_t)r, n);
1033  s += r;
1034  n -= r;
1035  }
1036  r = snprintf(s, n, "\"\n\t\t\t) }");
1037  } else {
1038  r = snprintf(s, n, "{ .vs = NULL }");
1039  }
1040  break;
1042  if (u->us) {
1043  r = snprintf(s, n,
1044  "{ .us = CO_UNICODE_STRING_C({\n\t\t\t\t");
1045  if (r < 0)
1046  return r;
1047  t += r;
1048  r = MIN((size_t)r, n);
1049  s += r;
1050  n -= r;
1051  size_t size = co_val_sizeof(type, val) / 2 + 1;
1052  for (size_t i = 0; i < size; i++) {
1053  // clang-format off
1054  r = snprintf(s, n, i && !(i % 4)
1055  ? ",\n\t\t\t\t0x%04x"
1056  : (i ? ", 0x%04x" : "0x%04x"),
1057  u->us[i]);
1058  // clang-format on
1059  if (r < 0)
1060  return r;
1061  t += r;
1062  r = MIN((size_t)r, n);
1063  s += r;
1064  n -= r;
1065  }
1066  r = snprintf(s, n, "\n\t\t\t}) }");
1067  } else {
1068  r = snprintf(s, n, "{ .us = NULL }");
1069  }
1070  break;
1072  r = snprintf(s, n,
1073  "{ .t = { "
1074  ".ms = 0x%08" PRIx32 ", "
1075  ".days = 0x%04" PRIx16 " "
1076  "} }",
1077  u->t.ms, u->t.days);
1078  break;
1079  case CO_DEFTYPE_TIME_DIFF:
1080  r = snprintf(s, n,
1081  "{ .t = { "
1082  ".ms = 0x%08" PRIx32 ", "
1083  ".days = 0x%04" PRIx16 " "
1084  "} }",
1085  u->td.ms, u->td.days);
1086  break;
1087  case CO_DEFTYPE_DOMAIN:
1088  if (u->dom) {
1089  r = snprintf(s, n,
1090  "{ .dom = CO_DOMAIN_C(co_unsigned8_t, {\n\t\t\t\t");
1091  if (r < 0)
1092  return r;
1093  t += r;
1094  r = MIN((size_t)r, n);
1095  s += r;
1096  n -= r;
1097  const co_unsigned8_t *bp = u->dom;
1098  size_t size = co_val_sizeof(type, val);
1099  for (size_t i = 0; i < size; i++) {
1100  // clang-format off
1101  r = snprintf(s, n, i && !(i % 8)
1102  ? ",\n\t\t\t\t0x%02x"
1103  : (i ? ", 0x%02x" : "0x%02x"),
1104  bp[i]);
1105  // clang-format on
1106  if (r < 0)
1107  return r;
1108  t += r;
1109  r = MIN((size_t)r, n);
1110  s += r;
1111  n -= r;
1112  }
1113  r = snprintf(s, n, "\n\t\t\t}) }");
1114  } else {
1115  r = snprintf(s, n, "{ .dom = NULL }");
1116  }
1117  break;
1118  case CO_DEFTYPE_INTEGER24:
1119  if (u->i24 == CO_INTEGER24_MIN) {
1120  r = snprintf(s, n, "{ .i24 = CO_INTEGER24_MIN }");
1121  } else if (u->i24 == CO_INTEGER24_MAX) {
1122  r = snprintf(s, n, "{ .i24 = CO_INTEGER24_MAX }");
1123  } else {
1124  r = snprintf(s, n, "{ .i24 = %" PRIi32 "l }", u->i24);
1125  }
1126  break;
1127  case CO_DEFTYPE_REAL64:
1128  if (u->r64 == CO_REAL64_MIN) {
1129  r = snprintf(s, n, "{ .r64 = CO_REAL64_MIN }");
1130  } else if (u->r64 == CO_REAL64_MAX) {
1131  r = snprintf(s, n, "{ .r64 = CO_REAL64_MAX }");
1132  } else {
1133  r = snprintf(s, n, "{ .r64 = %.*g }", DECIMAL_DIG,
1134  u->r64);
1135  }
1136  break;
1137  case CO_DEFTYPE_INTEGER40:
1138  if (u->i40 == CO_INTEGER40_MIN) {
1139  r = snprintf(s, n, "{ CO_INTEGER40_MIN }");
1140  } else if (u->i40 == CO_INTEGER40_MAX) {
1141  r = snprintf(s, n, "{ CO_INTEGER40_MAX }");
1142  } else {
1143  r = snprintf(s, n, "{ .i40 = %" PRIi64 "ll }", u->i40);
1144  }
1145  break;
1146  case CO_DEFTYPE_INTEGER48:
1147  if (u->i48 == CO_INTEGER48_MIN) {
1148  r = snprintf(s, n, "{ .i48 = CO_INTEGER48_MIN }");
1149  } else if (u->i48 == CO_INTEGER48_MAX) {
1150  r = snprintf(s, n, "{ .i48 = CO_INTEGER48_MAX }");
1151  } else {
1152  r = snprintf(s, n, "{ .i48 = %" PRIi64 "ll }", u->i48);
1153  }
1154  break;
1155  case CO_DEFTYPE_INTEGER56:
1156  if (u->i56 == CO_INTEGER56_MIN) {
1157  r = snprintf(s, n, "{ .i56 = CO_INTEGER56_MIN }");
1158  } else if (u->i56 == CO_INTEGER56_MAX) {
1159  r = snprintf(s, n, "{ .i56 = CO_INTEGER56_MAX }");
1160  } else {
1161  r = snprintf(s, n, "{ .i56 = %" PRIi64 "ll }", u->i56);
1162  }
1163  break;
1164  case CO_DEFTYPE_INTEGER64:
1165  if (u->i64 == CO_INTEGER64_MIN) {
1166  r = snprintf(s, n, "{ .i64 = CO_INTEGER64_MIN }");
1167  } else if (u->i64 == CO_INTEGER64_MAX) {
1168  r = snprintf(s, n, "{ .i64 = CO_INTEGER64_MAX }");
1169  } else {
1170  r = snprintf(s, n, "{ .i64 = %" PRIi64 "ll }", u->i64);
1171  }
1172  break;
1173  case CO_DEFTYPE_UNSIGNED24:
1174  if (u->u24 == CO_UNSIGNED24_MIN) {
1175  r = snprintf(s, n, "{ .u24 = CO_UNSIGNED24_MIN }");
1176  } else if (u->u24 == CO_UNSIGNED24_MAX) {
1177  r = snprintf(s, n, "{ .u24 = CO_UNSIGNED24_MAX }");
1178  } else {
1179  r = snprintf(s, n, "{ .u24 = 0x%06" PRIx32 "lu }",
1180  u->u24);
1181  }
1182  break;
1183  case CO_DEFTYPE_UNSIGNED40:
1184  if (u->u40 == CO_UNSIGNED40_MIN) {
1185  r = snprintf(s, n, "{ .u40 = CO_UNSIGNED40_MIN }");
1186  } else if (u->u40 == CO_UNSIGNED40_MAX) {
1187  r = snprintf(s, n, "{ .u40 = CO_UNSIGNED40_MAX }");
1188  } else {
1189  r = snprintf(s, n, "{ .u40 = 0x%010" PRIx64 "llu }",
1190  u->u40);
1191  }
1192  break;
1193  case CO_DEFTYPE_UNSIGNED48:
1194  if (u->u48 == CO_UNSIGNED48_MIN) {
1195  r = snprintf(s, n, "{ .u48 = CO_UNSIGNED48_MIN }");
1196  } else if (u->u48 == CO_UNSIGNED48_MAX) {
1197  r = snprintf(s, n, "{ .u48 = CO_UNSIGNED48_MAX }");
1198  } else {
1199  r = snprintf(s, n, "{ .u48 = 0x%012" PRIx64 "llu }",
1200  u->u48);
1201  }
1202  break;
1203  case CO_DEFTYPE_UNSIGNED56:
1204  if (u->u56 == CO_UNSIGNED56_MIN) {
1205  r = snprintf(s, n, "{ .u56 = CO_UNSIGNED56_MIN }");
1206  } else if (u->u56 == CO_UNSIGNED56_MAX) {
1207  r = snprintf(s, n, "{ .u56 = CO_UNSIGNED56_MAX }");
1208  } else {
1209  r = snprintf(s, n, "{ .u56 = 0x%014" PRIx64 "llu }",
1210  u->u56);
1211  }
1212  break;
1213  case CO_DEFTYPE_UNSIGNED64:
1214  if (u->u64 == CO_UNSIGNED64_MIN) {
1215  r = snprintf(s, n, "{ .u64 = CO_UNSIGNED64_MIN }");
1216  } else if (u->u64 == CO_UNSIGNED64_MAX) {
1217  r = snprintf(s, n, "{ .u64 = CO_UNSIGNED64_MAX }");
1218  } else {
1219  r = snprintf(s, n, "{ .u64 = 0x%016" PRIx64 "llu }",
1220  u->u64);
1221  }
1222  break;
1223  default: r = 0; break;
1224  }
1225  if (r < 0)
1226  return r;
1227  t += r;
1228 
1229  return t;
1230 }
1231 
1232 static int
1233 snprintf_c99_esc(char *s, size_t n, const char *esc)
1234 {
1235  if (!s)
1236  n = 0;
1237 
1238  if (!esc)
1239  return 0;
1240 
1241  int t = 0;
1242 
1243  for (;;) {
1244  // Read the next UTF-8 encoded Unicode character.
1245  char32_t c32;
1246  size_t chars = lex_utf8(esc, NULL, NULL, &c32);
1247  if (!chars || !c32)
1248  break;
1249  esc += chars;
1250  // Print the C99 escape sequence to a temporary buffer.
1251  char buf[12] = { '\0' };
1252  char *cp = buf;
1253  print_c99_esc(&cp, buf + sizeof(buf), c32);
1254  // Print the character to the string.
1255  int r = snprintf(s, n, "%s", buf);
1256  if (r < 0)
1257  return r;
1258  t += r;
1259  r = MIN((size_t)r, n);
1260  s += r;
1261  n -= r;
1262  }
1263 
1264  return t;
1265 }
1266 
1267 #endif // !LELY_NO_CO_SDEV
CO_DEFTYPE_UNSIGNED64
#define CO_DEFTYPE_UNSIGNED64
The data type (and object index) of a 64-bit unsigned integer.
Definition: type.h:110
co_obj_set_name
int co_obj_set_name(co_obj_t *obj, const char *name)
Sets the name of a CANopen object.
Definition: obj.c:262
CO_ACCESS_RW
#define CO_ACCESS_RW
Read or write access.
Definition: obj.h:75
CO_DEFTYPE_INTEGER8
#define CO_DEFTYPE_INTEGER8
The data type (and object index) of an 8-bit signed integer.
Definition: type.h:35
co_sub_set_max
size_t co_sub_set_max(co_sub_t *sub, const void *ptr, size_t n)
Sets the upper limit of a value of a CANopen sub-object.
Definition: obj.c:625
co_ssub::def
union co_val def
The default value of val.
Definition: sdev.h:95
co_val_init_max
int co_val_init_max(co_unsigned16_t type, void *val)
Initializes a value of the specified data type with its upper limit.
Definition: val.c:156
co_sdev::vendor_name
const char * vendor_name
A pointer to the vendor name.
Definition: sdev.h:36
CO_OBJ_FLAGS_DOWNLOAD_FILE
#define CO_OBJ_FLAGS_DOWNLOAD_FILE
If a write access is performed for the object, the data is stored in a file.
Definition: obj.h:102
co_sdev::product_code
co_unsigned32_t product_code
The product code.
Definition: sdev.h:42
co_dev_create_from_sdev
co_dev_t * co_dev_create_from_sdev(const struct co_sdev *sdev)
Creates a CANopen device from a static device description.
Definition: sdev.c:83
CO_INTEGER16_MIN
#define CO_INTEGER16_MIN
The minimum value of a 16-bit signed integer.
Definition: val.h:43
CO_DEFTYPE_INTEGER64
#define CO_DEFTYPE_INTEGER64
The data type (and object index) of a 64-bit signed integer.
Definition: type.h:95
co_sub_get_val
const void * co_sub_get_val(const co_sub_t *sub)
Returns a pointer to the current value of a CANopen sub-object.
Definition: obj.c:679
CO_UNSIGNED32_MIN
#define CO_UNSIGNED32_MIN
The minimum value of a 32-bit unsigned integer.
Definition: val.h:67
asprintf_c99_sdev
int asprintf_c99_sdev(char **ps, const co_dev_t *dev)
Equivalent to snprintf_c99_sdev(), except that it allocates a string large enough to hold the output,...
Definition: sdev.c:406
co_ssub::val
union co_val val
The sub-object value.
Definition: sdev.h:98
CO_REAL64_MIN
#define CO_REAL64_MIN
The minimum value of a 64-bit IEEE-754 floating-point number.
Definition: val.h:103
co_val_fini
void co_val_fini(co_unsigned16_t type, void *val)
Finalizes a value of the specified data type.
Definition: val.c:275
CO_DEFTYPE_INTEGER40
#define CO_DEFTYPE_INTEGER40
The data type (and object index) of a 40-bit signed integer.
Definition: type.h:86
CO_DEFTYPE_UNSIGNED32
#define CO_DEFTYPE_UNSIGNED32
The data type (and object index) of a 32-bit unsigned integer.
Definition: type.h:50
co_dev_get_vendor_id
co_unsigned32_t co_dev_get_vendor_id(const co_dev_t *dev)
Returns the vendor ID of a CANopen device.
Definition: dev.c:384
co_dev_get_rate
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:508
CO_ACCESS_RWW
#define CO_ACCESS_RWW
Read or write on process output.
Definition: obj.h:81
CO_DEFTYPE_INTEGER32
#define CO_DEFTYPE_INTEGER32
The data type (and object index) of a 32-bit signed integer.
Definition: type.h:41
co_ssub
A static CANopen sub-object.
Definition: sdev.h:78
co_val_init_min
int co_val_init_min(co_unsigned16_t type, void *val)
Initializes a value of the specified data type with its lower limit.
Definition: val.c:139
CO_DEFTYPE_UNSIGNED16
#define CO_DEFTYPE_UNSIGNED16
The data type (and object index) of a 16-bit unsigned integer.
Definition: type.h:47
CO_INTEGER56_MAX
#define CO_INTEGER56_MAX
The maximum value of a 56-bit signed integer (encoded as an int64_t).
Definition: val.h:124
co_val_addressof
const void * co_val_addressof(co_unsigned16_t type, const void *val)
Returns the address of the first byte in a value of the specified data type.
Definition: val.c:286
co_ssub::name
const char * name
A pointer to the name of the sub-object.
Definition: sdev.h:81
co_sub_get_name
const char * co_sub_get_name(const co_sub_t *sub)
Returns the name of a CANopen sub-object.
Definition: obj.c:538
co_sub_get_def
const void * co_sub_get_def(const co_sub_t *sub)
Returns a pointer to the default value of a CANopen sub-object.
Definition: obj.c:650
co_obj_set_code
int co_obj_set_code(co_obj_t *obj, co_unsigned8_t code)
Sets the code (type) of a CANopen object.
Definition: obj.c:294
__co_dev::baud
unsigned baud
The supported bit rates.
Definition: dev.c:63
MIN
#define MIN(a, b)
Returns the minimum of a and b.
Definition: util.h:57
co_obj_get_idx
co_unsigned16_t co_obj_get_idx(const co_obj_t *obj)
Returns the index of a CANopen object.
Definition: obj.c:154
co_dev_set_rate
void co_dev_set_rate(co_dev_t *dev, co_unsigned16_t rate)
Sets the (pending) baudrate of a CANopen device.
Definition: dev.c:516
CO_INTEGER56_MIN
#define CO_INTEGER56_MIN
The minimum value of a 56-bit signed integer (encoded as an int64_t).
Definition: val.h:121
CO_INTEGER40_MIN
#define CO_INTEGER40_MIN
The minimum value of a 40-bit signed integer (encoded as an int64_t).
Definition: val.h:109
CO_UNSIGNED8_MIN
#define CO_UNSIGNED8_MIN
The minimum value of an 8-bit unsigned integer.
Definition: val.h:55
co_dev_get_name
const char * co_dev_get_name(const co_dev_t *dev)
Returns the name of a CANopen device.
Definition: dev.c:324
CO_DEFTYPE_TIME_DIFF
#define CO_DEFTYPE_TIME_DIFF
The data type (and object index) of a 48-bit structure representing a time difference.
Definition: type.h:74
co_dev_get_id
co_unsigned8_t co_dev_get_id(const co_dev_t *dev)
Returns the node-ID of a CANopen device.
Definition: dev.c:207
get_errc
int get_errc(void)
Returns the last (thread-specific) native error code set by a system call or library function.
Definition: errnum.c:947
co_dev_get_product_name
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:400
CO_DEFTYPE_BOOLEAN
#define CO_DEFTYPE_BOOLEAN
The data type (and object index) of a boolean truth value.
Definition: type.h:32
CO_DEFTYPE_VISIBLE_STRING
#define CO_DEFTYPE_VISIBLE_STRING
The data type (and object index) of an array of visible characters.
Definition: type.h:56
co_sub_get_pdo_mapping
int co_sub_get_pdo_mapping(const co_sub_t *sub)
Returns 1 if it is possible to map the specified CANopen sub-object into a PDO, and 0 if not.
Definition: obj.c:769
co_sub_set_val
size_t co_sub_set_val(co_sub_t *sub, const void *ptr, size_t n)
Sets the current value of a CANopen sub-object.
Definition: obj.c:685
lex.h
CO_DEFTYPE_UNSIGNED8
#define CO_DEFTYPE_UNSIGNED8
The data type (and object index) of an 8-bit unsigned integer.
Definition: type.h:44
CO_DEFTYPE_DOMAIN
#define CO_DEFTYPE_DOMAIN
The data type (and object index) of an arbitrary large block of data.
Definition: type.h:77
co_dev_set_product_code
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:438
CO_INTEGER64_MIN
#define CO_INTEGER64_MIN
The minimum value of a 64-bit signed integer.
Definition: val.h:127
co.h
CO_UNSIGNED16_MIN
#define CO_UNSIGNED16_MIN
The minimum value of a 16-bit unsigned integer.
Definition: val.h:61
CO_INTEGER48_MIN
#define CO_INTEGER48_MIN
The minimum value of a 48-bit signed integer (encoded as an int64_t).
Definition: val.h:115
CO_UNSIGNED48_MIN
#define CO_UNSIGNED48_MIN
The minimum value of a 48-bit unsigned integer (encoded as a uint64_t).
Definition: val.h:145
CO_INTEGER32_MIN
#define CO_INTEGER32_MIN
The minimum value of a 32-bit signed integer.
Definition: val.h:49
CO_REAL32_MIN
#define CO_REAL32_MIN
The minimum value of a 32-bit IEEE-754 floating-point number.
Definition: val.h:73
co_dev_set_lss
void co_dev_set_lss(co_dev_t *dev, int lss)
Sets the LSS support flag.
Definition: dev.c:532
co_sdev::dummy
co_unsigned32_t dummy
The data types supported for mapping dummy entries in PDOs.
Definition: sdev.h:54
co_dev_get_revision
co_unsigned32_t co_dev_get_revision(const co_dev_t *dev)
Returns the revision number of a CANopen device.
Definition: dev.c:446
co_ssub::access
unsigned long access
The access type.
Definition: sdev.h:100
co_obj_find_sub
co_sub_t * co_obj_find_sub(const co_obj_t *obj, co_unsigned8_t subidx)
Finds a sub-object in a CANopen object.
Definition: obj.c:225
co_sdev::objs
const struct co_sobj * objs
An array of objects.
Definition: sdev.h:58
CO_OBJECT_DOMAIN
#define CO_OBJECT_DOMAIN
A large variable amount of data.
Definition: obj.h:33
CO_DEFTYPE_OCTET_STRING
#define CO_DEFTYPE_OCTET_STRING
The data type (and object index) of an array of octets.
Definition: type.h:59
CO_DEFTYPE_INTEGER56
#define CO_DEFTYPE_INTEGER56
The data type (and object index) of a 56-bit signed integer.
Definition: type.h:92
CO_OBJECT_DEFTYPE
#define CO_OBJECT_DEFTYPE
A type definitions.
Definition: obj.h:36
CO_DEFTYPE_REAL64
#define CO_DEFTYPE_REAL64
The data type (and object index) of a 64-bit IEEE-754 floating-point number.
Definition: type.h:83
co_sub_set_flags
void co_sub_set_flags(co_sub_t *sub, unsigned int flags)
Sets the object flags of a CANopen sub-object.
Definition: obj.c:793
co_obj_create
co_obj_t * co_obj_create(co_unsigned16_t idx)
Creates a CANopen object.
Definition: obj.c:106
co_sdev::lss
int lss
A flag specifying whether LSS is supported (1) or not (0).
Definition: sdev.h:52
CO_ACCESS_RWR
#define CO_ACCESS_RWR
Read or write on process input.
Definition: obj.h:78
co_sdev::name
const char * name
A pointer to the name of the device.
Definition: sdev.h:34
co_dev_get_dummy
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:540
co_sub_get_flags
unsigned int co_sub_get_flags(const co_sub_t *sub)
Returns the object flags of a CANopen sub-object.
Definition: obj.c:785
co_sub_destroy
void co_sub_destroy(co_sub_t *sub)
Destroys a CANopen sub-object.
Definition: obj.c:493
co_sub_set_name
int co_sub_set_name(co_sub_t *sub, const char *name)
Sets the name of a CANopen sub-object.
Definition: obj.c:546
set_errc
void set_errc(int errc)
Sets the current (thread-specific) native error code to errc.
Definition: errnum.c:957
lex_utf8
size_t lex_utf8(const char *begin, const char *end, struct floc *at, char32_t *pc32)
Lexes a UTF-8 encoded Unicode character from a memory buffer.
Definition: lex.c:83
CO_DEFTYPE_UNSIGNED56
#define CO_DEFTYPE_UNSIGNED56
The data type (and object index) of a 56-bit unsigned integer.
Definition: type.h:107
co_sobj::code
co_unsigned8_t code
The object code.
Definition: sdev.h:70
co_sdev::product_name
const char * product_name
A pointer to the product name.
Definition: sdev.h:40
co_sdev::vendor_id
co_unsigned32_t vendor_id
The vendor ID.
Definition: sdev.h:38
CO_INTEGER8_MIN
#define CO_INTEGER8_MIN
The minimum value of an 8-bit signed integer.
Definition: val.h:37
CO_UNSIGNED56_MAX
#define CO_UNSIGNED56_MAX
The maximum value of a 56-bit unsigned integer (encoded as a uint64_t).
Definition: val.h:154
errnum2c
int errnum2c(errnum_t errnum)
Transforms a platform-independent error number to a native error code.
Definition: errnum.c:825
co_sdev::rate
co_unsigned16_t rate
The (pending) baudrate (in kbit/s).
Definition: sdev.h:50
errnum.h
CO_INTEGER40_MAX
#define CO_INTEGER40_MAX
The maximum value of a 40-bit signed integer (encoded as an int64_t).
Definition: val.h:112
CO_INTEGER48_MAX
#define CO_INTEGER48_MAX
The maximum value of a 48-bit signed integer (encoded as an int64_t).
Definition: val.h:118
co_val_sizeof
size_t co_val_sizeof(co_unsigned16_t type, const void *val)
Returns the size (in bytes) of a value of the specified data type.
Definition: val.c:295
co_ssub::pdo_mapping
unsigned long pdo_mapping
A flag indicating if it is possible to map this object into a PDO.
Definition: sdev.h:102
co_obj_get_name
const char * co_obj_get_name(const co_obj_t *obj)
Returns the name of a CANopen object.
Definition: obj.c:254
CO_UNSIGNED24_MAX
#define CO_UNSIGNED24_MAX
The maximum value of a 24-bit unsigned integer (encoded as a uint32_t).
Definition: val.h:136
co_dev_get_idx
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:233
CO_UNSIGNED16_MAX
#define CO_UNSIGNED16_MAX
The maximum value of a 16-bit unsigned integer.
Definition: val.h:64
CO_DEFTYPE_UNSIGNED24
#define CO_DEFTYPE_UNSIGNED24
The data type (and object index) of a 24-bit unsigned integer.
Definition: type.h:98
co_sdev::id
co_unsigned8_t id
The node-ID.
Definition: sdev.h:32
ERRNUM_INVAL
@ ERRNUM_INVAL
Invalid argument.
Definition: errnum.h:129
co_sub_get_max
const void * co_sub_get_max(const co_sub_t *sub)
Returns a pointer to the upper limit of the value of a CANopen sub-object.
Definition: obj.c:619
stdio.h
print.h
CO_UNSIGNED64_MAX
#define CO_UNSIGNED64_MAX
The maximum value of a 64-bit unsigned integer.
Definition: val.h:160
CO_UNSIGNED64_MIN
#define CO_UNSIGNED64_MIN
The minimum value of a 64-bit unsigned integer.
Definition: val.h:157
CO_DEFTYPE_INTEGER48
#define CO_DEFTYPE_INTEGER48
The data type (and object index) of a 48-bit signed integer.
Definition: type.h:89
co_dev_get_vendor_name
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:354
CO_OBJECT_ARRAY
#define CO_OBJECT_ARRAY
A multiple data field object where each data field is a simple variable of the same basic data type.
Definition: obj.h:48
co_dev_set_order_code
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:470
co_dev_set_revision
void co_dev_set_revision(co_dev_t *dev, co_unsigned32_t revision)
Sets the revision number of a CANopen device.
Definition: dev.c:454
co_sub_get_access
unsigned int co_sub_get_access(const co_sub_t *sub)
Returns the access type of a CANopen sub-object.
Definition: obj.c:745
co_sdev
A static CANopen device.
Definition: sdev.h:30
co_dev_set_vendor_name
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:362
CO_OBJECT_DEFSTRUCT
#define CO_OBJECT_DEFSTRUCT
A record type definition.
Definition: obj.h:39
CO_OBJECT_NULL
#define CO_OBJECT_NULL
An object with no data fields.
Definition: obj.h:30
co_ssub::max
union co_val max
The upper limit of val.
Definition: sdev.h:91
snprintf_c99_sdev
int snprintf_c99_sdev(char *s, size_t n, const co_dev_t *dev)
Prints a C99 static initializer code fragment for a static device description (struct co_sdev) to a s...
Definition: sdev.c:108
co_sub_set_def
size_t co_sub_set_def(co_sub_t *sub, const void *ptr, size_t n)
Sets the default value of a CANopen sub-object.
Definition: obj.c:656
__co_dev::name
char * name
A pointer to the name of the device.
Definition: dev.c:49
CO_INTEGER24_MAX
#define CO_INTEGER24_MAX
The maximum value of a 24-bit signed integer (encoded as an int32_t).
Definition: val.h:100
CO_DEFTYPE_TIME_OF_DAY
#define CO_DEFTYPE_TIME_OF_DAY
The data type (and object index) of a 48-bit structure representing the absolute time.
Definition: type.h:68
CO_UNSIGNED40_MAX
#define CO_UNSIGNED40_MAX
The maximum value of a 40-bit unsigned integer (encoded as a uint64_t).
Definition: val.h:142
co_sobj::name
const char * name
A pointer to the name of the object.
Definition: sdev.h:65
co_val
A union of the CANopen static data types.
Definition: val.h:163
co_sdev::baud
unsigned baud
The supported bit rates.
Definition: sdev.h:48
co_dev_get_order_code
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:462
co_sub_set_pdo_mapping
void co_sub_set_pdo_mapping(co_sub_t *sub, int pdo_mapping)
Enables or disables PDO mapping a CANopen sub-object.
Definition: obj.c:777
co_dev_set_baud
void co_dev_set_baud(co_dev_t *dev, unsigned int baud)
Sets the supported bit rates of a CANopen device.
Definition: dev.c:500
co_sdev::order_code
const char * order_code
A pointer to the order code.
Definition: sdev.h:46
__co_obj
A CANopen object.
Definition: obj.h:32
CO_DEFTYPE_REAL32
#define CO_DEFTYPE_REAL32
The data type (and object index) of a 32-bit IEEE-754 floating-point number.
Definition: type.h:53
co_obj_get_subidx
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:162
co_dev_set_product_name
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:408
co_ssub::type
co_unsigned16_t type
The data type.
Definition: sdev.h:86
__co_dev
A CANopen device.
Definition: dev.c:41
co_sobj::nsub
co_unsigned8_t nsub
The number of sub-objects in subs.
Definition: sdev.h:72
CO_INTEGER64_MAX
#define CO_INTEGER64_MAX
The maximum value of a 64-bit signed integer.
Definition: val.h:130
CO_UNSIGNED8_MAX
#define CO_UNSIGNED8_MAX
The maximum value of an 8-bit unsigned integer.
Definition: val.h:58
co_ssub::min
union co_val min
The lower limit of val.
Definition: sdev.h:89
co_sub_get_min
const void * co_sub_get_min(const co_sub_t *sub)
Returns a pointer to the lower limit of the value of a CANopen sub-object.
Definition: obj.c:592
print_c99_esc
size_t print_c99_esc(char **pbegin, char *end, char32_t c32)
Prints a UTF-8 encoded Unicode character to a memory buffer.
Definition: print.c:106
co_sdev::revision
co_unsigned32_t revision
The revision number.
Definition: sdev.h:44
CO_OBJECT_RECORD
#define CO_OBJECT_RECORD
A multiple data field object where the data fields may be any combination of simple variables.
Definition: obj.h:54
CO_DEFTYPE_INTEGER16
#define CO_DEFTYPE_INTEGER16
The data type (and object index) of a 16-bit signed integer.
Definition: type.h:38
CO_DEFTYPE_UNICODE_STRING
#define CO_DEFTYPE_UNICODE_STRING
The data type (and object index) of an array of (16-bit) Unicode characters.
Definition: type.h:62
co_sobj::idx
co_unsigned16_t idx
The object index.
Definition: sdev.h:68
CO_REAL64_MAX
#define CO_REAL64_MAX
The maximum value of a 64-bit IEEE-754 floating-point number.
Definition: val.h:106
CO_ACCESS_WO
#define CO_ACCESS_WO
Write-only access.
Definition: obj.h:72
CO_DEFTYPE_INTEGER24
#define CO_DEFTYPE_INTEGER24
The data type (and object index) of a 24-bit signed integer.
Definition: type.h:80
co_sub_set_access
int co_sub_set_access(co_sub_t *sub, unsigned int access)
Sets the access type of a CANopen sub-object.
Definition: obj.c:753
CO_REAL32_MAX
#define CO_REAL32_MAX
The maximum value of a 32-bit IEEE-754 floating-point number.
Definition: val.h:76
co_dev_get_lss
int co_dev_get_lss(const co_dev_t *dev)
Returns 1 if LSS is supported and 0 if not.
Definition: dev.c:524
CO_ACCESS_CONST
#define CO_ACCESS_CONST
Constant value.
Definition: obj.h:84
CO_INTEGER24_MIN
#define CO_INTEGER24_MIN
The minimum value of a 24-bit signed integer (encoded as an int32_t).
Definition: val.h:97
co_obj_get_code
co_unsigned8_t co_obj_get_code(const co_obj_t *obj)
Returns the object code of a CANopen object.
Definition: obj.c:286
co_dev_set_vendor_id
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:392
co_sub_get_subidx
co_unsigned8_t co_sub_get_subidx(const co_sub_t *sub)
Returns the sub-index of a CANopen sub-object.
Definition: obj.c:528
co_dev_set_name
int co_dev_set_name(co_dev_t *dev, const char *name)
Sets the name of a CANopen device.
Definition: dev.c:332
co_ssub::flags
unsigned long flags
The object flags.
Definition: sdev.h:104
co_sub_create
co_sub_t * co_sub_create(co_unsigned8_t subidx, co_unsigned16_t type)
Creates a CANopen sub-object.
Definition: obj.c:468
sdev.h
CO_UNSIGNED24_MIN
#define CO_UNSIGNED24_MIN
The minimum value of a 24-bit unsigned integer (encoded as a uint32_t).
Definition: val.h:133
co_sobj
A static CANopen object.
Definition: sdev.h:62
stdlib.h
co_sub_set_min
size_t co_sub_set_min(co_sub_t *sub, const void *ptr, size_t n)
Sets the lower limit of a value of a CANopen sub-object.
Definition: obj.c:598
co_dev_set_dummy
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:548
co_sdev::nobj
co_unsigned16_t nobj
The number of objects in objs.
Definition: sdev.h:56
co_ssub::subidx
co_unsigned8_t subidx
The object sub-index.
Definition: sdev.h:84
CO_INTEGER16_MAX
#define CO_INTEGER16_MAX
The maximum value of a 16-bit signed integer.
Definition: val.h:46
__co_sub
A CANopen sub-object.
Definition: obj.h:54
co_dev_get_baud
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:492
CO_OBJ_FLAGS_UPLOAD_FILE
#define CO_OBJ_FLAGS_UPLOAD_FILE
If a read access is performed for the object, the data is stored in a file.
Definition: obj.h:96
CO_INTEGER8_MAX
#define CO_INTEGER8_MAX
The maximum value of an 8-bit signed integer.
Definition: val.h:40
co_sub_get_type
co_unsigned16_t co_sub_get_type(const co_sub_t *sub)
Returns the data type of a CANopen sub-object.
Definition: obj.c:570
CO_UNSIGNED32_MAX
#define CO_UNSIGNED32_MAX
The maximum value of a 32-bit unsigned integer.
Definition: val.h:70
CO_ACCESS_RO
#define CO_ACCESS_RO
Read-only access.
Definition: obj.h:69
co_dev_insert_obj
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:252
CO_DEFTYPE_UNSIGNED40
#define CO_DEFTYPE_UNSIGNED40
The data type (and object index) of a 40-bit unsigned integer.
Definition: type.h:101
CO_INTEGER32_MAX
#define CO_INTEGER32_MAX
The maximum value of a 32-bit signed integer.
Definition: val.h:52
CO_OBJECT_VAR
#define CO_OBJECT_VAR
A single value.
Definition: obj.h:42
co_sobj::subs
const struct co_ssub * subs
An array of sub-objects.
Definition: sdev.h:74
co_obj_destroy
void co_obj_destroy(co_obj_t *obj)
Destroys a CANopen object, including its sub-objects.
Definition: obj.c:118
co_dev_get_product_code
co_unsigned32_t co_dev_get_product_code(const co_dev_t *dev)
Returns the product code of a CANopen device.
Definition: dev.c:430
CO_DEFTYPE_UNSIGNED48
#define CO_DEFTYPE_UNSIGNED48
The data type (and object index) of a 48-bit unsigned integer.
Definition: type.h:104
CO_UNSIGNED56_MIN
#define CO_UNSIGNED56_MIN
The minimum value of a 56-bit unsigned integer (encoded as a uint64_t).
Definition: val.h:151
co_obj_insert_sub
int co_obj_insert_sub(co_obj_t *obj, co_sub_t *sub)
Inserts a sub-object into a CANopen object.
Definition: obj.c:182
CO_UNSIGNED40_MIN
#define CO_UNSIGNED40_MIN
The minimum value of a 40-bit unsigned integer (encoded as a uint64_t).
Definition: val.h:139
co_dev_find_obj
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:288
CO_UNSIGNED48_MAX
#define CO_UNSIGNED48_MAX
The maximum value of a 48-bit unsigned integer (encoded as a uint64_t).
Definition: val.h:148