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