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