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