Lely core libraries 1.9.2
gw_txt.c
Go to the documentation of this file.
1
24#include "co.h"
25
26#ifndef LELY_NO_CO_GW_TXT
27
28#include <lely/co/dev.h>
29#include <lely/co/gw_txt.h>
30#include <lely/co/nmt.h>
31#include <lely/co/pdo.h>
32#include <lely/co/sdo.h>
33#include <lely/co/val.h>
34#include <lely/libc/stdio.h>
35#include <lely/libc/strings.h>
36#include <lely/util/diag.h>
37#include <lely/util/lex.h>
38#include <lely/util/print.h>
39
40#include <assert.h>
41#include <inttypes.h>
42#include <stdlib.h>
43
47 int iec;
49 size_t pending;
53 void *recv_data;
57 void *send_data;
58};
59
61static int co_gw_txt_recv_con(co_gw_txt_t *gw, co_unsigned32_t seq,
62 const struct co_gw_con *con);
63
65static int co_gw_txt_recv_sdo_up(co_gw_txt_t *gw, co_unsigned32_t seq,
66 const struct co_gw_con_sdo_up *con);
67
69static int co_gw_txt_recv_pdo_read(co_gw_txt_t *gw, co_unsigned32_t seq,
70 const struct co_gw_con_pdo_read *con);
71
73static int co_gw_txt_recv_get_version(co_gw_txt_t *gw, co_unsigned32_t seq,
74 const struct co_gw_con_get_version *con);
75
77static int co_gw_txt_recv_lss_get_lssid(co_gw_txt_t *gw, co_unsigned32_t seq,
78 const struct co_gw_con_lss_get_lssid *con);
80static int co_gw_txt_recv_lss_get_id(co_gw_txt_t *gw, co_unsigned32_t seq,
81 const struct co_gw_con_lss_get_id *con);
82
84static int co_gw_txt_recv__lss_scan(co_gw_txt_t *gw, co_unsigned32_t seq,
85 const struct co_gw_con__lss_scan *con);
86
91static int co_gw_txt_recv_err(co_gw_txt_t *gw, co_unsigned32_t seq, int iec,
92 co_unsigned32_t ac);
93
95static int co_gw_txt_recv_rpdo(
96 co_gw_txt_t *gw, const struct co_gw_ind_rpdo *ind);
97
99static int co_gw_txt_recv_ec(co_gw_txt_t *gw, const struct co_gw_ind_ec *ind);
100
102static int co_gw_txt_recv_emcy(
103 co_gw_txt_t *gw, const struct co_gw_ind_emcy *ind);
104
106static int co_gw_txt_recv_sdo(co_gw_txt_t *gw, const struct co_gw_ind_sdo *ind);
107
109static int co_gw_txt_recv__boot(
110 co_gw_txt_t *gw, const struct co_gw_ind__boot *ind);
111
118static int co_gw_txt_recv_fmt(co_gw_txt_t *gw, const char *format, ...)
119 format_printf__(2, 3);
120
125static int co_gw_txt_recv_txt(co_gw_txt_t *gw, const char *txt);
126
128static size_t co_gw_txt_print_val(char **pbegin, char *end,
129 co_unsigned16_t type, const void *val);
130
132static void co_gw_txt_send_req(co_gw_txt_t *gw, const struct co_gw_req *req);
133
135static size_t co_gw_txt_send_sdo_up(co_gw_txt_t *gw, int srv, void *data,
136 co_unsigned16_t net, co_unsigned8_t node, const char *begin,
137 const char *end, struct floc *at);
139static size_t co_gw_txt_send_sdo_dn(co_gw_txt_t *gw, int srv, void *data,
140 co_unsigned16_t net, co_unsigned8_t node, const char *begin,
141 const char *end, struct floc *at);
143static size_t co_gw_txt_send_set_sdo_timeout(co_gw_txt_t *gw, int srv,
144 void *data, co_unsigned16_t net, const char *begin,
145 const char *end, struct floc *at);
146
148static size_t co_gw_txt_send_set_rpdo(co_gw_txt_t *gw, int srv, void *data,
149 co_unsigned16_t net, const char *begin, const char *end,
150 struct floc *at);
152static size_t co_gw_txt_send_set_tpdo(co_gw_txt_t *gw, int srv, void *data,
153 co_unsigned16_t net, const char *begin, const char *end,
154 struct floc *at);
156static size_t co_gw_txt_send_pdo_read(co_gw_txt_t *gw, int srv, void *data,
157 co_unsigned16_t net, const char *begin, const char *end,
158 struct floc *at);
160static size_t co_gw_txt_send_pdo_write(co_gw_txt_t *gw, int srv, void *data,
161 co_unsigned16_t net, const char *begin, const char *end,
162 struct floc *at);
163
165static size_t co_gw_txt_send_nmt_set_ng(co_gw_txt_t *gw, int srv, void *data,
166 co_unsigned16_t net, co_unsigned8_t node, const char *begin,
167 const char *end, struct floc *at);
169static size_t co_gw_txt_send_nmt_set_hb(co_gw_txt_t *gw, int srv, void *data,
170 co_unsigned16_t net, co_unsigned8_t node, const char *begin,
171 const char *end, struct floc *at);
172
174static size_t co_gw_txt_send_init(co_gw_txt_t *gw, int srv, void *data,
175 co_unsigned16_t net, const char *begin, const char *end,
176 struct floc *at);
178static size_t co_gw_txt_send_set_hb(co_gw_txt_t *gw, int srv, void *data,
179 co_unsigned16_t net, const char *begin, const char *end,
180 struct floc *at);
182static size_t co_gw_txt_send_set_id(co_gw_txt_t *gw, int srv, void *data,
183 co_unsigned16_t net, const char *begin, const char *end,
184 struct floc *at);
186static size_t co_gw_txt_send_set_cmd_timeout(co_gw_txt_t *gw, int srv,
187 void *data, const char *begin, const char *end,
188 struct floc *at);
190static size_t co_gw_txt_send_set_bootup_ind(co_gw_txt_t *gw, int srv,
191 void *data, co_unsigned16_t net, const char *begin,
192 const char *end, struct floc *at);
193
195static size_t co_gw_txt_send_set_net(co_gw_txt_t *gw, int srv, void *data,
196 const char *begin, const char *end, struct floc *at);
198static size_t co_gw_txt_send_set_node(co_gw_txt_t *gw, int srv, void *data,
199 co_unsigned16_t net, const char *begin, const char *end,
200 struct floc *at);
202static size_t co_gw_txt_send_set_cmd_size(co_gw_txt_t *gw, int srv, void *data,
203 const char *begin, const char *end, struct floc *at);
204
206static size_t co_gw_txt_send_lss_switch(co_gw_txt_t *gw, int srv, void *data,
207 co_unsigned16_t net, const char *begin, const char *end,
208 struct floc *at);
210static size_t co_gw_txt_send_lss_switch_sel(co_gw_txt_t *gw, int srv,
211 void *data, co_unsigned16_t net, const char *begin,
212 const char *end, struct floc *at);
214static size_t co_gw_txt_send_lss_set_id(co_gw_txt_t *gw, int srv, void *data,
215 co_unsigned16_t net, const char *begin, const char *end,
216 struct floc *at);
218static size_t co_gw_txt_send_lss_set_rate(co_gw_txt_t *gw, int srv, void *data,
219 co_unsigned16_t net, const char *begin, const char *end,
220 struct floc *at);
222static size_t co_gw_txt_send_lss_switch_rate(co_gw_txt_t *gw, int srv,
223 void *data, co_unsigned16_t net, const char *begin,
224 const char *end, struct floc *at);
226static size_t co_gw_txt_send_lss_get_lssid(co_gw_txt_t *gw, int srv, void *data,
227 co_unsigned16_t net, const char *begin, const char *end,
228 struct floc *at);
230static size_t co_gw_txt_send_lss_id_slave(co_gw_txt_t *gw, int srv, void *data,
231 co_unsigned16_t net, const char *begin, const char *end,
232 struct floc *at);
233
235static size_t co_gw_txt_send__lss_slowscan(co_gw_txt_t *gw, int srv, void *data,
236 co_unsigned16_t net, const char *begin, const char *end,
237 struct floc *at);
239static size_t co_gw_txt_send__lss_fastscan(co_gw_txt_t *gw, int srv, void *data,
240 co_unsigned16_t net, const char *begin, const char *end,
241 struct floc *at);
242
247static size_t co_gw_txt_lex_prefix(const char *begin, const char *end,
248 struct floc *at, co_unsigned32_t *pseq, co_unsigned16_t *pnet,
249 co_unsigned8_t *pnode);
250
252static size_t co_gw_txt_lex_srv(
253 const char *begin, const char *end, struct floc *at, int *psrv);
254
256static size_t co_gw_txt_lex_cmd(
257 const char *begin, const char *end, struct floc *at);
258
260static size_t co_gw_txt_lex_sdo(const char *begin, const char *end,
261 struct floc *at, co_unsigned16_t *pidx, co_unsigned8_t *psubidx,
262 co_unsigned16_t *ptype);
263
265static size_t co_gw_txt_lex_pdo(const char *begin, const char *end,
266 struct floc *at, int ext, co_unsigned16_t *pnum,
267 struct co_pdo_comm_par *pcomm, struct co_pdo_map_par *pmap);
268
270static size_t co_gw_txt_lex_type(const char *begin, const char *end,
271 struct floc *at, co_unsigned16_t *ptype);
272
274static size_t co_gw_txt_lex_val(const char *begin, const char *end,
275 struct floc *at, co_unsigned16_t type, void *val);
276
281static size_t co_gw_txt_lex_vs(const char *begin, const char *end,
282 struct floc *at, char *s, size_t *pn);
283
285static size_t co_gw_txt_lex_trans(const char *begin, const char *end,
286 struct floc *at, co_unsigned8_t *ptrans);
287
289static size_t co_gw_txt_lex_id(const char *begin, const char *end,
290 struct floc *at, struct co_id *pid);
291
293static size_t co_gw_txt_lex_id_sel(const char *begin, const char *end,
294 struct floc *at, struct co_id *plo, struct co_id *phi);
295
296void *
297__co_gw_txt_alloc(void)
298{
299 void *ptr = malloc(sizeof(struct __co_gw_txt));
300 if (__unlikely(!ptr))
301 set_errc(errno2c(errno));
302 return ptr;
303}
304
305void
306__co_gw_txt_free(void *ptr)
307{
308 free(ptr);
309}
310
311struct __co_gw_txt *
312__co_gw_txt_init(struct __co_gw_txt *gw)
313{
314 assert(gw);
315
316 gw->iec = 0;
317 gw->pending = 0;
318
319 gw->recv_func = NULL;
320 gw->recv_data = NULL;
321
322 gw->send_func = NULL;
323 gw->send_data = NULL;
324
325 return gw;
326}
327
328void
329__co_gw_txt_fini(struct __co_gw_txt *gw)
330{
331 (void)gw;
332}
333
336{
337 int errc = 0;
338
339 co_gw_txt_t *gw = __co_gw_txt_alloc();
340 if (__unlikely(!gw)) {
341 errc = get_errc();
342 goto error_alloc_gw;
343 }
344
345 if (__unlikely(!__co_gw_txt_init(gw))) {
346 errc = get_errc();
347 goto error_init_gw;
348 }
349
350 return gw;
351
352error_init_gw:
353 __co_gw_txt_free(gw);
354error_alloc_gw:
355 set_errc(errc);
356 return NULL;
357}
358
359void
361{
362 if (gw) {
363 __co_gw_txt_fini(gw);
364 __co_gw_txt_free(gw);
365 }
366}
367
368int
370{
371 assert(gw);
372
373 int iec = gw->iec;
374 gw->iec = 0;
375 return iec;
376}
377
378size_t
380{
381 assert(gw);
382
383 return gw->pending;
384}
385
386int
387co_gw_txt_recv(co_gw_txt_t *gw, const struct co_gw_srv *srv)
388{
389 assert(srv);
390
391 if (__unlikely(srv->size < sizeof(*srv))) {
393 return -1;
394 }
395
396 switch (srv->srv) {
397 case CO_GW_SRV_SDO_UP:
398 case CO_GW_SRV_SDO_DN:
413 case CO_GW_SRV_INIT:
414 case CO_GW_SRV_SET_HB:
415 case CO_GW_SRV_SET_ID:
434 if (__unlikely(srv->size < sizeof(struct co_gw_con))) {
436 return -1;
437 }
438 const struct co_gw_con *con = (const struct co_gw_con *)srv;
439 co_unsigned32_t seq = (uintptr_t)con->data;
440 return co_gw_txt_recv_con(gw, seq, con);
441 case CO_GW_SRV_RPDO:
442 if (__unlikely(srv->size < CO_GW_IND_RPDO_SIZE)) {
444 return -1;
445 }
446 return co_gw_txt_recv_rpdo(
447 gw, (const struct co_gw_ind_rpdo *)srv);
448 case CO_GW_SRV_EC:
449 if (__unlikely(srv->size < sizeof(struct co_gw_ind_ec))) {
451 return -1;
452 }
453 return co_gw_txt_recv_ec(gw, (const struct co_gw_ind_ec *)srv);
454 case CO_GW_SRV_EMCY:
455 if (__unlikely(srv->size < sizeof(struct co_gw_ind_emcy))) {
457 return -1;
458 }
459 return co_gw_txt_recv_emcy(
460 gw, (const struct co_gw_ind_emcy *)srv);
461 case CO_GW_SRV_SDO:
462 if (__unlikely(srv->size < sizeof(struct co_gw_ind_sdo))) {
464 return -1;
465 }
466 return co_gw_txt_recv_sdo(
467 gw, (const struct co_gw_ind_sdo *)srv);
468 case CO_GW_SRV__SYNC:
469 case CO_GW_SRV__TIME:
470 // Ignore synchronization and time stamp events.
471 return 0;
472 case CO_GW_SRV__BOOT:
473 if (__unlikely(srv->size < sizeof(struct co_gw_ind__boot))) {
475 return -1;
476 }
478 gw, (const struct co_gw_ind__boot *)srv);
479 default: set_errnum(ERRNUM_INVAL); return -1;
480 }
481}
482
483void
485 void **pdata)
486{
487 assert(gw);
488
489 if (pfunc)
490 *pfunc = gw->recv_func;
491 if (pdata)
492 *pdata = gw->recv_data;
493}
494
495size_t
496co_gw_txt_send(co_gw_txt_t *gw, const char *begin, const char *end,
497 struct floc *at)
498{
499 assert(gw);
500 assert(begin);
501 assert(!end || end >= begin);
502
503 struct floc *floc = NULL;
504 struct floc floc_;
505 if (at) {
506 floc = &floc_;
507 *floc = *at;
508 }
509
510 int iec = CO_GW_IEC_SYNTAX;
511
512 const char *cp = begin;
513 size_t chars = 0;
514
515 // Skip leading whitespace and/or comments.
516 for (;;) {
517 cp += lex_ctype(&isspace, cp, end, floc);
518 if (!(chars = lex_line_comment("#", cp, end, floc)))
519 break;
520 cp += chars;
521 }
522
523 // Ignore empty requests.
524 if ((end && cp >= end) || !*cp)
525 goto done;
526
527 co_unsigned32_t seq = 0;
528 co_unsigned16_t net = 0;
529 co_unsigned8_t node = 0xff;
530 // clang-format off
531 if (__unlikely(!(chars = co_gw_txt_lex_prefix(
532 cp, end, floc, &seq, &net, &node))))
533 // clang-format on
534 goto error;
535 cp += chars;
536 void *data = (void *)(uintptr_t)seq;
537
538 int srv = 0;
539 if (__unlikely(!(chars = co_gw_txt_lex_srv(cp, end, floc, &srv))))
540 goto error;
541 cp += chars;
542
543 switch (srv) {
548 if (__unlikely(node != 0xff)) {
550 "node-ID specified before global command");
551 goto error;
552 }
553 if (__unlikely(net)) {
555 "network-ID specified before global command");
556 goto error;
557 }
558 break;
562 case CO_GW_SRV_INIT:
563 case CO_GW_SRV_SET_HB:
564 case CO_GW_SRV_SET_ID:
579 // A single number preceding the command is normally interpreted
580 // as the node-ID. However, in this case we take it to be the
581 // network-ID.
582 if (__unlikely(net)) {
584 "node-ID specified before network-level command");
585 goto error;
586 }
587 net = node == 0xff ? 0 : node;
588 node = 0xff;
589 break;
590 }
591
592 cp += lex_ctype(&isblank, cp, end, at);
593
594 chars = 0;
595 switch (srv) {
596 case CO_GW_SRV_SDO_UP:
597 chars = co_gw_txt_send_sdo_up(
598 gw, srv, data, net, node, cp, end, floc);
599 break;
600 case CO_GW_SRV_SDO_DN:
601 chars = co_gw_txt_send_sdo_dn(
602 gw, srv, data, net, node, cp, end, floc);
603 break;
606 gw, srv, data, net, cp, end, floc);
607 break;
610 gw, srv, data, net, cp, end, floc);
611 break;
614 gw, srv, data, net, cp, end, floc);
615 break;
618 gw, srv, data, net, cp, end, floc);
619 break;
622 gw, srv, data, net, cp, end, floc);
623 break;
631 // 'start', 'stop', 'preop[erational]', 'reset node',
632 // 'reset comm[unication]', 'disable guarding' and
633 // 'disable heartbeat' are node-level commands without any
634 // additional parameters.
635 struct co_gw_req_node req = { .size = sizeof(req),
636 .srv = srv,
637 .data = data,
638 .net = net,
639 .node = node };
640 co_gw_txt_send_req(gw, (struct co_gw_req *)&req);
641 goto done;
642 }
645 gw, srv, data, net, node, cp, end, floc);
646 break;
649 gw, srv, data, net, node, cp, end, floc);
650 break;
651 case CO_GW_SRV_INIT:
652 chars = co_gw_txt_send_init(gw, srv, data, net, cp, end, floc);
653 break;
654 case CO_GW_SRV_SET_HB:
655 chars = co_gw_txt_send_set_hb(
656 gw, srv, data, net, cp, end, floc);
657 break;
658 case CO_GW_SRV_SET_ID:
659 chars = co_gw_txt_send_set_id(
660 gw, srv, data, net, cp, end, floc);
661 break;
664 gw, srv, data, cp, end, floc);
665 break;
668 gw, srv, data, net, cp, end, floc);
669 break;
671 chars = co_gw_txt_send_set_net(gw, srv, data, cp, end, floc);
672 break;
675 gw, srv, data, net, cp, end, floc);
676 break;
681 // 'info version', 'lss_store', 'lss_get_node' and
682 // 'lss_ident_nonconf' are network-level commands without any
683 // additional parameters.
684 struct co_gw_req_net req = { .size = sizeof(req),
685 .srv = srv,
686 .data = data,
687 .net = net };
688 co_gw_txt_send_req(gw, (struct co_gw_req *)&req);
689 goto done;
690 }
693 gw, srv, data, cp, end, floc);
694 break;
697 gw, srv, data, net, cp, end, floc);
698 break;
701 gw, srv, data, net, cp, end, floc);
702 break;
705 gw, srv, data, net, cp, end, floc);
706 break;
709 gw, srv, data, net, cp, end, floc);
710 break;
713 gw, srv, data, net, cp, end, floc);
714 break;
717 gw, srv, data, net, cp, end, floc);
718 break;
721 gw, srv, data, net, cp, end, floc);
722 break;
725 gw, srv, data, net, cp, end, floc);
726 break;
729 gw, srv, data, net, cp, end, floc);
730 break;
731 }
732 if (__unlikely(!chars))
733 goto error;
734 cp += chars;
735
736 // Skip trailing whitespace and/or comments.
737 cp += lex_ctype(&isblank, cp, end, floc);
738 cp += lex_line_comment("#", cp, end, floc);
739
740done:
741 if ((!end || cp < end) && *cp && !isbreak((unsigned char)*cp))
743 "expected line break after request");
744
745 iec = 0;
746
747error:
748 // Skip all characters until (and including) the next line break.
749 chars = 0;
750 while ((!end || cp + chars < end) && cp[chars] && cp[chars++] != '\n')
751 ;
752 cp += chars;
753
754 if (iec)
755 gw->iec = iec;
756
757 return floc_lex(at, begin, cp);
758}
759
760void
762 co_gw_txt_t *gw, co_gw_txt_recv_func_t *func, void *data)
763{
764 assert(gw);
765
766 gw->recv_func = func;
767 gw->recv_data = data;
768}
769
770void
772 void **pdata)
773{
774 assert(gw);
775
776 if (pfunc)
777 *pfunc = gw->send_func;
778 if (pdata)
779 *pdata = gw->send_data;
780}
781
782void
784 co_gw_txt_t *gw, co_gw_txt_send_func_t *func, void *data)
785{
786 assert(gw);
787
788 gw->send_func = func;
789 gw->send_data = data;
790}
791
792static int
793co_gw_txt_recv_con(co_gw_txt_t *gw, co_unsigned32_t seq,
794 const struct co_gw_con *con)
795{
796 assert(gw);
797 assert(con);
798
799 if (__likely(gw->pending))
800 gw->pending--;
801
802 if (con->iec || con->ac)
803 return co_gw_txt_recv_err(gw, seq, con->iec, con->ac);
804
805 switch (con->srv) {
806 case CO_GW_SRV_SDO_UP:
809 return -1;
810 }
812 gw, seq, (const struct co_gw_con_sdo_up *)con);
816 return -1;
817 }
818 return co_gw_txt_recv_pdo_read(gw, seq,
819 (const struct co_gw_con_pdo_read *)con);
821 // clang-format off
822 if (__unlikely(con->size
823 < sizeof(struct co_gw_con_get_version))) {
824 // clang-format on
826 return -1;
827 }
828 return co_gw_txt_recv_get_version(gw, seq,
829 (const struct co_gw_con_get_version *)con);
831 // clang-format off
832 if (__unlikely(con->size
833 < sizeof(struct co_gw_con_lss_get_lssid))) {
834 // clang-format on
836 return -1;
837 }
838 return co_gw_txt_recv_lss_get_lssid(gw, seq,
839 (const struct co_gw_con_lss_get_lssid *)con);
841 // clang-format off
842 if (__unlikely(con->size
843 < sizeof(struct co_gw_con_lss_get_id))) {
844 // clang-format on
846 return -1;
847 }
848 return co_gw_txt_recv_lss_get_id(gw, seq,
849 (const struct co_gw_con_lss_get_id *)con);
852 // clang-format off
853 if (__unlikely(con->size
854 < sizeof(struct co_gw_con__lss_scan))) {
855 // clang-format on
857 return -1;
858 }
859 return co_gw_txt_recv__lss_scan(gw, seq,
860 (const struct co_gw_con__lss_scan *)con);
861 default: return co_gw_txt_recv_err(gw, seq, 0, 0);
862 }
863}
864
865static int
866co_gw_txt_recv_sdo_up(co_gw_txt_t *gw, co_unsigned32_t seq,
867 const struct co_gw_con_sdo_up *con)
868{
869 assert(con);
870 assert(con->srv == CO_GW_SRV_SDO_UP);
871
872 if (__unlikely(con->size < CO_GW_CON_SDO_UP_SIZE + con->len)) {
874 return -1;
875 }
876
877 union co_val val;
878 const uint8_t *bp = (const uint8_t *)con->val;
879 // clang-format off
880 if (__unlikely(co_val_read(con->type, &val, bp, bp + con->len)
881 != con->len))
882 // clang-format on
884
885 int result = -1;
886
887 size_t chars = co_gw_txt_print_val(NULL, NULL, con->type, &val);
888#if __STDC_NO_VLA__
889 char *buf = malloc(chars + 1);
890 if (__likely(buf)) {
891 char *cp = buf;
892 co_gw_txt_print_val(&cp, cp + chars, con->type, &val);
893 *cp = '\0';
894
895 result = co_gw_txt_recv_fmt(gw, "[%" PRIu32 "] %s", seq, buf);
896
897 free(buf);
898 }
899#else
900 char buf[chars + 1];
901 char *cp = buf;
902 co_gw_txt_print_val(&cp, cp + chars, con->type, &val);
903 *cp = '\0';
904
905 result = co_gw_txt_recv_fmt(gw, "[%" PRIu32 "] %s", seq, buf);
906#endif
907
908 co_val_fini(con->type, &val);
909
910 return result;
911}
912
913static int
914co_gw_txt_recv_pdo_read(co_gw_txt_t *gw, co_unsigned32_t seq,
915 const struct co_gw_con_pdo_read *con)
916{
917 assert(con);
918 assert(con->srv == CO_GW_SRV_PDO_READ);
919
920 // clang-format off
922 + con->n * sizeof(*con->val))) {
923 // clang-format on
925 return -1;
926 }
927
928 int errc = get_errc();
929
930 char *buf;
931 int result = asprintf(
932 &buf, "[%" PRIu32 "] %u pdo %u", seq, con->net, con->n);
933 if (__unlikely(result < 0)) {
934 errc = get_errc();
935 buf = NULL;
936 goto error;
937 }
938
939 for (co_unsigned8_t i = 0; i < con->n; i++) {
940 char *tmp;
941 result = asprintf(&tmp, "%s 0x%" PRIx64, buf, con->val[i]);
942 if (__unlikely(result < 0)) {
943 errc = get_errc();
944 goto error;
945 }
946 free(buf);
947 buf = tmp;
948 }
949
950 result = co_gw_txt_recv_txt(gw, buf);
951
952error:
953 free(buf);
954 set_errc(errc);
955 return result;
956}
957
958static int
960 const struct co_gw_con_get_version *con)
961{
962 assert(con);
963 assert(con->srv == CO_GW_SRV_GET_VERSION);
964
965 return co_gw_txt_recv_fmt(gw,
966 "[%" PRIu32 "] %" PRIu32 " %" PRIu32 " %u.%u %" PRIu32
967 " %u %u.%u %u.%u",
968 seq, con->vendor_id, con->product_code,
969 (uint_least16_t)((con->revision >> 16) & 0xffff),
970 (uint_least16_t)(con->revision & 0xffff),
971 con->serial_nr, con->gw_class, con->prot_hi,
973}
974
975static int
977 const struct co_gw_con_lss_get_lssid *con)
978{
979 assert(con);
980 assert(con->srv == CO_GW_SRV_LSS_GET_LSSID);
981
982 return co_gw_txt_recv_fmt(
983 gw, "[%" PRIu32 "] 0x%08" PRIx32, seq, con->id);
984}
985
986static int
987co_gw_txt_recv_lss_get_id(co_gw_txt_t *gw, co_unsigned32_t seq,
988 const struct co_gw_con_lss_get_id *con)
989{
990 assert(con);
991 assert(con->srv == CO_GW_SRV_LSS_GET_ID);
992
993 return co_gw_txt_recv_fmt(gw, "[%" PRIu32 "] %u", seq, con->id);
994}
995
996static int
997co_gw_txt_recv__lss_scan(co_gw_txt_t *gw, co_unsigned32_t seq,
998 const struct co_gw_con__lss_scan *con)
999{
1000 assert(con);
1001
1002 return co_gw_txt_recv_fmt(gw,
1003 "[%" PRIu32 "] 0x%08" PRIx32 " 0x%08" PRIx32
1004 " 0x%08" PRIx32 " 0x%08" PRIx32,
1005 seq, con->id.vendor_id, con->id.product_code,
1006 con->id.revision, con->id.serial_nr);
1007}
1008
1009static int
1010co_gw_txt_recv_err(co_gw_txt_t *gw, co_unsigned32_t seq, int iec,
1011 co_unsigned32_t ac)
1012{
1013 if (iec) {
1014 gw->iec = iec;
1015 return co_gw_txt_recv_fmt(gw, "[%" PRIu32 "] ERROR: %d (%s)",
1016 seq, iec, co_gw_iec2str(iec));
1017 } else if (ac) {
1018 gw->iec = CO_GW_IEC_INTERN;
1019 return co_gw_txt_recv_fmt(gw,
1020 "[%" PRIu32 "] ERROR: %08" PRIX32 " (%s)", seq,
1021 ac, co_sdo_ac2str(ac));
1022 } else {
1023 return co_gw_txt_recv_fmt(gw, "[%" PRIu32 "] OK", seq);
1024 }
1025}
1026
1027static int
1029{
1030 assert(ind);
1031 assert(ind->srv == CO_GW_SRV_RPDO);
1032
1033 // clang-format off
1035 + ind->n * sizeof(*ind->val))) {
1036 // clang-format on
1038 return -1;
1039 }
1040
1041 int errc = get_errc();
1042
1043 char *buf;
1044 int result = asprintf(&buf, "%u pdo %u %u", ind->net, ind->num, ind->n);
1045 if (__unlikely(result < 0)) {
1046 errc = get_errc();
1047 buf = NULL;
1048 goto error;
1049 }
1050
1051 for (co_unsigned8_t i = 0; i < ind->n; i++) {
1052 char *tmp;
1053 result = asprintf(&tmp, "%s 0x%" PRIx64, buf, ind->val[i]);
1054 if (__unlikely(result < 0)) {
1055 errc = get_errc();
1056 goto error;
1057 }
1058 free(buf);
1059 buf = tmp;
1060 }
1061
1062 result = co_gw_txt_recv_txt(gw, buf);
1063
1064error:
1065 free(buf);
1066 set_errc(errc);
1067 return result;
1068}
1069
1070static int
1072{
1073 assert(ind);
1074 assert(ind->srv == CO_GW_SRV_EC);
1075
1076 if (ind->iec == CO_GW_IEC_BOOTUP)
1077 return co_gw_txt_recv_fmt(
1078 gw, "%u %u BOOT_UP", ind->net, ind->node);
1079
1080 const char *str;
1081 switch (ind->st) {
1082 case CO_NMT_ST_STOP: str = "ERRORx STOP"; break;
1083 case CO_NMT_ST_START: str = "ERRORx OPER"; break;
1084 case CO_NMT_ST_RESET_NODE: str = "ERRORx RAPP"; break;
1085 case CO_NMT_ST_RESET_COMM: str = "ERRORx RCOM"; break;
1086 case CO_NMT_ST_PREOP: str = "ERRORx PREO"; break;
1087 default: str = "ERROR"; break;
1088 }
1089 if (ind->iec)
1090 return co_gw_txt_recv_fmt(gw, "%u %u %s %d (%s)", ind->net,
1091 ind->node, str, ind->iec,
1092 co_gw_iec2str(ind->iec));
1093 else
1094 return co_gw_txt_recv_fmt(
1095 gw, "%u %u %s", ind->net, ind->node, str);
1096}
1097
1098static int
1100{
1101 assert(ind);
1102 assert(ind->srv == CO_GW_SRV_EMCY);
1103
1104 return co_gw_txt_recv_fmt(gw, "%u %u EMCY %04X %02X %u %u %u %u %u",
1105 ind->net, ind->node, ind->ec, ind->er, ind->msef[0],
1106 ind->msef[1], ind->msef[2], ind->msef[3], ind->msef[4]);
1107}
1108
1109static int
1111{
1112 assert(ind);
1113 assert(ind->srv == CO_GW_SRV_SDO);
1114
1115 return co_gw_txt_recv_fmt(gw, "%u %u SDO%c %" PRIu32, ind->net,
1116 ind->node, ind->up ? 'r' : 'w', ind->nbyte);
1117}
1118
1119static int
1121{
1122 assert(ind);
1123 assert(ind->srv == CO_GW_SRV__BOOT);
1124
1125 if (ind->es) {
1126 return co_gw_txt_recv_fmt(gw, "%u %u USER BOOT %c (%s)",
1127 ind->net, ind->node, ind->es,
1128 co_nmt_es2str(ind->es));
1129 } else {
1130 const char *str;
1131 switch (ind->st) {
1132 case CO_NMT_ST_STOP: str = "STOP"; break;
1133 case CO_NMT_ST_START: str = "OPER"; break;
1134 case CO_NMT_ST_RESET_NODE: str = "RAPP"; break;
1135 case CO_NMT_ST_RESET_COMM: str = "RCOM"; break;
1136 case CO_NMT_ST_PREOP: str = "PREOP"; break;
1137 default: str = "ERROR"; break;
1138 }
1139 return co_gw_txt_recv_fmt(gw, "%u %u USER BOOT %s", ind->net,
1140 ind->node, str);
1141 }
1142}
1143
1144static int
1145co_gw_txt_recv_fmt(co_gw_txt_t *gw, const char *format, ...)
1146{
1147 int result = -1;
1148
1149 va_list ap;
1150 va_start(ap, format);
1151#if __STDC_NO_VLA__
1152 char *buf = NULL;
1153 int n = vasprintf(&buf, format, ap);
1154 if (__likely(n > 0)) {
1155 result = co_gw_txt_recv_txt(gw, buf);
1156 free(buf);
1157 }
1158#else
1159 va_list aq;
1160 va_copy(aq, ap);
1161 int n = vsnprintf(NULL, 0, format, aq);
1162 va_end(aq);
1163
1164 assert(n > 0);
1165 char buf[n + 1];
1166 vsprintf(buf, format, ap);
1167 result = co_gw_txt_recv_txt(gw, buf);
1168#endif
1169 va_end(ap);
1170
1171 return result;
1172}
1173
1174static int
1175co_gw_txt_recv_txt(co_gw_txt_t *gw, const char *txt)
1176{
1177 assert(gw);
1178 assert(txt);
1179
1180 if (__unlikely(!gw->recv_func)) {
1182 return -1;
1183 }
1184
1185 return gw->recv_func(txt, gw->recv_data) ? -1 : 0;
1186}
1187
1188static size_t
1190 char **pbegin, char *end, co_unsigned16_t type, const void *val)
1191{
1192 const union co_val *u = val;
1193 assert(u);
1194 switch (type) {
1195 case CO_DEFTYPE_REAL32: return print_c99_flt(pbegin, end, u->r32);
1197 size_t chars = 0;
1198 chars += print_char(pbegin, end, '\"');
1199 const char *vs = u->vs;
1200 while (vs && *vs) {
1201 char32_t c32 = 0;
1202 vs += lex_utf8(vs, NULL, NULL, &c32);
1203 if (c32 == '\"') {
1204 chars += print_char(pbegin, end, '\"');
1205 chars += print_char(pbegin, end, '\"');
1206 } else {
1207 chars += print_c99_esc(pbegin, end, c32);
1208 }
1209 }
1210 chars += print_char(pbegin, end, '\"');
1211 return chars;
1212 }
1214 return co_val_print(CO_DEFTYPE_DOMAIN, val, pbegin, end);
1215 case CO_DEFTYPE_REAL64: return print_c99_dbl(pbegin, end, u->r64);
1216 default: return co_val_print(type, val, pbegin, end);
1217 }
1218}
1219
1220static size_t
1221co_gw_txt_send_sdo_up(co_gw_txt_t *gw, int srv, void *data, co_unsigned16_t net,
1222 co_unsigned8_t node, const char *begin, const char *end,
1223 struct floc *at)
1224{
1225 assert(srv == CO_GW_SRV_SDO_UP);
1226 assert(begin);
1227
1228 const char *cp = begin;
1229 size_t chars = 0;
1230
1231 co_unsigned16_t idx = 0;
1232 co_unsigned8_t subidx = 0;
1233 co_unsigned16_t type = 0;
1234 // clang-format off
1235 if (__unlikely(!(chars = co_gw_txt_lex_sdo(begin, end, at, &idx,
1236 &subidx, &type))))
1237 // clang-format on
1238 return 0;
1239 cp += chars;
1240
1241 struct co_gw_req_sdo_up req = { .size = sizeof(req),
1242 .srv = srv,
1243 .data = data,
1244 .net = net,
1245 .node = node,
1246 .idx = idx,
1247 .subidx = subidx,
1248 .type = type };
1249 co_gw_txt_send_req(gw, (struct co_gw_req *)&req);
1250
1251 return cp - begin;
1252}
1253
1254static size_t
1255co_gw_txt_send_sdo_dn(co_gw_txt_t *gw, int srv, void *data, co_unsigned16_t net,
1256 co_unsigned8_t node, const char *begin, const char *end,
1257 struct floc *at)
1258{
1259 assert(srv == CO_GW_SRV_SDO_DN);
1260 assert(begin);
1261
1262 const char *cp = begin;
1263 size_t chars = 0;
1264
1265 co_unsigned16_t idx = 0;
1266 co_unsigned8_t subidx = 0;
1267 co_unsigned16_t type = 0;
1268 // clang-format off
1269 if (__unlikely(!(chars = co_gw_txt_lex_sdo(begin, end, at, &idx,
1270 &subidx, &type))))
1271 // clang-format on
1272 goto error_lex_sdo;
1273 cp += chars;
1274 cp += lex_ctype(&isblank, cp, end, at);
1275
1276 union co_val val;
1277 co_val_init(type, &val);
1278
1279 if (__unlikely(!(chars = co_gw_txt_lex_val(cp, end, at, type, &val)))) {
1280 diag_if(DIAG_ERROR, 0, at, "unable to parse value");
1281 goto error_lex_val;
1282 }
1283 cp += chars;
1284
1285 size_t n = co_val_write(type, &val, NULL, NULL);
1286
1287 size_t size = MAX(CO_GW_REQ_SDO_DN_SIZE + n,
1288 sizeof(struct co_gw_req_sdo_dn));
1289 struct co_gw_req_sdo_dn *req = malloc(size);
1290 if (__unlikely(!req)) {
1291 diag_if(DIAG_ERROR, get_errc(), at, "unable to create value");
1292 goto error_malloc_req;
1293 }
1294
1295 *req = (struct co_gw_req_sdo_dn){ .size = size,
1296 .srv = srv,
1297 .data = data,
1298 .net = net,
1299 .node = node,
1300 .idx = idx,
1301 .subidx = subidx,
1302 .len = n };
1303
1304 uint8_t *bp = (uint8_t *)req->val;
1305 if (__unlikely(co_val_write(type, &val, bp, bp + n) != n)) {
1306 diag_if(DIAG_ERROR, get_errc(), at, "unable to write value");
1307 goto error_write_val;
1308 }
1309
1310 co_gw_txt_send_req(gw, (struct co_gw_req *)req);
1311
1312 free(req);
1313 co_val_fini(type, &val);
1314
1315 return cp - begin;
1316
1317error_write_val:
1318 free(req);
1319error_malloc_req:
1320error_lex_val:
1321 co_val_fini(type, &val);
1322error_lex_sdo:
1323 return 0;
1324}
1325
1326static size_t
1328 co_unsigned16_t net, const char *begin, const char *end,
1329 struct floc *at)
1330{
1331 assert(srv == CO_GW_SRV_SET_SDO_TIMEOUT);
1332 assert(begin);
1333
1334 const char *cp = begin;
1335 size_t chars = 0;
1336
1337 long timeout = 0;
1338 if (__unlikely(!(chars = lex_c99_long(cp, end, at, &timeout)))) {
1339 diag_if(DIAG_ERROR, 0, at, "expected SDO time-out");
1340 return 0;
1341 }
1342 cp += chars;
1343
1344 struct co_gw_req_set_sdo_timeout req = { .size = sizeof(req),
1345 .srv = srv,
1346 .data = data,
1347 .net = net,
1348 .timeout = timeout };
1349 co_gw_txt_send_req(gw, (struct co_gw_req *)&req);
1350
1351 return cp - begin;
1352}
1353
1354static size_t
1356 co_unsigned16_t net, const char *begin, const char *end,
1357 struct floc *at)
1358{
1359 assert(srv == CO_GW_SRV_SET_RPDO);
1360 assert(begin);
1361
1362 const char *cp = begin;
1363 size_t chars = 0;
1364
1365 co_unsigned16_t num = 0;
1368 // clang-format off
1369 if (__unlikely(!(chars = co_gw_txt_lex_pdo(
1370 cp, end, at, 0, &num, &comm, &map))))
1371 // clang-format on
1372 return 0;
1373 cp += chars;
1374
1376 + map.n * sizeof(*map.map),
1377 .srv = srv,
1378 .data = data,
1379 .net = net,
1380 .num = num,
1381 .cobid = comm.cobid,
1382 .trans = comm.trans,
1383 .n = map.n };
1384 for (co_unsigned8_t i = 0; i < map.n; i++)
1385 req.map[i] = map.map[i];
1386 co_gw_txt_send_req(gw, (struct co_gw_req *)&req);
1387
1388 return cp - begin;
1389}
1390
1391static size_t
1393 co_unsigned16_t net, const char *begin, const char *end,
1394 struct floc *at)
1395{
1396 assert(srv == CO_GW_SRV_SET_TPDO);
1397 assert(begin);
1398
1399 const char *cp = begin;
1400 size_t chars = 0;
1401
1402 // Check if this is an extended configure TPDO command.
1403 int ext = 0;
1404 if ((chars = lex_char('x', cp, end, at))) {
1405 cp += chars;
1406 cp += lex_ctype(&isblank, cp, end, at);
1407 ext = 1;
1408 }
1409
1410 co_unsigned16_t num = 0;
1413 // clang-format off
1414 if (__unlikely(!(chars = co_gw_txt_lex_pdo(
1415 cp, end, at, ext, &num, &comm, &map))))
1416 // clang-format on
1417 return 0;
1418 cp += chars;
1419
1421 + map.n * sizeof(*map.map),
1422 .srv = srv,
1423 .data = data,
1424 .net = net,
1425 .num = num,
1426 .cobid = comm.cobid,
1427 .trans = comm.trans,
1428 .inhibit = comm.inhibit,
1429 .event = comm.event,
1430 .sync = comm.sync,
1431 .n = map.n };
1432 for (co_unsigned8_t i = 0; i < map.n; i++)
1433 req.map[i] = map.map[i];
1434 co_gw_txt_send_req(gw, (struct co_gw_req *)&req);
1435
1436 return cp - begin;
1437}
1438
1439static size_t
1441 co_unsigned16_t net, const char *begin, const char *end,
1442 struct floc *at)
1443{
1444 assert(srv == CO_GW_SRV_PDO_READ);
1445 assert(begin);
1446
1447 const char *cp = begin;
1448 size_t chars = 0;
1449
1450 co_unsigned16_t num = 0;
1451 if (__unlikely(!(chars = lex_c99_u16(cp, end, at, &num)))) {
1452 diag_if(DIAG_ERROR, 0, at, "expected PDO number");
1453 return 0;
1454 }
1455 cp += chars;
1456 if (__unlikely(!num || num > 512)) {
1457 diag_if(DIAG_ERROR, 0, at,
1458 "PDO number must be in the range [1..512]");
1459 return 0;
1460 }
1461
1462 struct co_gw_req_pdo_read req = { .size = sizeof(req),
1463 .srv = srv,
1464 .data = data,
1465 .net = net,
1466 .num = num };
1467 co_gw_txt_send_req(gw, (struct co_gw_req *)&req);
1468
1469 return cp - begin;
1470}
1471
1472static size_t
1474 co_unsigned16_t net, const char *begin, const char *end,
1475 struct floc *at)
1476{
1477 assert(srv == CO_GW_SRV_PDO_WRITE);
1478 assert(begin);
1479
1480 const char *cp = begin;
1481 size_t chars = 0;
1482
1483 co_unsigned16_t num = 0;
1484 if (__unlikely(!(chars = lex_c99_u16(cp, end, at, &num)))) {
1485 diag_if(DIAG_ERROR, 0, at, "expected PDO number");
1486 return 0;
1487 }
1488 cp += chars;
1489
1490 if (__unlikely(!num || num > 512)) {
1491 diag_if(DIAG_ERROR, 0, at,
1492 "PDO number must be in the range [1..512]");
1493 return 0;
1494 }
1495
1496 cp += lex_ctype(&isblank, cp, end, at);
1497
1499 .srv = srv,
1500 .data = data,
1501 .net = net,
1502 .num = num };
1503
1504 if (__unlikely(!(chars = lex_c99_u8(cp, end, at, &req.n)))) {
1505 diag_if(DIAG_ERROR, 0, at, "expected number of values");
1506 return 0;
1507 }
1508 cp += chars;
1509 if (__unlikely(req.n > 0x40)) {
1510 diag_if(DIAG_ERROR, 0, at,
1511 "number of values must be in the range [0..64]");
1512 return 0;
1513 }
1514
1515 for (co_unsigned8_t i = 0; i < req.n; i++) {
1516 cp += lex_ctype(&isblank, cp, end, at);
1517
1518 chars = lex_c99_u64(cp, end, at, &req.val[i]);
1519 if (__unlikely(!chars)) {
1520 diag_if(DIAG_ERROR, 0, at, "expected value");
1521 return 0;
1522 }
1523 cp += chars;
1524 }
1525
1526 req.size += req.n * sizeof(*req.val);
1527 co_gw_txt_send_req(gw, (struct co_gw_req *)&req);
1528
1529 return cp - begin;
1530}
1531
1532static size_t
1534 co_unsigned16_t net, co_unsigned8_t node, const char *begin,
1535 const char *end, struct floc *at)
1536{
1537 assert(srv == CO_GW_SRV_NMT_NG_ENABLE);
1538 assert(begin);
1539
1540 const char *cp = begin;
1541 size_t chars = 0;
1542
1543 co_unsigned16_t gt = 0;
1544 if (__unlikely(!(chars = lex_c99_u16(cp, end, at, &gt)))) {
1545 diag_if(DIAG_ERROR, 0, at, "expected guard time");
1546 return 0;
1547 }
1548 cp += chars;
1549 cp += lex_ctype(&isblank, cp, end, at);
1550
1551 co_unsigned8_t ltf = 0;
1552 if (__unlikely(!(chars = lex_c99_u8(cp, end, at, &ltf)))) {
1553 diag_if(DIAG_ERROR, 0, at, "expected lifetime factor");
1554 return 0;
1555 }
1556 cp += chars;
1557
1558 struct co_gw_req_nmt_set_ng req = { .size = sizeof(req),
1559 .srv = srv,
1560 .data = data,
1561 .net = net,
1562 .node = node,
1563 .gt = gt,
1564 .ltf = ltf };
1565 co_gw_txt_send_req(gw, (struct co_gw_req *)&req);
1566
1567 return cp - begin;
1568}
1569
1570static size_t
1572 co_unsigned16_t net, co_unsigned8_t node, const char *begin,
1573 const char *end, struct floc *at)
1574{
1575 assert(srv == CO_GW_SRV_NMT_HB_ENABLE);
1576 assert(begin);
1577
1578 const char *cp = begin;
1579 size_t chars = 0;
1580
1581 co_unsigned16_t ms = 0;
1582 if (__unlikely(!(chars = lex_c99_u16(cp, end, at, &ms)))) {
1583 diag_if(DIAG_ERROR, 0, at, "expected heartbeat time");
1584 return 0;
1585 }
1586 cp += chars;
1587
1588 struct co_gw_req_nmt_set_hb req = { .size = sizeof(req),
1589 .srv = srv,
1590 .data = data,
1591 .net = net,
1592 .node = node,
1593 .ms = ms };
1594 co_gw_txt_send_req(gw, (struct co_gw_req *)&req);
1595
1596 return cp - begin;
1597}
1598
1599static size_t
1600co_gw_txt_send_init(co_gw_txt_t *gw, int srv, void *data, co_unsigned16_t net,
1601 const char *begin, const char *end, struct floc *at)
1602{
1603 assert(srv == CO_GW_SRV_INIT);
1604 assert(begin);
1605
1606 const char *cp = begin;
1607 size_t chars = 0;
1608
1609 co_unsigned8_t bitidx = 0;
1610 if (__unlikely(!(chars = lex_c99_u8(cp, end, at, &bitidx)))) {
1611 diag_if(DIAG_ERROR, 0, at, "expected bit timing index");
1612 return 0;
1613 }
1614 cp += chars;
1615
1616 if (__unlikely(bitidx > 9)) {
1617 diag_if(DIAG_ERROR, 0, at,
1618 "the bit timing must be in the range [0..9]");
1619 return 0;
1620 }
1621
1622 struct co_gw_req_init req = { .size = sizeof(req),
1623 .srv = srv,
1624 .data = data,
1625 .net = net,
1626 .bitidx = bitidx };
1627 co_gw_txt_send_req(gw, (struct co_gw_req *)&req);
1628
1629 return cp - begin;
1630}
1631
1632static size_t
1633co_gw_txt_send_set_hb(co_gw_txt_t *gw, int srv, void *data, co_unsigned16_t net,
1634 const char *begin, const char *end, struct floc *at)
1635{
1636 assert(srv == CO_GW_SRV_SET_HB);
1637 assert(begin);
1638
1639 const char *cp = begin;
1640 size_t chars = 0;
1641
1642 co_unsigned16_t ms = 0;
1643 if (__unlikely(!(chars = lex_c99_u16(cp, end, at, &ms)))) {
1644 diag_if(DIAG_ERROR, 0, at, "expected heartbeat time");
1645 return 0;
1646 }
1647 cp += chars;
1648
1649 struct co_gw_req_set_hb req = { .size = sizeof(req),
1650 .srv = srv,
1651 .data = data,
1652 .net = net,
1653 .ms = ms };
1654 co_gw_txt_send_req(gw, (struct co_gw_req *)&req);
1655
1656 return cp - begin;
1657}
1658
1659static size_t
1660co_gw_txt_send_set_id(co_gw_txt_t *gw, int srv, void *data, co_unsigned16_t net,
1661 const char *begin, const char *end, struct floc *at)
1662{
1663 assert(srv == CO_GW_SRV_SET_ID);
1664 assert(begin);
1665
1666 const char *cp = begin;
1667 size_t chars = 0;
1668
1669 co_unsigned8_t node = 0;
1670 if (__unlikely(!(chars = lex_c99_u8(cp, end, at, &node)))) {
1671 diag_if(DIAG_ERROR, 0, at, "expected node-ID");
1672 return 0;
1673 }
1674 cp += chars;
1675
1676 if (__unlikely(!node || (node > CO_NUM_NODES && node != 0xff))) {
1677 diag_if(DIAG_ERROR, 0, at,
1678 "the node-ID must be in the range [1..%u, 255]",
1679 CO_NUM_NODES);
1680 return 0;
1681 }
1682
1683 struct co_gw_req_node req = { .size = sizeof(req),
1684 .srv = srv,
1685 .data = data,
1686 .net = net,
1687 .node = node };
1688 co_gw_txt_send_req(gw, (struct co_gw_req *)&req);
1689
1690 return cp - begin;
1691}
1692
1693static size_t
1695 const char *begin, const char *end, struct floc *at)
1696{
1697 assert(srv == CO_GW_SRV_SET_CMD_TIMEOUT);
1698 assert(begin);
1699
1700 const char *cp = begin;
1701 size_t chars = 0;
1702
1703 long timeout = 0;
1704 if (__unlikely(!(chars = lex_c99_long(cp, end, at, &timeout)))) {
1705 diag_if(DIAG_ERROR, 0, at, "expected command time-out");
1706 return 0;
1707 }
1708 cp += chars;
1709
1710 struct co_gw_req_set_cmd_timeout req = { .size = sizeof(req),
1711 .srv = srv,
1712 .data = data,
1713 .timeout = timeout };
1714 co_gw_txt_send_req(gw, (struct co_gw_req *)&req);
1715
1716 return cp - begin;
1717}
1718
1719static size_t
1721 co_unsigned16_t net, const char *begin, const char *end,
1722 struct floc *at)
1723{
1724 assert(srv == CO_GW_SRV_SET_BOOTUP_IND);
1725 assert(begin);
1726
1727 const char *cp = begin;
1728 size_t chars = 0;
1729
1730 int cs;
1731
1732 chars = co_gw_txt_lex_cmd(cp, end, at);
1733 if (!strncasecmp("Disable", cp, chars)) {
1734 cp += chars;
1735 cs = 0;
1736 } else if (!strncasecmp("Disable", cp, chars)) {
1737 cp += chars;
1738 cs = 1;
1739 } else {
1740 diag_if(DIAG_ERROR, 0, at,
1741 "expected 'Disable' or 'Enable' after 'boot_up_indication'");
1742 return 0;
1743 }
1744
1745 struct co_gw_req_set_bootup_ind req = { .size = sizeof(req),
1746 .srv = srv,
1747 .data = data,
1748 .net = net,
1749 .cs = cs };
1750 co_gw_txt_send_req(gw, (struct co_gw_req *)&req);
1751
1752 return cp - begin;
1753}
1754
1755static size_t
1756co_gw_txt_send_set_net(co_gw_txt_t *gw, int srv, void *data, const char *begin,
1757 const char *end, struct floc *at)
1758{
1759 assert(srv == CO_GW_SRV_SET_NET);
1760 assert(begin);
1761
1762 const char *cp = begin;
1763 size_t chars = 0;
1764
1765 co_unsigned16_t net = 0;
1766 if (__unlikely(!(chars = lex_c99_u16(cp, end, at, &net)))) {
1767 diag_if(DIAG_ERROR, 0, at, "expected network-ID");
1768 return 0;
1769 }
1770 cp += chars;
1771
1772 if (__unlikely(net > CO_GW_NUM_NET)) {
1773 diag_if(DIAG_ERROR, 0, at,
1774 "the network-ID must be in the range [0, 1..%u]",
1776 return 0;
1777 }
1778
1779 struct co_gw_req_net req = {
1780 .size = sizeof(req), .srv = srv, .data = data, .net = net
1781 };
1782 co_gw_txt_send_req(gw, (struct co_gw_req *)&req);
1783
1784 return cp - begin;
1785}
1786
1787static size_t
1789 co_unsigned16_t net, const char *begin, const char *end,
1790 struct floc *at)
1791{
1792 assert(srv == CO_GW_SRV_SET_NODE);
1793 assert(begin);
1794
1795 const char *cp = begin;
1796 size_t chars = 0;
1797
1798 co_unsigned8_t node = 0;
1799 if (__unlikely(!(chars = lex_c99_u8(cp, end, at, &node)))) {
1800 diag_if(DIAG_ERROR, 0, at, "expected node-ID");
1801 return 0;
1802 }
1803 cp += chars;
1804
1805 if (__unlikely(node > CO_NUM_NODES)) {
1806 diag_if(DIAG_ERROR, 0, at,
1807 "the node-ID must be in the range [0, 1..%u]",
1808 CO_NUM_NODES);
1809 return 0;
1810 }
1811
1812 struct co_gw_req_node req = { .size = sizeof(req),
1813 .srv = srv,
1814 .data = data,
1815 .net = net,
1816 .node = node };
1817 co_gw_txt_send_req(gw, (struct co_gw_req *)&req);
1818
1819 return cp - begin;
1820}
1821
1822static size_t
1824 const char *begin, const char *end, struct floc *at)
1825{
1826 assert(srv == CO_GW_SRV_SET_CMD_SIZE);
1827 assert(begin);
1828
1829 const char *cp = begin;
1830 size_t chars = 0;
1831
1832 co_unsigned32_t n = 0;
1833 if (__unlikely(!(chars = lex_c99_u32(cp, end, at, &n)))) {
1834 diag_if(DIAG_ERROR, 0, at, "expected command size");
1835 return 0;
1836 }
1837 cp += chars;
1838
1839 struct co_gw_req_set_cmd_size req = {
1840 .size = sizeof(req), .srv = srv, .data = data, .n = n
1841 };
1842 co_gw_txt_send_req(gw, (struct co_gw_req *)&req);
1843
1844 return cp - begin;
1845}
1846
1847static size_t
1849 co_unsigned16_t net, const char *begin, const char *end,
1850 struct floc *at)
1851{
1852 assert(srv == CO_GW_SRV_LSS_SWITCH);
1853 assert(begin);
1854
1855 const char *cp = begin;
1856 size_t chars = 0;
1857
1858 co_unsigned8_t mode = 0;
1859 if (__unlikely(!(chars = lex_c99_u8(cp, end, at, &mode)) || mode > 1)) {
1860 diag_if(DIAG_ERROR, 0, at, "expected 0 or 1");
1861 return 0;
1862 }
1863 cp += chars;
1864
1865 struct co_gw_req_lss_switch req = { .size = sizeof(req),
1866 .srv = srv,
1867 .data = data,
1868 .net = net,
1869 .mode = mode };
1870 co_gw_txt_send_req(gw, (struct co_gw_req *)&req);
1871
1872 return cp - begin;
1873}
1874
1875static size_t
1877 co_unsigned16_t net, const char *begin, const char *end,
1878 struct floc *at)
1879{
1880 assert(srv == CO_GW_SRV_LSS_SWITCH_SEL);
1881 assert(begin);
1882
1883 const char *cp = begin;
1884 size_t chars = 0;
1885
1886 struct co_id id = CO_ID_INIT;
1887 if (__unlikely(!(chars = co_gw_txt_lex_id(cp, end, at, &id))))
1888 return 0;
1889 cp += chars;
1890
1891 struct co_gw_req_lss_switch_sel req = { .size = sizeof(req),
1892 .srv = srv,
1893 .data = data,
1894 .net = net,
1895 .id = id };
1896 co_gw_txt_send_req(gw, (struct co_gw_req *)&req);
1897
1898 return cp - begin;
1899}
1900
1901static size_t
1903 co_unsigned16_t net, const char *begin, const char *end,
1904 struct floc *at)
1905{
1906 assert(srv == CO_GW_SRV_LSS_SET_ID);
1907 assert(begin);
1908
1909 const char *cp = begin;
1910 size_t chars = 0;
1911
1912 co_unsigned8_t node = 0;
1913 if (__unlikely(!(chars = lex_c99_u8(cp, end, at, &node)))) {
1914 diag_if(DIAG_ERROR, 0, at, "expected node-ID");
1915 return 0;
1916 }
1917 cp += chars;
1918
1919 if (__unlikely(!node || (node > CO_NUM_NODES && node != 0xff))) {
1920 diag_if(DIAG_ERROR, 0, at,
1921 "the node-ID must be in the range [1..%u, 255]",
1922 CO_NUM_NODES);
1923 return 0;
1924 }
1925
1926 struct co_gw_req_node req = { .size = sizeof(req),
1927 .srv = srv,
1928 .data = data,
1929 .net = net,
1930 .node = node };
1931 co_gw_txt_send_req(gw, (struct co_gw_req *)&req);
1932
1933 return cp - begin;
1934}
1935
1936static size_t
1938 co_unsigned16_t net, const char *begin, const char *end,
1939 struct floc *at)
1940{
1941 assert(srv == CO_GW_SRV_LSS_SET_RATE);
1942 assert(begin);
1943
1944 const char *cp = begin;
1945 size_t chars = 0;
1946
1947 co_unsigned8_t bitsel = 0;
1948 if (__unlikely(!(chars = lex_c99_u8(cp, end, at, &bitsel)))) {
1949 diag_if(DIAG_ERROR, 0, at, "expected table selector");
1950 return 0;
1951 }
1952 cp += chars;
1953 cp += lex_ctype(&isblank, cp, end, at);
1954
1955 co_unsigned8_t bitidx = 0;
1956 if (__unlikely(!(chars = lex_c99_u8(cp, end, at, &bitidx)))) {
1957 diag_if(DIAG_ERROR, 0, at, "expected table index");
1958 return 0;
1959 }
1960 cp += chars;
1961
1962 struct co_gw_req_lss_set_rate req = { .size = sizeof(req),
1963 .srv = srv,
1964 .data = data,
1965 .net = net,
1966 .bitsel = bitsel,
1967 .bitidx = bitidx };
1968 co_gw_txt_send_req(gw, (struct co_gw_req *)&req);
1969
1970 return cp - begin;
1971}
1972
1973static size_t
1975 co_unsigned16_t net, const char *begin, const char *end,
1976 struct floc *at)
1977{
1978 assert(srv == CO_GW_SRV_LSS_SWITCH_RATE);
1979 assert(begin);
1980
1981 const char *cp = begin;
1982 size_t chars = 0;
1983
1984 co_unsigned16_t delay = 0;
1985 if (__unlikely(!(chars = lex_c99_u16(cp, end, at, &delay)))) {
1986 diag_if(DIAG_ERROR, 0, at, "expected switch delay");
1987 return 0;
1988 }
1989 cp += chars;
1990
1991 struct co_gw_req_lss_switch_rate req = { .size = sizeof(req),
1992 .srv = srv,
1993 .data = data,
1994 .net = net,
1995 .delay = delay };
1996 co_gw_txt_send_req(gw, (struct co_gw_req *)&req);
1997
1998 return cp - begin;
1999}
2000
2001static size_t
2003 co_unsigned16_t net, const char *begin, const char *end,
2004 struct floc *at)
2005{
2006 assert(srv == CO_GW_SRV_LSS_GET_LSSID);
2007 assert(begin);
2008
2009 const char *cp = begin;
2010 size_t chars = 0;
2011
2012 co_unsigned8_t cs = 0;
2013 if (__unlikely(!(chars = lex_c99_u8(cp, end, at, &cs)))) {
2014 diag_if(DIAG_ERROR, 0, at, "expected code for LSS number");
2015 return 0;
2016 }
2017 cp += chars;
2018 if (__unlikely(cs < 0x5a || cs > 0x5d)) {
2019 diag_if(DIAG_ERROR, 0, at,
2020 "code must be in the range [0x5A..0x5D]");
2021 return 0;
2022 }
2023
2024 struct co_gw_req_lss_get_lssid req = { .size = sizeof(req),
2025 .srv = srv,
2026 .data = data,
2027 .net = net,
2028 .cs = cs };
2029 co_gw_txt_send_req(gw, (struct co_gw_req *)&req);
2030
2031 return cp - begin;
2032}
2033
2034static size_t
2036 co_unsigned16_t net, const char *begin, const char *end,
2037 struct floc *at)
2038{
2039 assert(srv == CO_GW_SRV_LSS_ID_SLAVE);
2040 assert(begin);
2041
2042 const char *cp = begin;
2043 size_t chars = 0;
2044
2045 struct co_id lo = CO_ID_INIT;
2046 struct co_id hi = CO_ID_INIT;
2047 if (__unlikely(!(chars = co_gw_txt_lex_id_sel(cp, end, at, &lo, &hi))))
2048 return 0;
2049 cp += chars;
2050
2051 struct co_gw_req_lss_id_slave req = { .size = sizeof(req),
2052 .srv = srv,
2053 .data = data,
2054 .net = net,
2055 .lo = lo,
2056 .hi = hi };
2057 co_gw_txt_send_req(gw, (struct co_gw_req *)&req);
2058
2059 return cp - begin;
2060}
2061
2062static size_t
2064 co_unsigned16_t net, const char *begin, const char *end,
2065 struct floc *at)
2066{
2067 assert(srv == CO_GW_SRV__LSS_SLOWSCAN);
2068 assert(begin);
2069
2070 const char *cp = begin;
2071 size_t chars = 0;
2072
2073 struct co_id lo = CO_ID_INIT;
2074 struct co_id hi = CO_ID_INIT;
2075 if (__unlikely(!(chars = co_gw_txt_lex_id_sel(cp, end, at, &lo, &hi))))
2076 return 0;
2077 cp += chars;
2078
2079 struct co_gw_req__lss_scan req = { .size = sizeof(req),
2080 .srv = srv,
2081 .data = data,
2082 .net = net,
2083 .id_1 = lo,
2084 .id_2 = hi };
2085 co_gw_txt_send_req(gw, (struct co_gw_req *)&req);
2086
2087 return cp - begin;
2088}
2089
2090static size_t
2092 co_unsigned16_t net, const char *begin, const char *end,
2093 struct floc *at)
2094{
2095 assert(srv == CO_GW_SRV__LSS_FASTSCAN);
2096 assert(begin);
2097
2098 const char *cp = begin;
2099 size_t chars = 0;
2100
2101 struct co_id id = CO_ID_INIT;
2102 struct co_id mask = CO_ID_INIT;
2103
2104 if (__unlikely(!(chars = lex_c99_u32(cp, end, at, &id.vendor_id)))) {
2105 diag_if(DIAG_ERROR, 0, at, "expected vendor-ID");
2106 return 0;
2107 }
2108 cp += chars;
2109 cp += lex_ctype(&isblank, cp, end, at);
2110
2111 if (__unlikely(!(chars = lex_c99_u32(cp, end, at, &mask.vendor_id)))) {
2112 diag_if(DIAG_ERROR, 0, at, "expected vendor-ID mask");
2113 return 0;
2114 }
2115 cp += chars;
2116 cp += lex_ctype(&isblank, cp, end, at);
2117
2118 if (__unlikely(!(chars = lex_c99_u32(cp, end, at, &id.product_code)))) {
2119 diag_if(DIAG_ERROR, 0, at, "expected product code");
2120 return 0;
2121 }
2122 cp += chars;
2123 cp += lex_ctype(&isblank, cp, end, at);
2124
2125 // clang-format off
2126 if (__unlikely(!(chars = lex_c99_u32(
2127 cp, end, at, &mask.product_code)))) {
2128 // clang-format on
2129 diag_if(DIAG_ERROR, 0, at, "expected product code mask");
2130 return 0;
2131 }
2132 cp += chars;
2133 cp += lex_ctype(&isblank, cp, end, at);
2134
2135 if (__unlikely(!(chars = lex_c99_u32(cp, end, at, &id.revision)))) {
2136 diag_if(DIAG_ERROR, 0, at, "expected revision number");
2137 return 0;
2138 }
2139 cp += chars;
2140 cp += lex_ctype(&isblank, cp, end, at);
2141
2142 if (__unlikely(!(chars = lex_c99_u32(cp, end, at, &mask.revision)))) {
2143 diag_if(DIAG_ERROR, 0, at, "expected revision number mask");
2144 return 0;
2145 }
2146 cp += chars;
2147 cp += lex_ctype(&isblank, cp, end, at);
2148
2149 if (__unlikely(!(chars = lex_c99_u32(cp, end, at, &id.serial_nr)))) {
2150 diag_if(DIAG_ERROR, 0, at, "expected serial number");
2151 return 0;
2152 }
2153 cp += chars;
2154 cp += lex_ctype(&isblank, cp, end, at);
2155
2156 if (__unlikely(!(chars = lex_c99_u32(cp, end, at, &mask.serial_nr)))) {
2157 diag_if(DIAG_ERROR, 0, at, "expected serial number mask");
2158 return 0;
2159 }
2160 cp += chars;
2161
2162 struct co_gw_req__lss_scan req = { .size = sizeof(req),
2163 .srv = srv,
2164 .data = data,
2165 .net = net,
2166 .id_1 = id,
2167 .id_2 = mask };
2168 co_gw_txt_send_req(gw, (struct co_gw_req *)&req);
2169
2170 return cp - begin;
2171}
2172
2173static void
2175{
2176 assert(gw);
2177 assert(req);
2178
2179 if (gw->send_func) {
2180 gw->pending++;
2181 if (__unlikely(gw->send_func(req, gw->send_data))) {
2182 gw->pending--;
2184 "unable to send gateway request");
2185 }
2186 }
2187}
2188
2189static size_t
2190co_gw_txt_lex_prefix(const char *begin, const char *end, struct floc *at,
2191 co_unsigned32_t *pseq, co_unsigned16_t *pnet,
2192 co_unsigned8_t *pnode)
2193{
2194 assert(begin);
2195 assert(!end || end >= begin);
2196
2197 const char *cp = begin;
2198 size_t chars = 0;
2199
2200 if (__unlikely(!(chars = lex_char('[', cp, end, at))))
2201 diag_if(DIAG_WARNING, 0, at,
2202 "expected '[' before sequence number");
2203 cp += chars;
2204 cp += lex_ctype(&isblank, cp, end, at);
2205
2206 co_unsigned32_t seq = 0;
2207 if (__unlikely(!(chars = lex_c99_u32(cp, end, at, &seq)))) {
2208 diag_if(DIAG_ERROR, 0, at, "expected sequence number");
2209 return 0;
2210 }
2211 cp += chars;
2212 cp += lex_ctype(&isblank, cp, end, at);
2213
2214 if (__unlikely(!(chars = lex_char(']', cp, end, at))))
2215 diag_if(DIAG_WARNING, 0, at,
2216 "expected ']' after sequence number");
2217 cp += chars;
2218 cp += lex_ctype(&isblank, cp, end, at);
2219
2220 co_unsigned16_t net = 0;
2221 co_unsigned8_t node = 0xff;
2222
2223 // Try to parse the optional network-ID.
2224 if ((chars = lex_c99_u16(cp, end, at, &net))) {
2225 cp += chars;
2226 cp += lex_ctype(&isblank, cp, end, at);
2227
2228 // Try to parse the optional node-ID.
2229 if ((chars = lex_c99_u8(cp, end, at, &node))) {
2230 cp += chars;
2231 cp += lex_ctype(&isblank, cp, end, at);
2232
2233 if (__unlikely(!net || net > CO_GW_NUM_NET)) {
2234 diag_if(DIAG_ERROR, 0, at,
2235 "the network-ID must be in the range [1..%u]",
2237 return 0;
2238 }
2239
2240 if (__unlikely(node > CO_NUM_NODES)) {
2241 diag_if(DIAG_ERROR, 0, at,
2242 "the node-ID must be in the range [0..%u]",
2243 CO_NUM_NODES);
2244 return 0;
2245 }
2246 } else {
2247 if (__unlikely(net > CO_NUM_NODES)) {
2248 diag_if(DIAG_ERROR, 0, at,
2249 "the node-ID must be in the range [0..%u]",
2250 CO_NUM_NODES);
2251 return 0;
2252 }
2253 // If only a single ID was provided, interpret it as the
2254 // node-ID.
2255 node = net;
2256 net = 0;
2257 }
2258 }
2259
2260 if (pseq)
2261 *pseq = seq;
2262 if (pnet)
2263 *pnet = net;
2264 if (pnode)
2265 *pnode = node;
2266
2267 return cp - begin;
2268}
2269
2270static size_t
2272 const char *begin, const char *end, struct floc *at, int *psrv)
2273{
2274 assert(begin);
2275 assert(!end || end >= begin);
2276
2277 const char *cp = begin;
2278 size_t chars = 0;
2279
2280 int srv = 0;
2281
2282 cp += lex_ctype(&isblank, cp, end, at);
2283
2284 chars = co_gw_txt_lex_cmd(cp, end, at);
2285 if (__unlikely(!chars)) {
2286 diag_if(DIAG_ERROR, 0, at, "expected command");
2287 return 0;
2288 }
2289
2290 if (!strncasecmp("_lss_fastscan", cp, chars)) {
2291 cp += chars;
2293 } else if (!strncasecmp("_lss_slowscan", cp, chars)) {
2294 cp += chars;
2296 } else if (!strncasecmp("boot_up_indication", cp, chars)) {
2297 cp += chars;
2299 } else if (!strncasecmp("disable", cp, chars)) {
2300 cp += chars;
2301 cp += lex_ctype(&isblank, cp, end, at);
2302
2303 chars = co_gw_txt_lex_cmd(cp, end, at);
2304 if (!strncasecmp("guarding", cp, chars)) {
2305 cp += chars;
2307 } else if (!strncasecmp("heartbeat", cp, chars)) {
2308 cp += chars;
2310 } else {
2311 diag_if(DIAG_ERROR, 0, at,
2312 "expected 'guarding' or 'heartbeat'");
2313 return 0;
2314 }
2315 } else if (!strncasecmp("enable", cp, chars)) {
2316 cp += chars;
2317 cp += lex_ctype(&isblank, cp, end, at);
2318
2319 chars = co_gw_txt_lex_cmd(cp, end, at);
2320 if (!strncasecmp("guarding", cp, chars)) {
2321 cp += chars;
2323 } else if (!strncasecmp("heartbeat", cp, chars)) {
2324 cp += chars;
2326 } else {
2327 diag_if(DIAG_ERROR, 0, at,
2328 "expected 'guarding' or 'heartbeat'");
2329 return 0;
2330 }
2331 } else if (!strncasecmp("info", cp, chars)) {
2332 cp += chars;
2333 cp += lex_ctype(&isblank, cp, end, at);
2334
2335 chars = co_gw_txt_lex_cmd(cp, end, at);
2336 if (!strncasecmp("version", cp, chars)) {
2337 cp += chars;
2339 } else {
2340 diag_if(DIAG_ERROR, 0, at, "expected 'version'");
2341 return 0;
2342 }
2343 } else if (!strncasecmp("init", cp, chars)) {
2344 cp += chars;
2346 } else if (!strncasecmp("lss_activate_bitrate", cp, chars)) {
2347 cp += chars;
2349 } else if (!strncasecmp("lss_conf_bitrate", cp, chars)) {
2350 cp += chars;
2352 } else if (!strncasecmp("lss_get_node", cp, chars)) {
2353 cp += chars;
2355 } else if (!strncasecmp("lss_identity", cp, chars)) {
2356 cp += chars;
2358 } else if (!strncasecmp("lss_ident_nonconf", cp, chars)) {
2359 cp += chars;
2361 } else if (!strncasecmp("lss_inquire_addr", cp, chars)) {
2362 cp += chars;
2364 } else if (!strncasecmp("lss_set_node", cp, chars)) {
2365 cp += chars;
2367 } else if (!strncasecmp("lss_store", cp, chars)) {
2368 cp += chars;
2370 } else if (!strncasecmp("lss_switch_glob", cp, chars)) {
2371 cp += chars;
2373 } else if (!strncasecmp("lss_switch_sel", cp, chars)) {
2374 cp += chars;
2376 } else if (!strncasecmp("preop", cp, chars)
2377 || !strncasecmp("preoperational", cp, chars)) {
2378 cp += chars;
2380 } else if (!strncasecmp("r", cp, chars)
2381 || !strncasecmp("read", cp, chars)) {
2382 cp += chars;
2383 cp += lex_ctype(&isblank, cp, end, at);
2384
2385 if ((chars = co_gw_txt_lex_cmd(cp, end, at))) {
2386 if (!strncasecmp("p", cp, chars)
2387 || !strncasecmp("pdo", cp, chars)) {
2388 cp += chars;
2390 } else {
2391 diag_if(DIAG_ERROR, 0, at, "expected 'p[do]'");
2392 return 0;
2393 }
2394 } else {
2396 }
2397 } else if (!strncasecmp("reset", cp, chars)) {
2398 cp += chars;
2399 cp += lex_ctype(&isblank, cp, end, at);
2400
2401 chars = co_gw_txt_lex_cmd(cp, end, at);
2402 if (!strncasecmp("comm", cp, chars)
2403 || !strncasecmp("communication", cp, chars)) {
2404 cp += chars;
2406 } else if (!strncasecmp("node", cp, chars)) {
2407 cp += chars;
2409 } else {
2410 diag_if(DIAG_ERROR, 0, at,
2411 "expected 'node' or 'comm[unication]'");
2412 return 0;
2413 }
2414 } else if (!strncasecmp("set", cp, chars)) {
2415 cp += chars;
2416 cp += lex_ctype(&isblank, cp, end, at);
2417
2418 chars = co_gw_txt_lex_cmd(cp, end, at);
2419 if (!strncasecmp("command_size", cp, chars)) {
2420 cp += chars;
2422 } else if (!strncasecmp("command_timeout", cp, chars)) {
2423 cp += chars;
2425 } else if (!strncasecmp("heartbeat", cp, chars)) {
2426 cp += chars;
2428 } else if (!strncasecmp("id", cp, chars)) {
2429 cp += chars;
2431 } else if (!strncasecmp("network", cp, chars)) {
2432 cp += chars;
2434 } else if (!strncasecmp("node", cp, chars)) {
2435 cp += chars;
2437 } else if (!strncasecmp("rpdo", cp, chars)) {
2438 cp += chars;
2440 } else if (!strncasecmp("sdo_timeout", cp, chars)) {
2441 cp += chars;
2443 } else if (!strncasecmp("tpdo", cp, chars)) {
2444 cp += chars;
2446 } else if (!strncasecmp("tpdox", cp, chars)) {
2447 // Wait with parsing the 'x' until co_gw_txt_lex_pdo().
2448 cp += chars - 1;
2449 if (at)
2450 at->column--;
2452 } else {
2453 diag_if(DIAG_ERROR, 0, at,
2454 "expected 'command_size', 'command_timeout', 'heartbeat', 'id', 'network', 'node', 'rpdo', 'sdo_timeout' or 'tpdo[x]'");
2455 return 0;
2456 }
2457 } else if (!strncasecmp("start", cp, chars)) {
2458 cp += chars;
2460 } else if (!strncasecmp("stop", cp, chars)) {
2461 cp += chars;
2463 } else if (!strncasecmp("w", cp, chars)
2464 || !strncasecmp("write", cp, chars)) {
2465 cp += chars;
2466 cp += lex_ctype(&isblank, cp, end, at);
2467
2468 if ((chars = co_gw_txt_lex_cmd(cp, end, at))) {
2469 if (!strncasecmp("p", cp, chars)
2470 || !strncasecmp("pdo", cp, chars)) {
2471 cp += chars;
2473 } else {
2474 diag_if(DIAG_ERROR, 0, at, "expected 'p[do]'");
2475 return 0;
2476 }
2477 } else {
2479 }
2480 } else {
2481 diag_if(DIAG_ERROR, 0, at,
2482 "expected '_lss_fastscan', '_lss_slowscan', 'boot_up_indication', 'disable', 'enable', 'info', 'init', 'lss_activate_bitrate', 'lss_conf_bitrate', 'lss_get_node', 'lss_identity', 'lss_ident_nonconf', 'lss_inquire_addr', 'lss_set_node', 'lss_store', 'lss_switch_glob', 'lss_switch_sel', 'preop[erational]', 'r[ead]', 'reset', 'set', 'start', 'stop', or 'w[rite]'");
2483 return 0;
2484 }
2485
2486 if (psrv)
2487 *psrv = srv;
2488
2489 return cp - begin;
2490}
2491
2492static size_t
2493co_gw_txt_lex_cmd(const char *begin, const char *end, struct floc *at)
2494{
2495 assert(begin);
2496 assert(!end || end >= begin);
2497
2498 const char *cp = begin;
2499
2500 if ((end && cp >= end) || !(*cp == '_' || isalpha((unsigned char)*cp)))
2501 return 0;
2502 cp++;
2503
2504 while ((!end || cp < end)
2505 && (*cp == '_' || isalnum((unsigned char)*cp)))
2506 cp++;
2507
2508 return floc_lex(at, begin, cp);
2509}
2510
2511static size_t
2512co_gw_txt_lex_sdo(const char *begin, const char *end, struct floc *at,
2513 co_unsigned16_t *pidx, co_unsigned8_t *psubidx,
2514 co_unsigned16_t *ptype)
2515{
2516 assert(begin);
2517
2518 const char *cp = begin;
2519 size_t chars = 0;
2520
2521 if (__unlikely(!(chars = lex_c99_u16(cp, end, at, pidx)))) {
2522 diag_if(DIAG_ERROR, 0, at, "expected object index");
2523 return 0;
2524 }
2525 cp += chars;
2526 cp += lex_ctype(&isblank, cp, end, at);
2527
2528 if (__unlikely(!(chars = lex_c99_u8(cp, end, at, psubidx)))) {
2529 diag_if(DIAG_ERROR, 0, at, "expected object sub-index");
2530 return 0;
2531 }
2532 cp += chars;
2533 cp += lex_ctype(&isblank, cp, end, at);
2534
2535 if (__unlikely(!(chars = co_gw_txt_lex_type(cp, end, at, ptype))))
2536 return 0;
2537 cp += chars;
2538
2539 return cp - begin;
2540}
2541
2542static size_t
2543co_gw_txt_lex_pdo(const char *begin, const char *end, struct floc *at, int ext,
2544 co_unsigned16_t *pnum, struct co_pdo_comm_par *pcomm,
2545 struct co_pdo_map_par *pmap)
2546{
2547 assert(begin);
2548
2549 const char *cp = begin;
2550 size_t chars = 0;
2551
2552 co_unsigned16_t num = 0;
2553 if (__unlikely(!(chars = lex_c99_u16(cp, end, at, &num)))) {
2554 diag_if(DIAG_ERROR, 0, at, "expected PDO number");
2555 return 0;
2556 }
2557 cp += chars;
2558
2559 if (__unlikely(!num || num > 512)) {
2560 diag_if(DIAG_ERROR, 0, at,
2561 "PDO number must be in the range [1..512]");
2562 return 0;
2563 }
2564
2565 cp += lex_ctype(&isblank, cp, end, at);
2566
2568
2569 if (__unlikely(!(chars = lex_c99_u32(cp, end, at, &comm.cobid)))) {
2570 diag_if(DIAG_ERROR, 0, at, "expected COB-ID");
2571 return 0;
2572 }
2573 cp += chars;
2574 cp += lex_ctype(&isblank, cp, end, at);
2575
2576 // clang-format off
2577 if (__unlikely(!(chars = co_gw_txt_lex_trans(
2578 cp, end, at, &comm.trans))))
2579 // clang-format on
2580 return 0;
2581 cp += chars;
2582 if (ext && comm.trans >= 0xfe) {
2583 // clang-format off
2584 if (__unlikely(!(chars = lex_c99_u16(cp, end, at,
2585 &comm.inhibit)))) {
2586 // clang-format on
2587 diag_if(DIAG_ERROR, 0, at, "expected inhibit time");
2588 return 0;
2589 }
2590 cp += chars;
2591 }
2592 cp += lex_ctype(&isblank, cp, end, at);
2593
2594 if (ext && comm.trans >= 0xfd) {
2595 // clang-format off
2596 if (__unlikely(!(chars = lex_c99_u16(
2597 cp, end, at, &comm.event)))) {
2598 // clang-format on
2599 diag_if(DIAG_ERROR, 0, at, "expected event timer");
2600 return 0;
2601 }
2602 cp += chars;
2603 cp += lex_ctype(&isblank, cp, end, at);
2604 } else if (ext && comm.trans <= 240) {
2605 // clang-format off
2606 if (__unlikely(!(chars = lex_c99_u8(
2607 cp, end, at, &comm.sync)))) {
2608 // clang-format on
2609 diag_if(DIAG_ERROR, 0, at, "expected SYNC start value");
2610 return 0;
2611 }
2612 cp += chars;
2613 cp += lex_ctype(&isblank, cp, end, at);
2614 }
2615
2617
2618 if (__unlikely(!(chars = lex_c99_u8(cp, end, at, &map.n)))) {
2619 diag_if(DIAG_ERROR, 0, at, "expected number of values");
2620 return 0;
2621 }
2622 cp += chars;
2623 if (__unlikely(map.n > 0x40)) {
2624 diag_if(DIAG_ERROR, 0, at,
2625 "number of mapped values must be in the range [0..64]");
2626 return 0;
2627 }
2628
2629 for (co_unsigned8_t i = 0; i < map.n; i++) {
2630 cp += lex_ctype(&isblank, cp, end, at);
2631
2632 co_unsigned16_t idx = 0;
2633 co_unsigned8_t subidx = 0;
2634 chars = lex_c99_u16(cp, end, at, &idx);
2635 if (chars) {
2636 cp += chars;
2637 cp += lex_ctype(&isblank, cp, end, at);
2638
2639 chars = lex_c99_u8(cp, end, at, &subidx);
2640 if (__unlikely(!chars)) {
2641 diag_if(DIAG_ERROR, 0, at,
2642 "expected object sub-index");
2643 return 0;
2644 }
2645 cp += chars;
2646 cp += lex_ctype(&isblank, cp, end, at);
2647 }
2648
2649 co_unsigned16_t type = 0;
2650 chars = co_gw_txt_lex_type(cp, end, at, &type);
2651 if (__unlikely(!chars))
2652 return 0;
2653 cp += chars;
2654 if (__unlikely(!co_type_is_basic(type))) {
2655 diag_if(DIAG_ERROR, 0, at,
2656 "only basic types can be mapped to PDOs");
2657 return 0;
2658 }
2659
2660 co_unsigned8_t len = co_type_sizeof(type) * CHAR_BIT;
2661 // If no multiplexer was specified, use the type as the object
2662 // index (dummy mapping).
2663 map.map[i] = ((co_unsigned32_t)(idx ? idx : type) << 16)
2664 | ((co_unsigned32_t)subidx << 8) | len;
2665 }
2666
2667 if (pnum)
2668 *pnum = num;
2669
2670 if (pcomm)
2671 *pcomm = comm;
2672
2673 if (pmap) {
2674 pmap->n = map.n;
2675 for (co_unsigned8_t i = 0; i < map.n; i++)
2676 pmap->map[i] = map.map[i];
2677 }
2678
2679 return cp - begin;
2680}
2681
2682static size_t
2683co_gw_txt_lex_type(const char *begin, const char *end, struct floc *at,
2684 co_unsigned16_t *ptype)
2685{
2686 assert(begin);
2687
2688 const char *cp = begin;
2689 size_t chars = 0;
2690
2691 co_unsigned16_t type = 0;
2692
2693 chars = co_gw_txt_lex_cmd(cp, end, at);
2694 if (!strncasecmp("b", cp, chars)) {
2695 type = CO_DEFTYPE_BOOLEAN;
2696 } else if (!strncasecmp("d", cp, chars)) {
2697 type = CO_DEFTYPE_DOMAIN;
2698 } else if (!strncasecmp("i16", cp, chars)) {
2699 type = CO_DEFTYPE_INTEGER16;
2700 } else if (!strncasecmp("i24", cp, chars)) {
2701 type = CO_DEFTYPE_INTEGER24;
2702 } else if (!strncasecmp("i32", cp, chars)) {
2703 type = CO_DEFTYPE_INTEGER32;
2704 } else if (!strncasecmp("i40", cp, chars)) {
2705 type = CO_DEFTYPE_INTEGER40;
2706 } else if (!strncasecmp("i48", cp, chars)) {
2707 type = CO_DEFTYPE_INTEGER48;
2708 } else if (!strncasecmp("i56", cp, chars)) {
2709 type = CO_DEFTYPE_INTEGER56;
2710 } else if (!strncasecmp("i64", cp, chars)) {
2711 type = CO_DEFTYPE_INTEGER64;
2712 } else if (!strncasecmp("i8", cp, chars)) {
2713 type = CO_DEFTYPE_INTEGER8;
2714 } else if (!strncasecmp("os", cp, chars)) {
2716 } else if (!strncasecmp("r32", cp, chars)) {
2717 type = CO_DEFTYPE_REAL32;
2718 } else if (!strncasecmp("r64", cp, chars)) {
2719 type = CO_DEFTYPE_REAL64;
2720 } else if (!strncasecmp("t", cp, chars)) {
2722 } else if (!strncasecmp("td", cp, chars)) {
2723 type = CO_DEFTYPE_TIME_DIFF;
2724 } else if (!strncasecmp("u16", cp, chars)) {
2725 type = CO_DEFTYPE_UNSIGNED16;
2726 } else if (!strncasecmp("u24", cp, chars)) {
2727 type = CO_DEFTYPE_UNSIGNED24;
2728 } else if (!strncasecmp("u32", cp, chars)) {
2729 type = CO_DEFTYPE_UNSIGNED32;
2730 } else if (!strncasecmp("u40", cp, chars)) {
2731 type = CO_DEFTYPE_UNSIGNED40;
2732 } else if (!strncasecmp("u48", cp, chars)) {
2733 type = CO_DEFTYPE_UNSIGNED48;
2734 } else if (!strncasecmp("u56", cp, chars)) {
2735 type = CO_DEFTYPE_UNSIGNED56;
2736 } else if (!strncasecmp("u64", cp, chars)) {
2737 type = CO_DEFTYPE_UNSIGNED64;
2738 } else if (!strncasecmp("u8", cp, chars)) {
2739 type = CO_DEFTYPE_UNSIGNED8;
2740 } else if (!strncasecmp("us", cp, chars)) {
2742 } else if (!strncasecmp("vs", cp, chars)) {
2744 } else {
2745 diag_if(DIAG_ERROR, 0, at, "expected data type");
2746 return 0;
2747 }
2748 cp += chars;
2749
2750 if (ptype)
2751 *ptype = type;
2752
2753 return cp - begin;
2754}
2755
2756static size_t
2757co_gw_txt_lex_val(const char *begin, const char *end, struct floc *at,
2758 co_unsigned16_t type, void *val)
2759{
2760 assert(begin);
2761 assert(!end || end >= begin);
2762
2763 switch (type) {
2764 case CO_DEFTYPE_REAL32: return lex_c99_flt(begin, end, at, val);
2766 const char *cp = begin;
2767 size_t chars = 0;
2768
2769 if (__unlikely(!(chars = lex_char('\"', cp, end, at))))
2770 diag_if(DIAG_WARNING, 0, at,
2771 "expected '\"' before string");
2772 cp += chars;
2773
2774 size_t n = 0;
2775 chars = co_gw_txt_lex_vs(cp, end, at, NULL, &n);
2776 if (val) {
2777 if (__unlikely(co_val_init_vs_n(val, 0, n) == -1)) {
2779 "unable to create value of type VISIBLE_STRING");
2780 return 0;
2781 }
2782 // Parse the characters.
2783 char *vs = *(void **)val;
2784 assert(vs);
2785 co_gw_txt_lex_vs(cp, end, NULL, vs, &n);
2786 }
2787 cp += chars;
2788
2789 if (__unlikely(!(chars = lex_char('\"', cp, end, at))))
2790 diag_if(DIAG_WARNING, 0, at,
2791 "expected '\"' after string");
2792 cp += chars;
2793
2794 return cp - begin;
2795 }
2797 return co_val_lex(CO_DEFTYPE_DOMAIN, val, begin, end, at);
2798 case CO_DEFTYPE_REAL64: return lex_c99_dbl(begin, end, at, val);
2799 default: return co_val_lex(type, val, begin, end, at);
2800 }
2801}
2802
2803static size_t
2804co_gw_txt_lex_vs(const char *begin, const char *end, struct floc *at, char *s,
2805 size_t *pn)
2806{
2807 assert(begin);
2808
2809 struct floc *floc = NULL;
2810 struct floc floc_;
2811 if (at) {
2812 floc = &floc_;
2813 *floc = *at;
2814 }
2815
2816 const char *cp = begin;
2817
2818 size_t n = 0;
2819 char *ends = s + (s && pn ? *pn : 0);
2820
2821 while ((!end || cp < end) && *cp && !isbreak((unsigned char)*cp)) {
2822 char32_t c32 = 0;
2823 if (*cp == '\"') {
2824 if ((end && cp + 1 >= end) || cp[1] != '\"')
2825 break;
2826 c32 = *cp;
2827 cp += floc_lex(floc, cp, cp + 2);
2828 } else if (*cp == '\\') {
2829 cp += lex_c99_esc(cp, end, floc, &c32);
2830 } else {
2831 cp += lex_utf8(cp, end, floc, &c32);
2832 }
2833 if (s || pn)
2834 n += print_utf8(&s, ends, c32);
2835 }
2836
2837 if (pn)
2838 *pn = n;
2839
2840 if (at)
2841 *at = *floc;
2842
2843 return cp - begin;
2844}
2845
2846static size_t
2847co_gw_txt_lex_trans(const char *begin, const char *end, struct floc *at,
2848 co_unsigned8_t *ptrans)
2849{
2850 assert(begin);
2851
2852 const char *cp = begin;
2853 size_t chars = 0;
2854
2855 chars = co_gw_txt_lex_cmd(cp, end, at);
2856 if (__unlikely(!chars)) {
2857 diag_if(DIAG_ERROR, 0, at, "expected transmission type");
2858 return 0;
2859 }
2860
2861 co_unsigned8_t trans = 0;
2862
2863 if (!strncasecmp("event", cp, 5)) {
2864 cp += 5;
2865 if (at)
2866 at->column -= chars - 5;
2867 trans = 0xff;
2868 } else if (!strncasecmp("rtr", cp, chars)) {
2869 cp += chars;
2870 trans = 0xfd;
2871 } else if (!strncasecmp("sync", cp, 4)) {
2872 cp += 4;
2873 if (at)
2874 at->column -= chars - 4;
2875 if (__unlikely(!(chars = lex_c99_u8(cp, end, at, &trans)))) {
2876 diag_if(DIAG_ERROR, 0, at, "expected SYNC period");
2877 return 0;
2878 }
2879 cp += chars;
2880 if (__unlikely(trans > 240)) {
2881 diag_if(DIAG_ERROR, 0, at,
2882 "SYNC period must be in the range [0..240]");
2883 return 0;
2884 }
2885 } else {
2886 diag_if(DIAG_ERROR, 0, at,
2887 "expected 'event', 'rtr' or 'sync<0..240>'");
2888 return 0;
2889 }
2890
2891 if (ptrans)
2892 *ptrans = trans;
2893
2894 return cp - begin;
2895}
2896
2897static size_t
2898co_gw_txt_lex_id(const char *begin, const char *end, struct floc *at,
2899 struct co_id *pid)
2900{
2901 assert(begin);
2902
2903 const char *cp = begin;
2904 size_t chars = 0;
2905
2906 struct co_id id = CO_ID_INIT;
2907
2908 if (__unlikely(!(chars = lex_c99_u32(cp, end, at, &id.vendor_id)))) {
2909 diag_if(DIAG_ERROR, 0, at, "expected vendor-ID");
2910 return 0;
2911 }
2912 cp += chars;
2913 cp += lex_ctype(&isblank, cp, end, at);
2914
2915 if (__unlikely(!(chars = lex_c99_u32(cp, end, at, &id.product_code)))) {
2916 diag_if(DIAG_ERROR, 0, at, "expected product code");
2917 return 0;
2918 }
2919 cp += chars;
2920 cp += lex_ctype(&isblank, cp, end, at);
2921
2922 if (__unlikely(!(chars = lex_c99_u32(cp, end, at, &id.revision)))) {
2923 diag_if(DIAG_ERROR, 0, at, "expected revision number");
2924 return 0;
2925 }
2926 cp += chars;
2927 cp += lex_ctype(&isblank, cp, end, at);
2928
2929 if (__unlikely(!(chars = lex_c99_u32(cp, end, at, &id.serial_nr)))) {
2930 diag_if(DIAG_ERROR, 0, at, "expected serial number");
2931 return 0;
2932 }
2933 cp += chars;
2934
2935 if (pid)
2936 *pid = id;
2937
2938 return cp - begin;
2939}
2940
2941static size_t
2942co_gw_txt_lex_id_sel(const char *begin, const char *end, struct floc *at,
2943 struct co_id *plo, struct co_id *phi)
2944{
2945 assert(begin);
2946
2947 const char *cp = begin;
2948 size_t chars = 0;
2949
2950 struct co_id lo = CO_ID_INIT;
2951
2952 if (__unlikely(!(chars = lex_c99_u32(cp, end, at, &lo.vendor_id)))) {
2953 diag_if(DIAG_ERROR, 0, at, "expected vendor-ID");
2954 return 0;
2955 }
2956 cp += chars;
2957 cp += lex_ctype(&isblank, cp, end, at);
2958
2959 if (__unlikely(!(chars = lex_c99_u32(cp, end, at, &lo.product_code)))) {
2960 diag_if(DIAG_ERROR, 0, at, "expected product code");
2961 return 0;
2962 }
2963 cp += chars;
2964 cp += lex_ctype(&isblank, cp, end, at);
2965
2966 struct co_id hi = lo;
2967
2968 if (__unlikely(!(chars = lex_c99_u32(cp, end, at, &lo.revision)))) {
2969 diag_if(DIAG_ERROR, 0, at,
2970 "expected lower bound for revision number");
2971 return 0;
2972 }
2973 cp += chars;
2974 cp += lex_ctype(&isblank, cp, end, at);
2975
2976 if (__unlikely(!(chars = lex_c99_u32(cp, end, at, &hi.revision)))) {
2977 diag_if(DIAG_ERROR, 0, at,
2978 "expected upper bound for revision number");
2979 return 0;
2980 }
2981 cp += chars;
2982 cp += lex_ctype(&isblank, cp, end, at);
2983
2984 if (__unlikely(!(chars = lex_c99_u32(cp, end, at, &lo.serial_nr)))) {
2985 diag_if(DIAG_ERROR, 0, at,
2986 "expected lower bound for serial number");
2987 return 0;
2988 }
2989 cp += chars;
2990 cp += lex_ctype(&isblank, cp, end, at);
2991
2992 if (__unlikely(!(chars = lex_c99_u32(cp, end, at, &hi.serial_nr)))) {
2993 diag_if(DIAG_ERROR, 0, at,
2994 "expected upper bound for serial number");
2995 return 0;
2996 }
2997 cp += chars;
2998
2999 if (plo)
3000 *plo = lo;
3001
3002 if (phi)
3003 *phi = hi;
3004
3005 return cp - begin;
3006}
3007
3008#endif // !LELY_NO_CO_GW_TXT
This header file is part of the CANopen library; it contains the device description declarations.
#define CO_NUM_NODES
The maximum number of nodes in a CANopen network.
Definition: dev.h:56
#define CO_ID_INIT
The static initializer for struct co_id.
Definition: dev.h:47
This header file is part of the utilities library; it contains the diagnostic declarations.
size_t floc_lex(struct floc *at, const char *begin, const char *end)
Increments a file location by reading characters from a memory buffer.
Definition: diag.c:54
@ DIAG_WARNING
A warning.
Definition: diag.h:47
@ DIAG_ERROR
An error.
Definition: diag.h:49
void diag_if(enum diag_severity severity, int errc, const struct floc *at, const char *format,...)
Emits a diagnostic message occurring at a location in a text file.
Definition: diag.c:190
void diag(enum diag_severity severity, int errc, const char *format,...)
Emits a diagnostic message.
Definition: diag.c:156
@ ERRNUM_INVAL
Invalid argument.
Definition: errnum.h:129
int get_errc(void)
Returns the last (thread-specific) native error code set by a system call or library function.
Definition: errnum.c:947
void set_errc(int errc)
Sets the current (thread-specific) native error code to errc.
Definition: errnum.c:957
int errno2c(int errnum)
Transforms a standard C error number to a native error code.
Definition: errnum.c:43
void set_errnum(errnum_t errnum)
Sets the current (thread-specific) platform-independent error number to errnum.
Definition: errnum.h:375
#define __unlikely(x)
Indicates to the compiler that the expression is most-likely false.
Definition: features.h:286
#define __likely(x)
Indicates to the compiler that the expression is most-likely true.
Definition: features.h:273
#define CO_GW_SRV_SET_RPDO
CANopen gateway service: Configure RPDO.
Definition: gw.h:47
#define CO_GW_SRV_SET_CMD_TIMEOUT
CANopen gateway service: Set command time-out.
Definition: gw.h:110
#define CO_GW_SRV_NMT_STOP
CANopen gateway service: Start node.
Definition: gw.h:65
#define CO_GW_SRV_LSS_SET_ID
CANopen gateway service: LSS configure node-ID.
Definition: gw.h:134
#define CO_GW_SRV_LSS_SWITCH_RATE
CANopen gateway service: LSS activate new bit-rate.
Definition: gw.h:140
#define CO_GW_SRV_NMT_ENTER_PREOP
CANopen gateway service: Set node to pre-operational.
Definition: gw.h:68
#define CO_GW_SRV_SET_TPDO
CANopen gateway service: Configure TPDO.
Definition: gw.h:50
#define CO_GW_SRV_LSS_GET_LSSID
CANopen gateway service: Inquire LSS address.
Definition: gw.h:146
#define CO_GW_CON_SDO_UP_SIZE
The minimum size (in bytes) of a CANopen gateway 'SDO upload' confirmation.
Definition: gw.h:725
#define CO_GW_SRV_LSS_SWITCH
CANopen gateway service: LSS switch state global.
Definition: gw.h:128
#define CO_GW_REQ_SDO_DN_SIZE
The minimum size (in bytes) of a CANopen gateway 'SDO download' request.
Definition: gw.h:349
#define CO_GW_SRV_SET_SDO_TIMEOUT
CANopen gateway service: Configure SDO time-out.
Definition: gw.h:44
#define CO_GW_SRV_LSS_SET_RATE
CANopen gateway service: LSS configure bit-rate.
Definition: gw.h:137
#define CO_GW_SRV_RPDO
CANopen gateway service: RPDO received.
Definition: gw.h:59
#define CO_GW_SRV__BOOT
Lely-specific gateway service: Boot slave process completed.
Definition: gw.h:173
const char * co_gw_iec2str(int iec)
Returns a string describing an internal error code.
Definition: gw.c:458
#define CO_GW_SRV_SDO
CANopen gateway service: CiA 301 progress indication download.
Definition: gw.h:158
#define CO_GW_SRV_SET_CMD_SIZE
CANopen gateway service: Set command size.
Definition: gw.h:125
#define CO_GW_SRV_SET_BOOTUP_IND
CANopen gateway service: Boot-up forwarding.
Definition: gw.h:113
#define CO_GW_SRV_SET_NODE
CANopen gateway service: Set default node-ID.
Definition: gw.h:119
#define CO_GW_SRV_NMT_HB_ENABLE
CANopen gateway service: Start heartbeat consumer.
Definition: gw.h:83
#define CO_GW_SRV_LSS_ID_NON_CFG_SLAVE
CANopen gateway service: LSS identify non-configured remote slaves.
Definition: gw.h:155
#define CO_GW_SRV_PDO_WRITE
CANopen gateway service: Write PDO data.
Definition: gw.h:56
#define CO_GW_SRV_NMT_RESET_COMM
CANopen gateway service: Reset communication.
Definition: gw.h:74
#define CO_GW_SRV_SDO_UP
CANopen gateway service: SDO upload.
Definition: gw.h:38
#define CO_GW_SRV_PDO_READ
CANopen gateway service: Read PDO data.
Definition: gw.h:53
#define CO_GW_IND_RPDO_SIZE
The minimum size (in bytes) of a CANopen gateway 'RPDO received' indication.
Definition: gw.h:851
#define CO_GW_SRV_SET_ID
CANopen gateway service: Set node-ID.
Definition: gw.h:101
#define CO_GW_SRV_NMT_START
CANopen gateway service: Start node.
Definition: gw.h:62
#define CO_GW_SRV__SYNC
Lely-specific gateway service: Synchronization event received.
Definition: gw.h:167
#define CO_GW_SRV_EMCY
CANopen gateway service: Emergency event received.
Definition: gw.h:92
#define CO_GW_IEC_SYNTAX
CANopen gateway internal error: Syntax error.
Definition: gw.h:179
#define CO_GW_SRV_EC
CANopen gateway service: Error control event received.
Definition: gw.h:89
#define CO_GW_SRV_SET_NET
CANopen gateway service: Set default network.
Definition: gw.h:116
#define CO_GW_SRV__TIME
Lely-specific gateway service: Time stamp event received.
Definition: gw.h:170
#define CO_GW_SRV_NMT_RESET_NODE
CANopen gateway service: Reset node.
Definition: gw.h:71
#define CO_GW_REQ_SET_RPDO_SIZE
The minimum size (in bytes) of a CANopen gateway 'Configure RPDO' request.
Definition: gw.h:388
#define CO_GW_IEC_BOOTUP
CANopen gateway internal error: Boot-up.
Definition: gw.h:215
#define CO_GW_NUM_NET
The maximum number of networks in a CANopen gateway.
Definition: gw.h:29
#define CO_GW_SRV_LSS_ID_SLAVE
CANopen gateway service: LSS identify remote slave.
Definition: gw.h:152
#define CO_GW_SRV_LSS_STORE
CANopen gateway service: LSS store configuration.
Definition: gw.h:143
#define CO_GW_SRV__LSS_SLOWSCAN
Lely-specific gateway service: LSS Slowscan.
Definition: gw.h:161
#define CO_GW_SRV_LSS_GET_ID
CANopen gateway service: LSS inquire node-ID.
Definition: gw.h:149
#define CO_GW_SRV_GET_VERSION
CANopen gateway service: Get version.
Definition: gw.h:122
#define CO_GW_REQ_SET_TPDO_SIZE
The minimum size (in bytes) of a CANopen gateway 'Configure TPDO' request.
Definition: gw.h:419
#define CO_GW_CON_PDO_READ_SIZE
The minimum size (in bytes) of a CANopen gateway 'Read PDO' confirmation.
Definition: gw.h:750
#define CO_GW_REQ_PDO_WRITE_SIZE
The minimum size (in bytes) of a CANopen gateway 'Write PDO' request.
Definition: gw.h:454
#define CO_GW_SRV__LSS_FASTSCAN
Lely-specific gateway service: LSS Fastscan.
Definition: gw.h:164
#define CO_GW_SRV_NMT_NG_ENABLE
CANopen gateway service: Enable node guarding.
Definition: gw.h:77
#define CO_GW_SRV_NMT_NG_DISABLE
CANopen gateway service: Disable node guarding.
Definition: gw.h:80
#define CO_GW_IEC_INTERN
CANopen gateway internal error: Request not processed due to internal state.
Definition: gw.h:182
#define CO_GW_SRV_NMT_HB_DISABLE
CANopen gateway service: Disable heartbeat consumer.
Definition: gw.h:86
#define CO_GW_SRV_SET_HB
CANopen gateway service: Set heartbeat producer.
Definition: gw.h:98
#define CO_GW_SRV_INIT
CANopen gateway service: Initialize gateway.
Definition: gw.h:95
#define CO_GW_SRV_SDO_DN
CANopen gateway service: SDO download.
Definition: gw.h:41
#define CO_GW_SRV_LSS_SWITCH_SEL
CANopen gateway service: LSS switch state selective.
Definition: gw.h:131
static size_t co_gw_txt_send_set_cmd_timeout(co_gw_txt_t *gw, int srv, void *data, const char *begin, const char *end, struct floc *at)
Sends a 'Set command time-out' request after parsin gits parameters.
Definition: gw_txt.c:1694
void co_gw_txt_set_send_func(co_gw_txt_t *gw, co_gw_txt_send_func_t *func, void *data)
Sets the callback function used to send requests from the user to a CANopen gateway.
Definition: gw_txt.c:783
void co_gw_txt_destroy(co_gw_txt_t *gw)
Destroys a CANopen ASCII gateway.
Definition: gw_txt.c:360
static size_t co_gw_txt_send_set_hb(co_gw_txt_t *gw, int srv, void *data, co_unsigned16_t net, const char *begin, const char *end, struct floc *at)
Sends a 'Set heartbeat producer' request after parsing its parameters.
Definition: gw_txt.c:1633
static size_t co_gw_txt_send_lss_switch(co_gw_txt_t *gw, int srv, void *data, co_unsigned16_t net, const char *begin, const char *end, struct floc *at)
Sends an 'LSS switch state global' request after parsing its parameters.
Definition: gw_txt.c:1848
static size_t co_gw_txt_lex_id_sel(const char *begin, const char *end, struct floc *at, struct co_id *plo, struct co_id *phi)
Lexes an LSS address range.
Definition: gw_txt.c:2942
static int co_gw_txt_recv_lss_get_id(co_gw_txt_t *gw, co_unsigned32_t seq, const struct co_gw_con_lss_get_id *con)
Processes an 'LSS inquire node-ID' confirmation.
Definition: gw_txt.c:987
static size_t co_gw_txt_send__lss_fastscan(co_gw_txt_t *gw, int srv, void *data, co_unsigned16_t net, const char *begin, const char *end, struct floc *at)
Sends an 'LSS Fastscan' request after parsing its parameters.
Definition: gw_txt.c:2091
static size_t co_gw_txt_send_set_bootup_ind(co_gw_txt_t *gw, int srv, void *data, co_unsigned16_t net, const char *begin, const char *end, struct floc *at)
Sends a 'Boot-up forwarding' request after parsing its parameters.
Definition: gw_txt.c:1720
static size_t co_gw_txt_lex_sdo(const char *begin, const char *end, struct floc *at, co_unsigned16_t *pidx, co_unsigned8_t *psubidx, co_unsigned16_t *ptype)
Lexes the multiplexer and data type of an SDO upload/download request.
Definition: gw_txt.c:2512
static size_t co_gw_txt_send_set_node(co_gw_txt_t *gw, int srv, void *data, co_unsigned16_t net, const char *begin, const char *end, struct floc *at)
Sends a 'Set default node-ID' request after parsing its parameters.
Definition: gw_txt.c:1788
void co_gw_txt_get_recv_func(const co_gw_txt_t *gw, co_gw_txt_recv_func_t **pfunc, void **pdata)
Retrieves the callback function used to forward indications and confirmations received by a CANopen g...
Definition: gw_txt.c:484
static int co_gw_txt_recv_emcy(co_gw_txt_t *gw, const struct co_gw_ind_emcy *ind)
Processes an 'Emergency event received' indication.
Definition: gw_txt.c:1099
static size_t co_gw_txt_send_sdo_dn(co_gw_txt_t *gw, int srv, void *data, co_unsigned16_t net, co_unsigned8_t node, const char *begin, const char *end, struct floc *at)
Sends an 'SDO download' request after parsing its parameters.
Definition: gw_txt.c:1255
static size_t co_gw_txt_lex_srv(const char *begin, const char *end, struct floc *at, int *psrv)
Lexes the service number of a request.
Definition: gw_txt.c:2271
static size_t co_gw_txt_send__lss_slowscan(co_gw_txt_t *gw, int srv, void *data, co_unsigned16_t net, const char *begin, const char *end, struct floc *at)
Sends an 'LSS Slowscan' request after parsing its parameters.
Definition: gw_txt.c:2063
static size_t co_gw_txt_send_lss_switch_sel(co_gw_txt_t *gw, int srv, void *data, co_unsigned16_t net, const char *begin, const char *end, struct floc *at)
Sends an 'LSS switch state selective' request after parsing its parameters.
Definition: gw_txt.c:1876
static size_t co_gw_txt_send_lss_set_id(co_gw_txt_t *gw, int srv, void *data, co_unsigned16_t net, const char *begin, const char *end, struct floc *at)
Sends an 'LSS configure node-ID' request after parsing its parameters.
Definition: gw_txt.c:1902
static int co_gw_txt_recv_txt(co_gw_txt_t *gw, const char *txt)
Invokes the callback function to process a received indication or confirmation.
Definition: gw_txt.c:1175
static int co_gw_txt_recv_fmt(co_gw_txt_t *gw, const char *format,...)
Formats a received indication or confirmation and invokes the callback function to process it.
Definition: gw_txt.c:1145
static int co_gw_txt_recv_pdo_read(co_gw_txt_t *gw, co_unsigned32_t seq, const struct co_gw_con_pdo_read *con)
Processes a 'Read PDO data' confirmation.
Definition: gw_txt.c:914
void co_gw_txt_get_send_func(const co_gw_txt_t *gw, co_gw_txt_send_func_t **pfunc, void **pdata)
Retrieves the callback function used to send requests from the user to a CANopen gateway.
Definition: gw_txt.c:771
static size_t co_gw_txt_lex_type(const char *begin, const char *end, struct floc *at, co_unsigned16_t *ptype)
Lexes a data type.
Definition: gw_txt.c:2683
static size_t co_gw_txt_send_init(co_gw_txt_t *gw, int srv, void *data, co_unsigned16_t net, const char *begin, const char *end, struct floc *at)
Sends an 'Initialize gateway' request after parsing its parameters.
Definition: gw_txt.c:1600
static int co_gw_txt_recv_con(co_gw_txt_t *gw, co_unsigned32_t seq, const struct co_gw_con *con)
Processes a confirmation.
Definition: gw_txt.c:793
static int co_gw_txt_recv_sdo_up(co_gw_txt_t *gw, co_unsigned32_t seq, const struct co_gw_con_sdo_up *con)
Processes an 'SDO upload' confirmation.
Definition: gw_txt.c:866
size_t co_gw_txt_send(co_gw_txt_t *gw, const char *begin, const char *end, struct floc *at)
Sends a user request to a CANopen gateway.
Definition: gw_txt.c:496
static size_t co_gw_txt_send_lss_get_lssid(co_gw_txt_t *gw, int srv, void *data, co_unsigned16_t net, const char *begin, const char *end, struct floc *at)
Sends an 'Inquire LSS address' request after parsing its parameters.
Definition: gw_txt.c:2002
static size_t co_gw_txt_send_sdo_up(co_gw_txt_t *gw, int srv, void *data, co_unsigned16_t net, co_unsigned8_t node, const char *begin, const char *end, struct floc *at)
Sends an 'SDO upload' request after parsing its parameters.
Definition: gw_txt.c:1221
static size_t co_gw_txt_send_set_cmd_size(co_gw_txt_t *gw, int srv, void *data, const char *begin, const char *end, struct floc *at)
Sends a 'Set command size' request after parsing its parameters.
Definition: gw_txt.c:1823
co_gw_txt_t * co_gw_txt_create(void)
Creates a new CANopen ASCII gateway.
Definition: gw_txt.c:335
static size_t co_gw_txt_send_pdo_read(co_gw_txt_t *gw, int srv, void *data, co_unsigned16_t net, const char *begin, const char *end, struct floc *at)
Sends a 'Read PDO data' request after parsing its parameters.
Definition: gw_txt.c:1440
static size_t co_gw_txt_send_lss_set_rate(co_gw_txt_t *gw, int srv, void *data, co_unsigned16_t net, const char *begin, const char *end, struct floc *at)
Sends an 'LSS configure bit-rate' request after parsing its parameters.
Definition: gw_txt.c:1937
static int co_gw_txt_recv_sdo(co_gw_txt_t *gw, const struct co_gw_ind_sdo *ind)
Processes an 'CiA 301 progress indication download' indication.
Definition: gw_txt.c:1110
static size_t co_gw_txt_lex_trans(const char *begin, const char *end, struct floc *at, co_unsigned8_t *ptrans)
Lexes the transmission type of a configure PDO request.
Definition: gw_txt.c:2847
static size_t co_gw_txt_send_set_sdo_timeout(co_gw_txt_t *gw, int srv, void *data, co_unsigned16_t net, const char *begin, const char *end, struct floc *at)
Sends a 'Configure SDO time-out' request after parsing its parameters.
Definition: gw_txt.c:1327
static size_t co_gw_txt_send_set_id(co_gw_txt_t *gw, int srv, void *data, co_unsigned16_t net, const char *begin, const char *end, struct floc *at)
Sends a 'Set node-ID' request after parsing its parameters.
Definition: gw_txt.c:1660
void co_gw_txt_set_recv_func(co_gw_txt_t *gw, co_gw_txt_recv_func_t *func, void *data)
Sets the callback function used to forward indications and confirmations received by a CANopen gatewa...
Definition: gw_txt.c:761
int co_gw_txt_recv(co_gw_txt_t *gw, const struct co_gw_srv *srv)
Receives and forwards an indication or confirmation from a CANopen gateway.
Definition: gw_txt.c:387
static void co_gw_txt_send_req(co_gw_txt_t *gw, const struct co_gw_req *req)
Invokes the callback function to send a request.
Definition: gw_txt.c:2174
static size_t co_gw_txt_print_val(char **pbegin, char *end, co_unsigned16_t type, const void *val)
Prints a CANopen value.
Definition: gw_txt.c:1189
static size_t co_gw_txt_lex_val(const char *begin, const char *end, struct floc *at, co_unsigned16_t type, void *val)
Lexes a value for an SDO download request.
Definition: gw_txt.c:2757
static size_t co_gw_txt_lex_prefix(const char *begin, const char *end, struct floc *at, co_unsigned32_t *pseq, co_unsigned16_t *pnet, co_unsigned8_t *pnode)
Lexes the prefix (sequence number and optional network and node-ID) of a request.
Definition: gw_txt.c:2190
static int co_gw_txt_recv__boot(co_gw_txt_t *gw, const struct co_gw_ind__boot *ind)
Processes a 'Boot slave process completed' indication.
Definition: gw_txt.c:1120
static int co_gw_txt_recv__lss_scan(co_gw_txt_t *gw, co_unsigned32_t seq, const struct co_gw_con__lss_scan *con)
Processes an 'LSS Slowscan/Fastscan' confirmation.
Definition: gw_txt.c:997
int co_gw_txt_iec(co_gw_txt_t *gw)
Returns (and clears) the last internal error code.
Definition: gw_txt.c:369
static size_t co_gw_txt_send_lss_switch_rate(co_gw_txt_t *gw, int srv, void *data, co_unsigned16_t net, const char *begin, const char *end, struct floc *at)
Sends an 'LSS activate new bit-rate' request after parsing its parameters.
Definition: gw_txt.c:1974
static size_t co_gw_txt_send_nmt_set_ng(co_gw_txt_t *gw, int srv, void *data, co_unsigned16_t net, co_unsigned8_t node, const char *begin, const char *end, struct floc *at)
Sends an 'Enable node guarding' request after parsing its parameters.
Definition: gw_txt.c:1533
static size_t co_gw_txt_send_nmt_set_hb(co_gw_txt_t *gw, int srv, void *data, co_unsigned16_t net, co_unsigned8_t node, const char *begin, const char *end, struct floc *at)
Sends a 'Start heartbeat consumer' request after parsing its parameters.
Definition: gw_txt.c:1571
static int co_gw_txt_recv_lss_get_lssid(co_gw_txt_t *gw, co_unsigned32_t seq, const struct co_gw_con_lss_get_lssid *con)
Processes an 'Inquire LSS address' confirmation.
Definition: gw_txt.c:976
static size_t co_gw_txt_lex_cmd(const char *begin, const char *end, struct floc *at)
Lexes a single command.
Definition: gw_txt.c:2493
static int co_gw_txt_recv_get_version(co_gw_txt_t *gw, co_unsigned32_t seq, const struct co_gw_con_get_version *con)
Processes a 'Get version' confirmation.
Definition: gw_txt.c:959
size_t co_gw_txt_pending(const co_gw_txt_t *gw)
Returns the number of pending (i.e., unconfirmed) requests.
Definition: gw_txt.c:379
static int co_gw_txt_recv_err(co_gw_txt_t *gw, co_unsigned32_t seq, int iec, co_unsigned32_t ac)
Processes a confirmation with a non-zero internal error code or SDO abort code.
Definition: gw_txt.c:1010
static size_t co_gw_txt_send_set_tpdo(co_gw_txt_t *gw, int srv, void *data, co_unsigned16_t net, const char *begin, const char *end, struct floc *at)
Sends a 'Configure TPDO' request after parsing its parameters.
Definition: gw_txt.c:1392
static size_t co_gw_txt_send_lss_id_slave(co_gw_txt_t *gw, int srv, void *data, co_unsigned16_t net, const char *begin, const char *end, struct floc *at)
Sends an 'LSS identify remote slave' request after parsing its parameters.
Definition: gw_txt.c:2035
static size_t co_gw_txt_send_set_net(co_gw_txt_t *gw, int srv, void *data, const char *begin, const char *end, struct floc *at)
Sends a 'Set default network' request after parsing its parameters.
Definition: gw_txt.c:1756
static size_t co_gw_txt_lex_vs(const char *begin, const char *end, struct floc *at, char *s, size_t *pn)
Lexes an array of visible characters (CO_DEFTYPE_VISIBLE_STRING), excluding the delimiting quotes,...
Definition: gw_txt.c:2804
static size_t co_gw_txt_send_pdo_write(co_gw_txt_t *gw, int srv, void *data, co_unsigned16_t net, const char *begin, const char *end, struct floc *at)
Sends a 'Write PDO data' request after parsing its parameters.
Definition: gw_txt.c:1473
static size_t co_gw_txt_send_set_rpdo(co_gw_txt_t *gw, int srv, void *data, co_unsigned16_t net, const char *begin, const char *end, struct floc *at)
Sends a 'Configure RPDO' request after parsing its parameters.
Definition: gw_txt.c:1355
static size_t co_gw_txt_lex_pdo(const char *begin, const char *end, struct floc *at, int ext, co_unsigned16_t *pnum, struct co_pdo_comm_par *pcomm, struct co_pdo_map_par *pmap)
Lexes the communication and mapping parameters of a configure PDO request.
Definition: gw_txt.c:2543
static int co_gw_txt_recv_rpdo(co_gw_txt_t *gw, const struct co_gw_ind_rpdo *ind)
Processes an 'RPDO received' indication.
Definition: gw_txt.c:1028
static size_t co_gw_txt_lex_id(const char *begin, const char *end, struct floc *at, struct co_id *pid)
Lexes an LSS address.
Definition: gw_txt.c:2898
static int co_gw_txt_recv_ec(co_gw_txt_t *gw, const struct co_gw_ind_ec *ind)
Processes an 'Error control event received' indication.
Definition: gw_txt.c:1071
This header file is part of the CANopen library; it contains the ASCII gateway declarations (see CiA ...
int co_gw_txt_recv_func_t(const char *txt, void *data)
The type of a CANopen ASCII gateway receive callback function, invoked when when an indication of con...
Definition: gw_txt.h:58
#define CO_GW_TXT_IMPL_HI
The high number of the version of CiA 309-3 implemented by this gateway.
Definition: gw_txt.h:28
int co_gw_txt_send_func_t(const struct co_gw_req *req, void *data)
The type of a CANopen ASCII gateway send callback function, invoked when a request has been issued by...
Definition: gw_txt.h:70
#define CO_GW_TXT_IMPL_LO
The low number of the version of CiA 309-3 implemented by this gateway.
Definition: gw_txt.h:31
This header file is part of the CANopen library; it contains the Service Data Object (SDO) declaratio...
#define CO_SDO_AC_TYPE_LEN
SDO abort code: Data type does not match, length of service parameter does not match.
Definition: sdo.h:117
const char * co_sdo_ac2str(co_unsigned32_t ac)
Returns a string describing an SDO abort code.
Definition: sdo.c:57
#define MAX(a, b)
Returns the maximum of a and b.
Definition: util.h:65
This header file is part of the utilities library; it contains the lexer function declarations.
size_t lex_char(int c, const char *begin, const char *end, struct floc *at)
Lexes the specified character from a memory buffer.
Definition: lex.c:38
size_t lex_ctype(int(*ctype)(int), const char *begin, const char *end, struct floc *at)
Greedily lexes a sequence of characters of the specified class from a memory buffer.
Definition: lex.c:51
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
size_t lex_c99_long(const char *begin, const char *end, struct floc *at, long *pl)
Lexes a C99 long from a memory buffer.
Definition: lex.c:404
size_t lex_line_comment(const char *delim, const char *begin, const char *end, struct floc *at)
Lexes a single line-comment (excluding the line break) starting with the specified delimiter from a m...
Definition: lex.c:634
size_t lex_c99_u8(const char *begin, const char *end, struct floc *at, uint_least8_t *pu8)
Lexes a C99 uint_least8_t from a memory buffer.
Definition: lex.c:544
size_t lex_c99_flt(const char *begin, const char *end, struct floc *at, float *pf)
Lexes a C99 float from a memory buffer.
Definition: lex.c:416
size_t lex_c99_esc(const char *begin, const char *end, struct floc *at, char32_t *pc32)
Lexes a C99 character escape sequence from a memory buffer if the buffer begins with '\',...
Definition: lex.c:184
int isbreak(int c)
Returns 1 if c is a line break character, and 0 otherwise.
Definition: lex.h:314
size_t lex_c99_u32(const char *begin, const char *end, struct floc *at, uint_least32_t *pu32)
Lexes a C99 uint_least32_t from a memory buffer.
Definition: lex.c:582
size_t lex_c99_u64(const char *begin, const char *end, struct floc *at, uint_least64_t *pu64)
Lexes a C99 uint_least64_t from a memory buffer.
Definition: lex.c:605
size_t lex_c99_u16(const char *begin, const char *end, struct floc *at, uint_least16_t *pu16)
Lexes a C99 uint_least16_t from a memory buffer.
Definition: lex.c:563
size_t lex_c99_dbl(const char *begin, const char *end, struct floc *at, double *pd)
Lexes a C99 double from a memory buffer.
Definition: lex.c:417
This header file is part of the CANopen library; it contains the network management (NMT) declaration...
const char * co_nmt_es2str(char es)
Returns a pointer to a string describing an NMT boot error status.
Definition: nmt.c:679
#define CO_NMT_ST_PREOP
The NMT state 'pre-operational'.
Definition: nmt.h:70
#define CO_NMT_ST_START
The NMT state 'operational'.
Definition: nmt.h:61
#define CO_NMT_ST_RESET_NODE
The NMT sub-state 'reset application'.
Definition: nmt.h:64
#define CO_NMT_ST_RESET_COMM
The NMT sub-state 'reset communication'.
Definition: nmt.h:67
#define CO_NMT_ST_STOP
The NMT state 'stopped'.
Definition: nmt.h:58
This header file is part of the CANopen library; it contains the Process Data Object (PDO) declaratio...
#define CO_PDO_MAP_PAR_INIT
The static initializer from struct co_pdo_map_par.
Definition: pdo.h:78
#define CO_PDO_COMM_PAR_INIT
The static initializer from struct co_pdo_comm_par.
Definition: pdo.h:60
This header file is part of the utilities library; it contains the printing function declarations.
size_t print_c99_dbl(char **pbegin, char *end, double d)
Prints a C99 double to a memory buffer.
Definition: print.c:225
size_t print_char(char **pbegin, char *end, int c)
Prints a single character to a memory buffer.
Definition: print.h:284
size_t print_c99_flt(char **pbegin, char *end, float f)
Prints a C99 float to a memory buffer.
Definition: print.c:224
size_t print_c99_esc(char **pbegin, char *end, char32_t c32)
Prints a UTF-8 encoded Unicode character to a memory buffer.
Definition: print.c:106
size_t print_utf8(char **pbegin, char *end, char32_t c32)
Prints a UTF-8 encoded Unicode character to a memory buffer.
Definition: print.c:84
This is the internal header file of the CANopen library.
This header file is part of the C11 and POSIX compatibility library; it includes <stdio....
int asprintf(char **strp, const char *fmt,...)
Equivalent to sprintf(), except that it allocates a string large enough to hold the output,...
Definition: stdio.c:103
int vasprintf(char **strp, const char *fmt, va_list ap)
Equivalent to vsprintf(), except that it allocates a string large enough to hold the output,...
Definition: stdio.c:113
This header file is part of the C11 and POSIX compatibility library; it includes <stdlib....
This header file is part of the C11 and POSIX compatibility library; it includes <strings....
int strncasecmp(const char *s1, const char *s2, size_t n)
Compares at most n characters from the the string at s1 to the string at s2, ignoring differences in ...
Definition: strings.c:86
A CANopen ASCII gateway.
Definition: gw_txt.c:45
int iec
The last internal error code.
Definition: gw_txt.c:47
co_gw_txt_recv_func_t * recv_func
A pointer to the callback function invoked by co_gw_txt_recv().
Definition: gw_txt.c:51
size_t pending
The number of pending requests.
Definition: gw_txt.c:49
void * send_data
A pointer to the user-specified data for send_func.
Definition: gw_txt.c:57
void * recv_data
A pointer to the user-specified data for recv_func.
Definition: gw_txt.c:53
co_gw_txt_send_func_t * send_func
A pointer to the callback function invoked by co_gw_txt_send().
Definition: gw_txt.c:55
The parameters of a Lely-specific gateway 'LSS Slowscan/Fastscan' confirmation.
Definition: gw.h:816
struct co_id id
The LSS address.
Definition: gw.h:831
The parameters of a CANopen gateway 'Get version' confirmation.
Definition: gw.h:753
co_unsigned32_t product_code
The product code.
Definition: gw.h:767
int srv
The service number (CO_GW_SRV_GET_VERSION).
Definition: gw.h:757
co_unsigned8_t gw_class
The gateway class.
Definition: gw.h:773
co_unsigned8_t prot_hi
The protocol version (high number).
Definition: gw.h:775
co_unsigned32_t revision
The revision number.
Definition: gw.h:769
co_unsigned8_t prot_lo
The protocol version (low number).
Definition: gw.h:777
co_unsigned32_t vendor_id
The vendor-ID.
Definition: gw.h:765
co_unsigned32_t serial_nr
The serial number.
Definition: gw.h:771
The parameters of a CANopen gateway 'LSS inquire node-ID' confirmation.
Definition: gw.h:797
co_unsigned8_t id
The node-ID.
Definition: gw.h:809
int srv
The service number (CO_GW_SRV_LSS_GET_ID).
Definition: gw.h:801
The parameters of a CANopen gateway 'Inquire LSS address' confirmation.
Definition: gw.h:781
co_unsigned32_t id
The LSS number.
Definition: gw.h:793
int srv
The service number (CO_GW_SRV_LSS_GET_LSSID).
Definition: gw.h:785
The parameters of a CANopen gateway 'Read PDO' confirmation.
Definition: gw.h:728
co_unsigned8_t n
Number of mapped objects in PDO.
Definition: gw.h:744
co_unsigned16_t net
The network-ID.
Definition: gw.h:740
int srv
The service number (CO_GW_SRV_PDO_READ).
Definition: gw.h:732
co_unsigned64_t val[0x40]
An array of object values.
Definition: gw.h:746
size_t size
The size of this struct (in bytes).
Definition: gw.h:730
The parameters of a CANopen gateway 'SDO upload' confirmation.
Definition: gw.h:705
co_unsigned32_t len
The length of the value (in bytes).
Definition: gw.h:719
co_unsigned16_t type
The data type.
Definition: gw.h:717
size_t size
The size of this struct (in bytes).
Definition: gw.h:707
int srv
The service number (CO_GW_SRV_SDO_UP).
Definition: gw.h:709
char val[1]
The (first byte in the) value.
Definition: gw.h:721
The common parameters of a CANopen gateway confirmation.
Definition: gw.h:691
void * data
A pointer to user-specified data.
Definition: gw.h:697
int iec
The internal error code (0 on success).
Definition: gw.h:699
int srv
The service number.
Definition: gw.h:695
size_t size
The size of this struct (in bytes).
Definition: gw.h:693
co_unsigned32_t ac
The SDO abort code (0 on success).
Definition: gw.h:701
The parameters of a Lely-specific gateway 'Boot slave process completed' indication.
Definition: gw.h:947
co_unsigned16_t net
The network-ID.
Definition: gw.h:953
char es
The error status (in the range ['A'..'O'], or 0 on success).
Definition: gw.h:959
co_unsigned8_t node
The node-ID.
Definition: gw.h:955
int srv
The service number (CO_GW_SRV__BOOT).
Definition: gw.h:951
co_unsigned8_t st
The the state of the node (including the toggle bit).
Definition: gw.h:957
The parameters of a CANopen gateway 'Error control event received' indication.
Definition: gw.h:857
co_unsigned8_t node
The node-ID.
Definition: gw.h:865
int iec
The internal error code (0 on success).
Definition: gw.h:869
int srv
The service number (CO_GW_SRV_EC).
Definition: gw.h:861
co_unsigned16_t net
The network-ID.
Definition: gw.h:863
co_unsigned8_t st
The state of the node, or 0 in case of a boot-up event.
Definition: gw.h:867
The parameters of a CANopen gateway 'Emergency event received' indication.
Definition: gw.h:873
int srv
The service number (CO_GW_SRV_EMCY).
Definition: gw.h:877
co_unsigned16_t net
The network-ID.
Definition: gw.h:879
co_unsigned16_t ec
The emergency error code.
Definition: gw.h:883
co_unsigned8_t er
The error register.
Definition: gw.h:885
uint8_t msef[5]
The manufacturer-specific error code.
Definition: gw.h:887
co_unsigned8_t node
The node-ID.
Definition: gw.h:881
The parameters of a CANopen gateway 'RPDO received' indication.
Definition: gw.h:835
size_t size
The size of this struct (in bytes).
Definition: gw.h:837
co_unsigned16_t net
The network-ID.
Definition: gw.h:841
co_unsigned8_t n
Number of mapped objects in PDO.
Definition: gw.h:845
co_unsigned64_t val[0x40]
An array of object values.
Definition: gw.h:847
co_unsigned16_t num
The PDO number.
Definition: gw.h:843
int srv
The service number (CO_GW_SRV_RPDO).
Definition: gw.h:839
The parameters of a CANopen gateway 'CiA 301 progress indication download' indication.
Definition: gw.h:894
co_unsigned16_t net
The network-ID.
Definition: gw.h:900
int srv
The service number (CO_GW_SRV_SDO).
Definition: gw.h:898
co_unsigned8_t node
The node-ID.
Definition: gw.h:902
uint32_t nbyte
The transferred bytes.
Definition: gw.h:904
unsigned int up
The transfer direction: download (0) or upload (1).
Definition: gw.h:906
The parameters of a Lely-specific gateway 'LSS Slowscan/Fastscan' request.
Definition: gw.h:664
size_t size
The size of this struct (in bytes).
Definition: gw.h:666
struct co_id id_2
In case of an LSS Slowscan request, the upper bound of the LSS address; in case of an LSS Fastscan re...
Definition: gw.h:687
struct co_id id_1
In case of an LSS Slowscan request, the lower bound of the LSS address; in case of an LSS Fastscan re...
Definition: gw.h:681
void * data
A pointer to user-specified data.
Definition: gw.h:673
int srv
The service number (CO_GW_SRV__LSS_SLOWSCAN or CO_GW_SRV__LSS_FASTSCAN).
Definition: gw.h:671
co_unsigned16_t net
The network-ID.
Definition: gw.h:675
The parameters of a CANopen gateway 'Initialize gateway' request.
Definition: gw.h:491
int srv
The service number (CO_GW_SRV_INIT).
Definition: gw.h:495
co_unsigned16_t net
The network-ID.
Definition: gw.h:499
size_t size
The size of this struct (in bytes).
Definition: gw.h:493
void * data
A pointer to user-specified data.
Definition: gw.h:497
co_unsigned8_t bitidx
The bit timing index (in the range [0..9]).
Definition: gw.h:501
The parameters of a CANopen gateway 'Inquire LSS address' request.
Definition: gw.h:634
co_unsigned8_t cs
The command specifier (one of 0x5a, 0x5b, 0x5c or 0x5d).
Definition: gw.h:644
int srv
The service number (CO_GW_SRV_LSS_GET_LSSID).
Definition: gw.h:638
size_t size
The size of this struct (in bytes).
Definition: gw.h:636
co_unsigned16_t net
The network-ID.
Definition: gw.h:642
void * data
A pointer to user-specified data.
Definition: gw.h:640
The parameters of a CANopen gateway 'LSS identify remote slave' request.
Definition: gw.h:648
void * data
A pointer to user-specified data.
Definition: gw.h:654
size_t size
The size of this struct (in bytes).
Definition: gw.h:650
int srv
The service number (CO_GW_SRV_LSS_ID_SLAVE).
Definition: gw.h:652
struct co_id lo
The lower bound of the LSS address.
Definition: gw.h:658
co_unsigned16_t net
The network-ID.
Definition: gw.h:656
struct co_id hi
The upper bound of the LSS address.
Definition: gw.h:660
The parameters of a CANopen gateway 'LSS configure bit-rate' request.
Definition: gw.h:604
co_unsigned8_t bitsel
The bit timing selector.
Definition: gw.h:614
void * data
A pointer to user-specified data.
Definition: gw.h:610
size_t size
The size of this struct (in bytes).
Definition: gw.h:606
int srv
The service number (CO_GW_SRV_LSS_SET_RATE).
Definition: gw.h:608
co_unsigned16_t net
The network-ID.
Definition: gw.h:612
co_unsigned8_t bitidx
The bit timing index.
Definition: gw.h:616
The parameters of a CANopen gateway 'LSS activate new bit-rate' request.
Definition: gw.h:620
int srv
The service number (CO_GW_SRV_LSS_SWITCH_RATE).
Definition: gw.h:624
co_unsigned16_t delay
The delay (in milliseconds).
Definition: gw.h:630
void * data
A pointer to user-specified data.
Definition: gw.h:626
size_t size
The size of this struct (in bytes).
Definition: gw.h:622
co_unsigned16_t net
The network-ID.
Definition: gw.h:628
The parameters of a CANopen gateway 'LSS switch state selective' request.
Definition: gw.h:590
void * data
A pointer to user-specified data.
Definition: gw.h:596
size_t size
The size of this struct (in bytes).
Definition: gw.h:592
co_unsigned16_t net
The network-ID.
Definition: gw.h:598
int srv
The service number (CO_GW_SRV_LSS_SWITCH_SEL).
Definition: gw.h:594
The parameters of a CANopen gateway 'LSS switch state global' request.
Definition: gw.h:576
size_t size
The size of this struct (in bytes).
Definition: gw.h:578
int srv
The service number (CO_GW_SRV_LSS_SWITCH).
Definition: gw.h:580
co_unsigned8_t mode
0 for waiting state, 1 for configuration state.
Definition: gw.h:586
co_unsigned16_t net
The network-ID.
Definition: gw.h:584
void * data
A pointer to user-specified data.
Definition: gw.h:582
The common parameters of a CANopen gateway network-level request.
Definition: gw.h:281
int srv
The service number.
Definition: gw.h:285
size_t size
The size of this struct (in bytes).
Definition: gw.h:283
co_unsigned16_t net
The network-ID.
Definition: gw.h:289
void * data
A pointer to user-specified data.
Definition: gw.h:287
The parameters of a CANopen gateway 'Start heartbeat consumer' request.
Definition: gw.h:475
int srv
The service number (CO_GW_SRV_NMT_HB_ENABLE).
Definition: gw.h:479
co_unsigned16_t net
The network-ID.
Definition: gw.h:483
size_t size
The size of this struct (in bytes).
Definition: gw.h:477
void * data
A pointer to user-specified data.
Definition: gw.h:481
co_unsigned8_t node
The node-ID.
Definition: gw.h:485
co_unsigned16_t ms
The heartbeat time (in milliseconds).
Definition: gw.h:487
The parameters of a CANopen gateway 'Enable node guarding' request.
Definition: gw.h:457
co_unsigned8_t node
The node-ID.
Definition: gw.h:467
co_unsigned16_t net
The network-ID.
Definition: gw.h:465
co_unsigned8_t ltf
The lifetime factor.
Definition: gw.h:471
size_t size
The size of this struct (in bytes).
Definition: gw.h:459
void * data
A pointer to user-specified data.
Definition: gw.h:463
co_unsigned16_t gt
The guard time (in milliseconds).
Definition: gw.h:469
int srv
The service number (CO_GW_SRV_NMT_NG_ENABLE).
Definition: gw.h:461
The common parameters of a CANopen gateway node-level request.
Definition: gw.h:293
void * data
A pointer to user-specified data.
Definition: gw.h:299
co_unsigned16_t net
The network-ID.
Definition: gw.h:301
co_unsigned8_t node
The node-ID.
Definition: gw.h:303
size_t size
The size of this struct (in bytes).
Definition: gw.h:295
int srv
The service number.
Definition: gw.h:297
The parameters of a CANopen gateway 'Read PDO' request.
Definition: gw.h:422
co_unsigned16_t num
The PDO number.
Definition: gw.h:432
co_unsigned16_t net
The network-ID.
Definition: gw.h:430
void * data
A pointer to user-specified data.
Definition: gw.h:428
int srv
The service number (CO_GW_SRV_PDO_READ).
Definition: gw.h:426
size_t size
The size of this struct (in bytes).
Definition: gw.h:424
The parameters of a CANopen gateway 'Write PDO' request.
Definition: gw.h:436
co_unsigned8_t n
Number of mapped objects in PDO.
Definition: gw.h:448
void * data
A pointer to user-specified data.
Definition: gw.h:442
co_unsigned16_t num
The PDO number.
Definition: gw.h:446
co_unsigned16_t net
The network-ID.
Definition: gw.h:444
size_t size
The size of this struct (in bytes).
Definition: gw.h:438
int srv
The service number (CO_GW_SRV_PDO_WRITE).
Definition: gw.h:440
co_unsigned64_t val[0x40]
An array of object values.
Definition: gw.h:450
The parameters of a CANopen gateway 'SDO download' request.
Definition: gw.h:327
char val[1]
The (first byte in the) value.
Definition: gw.h:345
co_unsigned16_t net
The network-ID.
Definition: gw.h:335
co_unsigned16_t idx
The object index.
Definition: gw.h:339
void * data
A pointer to user-specified data.
Definition: gw.h:333
size_t size
The size of this struct (in bytes).
Definition: gw.h:329
co_unsigned8_t subidx
The object sub-index.
Definition: gw.h:341
co_unsigned8_t node
The node-ID.
Definition: gw.h:337
int srv
The service number (CO_GW_SRV_SDO_DN).
Definition: gw.h:331
The parameters of a CANopen gateway 'SDO upload' request.
Definition: gw.h:307
size_t size
The size of this struct (in bytes).
Definition: gw.h:309
co_unsigned8_t node
The node-ID.
Definition: gw.h:317
void * data
A pointer to user-specified data.
Definition: gw.h:313
co_unsigned8_t subidx
The object sub-index.
Definition: gw.h:321
co_unsigned16_t idx
The object index.
Definition: gw.h:319
int srv
The service number (CO_GW_SRV_SDO_UP).
Definition: gw.h:311
co_unsigned16_t type
The data type.
Definition: gw.h:323
co_unsigned16_t net
The network-ID.
Definition: gw.h:315
The parameters of a CANopen gateway 'Boot-up forwarding' request.
Definition: gw.h:547
co_unsigned16_t net
The network-ID.
Definition: gw.h:555
int srv
The service number (CO_GW_SRV_SET_BOOTUP_IND).
Definition: gw.h:551
unsigned cs
A flag indicating whether "boot-up event received" commands should be forwarded (1) or not (0).
Definition: gw.h:560
void * data
A pointer to user-specified data.
Definition: gw.h:553
size_t size
The size of this struct (in bytes).
Definition: gw.h:549
The parameters of a CANopen gateway 'Set command size' request.
Definition: gw.h:564
int srv
The service number (CO_GW_SRV_SET_CMD_TIMEOUT).
Definition: gw.h:568
co_unsigned32_t n
The command size (in bytes).
Definition: gw.h:572
size_t size
The size of this struct (in bytes).
Definition: gw.h:566
void * data
A pointer to user-specified data.
Definition: gw.h:570
The parameters of a CANopen gateway 'Set command time-out' request.
Definition: gw.h:535
int srv
The service number (CO_GW_SRV_SET_CMD_TIMEOUT).
Definition: gw.h:539
void * data
A pointer to user-specified data.
Definition: gw.h:541
int timeout
The command timeout (in milliseconds).
Definition: gw.h:543
size_t size
The size of this struct (in bytes).
Definition: gw.h:537
The parameters of a CANopen gateway 'Set heartbeat producer' request.
Definition: gw.h:505
co_unsigned16_t ms
The heartbeat time (in milliseconds).
Definition: gw.h:515
size_t size
The size of this struct (in bytes).
Definition: gw.h:507
co_unsigned16_t net
The network-ID.
Definition: gw.h:513
void * data
A pointer to user-specified data.
Definition: gw.h:511
int srv
The service number (CO_GW_SRV_SET_HB).
Definition: gw.h:509
The parameters of a CANopen gateway 'Configure RPDO' request.
Definition: gw.h:366
size_t size
The size of this struct (in bytes).
Definition: gw.h:368
int srv
The service number (CO_GW_SRV_SET_RPDO).
Definition: gw.h:370
co_unsigned32_t cobid
The COB-ID.
Definition: gw.h:378
co_unsigned32_t map[0x40]
An array of objects to be mapped.
Definition: gw.h:384
co_unsigned16_t num
The PDO number.
Definition: gw.h:376
co_unsigned16_t net
The network-ID.
Definition: gw.h:374
void * data
A pointer to user-specified data.
Definition: gw.h:372
The parameters of a CANopen gateway 'Configure SDO time-out' request.
Definition: gw.h:352
int timeout
The SDO timeout (in milliseconds).
Definition: gw.h:362
void * data
A pointer to user-specified data.
Definition: gw.h:358
int srv
The service number (CO_GW_SRV_SET_SDO_TIMEOUT).
Definition: gw.h:356
size_t size
The size of this struct (in bytes).
Definition: gw.h:354
co_unsigned16_t net
The network-ID.
Definition: gw.h:360
The parameters of a CANopen gateway 'Configure TPDO' request.
Definition: gw.h:391
co_unsigned32_t map[0x40]
An array of objects to be mapped.
Definition: gw.h:415
int srv
The service number (CO_GW_SRV_SET_TPDO).
Definition: gw.h:395
void * data
A pointer to user-specified data.
Definition: gw.h:397
co_unsigned16_t net
The network-ID.
Definition: gw.h:399
co_unsigned32_t cobid
The COB-ID.
Definition: gw.h:403
co_unsigned16_t num
The PDO number.
Definition: gw.h:401
size_t size
The size of this struct (in bytes).
Definition: gw.h:393
The common parameters of a CANopen gateway request.
Definition: gw.h:271
The common parameters of a CANopen gateway service.
Definition: gw.h:263
size_t size
The size of this struct (in bytes).
Definition: gw.h:265
int srv
The service number.
Definition: gw.h:267
An identity record.
Definition: dev.h:33
co_unsigned32_t product_code
Product code.
Definition: dev.h:39
co_unsigned32_t revision
Revision number.
Definition: dev.h:41
co_unsigned32_t vendor_id
Vendor-ID.
Definition: dev.h:37
co_unsigned32_t serial_nr
Serial number.
Definition: dev.h:43
A PDO communication parameter record.
Definition: pdo.h:43
co_unsigned8_t sync
SYNC start value.
Definition: pdo.h:56
co_unsigned16_t inhibit
Inhibit time.
Definition: pdo.h:51
co_unsigned16_t event
Event timer.
Definition: pdo.h:54
co_unsigned32_t cobid
COB-ID.
Definition: pdo.h:47
co_unsigned8_t trans
Transmission type.
Definition: pdo.h:49
A PDO mapping parameter record.
Definition: pdo.h:69
co_unsigned8_t n
Number of mapped objects in PDO.
Definition: pdo.h:71
co_unsigned32_t map[0x40]
An array of objects to be mapped.
Definition: pdo.h:73
A location in a text file.
Definition: diag.h:31
int column
The column number (starting from 1).
Definition: diag.h:37
A node in a pairing heap.
Definition: pheap.h:51
#define CO_DEFTYPE_UNICODE_STRING
The data type (and object index) of an array of (16-bit) Unicode characters.
Definition: type.h:62
#define CO_DEFTYPE_UNSIGNED16
The data type (and object index) of a 16-bit unsigned integer.
Definition: type.h:47
#define CO_DEFTYPE_INTEGER24
The data type (and object index) of a 24-bit signed integer.
Definition: type.h:80
#define CO_DEFTYPE_UNSIGNED48
The data type (and object index) of a 48-bit unsigned integer.
Definition: type.h:104
#define CO_DEFTYPE_INTEGER48
The data type (and object index) of a 48-bit signed integer.
Definition: type.h:89
#define CO_DEFTYPE_VISIBLE_STRING
The data type (and object index) of an array of visible characters.
Definition: type.h:56
#define CO_DEFTYPE_UNSIGNED40
The data type (and object index) of a 40-bit unsigned integer.
Definition: type.h:101
#define CO_DEFTYPE_INTEGER56
The data type (and object index) of a 56-bit signed integer.
Definition: type.h:92
#define CO_DEFTYPE_UNSIGNED64
The data type (and object index) of a 64-bit unsigned integer.
Definition: type.h:110
#define CO_DEFTYPE_INTEGER8
The data type (and object index) of an 8-bit signed integer.
Definition: type.h:35
#define CO_DEFTYPE_DOMAIN
The data type (and object index) of an arbitrary large block of data.
Definition: type.h:77
#define CO_DEFTYPE_UNSIGNED24
The data type (and object index) of a 24-bit unsigned integer.
Definition: type.h:98
#define CO_DEFTYPE_UNSIGNED8
The data type (and object index) of an 8-bit unsigned integer.
Definition: type.h:44
#define CO_DEFTYPE_REAL64
The data type (and object index) of a 64-bit IEEE-754 floating-point number.
Definition: type.h:83
#define CO_DEFTYPE_BOOLEAN
The data type (and object index) of a boolean truth value.
Definition: type.h:32
#define CO_DEFTYPE_INTEGER40
The data type (and object index) of a 40-bit signed integer.
Definition: type.h:86
#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
size_t co_type_sizeof(co_unsigned16_t type)
Returns the native size (in bytes) of a value of the specified data type, or 0 if it is not a static ...
Definition: type.c:52
#define CO_DEFTYPE_INTEGER32
The data type (and object index) of a 32-bit signed integer.
Definition: type.h:41
#define CO_DEFTYPE_INTEGER64
The data type (and object index) of a 64-bit signed integer.
Definition: type.h:95
#define CO_DEFTYPE_UNSIGNED56
The data type (and object index) of a 56-bit unsigned integer.
Definition: type.h:107
#define CO_DEFTYPE_UNSIGNED32
The data type (and object index) of a 32-bit unsigned integer.
Definition: type.h:50
#define CO_DEFTYPE_INTEGER16
The data type (and object index) of a 16-bit signed integer.
Definition: type.h:38
#define CO_DEFTYPE_OCTET_STRING
The data type (and object index) of an array of octets.
Definition: type.h:59
int co_type_is_basic(co_unsigned16_t type)
Returns 1 if the specified (static) data type is a basic type, and 0 if not.
Definition: type.c:28
#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_DEFTYPE_TIME_DIFF
The data type (and object index) of a 48-bit structure representing a time difference.
Definition: type.h:74
A union of the CANopen static data types.
Definition: val.h:163
This header file is part of the CANopen library; it contains the CANopen value declarations.
size_t co_val_write(co_unsigned16_t type, const void *val, uint8_t *begin, uint8_t *end)
Writes a value of the specified data type to a memory buffer.
Definition: val.c:718
int co_val_init(co_unsigned16_t type, void *val)
Initializes a value of the specified data type to zero.
Definition: val.c:120
size_t co_val_read(co_unsigned16_t type, void *val, const uint8_t *begin, const uint8_t *end)
Reads a value of the specified data type from a memory buffer.
Definition: val.c:470
int co_val_init_vs_n(char **val, const char *vs, size_t n)
Initializes an array of visible characters (CO_DEFTYPE_VISIBLE_STRING).
Definition: val.c:184
size_t co_val_print(co_unsigned16_t type, const void *val, char **pbegin, char *end)
Prints a value of the specified data type to a memory buffer.
Definition: val.c:1314
void co_val_fini(co_unsigned16_t type, void *val)
Finalizes a value of the specified data type.
Definition: val.c:273
size_t co_val_lex(co_unsigned16_t type, void *val, const char *begin, const char *end, struct floc *at)
Lexes a value of the specified data type from a memory buffer.
Definition: val.c:869