Lely core libraries 1.9.2
lss.c
Go to the documentation of this file.
1
24#include "co.h"
25
26#ifndef LELY_NO_CO_LSS
27
28#include <lely/co/lss.h>
29#include <lely/co/nmt.h>
30#include <lely/co/obj.h>
31#include <lely/co/val.h>
32#include <lely/util/endian.h>
33#include <lely/util/errnum.h>
34
35#include <assert.h>
36#include <stdlib.h>
37
38struct __co_lss_state;
40typedef const struct __co_lss_state co_lss_state_t;
41
43struct __co_lss {
52#ifndef LELY_NO_CO_MASTER
54 int master;
55#endif
58#ifndef LELY_NO_CO_MASTER
63#endif
65 co_unsigned8_t cs;
67 co_unsigned8_t lsspos;
68#ifndef LELY_NO_CO_MASTER
70 struct co_id lo;
72 struct co_id hi;
74 struct co_id mask;
76 co_unsigned8_t bitchk;
81 co_unsigned8_t lsssub;
83 co_unsigned8_t err;
85 co_unsigned8_t spec;
87 co_unsigned32_t lssid;
89 co_unsigned8_t nid;
91 struct co_id id;
92#endif
96 void *rate_data;
101#ifndef LELY_NO_CO_MASTER
105 void *cs_data;
109 void *err_data;
117 void *nid_data;
122#endif
123};
124
126static int co_lss_recv(const struct can_msg *msg, void *data);
127
128#ifndef LELY_NO_CO_MASTER
130static int co_lss_timer(const struct timespec *tp, void *data);
131#endif
132
137static void co_lss_enter(co_lss_t *lss, co_lss_state_t *next);
138
146static inline void co_lss_emit_recv(co_lss_t *lss, const struct can_msg *msg);
147
148#ifndef LELY_NO_CO_MASTER
156static inline void co_lss_emit_time(co_lss_t *lss, const struct timespec *tp);
157#endif
158
162 co_lss_state_t *(*on_enter)(co_lss_t *lss);
172 co_lss_state_t *(*on_recv)(co_lss_t *lss, const struct can_msg *msg);
173#ifndef LELY_NO_CO_MASTER
182 co_lss_state_t *(*on_time)(co_lss_t *lss, const struct timespec *tp);
183#endif
185 void (*on_leave)(co_lss_t *lss);
186};
187
188#define LELY_CO_DEFINE_STATE(name, ...) \
189 static co_lss_state_t *const name = &(co_lss_state_t){ __VA_ARGS__ };
190
193
195// clang-format off
196LELY_CO_DEFINE_STATE(co_lss_wait_state,
197 .on_enter = &co_lss_wait_on_enter
199// clang-format on
200
201
203
209 co_lss_t *lss, const struct can_msg *msg);
210
212// clang-format off
213LELY_CO_DEFINE_STATE(co_lss_wait_slave_state,
214 .on_enter = &co_lss_wait_slave_on_enter,
215 .on_recv = &co_lss_wait_slave_on_recv
217// clang-format on
218
224 co_lss_t *lss, const struct can_msg *msg);
225
227// clang-format off
228LELY_CO_DEFINE_STATE(co_lss_cfg_state,
229 .on_recv = &co_lss_cfg_on_recv
231// clang-format on
232
233#ifndef LELY_NO_CO_MASTER
234
237 co_lss_t *lss, const struct can_msg *msg);
238
241 co_lss_t *lss, const struct timespec *tp);
242
244static void co_lss_cs_on_leave(co_lss_t *lss);
245
247// clang-format off
248LELY_CO_DEFINE_STATE(co_lss_cs_state,
249 .on_recv = &co_lss_cs_on_recv,
250 .on_time = &co_lss_cs_on_time,
251 .on_leave = &co_lss_cs_on_leave
253// clang-format on
254
255
257 co_lss_t *lss, const struct can_msg *msg);
258
261 co_lss_t *lss, const struct timespec *tp);
262
264static void co_lss_err_on_leave(co_lss_t *lss);
265
267// clang-format off
268LELY_CO_DEFINE_STATE(co_lss_err_state,
269 .on_recv = &co_lss_err_on_recv,
270 .on_time = &co_lss_err_on_time,
271 .on_leave = &co_lss_err_on_leave
273// clang-format on
274
277 co_lss_t *lss, const struct can_msg *msg);
278
281 co_lss_t *lss, const struct timespec *tp);
282
284static void co_lss_lssid_on_leave(co_lss_t *lss);
285
287// clang-format off
288LELY_CO_DEFINE_STATE(co_lss_lssid_state,
289 .on_recv = &co_lss_lssid_on_recv,
290 .on_time = &co_lss_lssid_on_time,
291 .on_leave = &co_lss_lssid_on_leave
293// clang-format on
294
297 co_lss_t *lss, const struct can_msg *msg);
298
301 co_lss_t *lss, const struct timespec *tp);
302
304static void co_lss_nid_on_leave(co_lss_t *lss);
305
307// clang-format off
308LELY_CO_DEFINE_STATE(co_lss_nid_state,
309 .on_recv = &co_lss_nid_on_recv,
310 .on_time = &co_lss_nid_on_time,
311 .on_leave = &co_lss_nid_on_leave
313// clang-format on
314
320 co_lss_t *lss, const struct can_msg *msg);
321
324 co_lss_t *lss, const struct timespec *tp);
325
327// clang-format off
328LELY_CO_DEFINE_STATE(co_lss_slowscan_init_state,
332// clang-format on
333
336
339 co_lss_t *lss, const struct can_msg *msg);
340
343 co_lss_t *lss, const struct timespec *tp);
344
345static co_lss_state_t *co_lss_slowscan_scan_on_res(co_lss_t *lss, int timeout);
346
348// clang-format off
349LELY_CO_DEFINE_STATE(co_lss_slowscan_scan_state,
354// clang-format on
355
358 co_lss_t *lss, const struct can_msg *msg);
359
362 co_lss_t *lss, const struct timespec *tp);
363
365// clang-format off
366LELY_CO_DEFINE_STATE(co_lss_slowscan_wait_state,
370// clang-format on
371
374
380 co_lss_t *lss, const struct can_msg *msg);
381
387 co_lss_t *lss, const struct timespec *tp);
388
390// clang-format off
391LELY_CO_DEFINE_STATE(co_lss_slowscan_switch_state,
396// clang-format on
397
400
403
405// clang-format off
406LELY_CO_DEFINE_STATE(co_lss_slowscan_fini_state,
410// clang-format on
411
417 co_lss_t *lss, const struct can_msg *msg);
418
421 co_lss_t *lss, const struct timespec *tp);
422
424// clang-format off
425LELY_CO_DEFINE_STATE(co_lss_fastscan_init_state,
429// clang-format on
430
433
436 co_lss_t *lss, const struct can_msg *msg);
437
440 co_lss_t *lss, const struct timespec *tp);
441
442static co_lss_state_t *co_lss_fastscan_scan_on_res(co_lss_t *lss, int timeout);
443
445// clang-format off
446LELY_CO_DEFINE_STATE(co_lss_fastscan_scan_state,
451// clang-format on
452
455 co_lss_t *lss, const struct can_msg *msg);
456
459 co_lss_t *lss, const struct timespec *tp);
460
462// clang-format off
463LELY_CO_DEFINE_STATE(co_lss_fastscan_wait_state,
467// clang-format on
468
471
474
476// clang-format off
477LELY_CO_DEFINE_STATE(co_lss_fastscan_fini_state,
481// clang-format on
482
483#endif // !LELY_NO_CO_MASTER
484
485#undef LELY_CO_DEFINE_STATE
486
498 co_lss_t *lss, co_unsigned8_t cs, co_unsigned32_t id);
499
508static void co_lss_id_slave(
509 co_lss_t *lss, co_unsigned8_t cs, co_unsigned32_t id);
510
515static void co_lss_id_non_cfg_slave(const co_lss_t *lss);
516
531static co_lss_state_t *co_lss_fastscan(co_lss_t *lss, co_unsigned32_t id,
532 co_unsigned8_t bitchk, co_unsigned8_t lsssub,
533 co_unsigned8_t lssnext);
534
542static void co_lss_init_req(
543 const co_lss_t *lss, struct can_msg *msg, co_unsigned8_t cs);
544
545#ifndef LELY_NO_CO_MASTER
546
557 const co_lss_t *lss, const struct co_id *id);
558
570static int co_lss_send_id_slave_req(const co_lss_t *lss, const struct co_id *lo,
571 const struct co_id *hi);
572
584static int co_lss_send_fastscan_req(const co_lss_t *lss, co_unsigned32_t id,
585 co_unsigned8_t bitchk, co_unsigned8_t lsssub,
586 co_unsigned8_t lssnext);
587
594static void co_lss_init_ind(co_lss_t *lss, co_unsigned8_t cs);
595
596#endif
597
598void *
599__co_lss_alloc(void)
600{
601 void *ptr = malloc(sizeof(struct __co_lss));
602 if (__unlikely(!ptr))
603 set_errc(errno2c(errno));
604 return ptr;
605}
606
607void
608__co_lss_free(void *ptr)
609{
610 free(ptr);
611}
612
613struct __co_lss *
614__co_lss_init(struct __co_lss *lss, co_nmt_t *nmt)
615{
616 assert(lss);
617 assert(nmt);
618
619 int errc = 0;
620
621 lss->nmt = nmt;
622 lss->net = co_nmt_get_net(lss->nmt);
623 lss->dev = co_nmt_get_dev(lss->nmt);
624
625 lss->state = NULL;
626
627#ifndef LELY_NO_CO_MASTER
628 lss->master = 0;
629#endif
630
631 lss->recv = can_recv_create();
632 if (__unlikely(!lss->recv)) {
633 errc = get_errc();
634 goto error_create_recv;
635 }
637
638#ifndef LELY_NO_CO_MASTER
640
641 lss->timer = can_timer_create();
642 if (__unlikely(!lss->timer)) {
643 errc = get_errc();
644 goto error_create_timer;
645 }
647#endif
648
649 lss->cs = 0;
650 lss->lsspos = 0;
651#ifndef LELY_NO_CO_MASTER
652 lss->lo = (struct co_id)CO_ID_INIT;
653 lss->hi = (struct co_id)CO_ID_INIT;
654 lss->mask = (struct co_id)CO_ID_INIT;
655 lss->bitchk = 0;
656 lss->lsssub = 0;
657 lss->err = 0;
658 lss->spec = 0;
659 lss->lssid = 0;
660 lss->nid = 0;
661 lss->id = (struct co_id)CO_ID_INIT;
662#endif
663
664 lss->rate_ind = NULL;
665 lss->rate_data = NULL;
666 lss->store_ind = NULL;
667 lss->store_data = NULL;
668#ifndef LELY_NO_CO_MASTER
669 lss->cs_ind = NULL;
670 lss->cs_data = NULL;
671 lss->err_ind = NULL;
672 lss->err_data = NULL;
673 lss->lssid_ind = NULL;
674 lss->lssid_data = NULL;
675 lss->nid_ind = NULL;
676 lss->nid_data = NULL;
677 lss->scan_ind = NULL;
678 lss->scan_data = NULL;
679#endif
680
682 return lss;
683
684#ifndef LELY_NO_CO_MASTER
686error_create_timer:
687#endif
689error_create_recv:
690 set_errc(errc);
691 return NULL;
692}
693
694void
695__co_lss_fini(struct __co_lss *lss)
696{
697 assert(lss);
698
699#ifndef LELY_NO_CO_MASTER
701#endif
703}
704
705co_lss_t *
707{
708 trace("creating LSS");
709
710 int errc = 0;
711
712 co_lss_t *lss = __co_lss_alloc();
713 if (__unlikely(!lss)) {
714 errc = get_errc();
715 goto error_alloc_lss;
716 }
717
718 if (__unlikely(!__co_lss_init(lss, nmt))) {
719 errc = get_errc();
720 goto error_init_lss;
721 }
722
723 return lss;
724
725error_init_lss:
726 __co_lss_free(lss);
727error_alloc_lss:
728 set_errc(errc);
729 return NULL;
730}
731
732void
734{
735 if (lss) {
736 trace("destroying LSS");
737 __co_lss_fini(lss);
738 __co_lss_free(lss);
739 }
740}
741
742co_nmt_t *
744{
745 assert(lss);
746
747 return lss->nmt;
748}
749
750void
751co_lss_get_rate_ind(const co_lss_t *lss, co_lss_rate_ind_t **pind, void **pdata)
752{
753 assert(lss);
754
755 if (pind)
756 *pind = lss->rate_ind;
757 if (pdata)
758 *pdata = lss->rate_data;
759}
760
761void
763{
764 assert(lss);
765
766 lss->rate_ind = ind;
767 lss->rate_data = data;
768}
769
770void
772 const co_lss_t *lss, co_lss_store_ind_t **pind, void **pdata)
773{
774 assert(lss);
775
776 if (pind)
777 *pind = lss->store_ind;
778 if (pdata)
779 *pdata = lss->store_data;
780}
781
782void
784{
785 assert(lss);
786
787 lss->store_ind = ind;
788 lss->store_data = data;
789}
790
791#ifndef LELY_NO_CO_MASTER
792
793int
795{
796 assert(lss);
797
798 return lss->timeout;
799}
800
801void
802co_lss_set_timeout(co_lss_t *lss, int timeout)
803{
804 assert(lss);
805
806 if (lss->timeout && timeout <= 0)
807 can_timer_stop(lss->timer);
808
809 lss->timeout = MAX(0, timeout);
810}
811
812#endif
813
814int
816{
817#ifdef LELY_NO_CO_MASTER
818 (void)lss;
819
820 return 0;
821#else
822 assert(lss);
823
824 return lss->master;
825#endif
826}
827
828#ifndef LELY_NO_CO_MASTER
829
830int
832{
833 assert(lss);
834
835 return lss->state == co_lss_wait_state;
836}
837
838void
840{
841 assert(lss);
842
844}
845
846int
847co_lss_switch_req(co_lss_t *lss, co_unsigned8_t mode)
848{
849 if (__unlikely(!co_lss_is_master(lss) || !co_lss_is_idle(lss))) {
851 return -1;
852 }
853
854 if (__unlikely(mode > 0x01)) {
856 return -1;
857 }
858
859 trace("LSS: switch state global");
860
861 // Switch state global (see Fig. 31 in CiA 305 version 3.0.0).
862 struct can_msg req;
863 co_lss_init_req(lss, &req, 0x04);
864 req.data[1] = mode;
865 return can_net_send(lss->net, &req);
866}
867
868int
869co_lss_switch_sel_req(co_lss_t *lss, const struct co_id *id,
870 co_lss_cs_ind_t *ind, void *data)
871{
872 if (__unlikely(!co_lss_is_master(lss) || !co_lss_is_idle(lss))) {
874 return -1;
875 }
876
877 trace("LSS: switch state selective");
878
879 // Switch state selective (see Fig. 32 in CiA 305 version 3.0.0).
880 if (__unlikely(co_lss_send_switch_sel_req(lss, id) == -1))
881 return -1;
882
883 // Wait for response.
884 co_lss_init_ind(lss, 0x44);
885 lss->cs_ind = ind;
886 lss->cs_data = data;
888
889 return 0;
890}
891
892int
893co_lss_set_id_req(co_lss_t *lss, co_unsigned8_t id, co_lss_err_ind_t *ind,
894 void *data)
895{
896 if (__unlikely(!co_lss_is_master(lss) || !co_lss_is_idle(lss))) {
898 return -1;
899 }
900
901 if (__unlikely(!id || (id > CO_NUM_NODES && id != 0xff))) {
903 return -1;
904 }
905
906 trace("LSS: configure node-ID");
907
908 // Configure node-ID (see Fig. 33 in CiA 305 version 3.0.0).
909 struct can_msg req;
910 co_lss_init_req(lss, &req, 0x11);
911 req.data[1] = id;
912 if (__unlikely(can_net_send(lss->net, &req) == -1))
913 return -1;
914
915 // Wait for response.
916 co_lss_init_ind(lss, req.data[0]);
917 lss->err_ind = ind;
918 lss->err_data = data;
920
921 return 0;
922}
923
924int
925co_lss_set_rate_req(co_lss_t *lss, co_unsigned16_t rate, co_lss_err_ind_t *ind,
926 void *data)
927{
928 if (__unlikely(!co_lss_is_master(lss) || !co_lss_is_idle(lss))) {
930 return -1;
931 }
932
933 // Configure bit timing parameters (see Fig. 34 in CiA 305 version
934 // 3.0.0).
935 struct can_msg req;
936 co_lss_init_req(lss, &req, 0x13);
937 req.data[1] = 0;
938 switch (rate) {
939 case 1000: req.data[2] = 0; break;
940 case 800: req.data[2] = 1; break;
941 case 500: req.data[2] = 2; break;
942 case 250: req.data[2] = 3; break;
943 case 125: req.data[2] = 4; break;
944 case 50: req.data[2] = 6; break;
945 case 20: req.data[2] = 7; break;
946 case 10: req.data[2] = 8; break;
947 case 0: req.data[2] = 9; break;
948 default: set_errnum(ERRNUM_INVAL); return 0;
949 }
950
951 trace("LSS: configure bit timing parameters");
952
953 if (__unlikely(can_net_send(lss->net, &req) == -1))
954 return -1;
955
956 // Wait for response.
957 co_lss_init_ind(lss, req.data[0]);
958 lss->err_ind = ind;
959 lss->err_data = data;
961
962 return 0;
963}
964
965int
967{
968 if (__unlikely(!co_lss_is_master(lss) || !co_lss_is_idle(lss))) {
970 return -1;
971 }
972
973 // clang-format off
974 if (__unlikely(delay < CO_UNSIGNED16_MIN
975 || delay > CO_UNSIGNED16_MAX)) {
976 // clang-format on
978 return -1;
979 }
980
981 trace("LSS: activate bit timing parameters");
982
983 // Activate bit timing parameters (see Fig. 35 in CiA 305 version
984 // 3.0.0).
985 struct can_msg req;
986 co_lss_init_req(lss, &req, 0x15);
987 stle_u16(req.data + 1, (co_unsigned16_t)delay);
988 return can_net_send(lss->net, &req);
989}
990
991int
993{
994 if (__unlikely(!co_lss_is_master(lss) || !co_lss_is_idle(lss))) {
996 return -1;
997 }
998
999 trace("LSS: store configuration");
1000
1001 // Store configuration (see Fig. 36 in CiA 305 version 3.0.0).
1002 struct can_msg req;
1003 co_lss_init_req(lss, &req, 0x17);
1004 if (__unlikely(can_net_send(lss->net, &req) == -1))
1005 return -1;
1006
1007 // Wait for response.
1008 co_lss_init_ind(lss, req.data[0]);
1009 lss->err_ind = ind;
1010 lss->err_data = data;
1012
1013 return 0;
1014}
1015
1016int
1018{
1019 if (__unlikely(!co_lss_is_master(lss) || !co_lss_is_idle(lss))) {
1021 return -1;
1022 }
1023
1024 trace("LSS: inquire identity vendor-ID");
1025
1026 // Inquire identity vendor-ID (see Fig. 37 in CiA 305 version 3.0.0).
1027 struct can_msg req;
1028 co_lss_init_req(lss, &req, 0x5a);
1029 if (__unlikely(can_net_send(lss->net, &req) == -1))
1030 return -1;
1031
1032 // Wait for response.
1033 co_lss_init_ind(lss, req.data[0]);
1034 lss->lssid_ind = ind;
1035 lss->lssid_data = data;
1037
1038 return 0;
1039}
1040
1041int
1043{
1044 if (__unlikely(!co_lss_is_master(lss) || !co_lss_is_idle(lss))) {
1046 return -1;
1047 }
1048
1049 trace("LSS: inquire identity product-code");
1050
1051 // Inquire identity product-code (see Fig. 38 in CiA 305 version 3.0.0).
1052 struct can_msg req;
1053 co_lss_init_req(lss, &req, 0x5b);
1054 if (__unlikely(can_net_send(lss->net, &req) == -1))
1055 return -1;
1056
1057 // Wait for response.
1058 co_lss_init_ind(lss, req.data[0]);
1059 lss->lssid_ind = ind;
1060 lss->lssid_data = data;
1062
1063 return 0;
1064}
1065
1066int
1068{
1069 if (__unlikely(!co_lss_is_master(lss) || !co_lss_is_idle(lss))) {
1071 return -1;
1072 }
1073
1074 trace("LSS: inquire identity revision-number");
1075
1076 // Inquire identity revision-number (see Fig. 39 in CiA 305 version
1077 // 3.0.0).
1078 struct can_msg req;
1079 co_lss_init_req(lss, &req, 0x5c);
1080 if (__unlikely(can_net_send(lss->net, &req) == -1))
1081 return -1;
1082
1083 // Wait for response.
1084 co_lss_init_ind(lss, req.data[0]);
1085 lss->lssid_ind = ind;
1086 lss->lssid_data = data;
1088
1089 return 0;
1090}
1091
1092int
1094{
1095 if (__unlikely(!co_lss_is_master(lss) || !co_lss_is_idle(lss))) {
1097 return -1;
1098 }
1099
1100 trace("LSS: inquire identity serial number");
1101
1102 // Inquire identity serial-number (see Fig. 40 in CiA 305 version
1103 // 3.0.0).
1104 struct can_msg req;
1105 co_lss_init_req(lss, &req, 0x5d);
1106 if (__unlikely(can_net_send(lss->net, &req) == -1))
1107 return -1;
1108
1109 // Wait for response.
1110 co_lss_init_ind(lss, req.data[0]);
1111 lss->lssid_ind = ind;
1112 lss->lssid_data = data;
1114
1115 return 0;
1116}
1117
1118int
1120{
1121 if (__unlikely(!co_lss_is_master(lss) || !co_lss_is_idle(lss))) {
1123 return -1;
1124 }
1125
1126 trace("LSS: inquire node-ID");
1127
1128 // Inquire node-ID (see Fig. 41 in CiA 305 version 3.0.0).
1129 struct can_msg req;
1130 co_lss_init_req(lss, &req, 0x5e);
1131 if (__unlikely(can_net_send(lss->net, &req) == -1))
1132 return -1;
1133
1134 // Wait for response.
1135 co_lss_init_ind(lss, req.data[0]);
1136 lss->nid_ind = ind;
1137 lss->nid_data = data;
1139
1140 return 0;
1141}
1142
1143int
1144co_lss_id_slave_req(co_lss_t *lss, const struct co_id *lo,
1145 const struct co_id *hi, co_lss_cs_ind_t *ind, void *data)
1146{
1147 if (__unlikely(!co_lss_is_master(lss) || !co_lss_is_idle(lss))) {
1149 return -1;
1150 }
1151
1152 trace("LSS: identify remote slave");
1153
1154 // LSS identify remote slave (see Fig. 42 in CiA 305 version 3.0.0).
1155 if (__unlikely(co_lss_send_id_slave_req(lss, lo, hi) == -1))
1156 return -1;
1157
1158 // Wait for response (see Fig. 43 in CiA 305 version 3.0.0).
1159 co_lss_init_ind(lss, 0x4f);
1160 lss->cs_ind = ind;
1161 lss->cs_data = data;
1163
1164 return 0;
1165}
1166
1167int
1169{
1170 if (__unlikely(!co_lss_is_master(lss) || !co_lss_is_idle(lss))) {
1172 return -1;
1173 }
1174
1175 trace("LSS: identify non-configured remote slave");
1176
1177 // LSS identify non-configured remote slave (see Fig. 44 in CiA 305
1178 // version 3.0.0).
1179 struct can_msg req;
1180 co_lss_init_req(lss, &req, 0x4c);
1181 if (__unlikely(can_net_send(lss->net, &req) == -1))
1182 return -1;
1183
1184 // Wait for response (see Fig. 45 in CiA 305 version 3.0.0).
1185 co_lss_init_ind(lss, 0x50);
1186 lss->cs_ind = ind;
1187 lss->cs_data = data;
1189
1190 return 0;
1191}
1192
1193int
1194co_lss_slowscan_req(co_lss_t *lss, const struct co_id *lo,
1195 const struct co_id *hi, co_lss_scan_ind_t *ind, void *data)
1196{
1197 assert(lo);
1198 assert(hi);
1199
1200 if (__unlikely(!co_lss_is_master(lss) || !co_lss_is_idle(lss))) {
1202 return -1;
1203 }
1204
1205 trace("LSS: Slowscan");
1206
1207 lss->lo = *lo;
1208 lss->lo.n = 4;
1209 lss->hi = *hi;
1210 lss->hi.n = 4;
1211
1212 // LSS identify remote slave (see Fig. 42 in CiA 305 version 3.0.0).
1213 if (__unlikely(co_lss_send_id_slave_req(lss, &lss->lo, &lss->hi) == -1))
1214 return -1;
1215
1216 lss->id = (struct co_id)CO_ID_INIT;
1217
1218 // Wait for response (see Fig. 43 in CiA 305 version 3.0.0).
1219 co_lss_init_ind(lss, 0x4f);
1220 lss->scan_ind = ind;
1221 lss->scan_data = data;
1223
1224 return 0;
1225}
1226
1227int
1228co_lss_fastscan_req(co_lss_t *lss, const struct co_id *id,
1229 const struct co_id *mask, co_lss_scan_ind_t *ind, void *data)
1230{
1231 if (__unlikely(!co_lss_is_master(lss) || !co_lss_is_idle(lss))) {
1233 return -1;
1234 }
1235
1236 trace("LSS: Fastscan");
1237
1238 lss->id = (struct co_id)CO_ID_INIT;
1239 lss->mask = (struct co_id)CO_ID_INIT;
1240 if (mask) {
1241 lss->mask = *mask;
1242 lss->mask.n = 4;
1243 if (id) {
1244 lss->id = *id;
1245 lss->id.n = 4;
1246 // Clear all unmasked bits in the LSS address.
1247 lss->id.vendor_id &= lss->mask.vendor_id;
1248 lss->id.product_code &= lss->mask.product_code;
1249 lss->id.revision &= lss->mask.revision;
1250 lss->id.serial_nr &= lss->mask.serial_nr;
1251 }
1252 }
1253 lss->bitchk = 0x80;
1254 lss->lsssub = 0;
1255
1256 // LSS Fastscan (see Fig. 46 in CiA 305 version 3.0.0).
1257 struct can_msg req;
1258 co_lss_init_req(lss, &req, 0x51);
1259 req.data[5] = lss->bitchk;
1260 if (__unlikely(can_net_send(lss->net, &req) == -1))
1261 return -1;
1262
1263 // Wait for response (see Fig. 43 in CiA 305 version 3.0.0).
1264 co_lss_init_ind(lss, 0x4f);
1265 lss->scan_ind = ind;
1266 lss->scan_data = data;
1268
1269 return 0;
1270}
1271
1272#endif // !LELY_NO_CO_MASTER
1273
1274static int
1275co_lss_recv(const struct can_msg *msg, void *data)
1276{
1277 assert(msg);
1278 co_lss_t *lss = data;
1279 assert(lss);
1280
1281 co_lss_emit_recv(lss, msg);
1282
1283 return 0;
1284}
1285
1286#ifndef LELY_NO_CO_MASTER
1287static int
1288co_lss_timer(const struct timespec *tp, void *data)
1289{
1290 assert(tp);
1291 co_lss_t *lss = data;
1292 assert(lss);
1293
1294 co_lss_emit_time(lss, tp);
1295
1296 return 0;
1297}
1298#endif
1299
1300static void
1302{
1303 assert(lss);
1304
1305 while (next) {
1306 co_lss_state_t *prev = lss->state;
1307 lss->state = next;
1308
1309 if (prev && prev->on_leave)
1310 prev->on_leave(lss);
1311
1312 next = next->on_enter ? next->on_enter(lss) : NULL;
1313 }
1314}
1315
1316static inline void
1317co_lss_emit_recv(co_lss_t *lss, const struct can_msg *msg)
1318{
1319 assert(lss);
1320 assert(lss->state);
1321 assert(lss->state->on_recv);
1322
1323 co_lss_enter(lss, lss->state->on_recv(lss, msg));
1324}
1325
1326#ifndef LELY_NO_CO_MASTER
1327static inline void
1328co_lss_emit_time(co_lss_t *lss, const struct timespec *tp)
1329{
1330 assert(lss);
1331 assert(lss->state);
1332 assert(lss->state->on_time);
1333
1334 co_lss_enter(lss, lss->state->on_time(lss, tp));
1335}
1336#endif
1337
1338static co_lss_state_t *
1340{
1341 assert(lss);
1342
1343#ifndef LELY_NO_CO_MASTER
1344 // Only an NMT master can be an LSS master.
1345 lss->master = co_nmt_is_master(lss->nmt);
1346 if (lss->master)
1347 return NULL;
1348#endif
1349
1351}
1352
1353static co_lss_state_t *
1355{
1356 assert(lss);
1357
1358 lss->cs = 0;
1359 lss->lsspos = 0;
1360
1361 // Start receiving LSS commands from the master.
1362 can_recv_start(lss->recv, lss->net, CO_LSS_CANID(1), 0);
1363
1364 return NULL;
1365}
1366
1367static co_lss_state_t *
1369{
1370 assert(lss);
1371 assert(msg);
1372
1373 if (__unlikely(!msg->len))
1374 return NULL;
1375
1376 uint8_t cs = msg->data[0];
1377 switch (cs) {
1378 // Switch state global (see Fig. 31 in CiA 305 version 3.0.0).
1379 case 0x04:
1380 if (__unlikely(msg->len < 2))
1381 return NULL;
1382 switch (msg->data[1]) {
1383 case 0x00:
1384 // Re-enter the waiting state.
1385 trace("LSS: switching to waiting state");
1386 return co_lss_wait_state;
1387 case 0x01:
1388 // Switch to the configuration state.
1389 trace("LSS: switching to configuration state");
1390 return co_lss_cfg_state;
1391 }
1392 break;
1393 // Switch state selective.
1394 case 0x40:
1395 case 0x41:
1396 case 0x42:
1397 case 0x43:
1398 if (msg->len < 5)
1399 return NULL;
1400 return co_lss_switch_sel(lss, cs, ldle_u32(msg->data + 1));
1401 // LSS identify remote slave.
1402 case 0x46:
1403 case 0x47:
1404 case 0x48:
1405 case 0x49:
1406 case 0x4a:
1407 case 0x4b:
1408 if (msg->len < 5)
1409 return NULL;
1410 co_lss_id_slave(lss, msg->data[0], ldle_u32(msg->data + 1));
1411 break;
1412 // LSS identify non-configured remote slave.
1413 case 0x4c: co_lss_id_non_cfg_slave(lss); break;
1414 // LSS Fastscan.
1415 case 0x51:
1416 if (msg->len < 8)
1417 return NULL;
1418 return co_lss_fastscan(lss, ldle_u32(msg->data + 1),
1419 msg->data[5], msg->data[6], msg->data[7]);
1420 }
1421
1422 return NULL;
1423}
1424
1425static co_lss_state_t *
1426co_lss_cfg_on_recv(co_lss_t *lss, const struct can_msg *msg)
1427{
1428 assert(lss);
1429 assert(msg);
1430
1431 int errc = get_errc();
1432 co_obj_t *obj_1018 = co_dev_find_obj(lss->dev, 0x1018);
1433 struct can_msg req;
1434
1435 if (__unlikely(!msg->len))
1436 return NULL;
1437
1438 co_unsigned8_t cs = msg->data[0];
1439 switch (cs) {
1440 // Switch state global (see Fig. 31 in CiA 305 version 3.0.0).
1441 case 0x04:
1442 if (__unlikely(msg->len < 2))
1443 return NULL;
1444 switch (msg->data[1]) {
1445 case 0x00:
1446 // Switch to the waiting state.
1447 trace("LSS: switching to waiting state");
1448 return co_lss_wait_state;
1449 case 0x01:
1450 // Re-enter the configuration state.
1451 trace("LSS: switching to configuration state");
1452 return co_lss_cfg_state;
1453 }
1454 break;
1455 // Configure node-ID (see Fig. 33 in CiA 305 version 3.0.0).
1456 case 0x11:
1457 if (msg->len < 2)
1458 return NULL;
1459 // Configure the pending node-ID.
1460 trace("LSS: configuring node-ID");
1461 co_lss_init_req(lss, &req, cs);
1462 if (co_nmt_set_id(lss->nmt, msg->data[1]) == -1) {
1463 // Discard the error code if the node-ID was invalid.
1464 set_errc(errc);
1465 req.data[1] = 1;
1466 }
1467 can_net_send(lss->net, &req);
1468 break;
1469 // Configure bit timing parameters (see Fig. 34 in CiA 305 version
1470 // 3.0.0).
1471 case 0x13:
1472 if (msg->len < 3)
1473 return NULL;
1474 // Configure the pending baudrate.
1475 trace("LSS: configuring bit timing parameters");
1476 co_lss_init_req(lss, &req, cs);
1477 if (__unlikely(!lss->rate_ind || msg->data[1])) {
1478 req.data[1] = 1;
1479 } else {
1480 unsigned int baud = co_dev_get_baud(lss->dev);
1481 switch (msg->data[2]) {
1482 case 0:
1483 if (!(req.data[1] = !(baud & CO_BAUD_1000)))
1484 co_dev_set_rate(lss->dev, 1000);
1485 break;
1486 case 1:
1487 if (!(req.data[1] = !(baud & CO_BAUD_800)))
1488 co_dev_set_rate(lss->dev, 800);
1489 break;
1490 case 2:
1491 if (!(req.data[1] = !(baud & CO_BAUD_500)))
1492 co_dev_set_rate(lss->dev, 500);
1493 break;
1494 case 3:
1495 if (!(req.data[1] = !(baud & CO_BAUD_250)))
1496 co_dev_set_rate(lss->dev, 250);
1497 break;
1498 case 4:
1499 if (!(req.data[1] = !(baud & CO_BAUD_125)))
1500 co_dev_set_rate(lss->dev, 135);
1501 break;
1502 case 6:
1503 if (!(req.data[1] = !(baud & CO_BAUD_50)))
1504 co_dev_set_rate(lss->dev, 50);
1505 break;
1506 case 7:
1507 if (!(req.data[1] = !(baud & CO_BAUD_20)))
1508 co_dev_set_rate(lss->dev, 20);
1509 break;
1510 case 8:
1511 if (!(req.data[1] = !(baud & CO_BAUD_10)))
1512 co_dev_set_rate(lss->dev, 10);
1513 break;
1514 case 9:
1515 if (!(req.data[1] = !(baud & CO_BAUD_AUTO)))
1516 co_dev_set_rate(lss->dev, 0);
1517 break;
1518 default: req.data[1] = 1; break;
1519 }
1520 }
1521 can_net_send(lss->net, &req);
1522 break;
1523 // Activate bit timing parameters (see Fig. 35 in CiA 305 version
1524 // 3.0.0).
1525 case 0x15:
1526 if (msg->len < 3 || !lss->rate_ind)
1527 return NULL;
1528 // Invoke the user-specified callback function to perform the
1529 // baudrate switch.
1530 trace("LSS: activating bit timing parameters");
1531 lss->rate_ind(lss, co_dev_get_rate(lss->dev),
1532 ldle_u16(msg->data + 1), lss->rate_data);
1533 break;
1534 // Store configuration (see Fig. 36 in CiA 305 version 3.0.0).
1535 case 0x17:
1536 trace("LSS: storing configuration");
1537 co_lss_init_req(lss, &req, cs);
1538 if (lss->store_ind) {
1539 // Store the pending node-ID and baudrate.
1540 // clang-format off
1541 if (__unlikely(lss->store_ind(lss,
1542 co_nmt_get_id(lss->nmt),
1543 co_dev_get_rate(lss->dev),
1544 lss->store_data) == -1)) {
1545 // clang-format on
1546 // Discard the error code.
1547 set_errc(errc);
1548 req.data[1] = 2;
1549 }
1550 } else {
1551 req.data[1] = 1;
1552 }
1553 can_net_send(lss->net, &req);
1554 break;
1555 // LSS identify remote slave.
1556 case 0x46:
1557 case 0x47:
1558 case 0x48:
1559 case 0x49:
1560 case 0x4a:
1561 case 0x4b:
1562 if (msg->len < 5)
1563 return NULL;
1564 co_lss_id_slave(lss, cs, ldle_u32(msg->data + 1));
1565 break;
1566 // LSS identify non-configured remote slave.
1567 case 0x4c: co_lss_id_non_cfg_slave(lss); break;
1568 // Inquire identity vendor-ID (Fig. 37 in CiA 305 version 3.0.0).
1569 case 0x5a:
1570 trace("LSS: sending vendor-ID");
1571 co_lss_init_req(lss, &req, cs);
1572 stle_u32(req.data + 1, co_obj_get_val_u32(obj_1018, 0x01));
1573 can_net_send(lss->net, &req);
1574 break;
1575 // Inquire identity product-code (Fig. 38 in CiA 305 version 3.0.0).
1576 case 0x5b:
1577 trace("LSS: sending product-code");
1578 co_lss_init_req(lss, &req, cs);
1579 stle_u32(req.data + 1, co_obj_get_val_u32(obj_1018, 0x02));
1580 can_net_send(lss->net, &req);
1581 break;
1582 // Inquire identity revision-number (Fig. 39 in CiA 305 version 3.0.0).
1583 case 0x5c:
1584 trace("LSS: sending revision-number");
1585 co_lss_init_req(lss, &req, cs);
1586 stle_u32(req.data + 1, co_obj_get_val_u32(obj_1018, 0x03));
1587 can_net_send(lss->net, &req);
1588 break;
1589 // Inquire identity serial-number (Fig. 40 in CiA 305 version 3.0.0).
1590 case 0x5d:
1591 trace("LSS: sending serial-number");
1592 co_lss_init_req(lss, &req, cs);
1593 stle_u32(req.data + 1, co_obj_get_val_u32(obj_1018, 0x04));
1594 can_net_send(lss->net, &req);
1595 break;
1596 // Inquire node-ID (Fig. 41 in CiA 305 version 3.0.0).
1597 case 0x5e:
1598 trace("LSS: sending node-ID");
1599 co_lss_init_req(lss, &req, cs);
1600 // Respond with the active or pending node-ID, depending on
1601 // whether the device is in the NMT state Initializing.
1602 switch (co_nmt_get_st(lss->nmt)) {
1603 case CO_NMT_ST_BOOTUP:
1606 req.data[1] = co_nmt_get_id(lss->nmt);
1607 break;
1608 default: req.data[1] = co_dev_get_id(lss->dev); break;
1609 }
1610 can_net_send(lss->net, &req);
1611 break;
1612 }
1613
1614 return NULL;
1615}
1616
1617#ifndef LELY_NO_CO_MASTER
1618
1619static co_lss_state_t *
1620co_lss_cs_on_recv(co_lss_t *lss, const struct can_msg *msg)
1621{
1622 assert(lss);
1623 assert(msg);
1624
1625 if (msg->len < 1 || msg->data[0] != lss->cs)
1626 return NULL;
1627
1628 return co_lss_wait_state;
1629}
1630
1631static co_lss_state_t *
1632co_lss_cs_on_time(co_lss_t *lss, const struct timespec *tp)
1633{
1634 assert(lss);
1635 (void)tp;
1636
1637 lss->cs = 0;
1638 return co_lss_wait_state;
1639}
1640
1641static void
1643{
1644 assert(lss);
1645
1646 can_timer_stop(lss->timer);
1647 can_recv_stop(lss->recv);
1648
1649 if (lss->cs_ind)
1650 lss->cs_ind(lss, lss->cs, lss->cs_data);
1651}
1652
1653static co_lss_state_t *
1654co_lss_err_on_recv(co_lss_t *lss, const struct can_msg *msg)
1655{
1656 assert(lss);
1657 assert(msg);
1658
1659 if (msg->len < 3 || msg->data[0] != lss->cs)
1660 return NULL;
1661
1662 lss->err = msg->data[1];
1663 lss->spec = lss->err == 0xff ? msg->data[2] : 0;
1664 return co_lss_wait_state;
1665}
1666
1667static co_lss_state_t *
1668co_lss_err_on_time(co_lss_t *lss, const struct timespec *tp)
1669{
1670 assert(lss);
1671 (void)tp;
1672
1673 lss->cs = 0;
1674 return co_lss_wait_state;
1675}
1676
1677static void
1679{
1680 assert(lss);
1681
1682 can_timer_stop(lss->timer);
1683 can_recv_stop(lss->recv);
1684
1685 if (lss->err_ind)
1686 lss->err_ind(lss, lss->cs, lss->err, lss->spec, lss->err_data);
1687}
1688
1689static co_lss_state_t *
1690co_lss_lssid_on_recv(co_lss_t *lss, const struct can_msg *msg)
1691{
1692 assert(lss);
1693 assert(msg);
1694
1695 if (msg->len < 5 || msg->data[0] != lss->cs)
1696 return NULL;
1697
1698 lss->lssid = ldle_u32(msg->data + 1);
1699 return co_lss_wait_state;
1700}
1701
1702static co_lss_state_t *
1704{
1705 assert(lss);
1706 (void)tp;
1707
1708 lss->cs = 0;
1709 return co_lss_wait_state;
1710}
1711
1712static void
1714{
1715 assert(lss);
1716
1717 can_timer_stop(lss->timer);
1718 can_recv_stop(lss->recv);
1719
1720 if (lss->lssid_ind)
1721 lss->lssid_ind(lss, lss->cs, lss->lssid, lss->lssid_data);
1722}
1723
1724static co_lss_state_t *
1725co_lss_nid_on_recv(co_lss_t *lss, const struct can_msg *msg)
1726{
1727 assert(lss);
1728 assert(msg);
1729
1730 if (msg->len < 2 || msg->data[0] != lss->cs)
1731 return NULL;
1732
1733 lss->nid = msg->data[1];
1734 return co_lss_wait_state;
1735}
1736
1737static co_lss_state_t *
1738co_lss_nid_on_time(co_lss_t *lss, const struct timespec *tp)
1739{
1740 assert(lss);
1741 (void)tp;
1742
1743 lss->cs = 0;
1744 return co_lss_wait_state;
1745}
1746
1747static void
1749{
1750 assert(lss);
1751
1752 can_timer_stop(lss->timer);
1753 can_recv_stop(lss->recv);
1754
1755 if (lss->nid_ind)
1756 lss->nid_ind(lss, lss->cs, lss->nid, lss->nid_data);
1757}
1758
1759static co_lss_state_t *
1761{
1762 assert(lss);
1763 assert(msg);
1764
1765 if (msg->len < 1 || msg->data[0] != lss->cs)
1766 return NULL;
1767
1769}
1770
1771static co_lss_state_t *
1773{
1774 assert(lss);
1775 (void)tp;
1776
1777 // Abort if we did not receive a response on the first request.
1778 lss->cs = 0;
1780}
1781
1782static co_lss_state_t *
1784{
1785 assert(lss);
1786
1787 struct co_id *id = &lss->id;
1788
1789 // Calculate the midpoint while avoiding integer overflow.
1790 *id = lss->lo;
1791 if (id->revision < lss->hi.revision) {
1792 id->revision += (lss->hi.revision - id->revision) / 2;
1793 id->serial_nr = lss->hi.serial_nr;
1794 } else {
1795 id->serial_nr += (lss->hi.serial_nr - id->serial_nr) / 2;
1796 }
1797
1798 // LSS identify remote slave (see Fig. 42 in CiA 305 version 3.0.0).
1799 if (__unlikely(co_lss_send_id_slave_req(lss, &lss->lo, id) == -1)) {
1800 // Abort if sending the CAN frame failed.
1801 lss->cs = 0;
1803 }
1804
1805 // Restart the timeout for the next response.
1806 can_timer_timeout(lss->timer, lss->net, lss->timeout);
1807 return NULL;
1808}
1809
1810static co_lss_state_t *
1812{
1813 assert(lss);
1814 assert(msg);
1815
1816 if (msg->len < 1 || msg->data[0] != lss->cs)
1817 return NULL;
1818
1819 // Wait until the timeout expires before handling the response.
1821}
1822
1823static co_lss_state_t *
1825{
1826 assert(lss);
1827 (void)tp;
1828
1829 return co_lss_slowscan_scan_on_res(lss, 1);
1830}
1831
1832static co_lss_state_t *
1833co_lss_slowscan_scan_on_res(co_lss_t *lss, int timeout)
1834{
1835 assert(lss);
1836
1837 if (lss->lo.revision == lss->hi.revision
1838 && lss->lo.serial_nr == lss->hi.serial_nr) {
1839 // Abort if we timeout after sending the final LSS address.
1840 if (timeout) {
1841 lss->cs = 0;
1843 }
1844 // Switch the slave to the LSS configuration state.
1845 co_lss_init_ind(lss, 0x44);
1847 }
1848
1849 // Update the bounds on the LSS address.
1850 if (timeout) {
1851 if (lss->id.revision < lss->hi.revision)
1852 lss->lo.revision = lss->id.revision + 1;
1853 else
1854 lss->lo.serial_nr = lss->id.serial_nr + 1;
1855 } else {
1856 lss->hi = lss->id;
1857 }
1858
1859 // Start the next cycle.
1861}
1862
1863static co_lss_state_t *
1865{
1866 (void)lss;
1867 (void)msg;
1868
1869 // Ignore further responses from slaves.
1870 return NULL;
1871}
1872
1873static co_lss_state_t *
1875{
1876 (void)lss;
1877 (void)tp;
1878
1879 // All slaves should have responded by now.
1880 return co_lss_slowscan_scan_on_res(lss, 0);
1881}
1882
1883static co_lss_state_t *
1885{
1886 assert(lss);
1887
1888 // Switch state selective (see Fig. 32 in CiA 305 version 3.0.0).
1889 if (__unlikely(co_lss_send_switch_sel_req(lss, &lss->id) == -1)) {
1890 // Abort if sending the CAN frame failed.
1891 lss->cs = 0;
1893 }
1894
1895 // Restart the timeout for the response.
1896 can_timer_timeout(lss->timer, lss->net, lss->timeout);
1897 return NULL;
1898}
1899
1900static co_lss_state_t *
1902{
1903 assert(lss);
1904 assert(msg);
1905
1906 if (msg->len < 1 || msg->data[0] != lss->cs)
1907 return NULL;
1908
1910}
1911
1912static co_lss_state_t *
1914{
1915 assert(lss);
1916 (void)tp;
1917
1918 // Abort if no response was received.
1919 lss->cs = 0;
1921}
1922
1923static co_lss_state_t *
1925{
1926 (void)lss;
1927
1928 return co_lss_wait_state;
1929}
1930
1931static void
1933{
1934 assert(lss);
1935
1936 can_timer_stop(lss->timer);
1937 can_recv_stop(lss->recv);
1938
1939 if (lss->scan_ind)
1940 lss->scan_ind(lss, lss->cs, lss->cs ? &lss->id : NULL,
1941 lss->scan_data);
1942}
1943
1944static co_lss_state_t *
1946{
1947 assert(lss);
1948 assert(msg);
1949
1950 if (msg->len < 1 || msg->data[0] != lss->cs)
1951 return NULL;
1952
1953 lss->bitchk = 31;
1955}
1956
1957static co_lss_state_t *
1959{
1960 assert(lss);
1961 (void)tp;
1962
1963 // Abort if we did not receive a response on the reset request.
1964 lss->cs = 0;
1966}
1967
1968static co_lss_state_t *
1970{
1971 assert(lss);
1972
1973 const co_unsigned32_t *pid = &lss->id.vendor_id;
1974 const co_unsigned32_t *pmask = &lss->mask.vendor_id;
1975
1976 // Find the next unknown bit.
1977 for (; lss->bitchk
1978 && (pmask[lss->lsssub] & (UINT32_C(1) << lss->bitchk));
1979 lss->bitchk--)
1980 ;
1981
1982 co_unsigned8_t lssnext = lss->lsssub;
1983 // If we obtained the complete LSS number, send it again and prepare for
1984 // the next number.
1985 if (!lss->bitchk && (pmask[lss->lsssub] & 1)) {
1986 if (lssnext < 3) {
1987 lssnext++;
1988 } else {
1989 lssnext = 0;
1990 }
1991 }
1992
1993 // LSS Fastscan (see Fig. 46 in CiA 305 version 3.0.0).
1994 // clang-format off
1995 if (__unlikely(co_lss_send_fastscan_req(lss, pid[lss->lsssub],
1996 lss->bitchk, lss->lsssub, lssnext) == -1)) {
1997 // Abort if sending the CAN frame failed.
1998 // clang-format on
1999 lss->cs = 0;
2001 }
2002
2003 // Restart the timeout for the next response.
2004 can_timer_timeout(lss->timer, lss->net, lss->timeout);
2005 return NULL;
2006}
2007
2008static co_lss_state_t *
2010{
2011 assert(lss);
2012 assert(msg);
2013
2014 if (msg->len < 1 || msg->data[0] != lss->cs)
2015 return NULL;
2016
2017 // Wait until the timeout expires before handling the response.
2019}
2020
2021static co_lss_state_t *
2023{
2024 assert(lss);
2025 (void)tp;
2026
2027 return co_lss_fastscan_scan_on_res(lss, 1);
2028}
2029
2030static co_lss_state_t *
2031co_lss_fastscan_scan_on_res(co_lss_t *lss, int timeout)
2032{
2033 assert(lss);
2034 assert(lss->bitchk <= 31);
2035 assert(lss->lsssub < 4);
2036
2037 co_unsigned32_t *pid = &lss->id.vendor_id;
2038 co_unsigned32_t *pmask = &lss->mask.vendor_id;
2039
2040 if (!lss->bitchk && (pmask[lss->lsssub] & 1)) {
2041 // Abort if we timeout after sending the complete LSS number.
2042 if (__unlikely(timeout)) {
2043 lss->cs = 0;
2045 }
2046 // We're done if this was the last LSS number.
2047 if (++lss->lsssub == 4)
2049 lss->bitchk = 31;
2050 } else {
2051 // Update the LSS address. A timeout indicates the bit is 1.
2052 if (timeout)
2053 pid[lss->lsssub] |= UINT32_C(1) << lss->bitchk;
2054 pmask[lss->lsssub] |= UINT32_C(1) << lss->bitchk;
2055 }
2056
2057 // Start the next cycle.
2059}
2060
2061static co_lss_state_t *
2063{
2064 (void)lss;
2065 (void)msg;
2066
2067 // Ignore further responses from slaves.
2068 return NULL;
2069}
2070
2071static co_lss_state_t *
2073{
2074 (void)lss;
2075 (void)tp;
2076
2077 // All slaves should have responded by now.
2078 return co_lss_fastscan_scan_on_res(lss, 0);
2079}
2080
2081static co_lss_state_t *
2083{
2084 (void)lss;
2085
2086 return co_lss_wait_state;
2087}
2088
2089static void
2091{
2092 assert(lss);
2093
2094 can_timer_stop(lss->timer);
2095 can_recv_stop(lss->recv);
2096
2097 if (lss->scan_ind)
2098 lss->scan_ind(lss, lss->cs, lss->cs ? &lss->id : NULL,
2099 lss->scan_data);
2100}
2101
2102#endif // !LELY_NO_CO_MASTER
2103
2104static co_lss_state_t *
2105co_lss_switch_sel(co_lss_t *lss, co_unsigned8_t cs, co_unsigned32_t id)
2106{
2107 assert(lss);
2108
2109 co_obj_t *obj_1018 = co_dev_find_obj(lss->dev, 0x1018);
2110 struct can_msg req;
2111
2112 switch (cs) {
2113 case 0x40:
2114 if (id != co_obj_get_val_u32(obj_1018, 0x01)) {
2115 lss->cs = 0;
2116 return NULL;
2117 }
2118 lss->cs = 0x41;
2119 return NULL;
2120 case 0x41:
2121 if (cs != lss->cs || id != co_obj_get_val_u32(obj_1018, 0x02)) {
2122 lss->cs = 0;
2123 return NULL;
2124 }
2125 lss->cs = 0x42;
2126 return NULL;
2127 case 0x42:
2128 if (cs != lss->cs || id != co_obj_get_val_u32(obj_1018, 0x03)) {
2129 lss->cs = 0;
2130 return NULL;
2131 }
2132 lss->cs = 0x43;
2133 return NULL;
2134 case 0x43:
2135 if (cs != lss->cs || id != co_obj_get_val_u32(obj_1018, 0x04)) {
2136 lss->cs = 0;
2137 return NULL;
2138 }
2139 lss->cs = 0;
2140 // Notify the master of the state switch.
2141 co_lss_init_req(lss, &req, 0x44);
2142 can_net_send(lss->net, &req);
2143 // Switch to the configuration state.
2144 trace("LSS: switching to configuration state");
2145 return co_lss_cfg_state;
2146 default: return NULL;
2147 }
2148}
2149
2150static void
2151co_lss_id_slave(co_lss_t *lss, co_unsigned8_t cs, co_unsigned32_t id)
2152{
2153 assert(lss);
2154
2155 co_obj_t *obj_1018 = co_dev_find_obj(lss->dev, 0x1018);
2156 struct can_msg req;
2157
2158 switch (cs) {
2159 case 0x46:
2160 // Check the vendor-ID.
2161 if (id != co_obj_get_val_u32(obj_1018, 0x01)) {
2162 lss->cs = 0;
2163 return;
2164 }
2165 lss->cs = 0x47;
2166 break;
2167 case 0x47:
2168 // Check the product-code.
2169 if (cs != lss->cs || id != co_obj_get_val_u32(obj_1018, 0x02)) {
2170 lss->cs = 0;
2171 return;
2172 }
2173 lss->cs = 0x48;
2174 break;
2175 case 0x48:
2176 // Check the lower bound of the revision-number.
2177 if (cs != lss->cs || id > co_obj_get_val_u32(obj_1018, 0x03)) {
2178 lss->cs = 0;
2179 return;
2180 }
2181 lss->cs = 0x49;
2182 break;
2183 case 0x49:
2184 // Check the upper bound of the revision-number.
2185 if (cs != lss->cs || id < co_obj_get_val_u32(obj_1018, 0x03)) {
2186 lss->cs = 0;
2187 return;
2188 }
2189 lss->cs = 0x4a;
2190 break;
2191 case 0x4a:
2192 // Check the lower bound of the serial-number.
2193 if (cs != lss->cs || id > co_obj_get_val_u32(obj_1018, 0x04)) {
2194 lss->cs = 0;
2195 return;
2196 }
2197 lss->cs = 0x4b;
2198 break;
2199 case 0x4b:
2200 // Check the upper bound of the serial-number.
2201 if (cs != lss->cs || id < co_obj_get_val_u32(obj_1018, 0x04)) {
2202 lss->cs = 0;
2203 return;
2204 }
2205 lss->cs = 0;
2206 // Notify the master that it is a match.
2207 co_lss_init_req(lss, &req, 0x4f);
2208 can_net_send(lss->net, &req);
2209 break;
2210 }
2211}
2212
2213static void
2215{
2216 assert(lss);
2217
2218 // Check if both the active and the pending node-ID are invalid.
2219 if (co_dev_get_id(lss->dev) != 0xff || co_nmt_get_id(lss->nmt) != 0xff)
2220 return;
2221
2222 // Check if the device is in the NMT state Initialization.
2223 switch (co_nmt_get_st(lss->nmt)) {
2224 case CO_NMT_ST_BOOTUP:
2226 case CO_NMT_ST_RESET_COMM: break;
2227 default: return;
2228 }
2229
2230 struct can_msg req;
2231 co_lss_init_req(lss, &req, 0x50);
2232 can_net_send(lss->net, &req);
2233}
2234
2235static co_lss_state_t *
2236co_lss_fastscan(co_lss_t *lss, co_unsigned32_t id, co_unsigned8_t bitchk,
2237 co_unsigned8_t lsssub, co_unsigned8_t lssnext)
2238{
2239 assert(lss);
2240
2241 co_obj_t *obj_1018 = co_dev_find_obj(lss->dev, 0x1018);
2242 struct can_msg req;
2243 co_lss_state_t *next = NULL;
2244
2245 if (__unlikely(bitchk > 31 && bitchk != 0x80))
2246 return NULL;
2247
2248 if (bitchk == 0x80) {
2249 lss->lsspos = 0;
2250 } else {
2251 if (lss->lsspos > 3 || lss->lsspos != lsssub)
2252 return NULL;
2253 // Check if the unmasked bits of the specified IDNumber match.
2254 co_unsigned32_t pid[] = { co_obj_get_val_u32(obj_1018, 0x01),
2255 co_obj_get_val_u32(obj_1018, 0x02),
2256 co_obj_get_val_u32(obj_1018, 0x03),
2257 co_obj_get_val_u32(obj_1018, 0x04) };
2258 if ((id ^ pid[lss->lsspos]) & ~((UINT32_C(1) << bitchk) - 1))
2259 return NULL;
2260 lss->lsspos = lssnext;
2261 // If this was the final bit, switch to the configuration state.
2262 if (!bitchk && lss->lsspos < lsssub)
2263 next = co_lss_cfg_state;
2264 }
2265
2266 // Notify the master that it is a match.
2267 co_lss_init_req(lss, &req, 0x4f);
2268 can_net_send(lss->net, &req);
2269
2270 return next;
2271}
2272
2273static void
2274co_lss_init_req(const co_lss_t *lss, struct can_msg *msg, co_unsigned8_t cs)
2275{
2276 assert(lss);
2277 assert(msg);
2278
2279 *msg = (struct can_msg)CAN_MSG_INIT;
2280 msg->id = CO_LSS_CANID(co_lss_is_master(lss));
2281 msg->len = CAN_MAX_LEN;
2282 msg->data[0] = cs;
2283}
2284
2285#ifndef LELY_NO_CO_MASTER
2286
2287static int
2288co_lss_send_switch_sel_req(const co_lss_t *lss, const struct co_id *id)
2289{
2290 assert(id);
2291
2292 // Switch state selective (see Fig. 32 in CiA 305 version 3.0.0).
2293 struct can_msg req;
2294 co_lss_init_req(lss, &req, 0x40);
2295 stle_u32(req.data + 1, id->vendor_id);
2296 if (__unlikely(can_net_send(lss->net, &req) == -1))
2297 return -1;
2298 co_lss_init_req(lss, &req, 0x41);
2299 stle_u32(req.data + 1, id->product_code);
2300 if (__unlikely(can_net_send(lss->net, &req) == -1))
2301 return -1;
2302 co_lss_init_req(lss, &req, 0x42);
2303 stle_u32(req.data + 1, id->revision);
2304 if (__unlikely(can_net_send(lss->net, &req) == -1))
2305 return -1;
2306 co_lss_init_req(lss, &req, 0x43);
2307 stle_u32(req.data + 1, id->serial_nr);
2308 if (__unlikely(can_net_send(lss->net, &req) == -1))
2309 return -1;
2310
2311 return 0;
2312}
2313
2314static int
2315co_lss_send_id_slave_req(const co_lss_t *lss, const struct co_id *lo,
2316 const struct co_id *hi)
2317{
2318 assert(lo);
2319 assert(hi);
2320
2321 // clang-format off
2322 if (__unlikely(lo->vendor_id != hi->vendor_id
2323 || lo->product_code != hi->product_code)
2324 || lo->revision > hi->revision
2325 || lo->serial_nr > hi->serial_nr) {
2326 // clang-format on
2328 return -1;
2329 }
2330
2331 // LSS identify remote slave (see Fig. 42 in CiA 305 version 3.0.0).
2332 struct can_msg req;
2333 co_lss_init_req(lss, &req, 0x46);
2334 stle_u32(req.data + 1, lo->vendor_id);
2335 if (__unlikely(can_net_send(lss->net, &req) == -1))
2336 return -1;
2337 co_lss_init_req(lss, &req, 0x47);
2338 stle_u32(req.data + 1, lo->product_code);
2339 if (__unlikely(can_net_send(lss->net, &req) == -1))
2340 return -1;
2341 co_lss_init_req(lss, &req, 0x48);
2342 stle_u32(req.data + 1, lo->revision);
2343 if (__unlikely(can_net_send(lss->net, &req) == -1))
2344 return -1;
2345 co_lss_init_req(lss, &req, 0x49);
2346 stle_u32(req.data + 1, hi->revision);
2347 if (__unlikely(can_net_send(lss->net, &req) == -1))
2348 return -1;
2349 co_lss_init_req(lss, &req, 0x4a);
2350 stle_u32(req.data + 1, lo->serial_nr);
2351 if (__unlikely(can_net_send(lss->net, &req) == -1))
2352 return -1;
2353 co_lss_init_req(lss, &req, 0x4b);
2354 stle_u32(req.data + 1, hi->serial_nr);
2355 if (__unlikely(can_net_send(lss->net, &req) == -1))
2356 return -1;
2357
2358 return 0;
2359}
2360
2361static int
2362co_lss_send_fastscan_req(const co_lss_t *lss, co_unsigned32_t id,
2363 co_unsigned8_t bitchk, co_unsigned8_t lsssub,
2364 co_unsigned8_t lssnext)
2365{
2366 // LSS Fastscan (see Fig. 46 in CiA 305 version 3.0.0).
2367 struct can_msg req;
2368 co_lss_init_req(lss, &req, 0x51);
2369 stle_u32(req.data + 1, id);
2370 req.data[5] = bitchk;
2371 req.data[6] = lsssub;
2372 req.data[7] = lssnext;
2373 return can_net_send(lss->net, &req);
2374}
2375
2376static void
2377co_lss_init_ind(co_lss_t *lss, co_unsigned8_t cs)
2378{
2379 assert(lss);
2380
2381 lss->cs = cs;
2382 lss->err = 0;
2383 lss->spec = 0;
2384 lss->lssid = 0;
2385 lss->nid = 0;
2386
2387 can_recv_start(lss->recv, lss->net, CO_LSS_CANID(0), 0);
2388 can_timer_timeout(lss->timer, lss->net, lss->timeout);
2389}
2390
2391#endif // !LELY_NO_CO_MASTER
2392
2393#endif // !LELY_NO_CO_LSS
co_obj_t * co_dev_find_obj(const co_dev_t *dev, co_unsigned16_t idx)
Finds an object in the object dictionary of a CANopen device.
Definition: dev.c:279
co_unsigned8_t co_dev_get_id(const co_dev_t *dev)
Returns the node-ID of a CANopen device.
Definition: dev.c:198
#define CO_BAUD_20
A bit rate of 20 kbit/s.
Definition: dev.h:77
#define CO_BAUD_AUTO
Automatic bit rate detection.
Definition: dev.h:83
#define CO_BAUD_125
A bit rate of 125 kbit/s.
Definition: dev.h:71
#define CO_NUM_NODES
The maximum number of nodes in a CANopen network.
Definition: dev.h:56
co_unsigned16_t co_dev_get_rate(const co_dev_t *dev)
Returns the (pending) baudrate of a CANopen device (in kbit/s).
Definition: dev.c:481
#define CO_ID_INIT
The static initializer for struct co_id.
Definition: dev.h:47
#define CO_BAUD_10
A bit rate of 10 kbit/s.
Definition: dev.h:80
#define CO_BAUD_250
A bit rate of 250 kbit/s.
Definition: dev.h:68
void co_dev_set_rate(co_dev_t *dev, co_unsigned16_t rate)
Sets the (pending) baudrate of a CANopen device.
Definition: dev.c:489
#define CO_BAUD_1000
A bit rate of 1 Mbit/s.
Definition: dev.h:59
#define CO_BAUD_500
A bit rate of 500 kbit/s.
Definition: dev.h:65
#define CO_BAUD_800
A bit rate of 800 kbit/s.
Definition: dev.h:62
unsigned int co_dev_get_baud(const co_dev_t *dev)
Returns the supported bit rates of a CANopen device (any combination of CO_BAUD_1000,...
Definition: dev.c:465
#define CO_BAUD_50
A bit rate of 50 kbit/s.
Definition: dev.h:74
This header file is part of the utilities library; it contains the byte order (endianness) function d...
void stle_u16(void *ptr, uint_least16_t x)
Stores a 16-bit unsigned integer in little-endian byte order.
Definition: endian.h:480
void stle_u32(void *ptr, uint_least32_t x)
Stores a 32-bit unsigned integer in little-endian byte order.
Definition: endian.h:534
uint_least32_t ldle_u32(const void *ptr)
Loads a 32-bit unsigned integer in little-endian byte order.
Definition: endian.h:541
uint_least16_t ldle_u16(const void *ptr)
Loads a 16-bit unsigned integer in little-endian byte order.
Definition: endian.h:487
This header file is part of the utilities library; it contains the native and platform-independent er...
@ ERRNUM_PERM
Operation not permitted.
Definition: errnum.h:205
@ ERRNUM_INVAL
Invalid argument.
Definition: errnum.h:129
int get_errc(void)
Returns the last (thread-specific) native error code set by a system call or library function.
Definition: errnum.c:947
void set_errc(int errc)
Sets the current (thread-specific) native error code to errc.
Definition: errnum.c:957
int errno2c(int errnum)
Transforms a standard C error number to a native error code.
Definition: errnum.c:43
void set_errnum(errnum_t errnum)
Sets the current (thread-specific) platform-independent error number to errnum.
Definition: errnum.h:375
#define __unlikely(x)
Indicates to the compiler that the expression is most-likely false.
Definition: features.h:286
This header file is part of the CANopen library; it contains the object dictionary declarations.
#define MAX(a, b)
Returns the maximum of a and b.
Definition: util.h:65
static co_lss_state_t * co_lss_cs_on_recv(co_lss_t *lss, const struct can_msg *msg)
The 'CAN frame received' transition function of the command received state.
Definition: lss.c:1620
static co_lss_state_t *const co_lss_slowscan_wait_state
The Slowscan waiting state.
Definition: lss.c:369
static co_lss_state_t * co_lss_slowscan_wait_on_recv(co_lss_t *lss, const struct can_msg *msg)
The 'CAN frame received' transition function of the Slowscan waiting state.
Definition: lss.c:1864
int co_lss_get_vendor_id_req(co_lss_t *lss, co_lss_lssid_ind_t *ind, void *data)
Requests the 'inquire identity vendor-ID' service.
Definition: lss.c:1017
void co_lss_destroy(co_lss_t *lss)
Destroys a CANopen LSS master/slave service.
Definition: lss.c:733
static co_lss_state_t * co_lss_slowscan_init_on_time(co_lss_t *lss, const struct timespec *tp)
The 'timeout' transition function of the Slowscan initialization state.
Definition: lss.c:1772
static int co_lss_send_fastscan_req(const co_lss_t *lss, co_unsigned32_t id, co_unsigned8_t bitchk, co_unsigned8_t lsssub, co_unsigned8_t lssnext)
Sends an LSS Fastscan request (see Fig.
Definition: lss.c:2362
static co_lss_state_t * co_lss_slowscan_scan_on_time(co_lss_t *lss, const struct timespec *tp)
The 'timeout' transition function of the Slowscan scanning state.
Definition: lss.c:1824
static co_lss_state_t * co_lss_slowscan_switch_on_enter(co_lss_t *lss)
The entry function of the Slowscan 'switch state selective' state.
Definition: lss.c:1884
static co_lss_state_t * co_lss_nid_on_time(co_lss_t *lss, const struct timespec *tp)
The 'timeout' transition function of the inquire node-ID state.
Definition: lss.c:1738
static void co_lss_fastscan_fini_on_leave(co_lss_t *lss)
The exit function of the Fastscan finalization state.
Definition: lss.c:2090
static co_lss_state_t *const co_lss_slowscan_scan_state
The Slowscan scanning state.
Definition: lss.c:353
static co_lss_state_t *const co_lss_fastscan_fini_state
The Fastscan finalization state.
Definition: lss.c:480
static co_lss_state_t *const co_lss_cs_state
The command received state.
Definition: lss.c:252
int co_lss_is_master(const co_lss_t *lss)
Returns 1 if the specified CANopen LSS service is a master, and 0 if not.
Definition: lss.c:815
static co_lss_state_t *const co_lss_slowscan_init_state
The Slowscan initialization state.
Definition: lss.c:331
int co_lss_set_id_req(co_lss_t *lss, co_unsigned8_t id, co_lss_err_ind_t *ind, void *data)
Requests the 'configure node-ID' service.
Definition: lss.c:893
void co_lss_set_timeout(co_lss_t *lss, int timeout)
Sets the timeout of an LSS master service.
Definition: lss.c:802
static co_lss_state_t * co_lss_fastscan_fini_on_enter(co_lss_t *lss)
The entry function of the Fastscan finalization state.
Definition: lss.c:2082
static co_lss_state_t * co_lss_fastscan_scan_on_enter(co_lss_t *lss)
The entry function of the Fastscan scanning state.
Definition: lss.c:1969
static co_lss_state_t *const co_lss_wait_state
The 'waiting' state of an LSS master or slave.
Definition: lss.c:198
static void co_lss_id_slave(co_lss_t *lss, co_unsigned8_t cs, co_unsigned32_t id)
Implements the LSS identify remote slave service for an LSS slave.
Definition: lss.c:2151
static void co_lss_err_on_leave(co_lss_t *lss)
The exit function of the error received state.
Definition: lss.c:1678
static void co_lss_init_req(const co_lss_t *lss, struct can_msg *msg, co_unsigned8_t cs)
Initializes an LSS request CAN frame.
Definition: lss.c:2274
int co_lss_slowscan_req(co_lss_t *lss, const struct co_id *lo, const struct co_id *hi, co_lss_scan_ind_t *ind, void *data)
Requests the 'LSS Slowscan' service.
Definition: lss.c:1194
int co_lss_switch_rate_req(co_lss_t *lss, int delay)
Requests the 'activate bit timing parameters' service.
Definition: lss.c:966
static co_lss_state_t * co_lss_nid_on_recv(co_lss_t *lss, const struct can_msg *msg)
The 'CAN frame received' transition function of the inquire node-ID state.
Definition: lss.c:1725
static co_lss_state_t * co_lss_slowscan_switch_on_time(co_lss_t *lss, const struct timespec *tp)
The 'timeout' transition function of the Slowscan 'switch state selective' state.
Definition: lss.c:1913
int co_lss_get_id_req(co_lss_t *lss, co_lss_nid_ind_t *ind, void *data)
Requests the 'inquire node-ID' service.
Definition: lss.c:1119
static co_lss_state_t * co_lss_fastscan_scan_on_recv(co_lss_t *lss, const struct can_msg *msg)
The 'CAN frame received' transition function of the Fastscan scanning state.
Definition: lss.c:2009
static void co_lss_init_ind(co_lss_t *lss, co_unsigned8_t cs)
Prepares an LSS master to receive an indication from a slave.
Definition: lss.c:2377
int co_lss_get_revision_req(co_lss_t *lss, co_lss_lssid_ind_t *ind, void *data)
Requests the 'inquire identity revision-number' service.
Definition: lss.c:1067
void co_lss_set_store_ind(co_lss_t *lss, co_lss_store_ind_t *ind, void *data)
Sets the indication function invoked when an LSS 'store configuration' request is received.
Definition: lss.c:783
int co_lss_switch_sel_req(co_lss_t *lss, const struct co_id *id, co_lss_cs_ind_t *ind, void *data)
Requests the 'switch state selective' service.
Definition: lss.c:869
static co_lss_state_t * co_lss_slowscan_switch_on_recv(co_lss_t *lss, const struct can_msg *msg)
The 'CAN frame received' transition function of the Slowscan 'switch state selective' state.
Definition: lss.c:1901
void co_lss_get_rate_ind(const co_lss_t *lss, co_lss_rate_ind_t **pind, void **pdata)
Retrieves the indication function invoked when an LSS 'activate bit timing' request is received.
Definition: lss.c:751
int co_lss_switch_req(co_lss_t *lss, co_unsigned8_t mode)
Requests the 'switch state global' service.
Definition: lss.c:847
static void co_lss_emit_recv(co_lss_t *lss, const struct can_msg *msg)
Invokes the 'CAN frame received' transition function of the current state of an LSS service.
Definition: lss.c:1317
int co_lss_set_rate_req(co_lss_t *lss, co_unsigned16_t rate, co_lss_err_ind_t *ind, void *data)
Requests the 'configure bit timing parameters' service.
Definition: lss.c:925
static void co_lss_cs_on_leave(co_lss_t *lss)
The exit function of the command received state.
Definition: lss.c:1642
static co_lss_state_t *const co_lss_cfg_state
The 'configuration' state of an LSS slave.
Definition: lss.c:230
int co_lss_is_idle(const co_lss_t *lss)
Returns 1 if the specified LSS master is idle, and 0 if a request is ongoing.
Definition: lss.c:831
static co_lss_state_t *const co_lss_fastscan_scan_state
The Fastscan scanning state.
Definition: lss.c:450
void co_lss_set_rate_ind(co_lss_t *lss, co_lss_rate_ind_t *ind, void *data)
Sets the indication function invoked when an LSS 'activate bit timing' request is received.
Definition: lss.c:762
static int co_lss_send_id_slave_req(const co_lss_t *lss, const struct co_id *lo, const struct co_id *hi)
Sends an LSS identify remote slave request (see Fig.
Definition: lss.c:2315
static co_lss_state_t * co_lss_cfg_on_recv(co_lss_t *lss, const struct can_msg *msg)
The 'CAN frame received' transition function of the 'configuration' state of an LSS slave.
Definition: lss.c:1426
int co_lss_get_timeout(const co_lss_t *lss)
Returns the timeout (in milliseconds) of an LSS master service.
Definition: lss.c:794
co_lss_t * co_lss_create(co_nmt_t *nmt)
Creates a new CANopen LSS master/slave service.
Definition: lss.c:706
static co_lss_state_t * co_lss_fastscan_init_on_time(co_lss_t *lss, const struct timespec *tp)
The 'timeout' transition function of the Fastscan initialization state.
Definition: lss.c:1958
co_nmt_t * co_lss_get_nmt(const co_lss_t *lss)
Returns a pointer to the NMT service of an LSS master/slave service.
Definition: lss.c:743
int co_lss_get_product_code_req(co_lss_t *lss, co_lss_lssid_ind_t *ind, void *data)
Requests the 'inquire identity product-code' service.
Definition: lss.c:1042
static co_lss_state_t *const co_lss_slowscan_fini_state
The Slowscan finalization state.
Definition: lss.c:409
int co_lss_id_slave_req(co_lss_t *lss, const struct co_id *lo, const struct co_id *hi, co_lss_cs_ind_t *ind, void *data)
Requests the 'LSS identify remote slave' service.
Definition: lss.c:1144
static co_lss_state_t *const co_lss_nid_state
The inquire node-ID state.
Definition: lss.c:312
static void co_lss_slowscan_fini_on_leave(co_lss_t *lss)
The exit function of the Slowscan finalization state.
Definition: lss.c:1932
static co_lss_state_t * co_lss_fastscan_wait_on_recv(co_lss_t *lss, const struct can_msg *msg)
The 'CAN frame received' transition function of the Fastscan waiting state.
Definition: lss.c:2062
int co_lss_store_req(co_lss_t *lss, co_lss_err_ind_t *ind, void *data)
Requests the 'store configuration' service.
Definition: lss.c:992
static co_lss_state_t * co_lss_fastscan_wait_on_time(co_lss_t *lss, const struct timespec *tp)
The 'timeout' transition function of the Fastscan waiting state.
Definition: lss.c:2072
static co_lss_state_t * co_lss_slowscan_init_on_recv(co_lss_t *lss, const struct can_msg *msg)
The 'CAN frame received' transition function of the Slowscan initialization state.
Definition: lss.c:1760
static co_lss_state_t * co_lss_cs_on_time(co_lss_t *lss, const struct timespec *tp)
The 'timeout' transition function of the command received state.
Definition: lss.c:1632
static co_lss_state_t * co_lss_lssid_on_recv(co_lss_t *lss, const struct can_msg *msg)
The 'CAN frame received' transition function of the inquire identity state.
Definition: lss.c:1690
int co_lss_id_non_cfg_slave_req(co_lss_t *lss, co_lss_cs_ind_t *ind, void *data)
Requests the 'LSS identify non-configured remote slave' service.
Definition: lss.c:1168
static co_lss_state_t *const co_lss_fastscan_wait_state
The Fastscan waiting state.
Definition: lss.c:466
static co_lss_state_t * co_lss_slowscan_fini_on_enter(co_lss_t *lss)
The entry function of the Slowscan finalization state.
Definition: lss.c:1924
static co_lss_state_t * co_lss_slowscan_scan_on_enter(co_lss_t *lss)
The entry function of the Slowscan scanning state.
Definition: lss.c:1783
static int co_lss_timer(const struct timespec *tp, void *data)
The CAN timer callback function for an LSS service.
Definition: lss.c:1288
static co_lss_state_t * co_lss_wait_slave_on_enter(co_lss_t *lss)
The entry function of the 'waiting' state of an LSS slave.
Definition: lss.c:1354
static co_lss_state_t *const co_lss_slowscan_switch_state
The Slowscan 'switch state selective' state.
Definition: lss.c:395
static co_lss_state_t * co_lss_slowscan_wait_on_time(co_lss_t *lss, const struct timespec *tp)
The 'timeout' transition function of the Slowscan waiting state.
Definition: lss.c:1874
static co_lss_state_t * co_lss_fastscan(co_lss_t *lss, co_unsigned32_t id, co_unsigned8_t bitchk, co_unsigned8_t lsssub, co_unsigned8_t lssnext)
Implements the LSS fastscan service for an LSS slave.
Definition: lss.c:2236
int co_lss_fastscan_req(co_lss_t *lss, const struct co_id *id, const struct co_id *mask, co_lss_scan_ind_t *ind, void *data)
Requests the 'LSS Fastscan' service.
Definition: lss.c:1228
static void co_lss_enter(co_lss_t *lss, co_lss_state_t *next)
Enters the specified state of an LSS service and invokes the exit and entry functions.
Definition: lss.c:1301
static void co_lss_id_non_cfg_slave(const co_lss_t *lss)
Implements the LSS identify non-configured remote slave service for an LSS slave.
Definition: lss.c:2214
static co_lss_state_t * co_lss_wait_slave_on_recv(co_lss_t *lss, const struct can_msg *msg)
The 'CAN frame received' transition function of the 'waiting' state of an LSS slave.
Definition: lss.c:1368
static co_lss_state_t *const co_lss_err_state
The error received state.
Definition: lss.c:272
static void co_lss_nid_on_leave(co_lss_t *lss)
The exit function of the inquire node-ID state.
Definition: lss.c:1748
int co_lss_get_serial_nr_req(co_lss_t *lss, co_lss_lssid_ind_t *ind, void *data)
Requests the 'inquire identity serial-number' service.
Definition: lss.c:1093
static co_lss_state_t * co_lss_fastscan_init_on_recv(co_lss_t *lss, const struct can_msg *msg)
The 'CAN frame received' transition function of the Fastscan initialization state.
Definition: lss.c:1945
void co_lss_abort_req(co_lss_t *lss)
Aborts the current LSS master request.
Definition: lss.c:839
static co_lss_state_t * co_lss_switch_sel(co_lss_t *lss, co_unsigned8_t cs, co_unsigned32_t id)
Implements the switch state selective service for an LSS slave.
Definition: lss.c:2105
static co_lss_state_t * co_lss_lssid_on_time(co_lss_t *lss, const struct timespec *tp)
The 'timeout' transition function of the inquire identity state.
Definition: lss.c:1703
static int co_lss_recv(const struct can_msg *msg, void *data)
The CAN receive callback function for an LSS service.
Definition: lss.c:1275
static void co_lss_lssid_on_leave(co_lss_t *lss)
The exit function of the inquire identity state.
Definition: lss.c:1713
static co_lss_state_t * co_lss_wait_on_enter(co_lss_t *lss)
The entry function of the 'waiting' state an LSS master or slave.
Definition: lss.c:1339
static void co_lss_emit_time(co_lss_t *lss, const struct timespec *tp)
Invokes the 'timeout' transition function of the current state of an LSS service.
Definition: lss.c:1328
static int co_lss_send_switch_sel_req(const co_lss_t *lss, const struct co_id *id)
Sends a switch state selective request (see Fig.
Definition: lss.c:2288
static co_lss_state_t *const co_lss_fastscan_init_state
The Fastscan initialization state.
Definition: lss.c:428
static co_lss_state_t * co_lss_fastscan_scan_on_time(co_lss_t *lss, const struct timespec *tp)
The 'timeout' transition function of the Fastscan scanning state.
Definition: lss.c:2022
static co_lss_state_t *const co_lss_wait_slave_state
The 'waiting' state of an LSS slave.
Definition: lss.c:216
static co_lss_state_t *const co_lss_lssid_state
The inquire identity state.
Definition: lss.c:292
static co_lss_state_t * co_lss_err_on_recv(co_lss_t *lss, const struct can_msg *msg)
The 'CAN frame received' transition function of the error received state.
Definition: lss.c:1654
static co_lss_state_t * co_lss_slowscan_scan_on_recv(co_lss_t *lss, const struct can_msg *msg)
The 'CAN frame received' transition function of the Slowscan scanning state.
Definition: lss.c:1811
static co_lss_state_t * co_lss_err_on_time(co_lss_t *lss, const struct timespec *tp)
The 'timeout' transition function of the error received state.
Definition: lss.c:1668
void co_lss_get_store_ind(const co_lss_t *lss, co_lss_store_ind_t **pind, void **pdata)
Retrieves the indication function invoked when an LSS 'store configuration' request is received.
Definition: lss.c:771
This header file is part of the CANopen library; it contains the Layer Setting Services (LSS) and pro...
void co_lss_lssid_ind_t(co_lss_t *lss, co_unsigned8_t cs, co_unsigned32_t id, void *data)
The type of a CANopen LSS inquire identity indication function, invoked when an 'inquire identity ven...
Definition: lss.h:109
int co_lss_store_ind_t(co_lss_t *lss, co_unsigned8_t id, co_unsigned16_t rate, void *data)
The type of a CANopen LSS 'store configuration' indication function, invoked when the pending node-ID...
Definition: lss.h:67
#define CO_LSS_CANID(master)
The CAN identifier used for LSS by the master (1) or the slave (0).
Definition: lss.h:34
void co_lss_err_ind_t(co_lss_t *lss, co_unsigned8_t cs, co_unsigned8_t err, co_unsigned8_t spec, void *data)
The type of a CANopen LSS error received indication function, invoked when a 'configure node-ID',...
Definition: lss.h:94
void co_lss_nid_ind_t(co_lss_t *lss, co_unsigned8_t cs, co_unsigned8_t id, void *data)
The type of a CANopen LSS inquire node-ID indication function, invoked when an 'inquire node-ID' requ...
Definition: lss.h:121
void co_lss_scan_ind_t(co_lss_t *lss, co_unsigned8_t cs, const struct co_id *id, void *data)
The type of a CANopen LSS identify remote slave indication function, invoked when a 'Slowscan' or 'Fa...
Definition: lss.h:135
void co_lss_cs_ind_t(co_lss_t *lss, co_unsigned8_t cs, void *data)
The type of a CANopen LSS command received indication function, invoked when a 'switch state selectiv...
Definition: lss.h:80
void co_lss_rate_ind_t(co_lss_t *lss, co_unsigned16_t rate, int delay, void *data)
The type of a CANopen LSS 'activate bit timing' indication function, invoked when a baudrate switch i...
Definition: lss.h:51
#define LELY_CO_LSS_TIMEOUT
The default LSS timeout (in milliseconds).
Definition: lss.h:30
#define CAN_MAX_LEN
The maximum number of bytes in the payload of a CAN format frame.
Definition: msg.h:73
#define CAN_MSG_INIT
The static initializer for can_msg.
Definition: msg.h:114
void can_timer_stop(can_timer_t *timer)
Stops a CAN timer and unregisters it with a network interface.
Definition: net.c:468
int can_net_send(can_net_t *net, const struct can_msg *msg)
Sends a CAN frame from a network interface.
Definition: net.c:308
can_timer_t * can_timer_create(void)
Creates a new CAN timer.
Definition: net.c:382
void can_timer_set_func(can_timer_t *timer, can_timer_func_t *func, void *data)
Sets the callback function invoked when a CAN timer is triggered.
Definition: net.c:428
void can_recv_stop(can_recv_t *recv)
Stops a CAN frame receiver from processing frames and unregisters it with the network interface.
Definition: net.c:613
void can_recv_set_func(can_recv_t *recv, can_recv_func_t *func, void *data)
Sets the callback function used to process CAN frames with a receiver.
Definition: net.c:582
void can_recv_destroy(can_recv_t *recv)
Destroys a CAN frame receiver.
Definition: net.c:562
void can_timer_timeout(can_timer_t *timer, can_net_t *net, int timeout)
Starts a CAN timer and registers it with a network interface.
Definition: net.c:484
void can_recv_start(can_recv_t *recv, can_net_t *net, uint_least32_t id, uint_least8_t flags)
Registers a CAN frame receiver with a network interface and starts processing frames.
Definition: net.c:591
can_recv_t * can_recv_create(void)
Creates a new CAN frame receiver.
Definition: net.c:537
void can_timer_destroy(can_timer_t *timer)
Destroys a CAN timer.
Definition: net.c:407
This header file is part of the CANopen library; it contains the network management (NMT) declaration...
#define CO_NMT_ST_BOOTUP
The NMT state 'boot-up'.
Definition: nmt.h:55
co_unsigned8_t co_nmt_get_id(const co_nmt_t *nmt)
Returns the pending node-ID.
Definition: nmt.c:1392
can_net_t * co_nmt_get_net(const co_nmt_t *nmt)
Returns a pointer to the CAN network of an NMT master/slave service.
Definition: nmt.c:1036
co_dev_t * co_nmt_get_dev(const co_nmt_t *nmt)
Returns a pointer to the CANopen device of an NMT master/slave service.
Definition: nmt.c:1044
co_unsigned8_t co_nmt_get_st(const co_nmt_t *nmt)
Returns the current state of a CANopen NMT service (one of CO_NMT_ST_BOOTUP, CO_NMT_ST_STOP,...
Definition: nmt.c:1415
#define CO_NMT_ST_RESET_NODE
The NMT sub-state 'reset application'.
Definition: nmt.h:64
#define CO_NMT_ST_RESET_COMM
The NMT sub-state 'reset communication'.
Definition: nmt.h:67
int co_nmt_set_id(co_nmt_t *nmt, co_unsigned8_t id)
Sets the pending node-ID.
Definition: nmt.c:1400
int co_nmt_is_master(const co_nmt_t *nmt)
Returns 1 if the specified CANopen NMT service is a master, and 0 if not.
Definition: nmt.c:1423
This is the internal header file of the CANopen library.
This header file is part of the C11 and POSIX compatibility library; it includes <stdlib....
A CAN network interface.
Definition: net.c:37
A CAN frame receiver.
Definition: net.c:99
A CAN timer.
Definition: net.c:63
A CANopen device.
Definition: dev.c:38
A CANopen LSS state.
Definition: lss.c:160
co_lss_state_t *(* on_recv)(co_lss_t *lss, const struct can_msg *msg)
A pointer to the transition function invoked when a CAN frame has been received.
Definition: lss.c:172
co_lss_state_t *(* on_time)(co_lss_t *lss, const struct timespec *tp)
A pointer to the transition function invoked when a timeout occurs.
Definition: lss.c:182
void(* on_leave)(co_lss_t *lss)
A pointer to the function invoked when the current state is left.
Definition: lss.c:185
co_lss_state_t *(* on_enter)(co_lss_t *lss)
A pointer to the function invoked when a new state is entered.
Definition: lss.c:162
A CANopen LSS master/slave service.
Definition: lss.c:43
void * err_data
A pointer to user-specified data for err_ind.
Definition: lss.c:109
co_unsigned8_t spec
The received implementation-specific error code.
Definition: lss.c:85
co_unsigned8_t cs
The expected command specifier.
Definition: lss.c:65
struct co_id id
The LSS address obtained from the LSS Slowscan or Fastscan service.
Definition: lss.c:91
can_timer_t * timer
A pointer to the CAN timer.
Definition: lss.c:62
co_nmt_t * nmt
A pointer to an NMT master/slave service.
Definition: lss.c:45
co_unsigned8_t lsspos
The LSSPos value.
Definition: lss.c:67
co_lss_nid_ind_t * nid_ind
A pointer to the inquire node-ID indication function.
Definition: lss.c:115
co_lss_scan_ind_t * scan_ind
A pointer to the identify remote slave indication function.
Definition: lss.c:119
co_unsigned8_t err
The received error code.
Definition: lss.c:83
void * nid_data
A pointer to user-specified data for nid_ind.
Definition: lss.c:117
can_recv_t * recv
A pointer to the CAN frame receiver.
Definition: lss.c:57
void * cs_data
A pointer to user-specified data for cs_ind.
Definition: lss.c:105
co_lss_lssid_ind_t * lssid_ind
A pointer to the inquire identity indication function.
Definition: lss.c:111
co_lss_err_ind_t * err_ind
A pointer to the error indication function.
Definition: lss.c:107
co_unsigned8_t nid
The received node-ID.
Definition: lss.c:89
void * lssid_data
A pointer to user-specified data for lssid_ind.
Definition: lss.c:113
int master
A flag specifying whether the LSS service is a master or a slave.
Definition: lss.c:54
co_unsigned8_t lsssub
The index of the current LSS number being checked during the Fastscan service.
Definition: lss.c:81
void * rate_data
A pointer to user-specified data for rate_ind.
Definition: lss.c:96
struct co_id mask
The mask used during the Fastscan service.
Definition: lss.c:74
co_dev_t * dev
A pointer to a CANopen device.
Definition: lss.c:49
co_unsigned8_t bitchk
The least-significant bit being checked during the Fastscan service.
Definition: lss.c:76
struct co_id lo
The lower bound of the LSS address used during the Slowscan service.
Definition: lss.c:70
int timeout
The timeout (in milliseconds).
Definition: lss.c:60
void * scan_data
A pointer to user-specified data for scan_ind.
Definition: lss.c:121
void * store_data
A pointer to user-specified data for store_ind.
Definition: lss.c:100
co_unsigned32_t lssid
The received LSS number.
Definition: lss.c:87
co_lss_store_ind_t * store_ind
A pointer to the 'store configuration' indication function.
Definition: lss.c:98
co_lss_cs_ind_t * cs_ind
A pointer to the command indication function.
Definition: lss.c:103
co_lss_state_t * state
A pointer to the current state.
Definition: lss.c:51
co_lss_rate_ind_t * rate_ind
A pointer to the 'activate bit timing' indication function.
Definition: lss.c:94
struct co_id hi
The upper bound of the LSS address used during the Slowscan service.
Definition: lss.c:72
can_net_t * net
A pointer to a CAN network interface.
Definition: lss.c:47
A CANopen NMT master/slave service.
Definition: nmt.c:104
A CANopen object.
Definition: obj.h:32
A CAN or CAN FD format frame.
Definition: msg.h:88
uint_least8_t data[CAN_MSG_MAX_LEN]
The frame payload (in case of a data frame).
Definition: msg.h:103
uint_least32_t id
The identifier (11 or 29 bits, depending on the CAN_FLAG_IDE flag).
Definition: msg.h:90
uint_least8_t len
The number of bytes in data (or the requested number of bytes in case of a remote frame).
Definition: msg.h:101
An identity record.
Definition: dev.h:33
co_unsigned32_t product_code
Product code.
Definition: dev.h:39
co_unsigned32_t revision
Revision number.
Definition: dev.h:41
co_unsigned8_t n
Highest sub-index supported.
Definition: dev.h:35
co_unsigned32_t vendor_id
Vendor-ID.
Definition: dev.h:37
co_unsigned32_t serial_nr
Serial number.
Definition: dev.h:43
A time type with nanosecond resolution.
Definition: time.h:83
This header file is part of the CANopen library; it contains the CANopen value declarations.
#define CO_UNSIGNED16_MIN
The minimum value of a 16-bit unsigned integer.
Definition: val.h:61
#define CO_UNSIGNED16_MAX
The maximum value of a 16-bit unsigned integer.
Definition: val.h:64