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