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