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