Lely core libraries 2.3.4
wtm.c
Go to the documentation of this file.
1
24#include "co.h"
25
26#if !LELY_NO_CO_WTM
27
28#include <lely/can/err.h>
29#include <lely/co/crc.h>
30#include <lely/co/wtm.h>
31#include <lely/util/diag.h>
32#include <lely/util/endian.h>
33#include <lely/util/time.h>
34
35#include <assert.h>
36#if !LELY_NO_STDIO
37#include <inttypes.h>
38#endif
39#include <stdlib.h>
40#include <string.h>
41
43#define CO_WTM_MAX_NIF 127
44
46struct co_wtm_can {
52 uint_least8_t st;
59 uint_least8_t err;
64 uint_least8_t load;
70 uint_least16_t ec;
75 uint_least16_t foc;
80 uint_least16_t coc;
87};
88
156
158static int co_wtm_send_diag_can_res(co_wtm_t *wtm, uint_least8_t nif);
159
161static int co_wtm_send_diag_wtm_res(co_wtm_t *wtm);
162
164static void co_wtm_diag_ac(co_wtm_t *wtm, uint_least32_t ac);
165
167static void default_wtm_diag_ac_ind(
168 co_wtm_t *wtm, uint_least32_t ac, void *data);
169
179static uint_least32_t co_wtm_recv_can(
180 co_wtm_t *wtm, const void *buf, size_t nbytes);
181
182const char *
183co_wtm_ac_str(uint_least32_t ac)
184{
185 switch (ac) {
186 case CO_WTM_AC_ERROR: return "General error";
188 return "Diagnostic protocol timed out limit reached";
189 case CO_WTM_AC_NO_MEM: return "Out of memory";
190 case CO_WTM_AC_HARDWARE: return "Access failed due to a hardware error";
191 case CO_WTM_AC_DATA:
192 return "Data cannot be transferred or stored to the application";
194 return "Data cannot be transferred or stored to the application because of local control";
196 return "Data cannot be transferred or stored to the application because of the present device state";
197 case CO_WTM_AC_NO_DATA: return "No data available";
198 case CO_WTM_AC_NO_IF: return "Requested interface not implemented";
199 case CO_WTM_AC_IF_DOWN: return "Requested interface disabled";
200 case CO_WTM_AC_DIAG: return "Diagnostic data generation not supported";
202 return "Diagnostic data generation for requested CAN interface not supported";
204 return "Diagnostic data generation for requested WTM interface not supported";
205 case CO_WTM_AC_FRAME: return "General generic frame error";
206 case CO_WTM_AC_PREAMBLE: return "Invalid generic frame preamble";
207 case CO_WTM_AC_SEQ: return "Invalid sequence counter in generic frame";
208 case CO_WTM_AC_TYPE: return "Message type not valid or unknown";
209 case CO_WTM_AC_PAYLOAD: return "Payload field in generic frame invalid";
210 case CO_WTM_AC_CRC: return "CRC error (Generic frame)";
211 case CO_WTM_AC_CAN: return "CAN telegram essentials invalid";
212 default: return "Unknown abort code";
213 }
214}
215
216void *
217__co_wtm_alloc(void)
218{
219 void *ptr = malloc(sizeof(struct __co_wtm));
220#if !LELY_NO_ERRNO
221 if (!ptr)
222 set_errc(errno2c(errno));
223#endif
224 return ptr;
225}
226
227void
228__co_wtm_free(void *ptr)
229{
230 free(ptr);
231}
232
233struct __co_wtm *
234__co_wtm_init(struct __co_wtm *wtm)
235{
236 assert(wtm);
237
238 wtm->nif = 1;
239
240 wtm->quality = 0xff;
241
242 for (uint_least8_t nif = 1; nif <= CO_WTM_MAX_NIF; nif++) {
243 struct co_wtm_can *can = &wtm->can[nif - 1];
244
245 can->st = 0xf;
246 can->err = 0xf;
247 can->load = 0xff;
248 can->ec = 0xffff;
249 can->foc = 0xffff;
250 can->coc = 0xffff;
251
252 can->recv_time = (struct timespec){ 0, 0 };
253 can->send_time = (struct timespec){ 0, 0 };
254 can->send_next = (struct timespec){ 0, 0 };
255 }
256
257 wtm->diag_can_con = NULL;
258 wtm->diag_can_con_data = NULL;
259
260 wtm->diag_wtm_con = NULL;
261 wtm->diag_wtm_con_data = NULL;
262
263 wtm->diag_can_ind = NULL;
264 wtm->diag_can_ind_data = NULL;
265
266 wtm->diag_wtm_ind = NULL;
267 wtm->diag_wtm_ind_data = NULL;
268
270 wtm->diag_ac_data = NULL;
271
272 wtm->recv_func = NULL;
273 wtm->recv_data = NULL;
274
275 wtm->send_func = NULL;
276 wtm->send_data = NULL;
277
278 wtm->recv_nbytes = 0;
279 wtm->recv_nseq = 0;
280
281 wtm->send_nbytes = 0;
282 wtm->send_nseq = 0;
283
284 return wtm;
285}
286
287void
288__co_wtm_fini(struct __co_wtm *wtm)
289{
290 (void)wtm;
291}
292
293co_wtm_t *
295{
296 int errc = 0;
297
298 co_wtm_t *wtm = __co_wtm_alloc();
299 if (!wtm) {
300 errc = get_errc();
301 goto error_alloc_wtm;
302 }
303
304 if (!__co_wtm_init(wtm)) {
305 errc = get_errc();
306 goto error_init_wtm;
307 }
308
309 return wtm;
310
311error_init_wtm:
312 __co_wtm_free(wtm);
313error_alloc_wtm:
314 set_errc(errc);
315 return NULL;
316}
317
318void
320{
321 if (wtm) {
322 __co_wtm_fini(wtm);
323 __co_wtm_free(wtm);
324 }
325}
326
327uint_least8_t
329{
330 assert(wtm);
331
332 return wtm->nif;
333}
334
335int
336co_wtm_set_nif(co_wtm_t *wtm, uint_least8_t nif)
337{
338 assert(wtm);
339
340 if (!nif || nif > CO_WTM_MAX_NIF) {
342 return -1;
343 }
344
345 wtm->nif = nif;
346
347 return 0;
348}
349
350int
351co_wtm_set_diag_can(co_wtm_t *wtm, uint_least8_t nif, uint_least8_t st,
352 uint_least8_t err, uint_least8_t load, uint_least16_t ec,
353 uint_least16_t foc, uint_least16_t coc)
354{
355 assert(wtm);
356
357 if (!nif || nif > CO_WTM_MAX_NIF) {
359 return -1;
360 }
361 struct co_wtm_can *can = &wtm->can[nif - 1];
362
363 switch (st) {
364 case CAN_STATE_ACTIVE: st = 0; break;
365 case CAN_STATE_PASSIVE: st = 1; break;
366 case CAN_STATE_BUSOFF: st = 2; break;
367 case 0xf: break;
368 default: set_errnum(ERRNUM_INVAL); return -1;
369 }
370
371 if (err == 0xf) {
372 } else if (err & CAN_ERROR_BIT) {
373 err = 1;
374 } else if (err & CAN_ERROR_STUFF) {
375 err = 2;
376 } else if (err & CAN_ERROR_CRC) {
377 err = 3;
378 } else if (err & CAN_ERROR_FORM) {
379 err = 4;
380 } else if (err & CAN_ERROR_ACK) {
381 err = 5;
382 } else if (err) {
383 err = 0xf;
384 }
385
386 if (load > 100 && load != 0xff) {
388 return -1;
389 }
390
391 can->st = st;
392 can->err = err;
393 can->load = load;
394 can->ec = ec;
395 can->foc = foc;
396 can->coc = coc;
397
398 return 0;
399}
400
401int
402co_wtm_set_diag_wtm(co_wtm_t *wtm, uint_least8_t quality)
403{
404 assert(wtm);
405
406 if (quality > 100 && quality != 0xff) {
408 return -1;
409 }
410
411 wtm->quality = quality;
412
413 return 0;
414}
415
416void
418 const co_wtm_t *wtm, co_wtm_diag_can_con_t **pcon, void **pdata)
419{
420 assert(wtm);
421
422 if (pcon)
423 *pcon = wtm->diag_can_con;
424 if (pdata)
425 *pdata = wtm->diag_can_con_data;
426}
427
428void
430{
431 assert(wtm);
432
433 wtm->diag_can_con = con;
434 wtm->diag_can_con_data = data;
435}
436
437void
439 const co_wtm_t *wtm, co_wtm_diag_wtm_con_t **pcon, void **pdata)
440{
441 assert(wtm);
442
443 if (pcon)
444 *pcon = wtm->diag_wtm_con;
445 if (pdata)
446 *pdata = wtm->diag_wtm_con_data;
447}
448
449void
451{
452 assert(wtm);
453
454 wtm->diag_wtm_con = con;
455 wtm->diag_wtm_con_data = data;
456}
457
458void
460 const co_wtm_t *wtm, co_wtm_diag_can_ind_t **pcon, void **pdata)
461{
462 assert(wtm);
463
464 if (pcon)
465 *pcon = wtm->diag_can_ind;
466 if (pdata)
467 *pdata = wtm->diag_can_ind_data;
468}
469
470void
472{
473 assert(wtm);
474
475 wtm->diag_can_ind = con;
476 wtm->diag_can_ind_data = data;
477}
478
479void
481 const co_wtm_t *wtm, co_wtm_diag_wtm_ind_t **pcon, void **pdata)
482{
483 assert(wtm);
484
485 if (pcon)
486 *pcon = wtm->diag_wtm_ind;
487 if (pdata)
488 *pdata = wtm->diag_wtm_ind_data;
489}
490
491void
493{
494 assert(wtm);
495
496 wtm->diag_wtm_ind = con;
497 wtm->diag_wtm_ind_data = data;
498}
499
500void
502 const co_wtm_t *wtm, co_wtm_diag_ac_ind_t **pind, void **pdata)
503{
504 assert(wtm);
505
506 if (pind)
507 *pind = wtm->diag_ac_ind;
508 if (pdata)
509 *pdata = wtm->diag_ac_data;
510}
511
512void
514{
515 assert(wtm);
516
517 wtm->diag_ac_ind = ind ? ind : &default_wtm_diag_ac_ind;
518 wtm->diag_ac_data = ind ? data : NULL;
519}
520
521void
522co_wtm_recv(co_wtm_t *wtm, const void *buf, size_t nbytes)
523{
524 assert(wtm);
525 assert(wtm->diag_ac_ind);
526 assert(buf);
527
528 for (const uint_least8_t *bp = buf; nbytes;) {
529 uint_least32_t ac = 0;
530 // Search for the preamble (see section 5.2 in CiA 315 version
531 // 1.0.0).
532 size_t size = 1;
533 if (wtm->recv_nbytes < size) {
534 wtm->recv_buf[wtm->recv_nbytes] = *bp;
535 wtm->recv_nbytes++;
536 bp++;
537 nbytes--;
538 }
539 if (wtm->recv_buf[0] != 0x55) {
541 goto error;
542 }
543 // Copy the rest of the header (plus the CRC checksum if there
544 // is no payload).
545 size += 5;
546 if (wtm->recv_nbytes < size) {
547 size_t n = MIN(nbytes, size - wtm->recv_nbytes);
548 memcpy(wtm->recv_buf + wtm->recv_nbytes, bp, n);
549 wtm->recv_nbytes += n;
550 bp += n;
551 nbytes -= n;
552 if (wtm->recv_nbytes < size)
553 continue;
554 }
555 // Copy the payload (plus the CRC checksum).
556 uint_least8_t len = wtm->recv_buf[1];
557 size += len;
558 if (wtm->recv_nbytes < size) {
559 size_t n = MIN(nbytes, size - wtm->recv_nbytes);
560 memcpy(wtm->recv_buf + wtm->recv_nbytes, bp, n);
561 wtm->recv_nbytes += n;
562 bp += n;
563 nbytes -= n;
564 if (wtm->recv_nbytes < size)
565 continue;
566 }
567 // Check the CRC checksum (see section 5.7 in CiA 315 version
568 // 1.0.0).
569 uint_least16_t crc = co_crc(0xffff, wtm->recv_buf, 4 + len);
570 if (crc != ldle_u16(wtm->recv_buf + 4 + len)) {
571 ac = CO_WTM_AC_CRC;
572 goto error;
573 }
574 // Check the sequence counter (see section 5.4 in CiA 315
575 // version 1.0.0).
576 uint_least8_t seq = wtm->recv_buf[2];
577 if (seq != wtm->recv_nseq)
578 // Generate an error, but do not abort processing the
579 // message.
581 wtm->recv_nseq = seq + 1;
582 // Process message payload based on its type (see Table 2 in CiA
583 // 315 version 1.0.0).
584 uint_least8_t type = wtm->recv_buf[3];
585 uint_least8_t nif;
586 switch (type) {
587 // CAN messages forwarding (see section 6 in CiA 315 version
588 // 1.0.0).
589 case 0x00:
590 // Process the CAN frames.
591 if ((ac = co_wtm_recv_can(wtm, wtm->recv_buf + 4, len))
592 != 0)
593 goto error;
594 break;
595 // Keep-alive (see section 7.3 in CiA 315 version 1.0.0).
596 case 0x10:
597 if (len < 1) {
599 goto error;
600 }
601 // Obtain the WTM interface indicator.
602 nif = wtm->recv_buf[4];
603 if (nif <= 0x80) {
605 goto error;
606 }
607 // Ignore keep-alive messages for other WTM interfaces.
608 if (nif != 0x80 + wtm->nif)
609 break;
610 // TODO: handle keep-alive message.
611 break;
612 // Timer-overrun (see section 7.4 in CiA 315 version 1.0.0).
613 case 0x11:
614 if (len < 1) {
616 goto error;
617 }
618 // Obtain the CAN interface indicator.
619 nif = wtm->recv_buf[4];
620 if (!nif || nif > CO_WTM_MAX_NIF) {
622 goto error;
623 }
624 // Add 6553.5 ms to the CAN interface timer.
626 &wtm->can[nif - 1].recv_time, 6553500);
627 break;
628 // Communication quality request.
629 case 0x12:
630 if (len < 1) {
632 goto error;
633 }
634 // Obtain the interface indicator.
635 nif = wtm->recv_buf[4];
636 if (nif <= 0x80) {
637 if (!nif || nif > CO_WTM_MAX_NIF) {
639 wtm, CO_WTM_AC_NO_IF);
640 break;
641 }
642 // Send the communication quality response.
643 co_wtm_send_diag_can_res(wtm, nif);
644 } else {
645 // Only accept communication quality requests
646 // for this WTM interface.
647 if (nif != 0x80 + wtm->nif) {
649 wtm, CO_WTM_AC_NO_IF);
650 break;
651 }
652 // Send the communication quality response.
654 }
655 break;
656 // Communication quality response.
657 case 0x13:
658 if (len < 2) {
660 goto error;
661 }
662 // Obtain the interface indicator.
663 nif = wtm->recv_buf[4];
664 if (!nif || nif == 0x80) {
666 goto error;
667 }
668 if (nif < 0x80) {
669 if (len < 9) {
671 goto error;
672 }
673 if (!wtm->diag_can_con)
674 continue;
675 uint_least8_t st = 0xf;
676 switch ((wtm->recv_buf[5] >> 4) & 0xf) {
677 case 0: st = CAN_STATE_ACTIVE; break;
678 case 1: st = CAN_STATE_PASSIVE; break;
679 case 2: st = CAN_STATE_BUSOFF; break;
680 }
681 uint_least8_t err = 0xf;
682 switch (wtm->recv_buf[5] & 0xf) {
683 case 1: err = CAN_ERROR_BIT; break;
684 case 2: err = CAN_ERROR_STUFF; break;
685 case 3: err = CAN_ERROR_CRC; break;
686 case 4: err = CAN_ERROR_FORM; break;
687 case 5: err = CAN_ERROR_ACK; break;
688 }
689 uint_least8_t load = wtm->recv_buf[6];
690 uint_least16_t ec = ldle_u16(wtm->recv_buf + 7);
691 uint_least16_t foc =
692 ldle_u16(wtm->recv_buf + 9);
693 uint_least16_t coc =
694 ldle_u16(wtm->recv_buf + 11);
695 wtm->diag_can_con(wtm, nif, st, err, load, ec,
696 foc, coc,
697 wtm->diag_can_con_data);
698 } else {
699 if (!wtm->diag_wtm_con)
700 continue;
701 uint_least8_t quality = wtm->recv_buf[5];
702 wtm->diag_wtm_con(wtm, nif - 0x80, quality,
703 wtm->diag_wtm_con_data);
704 }
705 break;
706 // Communication quality reset.
707 case 0x14:
708 if (len < 1) {
710 goto error;
711 }
712 // Obtain the interface indicator.
713 nif = wtm->recv_buf[4];
714 if (nif <= 0x80) {
715 if (!nif || nif > CO_WTM_MAX_NIF) {
717 wtm, CO_WTM_AC_NO_IF);
718 break;
719 }
720 struct co_wtm_can *can = &wtm->can[nif - 1];
721 can->st = 0xf;
722 can->err = 0xf;
723 can->load = 0xff;
724 can->ec = 0xffff;
725 can->foc = 0xffff;
726 can->coc = 0xffff;
727 if (wtm->diag_can_ind)
728 wtm->diag_can_ind(wtm, nif,
729 wtm->diag_can_ind_data);
730 } else {
731 // Only accept communication quality reset
732 // messages for this WTM interface.
733 if (nif != 0x80 + wtm->nif) {
735 wtm, CO_WTM_AC_NO_IF);
736 break;
737 }
738 wtm->quality = 0xff;
739 if (wtm->diag_wtm_ind)
740 wtm->diag_wtm_ind(wtm,
741 wtm->diag_wtm_ind_data);
742 }
743 break;
744 // Diagnostic abort message.
745 case 0x15:
746 if (len < 5) {
748 goto error;
749 }
750 // Obtain the WTM interface indicator.
751 nif = wtm->recv_buf[4];
752 if (nif <= 0x80) {
754 goto error;
755 }
756 // Ignore diagnostic abort messages for other WTM
757 // interfaces.
758 if (nif != 0x80 + wtm->nif)
759 break;
760 ac = ldle_u32(wtm->recv_buf + 5);
761 break;
762 default: ac = CO_WTM_AC_TYPE; goto error;
763 }
764 error:
765 if (ac)
766 co_wtm_diag_ac(wtm, ac);
767 // Empty the buffer for the next message.
768 wtm->recv_nbytes = 0;
769 }
770}
771
772void
774 const co_wtm_t *wtm, co_wtm_recv_func_t **pfunc, void **pdata)
775{
776 assert(wtm);
777
778 if (pfunc)
779 *pfunc = wtm->recv_func;
780 if (pdata)
781 *pdata = wtm->recv_data;
782}
783
784void
786{
787 assert(wtm);
788
789 wtm->recv_func = func;
790 wtm->recv_data = data;
791}
792
793int
794co_wtm_get_time(const co_wtm_t *wtm, uint_least8_t nif, struct timespec *tp)
795{
796 assert(wtm);
797
798 if (!nif || nif > CO_WTM_MAX_NIF) {
800 return -1;
801 }
802
803 if (tp)
804 *tp = wtm->can[nif - 1].send_next;
805
806 return 0;
807}
808
809int
810co_wtm_set_time(co_wtm_t *wtm, uint_least8_t nif, const struct timespec *tp)
811{
812 assert(wtm);
813 assert(tp);
814
815 if (!nif || nif > CO_WTM_MAX_NIF) {
817 return -1;
818 }
819 struct co_wtm_can *can = &wtm->can[nif - 1];
820
821 // Since the time stamp is relative, store the absolute time on the
822 // first invocation.
823 if (!can->send_time.tv_sec && !can->send_time.tv_nsec)
824 can->send_time = *tp;
825 // Update the time stamp for the next CAN frame.
826 can->send_next = *tp;
827
828 // If the difference between the current (reference) and next time is
829 // larger than 6553.5 ms, send a timer-overrun message.
830 while (timespec_diff_usec(&can->send_next, &can->send_time) > 6553500) {
831 if (co_wtm_flush(wtm) == -1)
832 return -1;
833 wtm->send_buf[3] = 0x11;
834 wtm->send_buf[4] = nif;
835 wtm->send_nbytes = 5;
836 // Update the current (reference) time.
837 timespec_add_usec(&can->send_time, 6553500);
838 }
839
840 return 0;
841}
842
843int
844co_wtm_send(co_wtm_t *wtm, uint_least8_t nif, const struct can_msg *msg)
845{
846 assert(wtm);
847 assert(msg);
848
849 if (!nif || nif > CO_WTM_MAX_NIF) {
851 return -1;
852 }
853 struct co_wtm_can *can = &wtm->can[nif - 1];
854
855#if !LELY_NO_CANFD
856 // CAN FD frames are not supported.
857 if (msg->flags & CAN_FLAG_EDL) {
859 return -1;
860 }
861#endif
862
863 if (msg->len > CAN_MAX_LEN) {
865 return -1;
866 }
867
868 // Compute the length of the CAN frame.
869 size_t len = 1 + (nif != 1) + ((msg->flags & CAN_FLAG_IDE) ? 4 : 2)
870 + msg->len + 2;
871 // Flush the buffer if necessary.
872 if ((wtm->send_nbytes > 3 && wtm->send_buf[3] != 0x00)
873 || wtm->send_nbytes + len + 2 > CO_WTM_MAX_LEN) {
874 if (co_wtm_flush(wtm) == -1)
875 return -1;
876 }
877 wtm->send_buf[3] = 0x00;
878 wtm->send_nbytes = MAX(wtm->send_nbytes, 4);
879 uint_least8_t *bp = wtm->send_buf + wtm->send_nbytes;
880 size_t nbytes = wtm->send_nbytes;
881
882 // Write the data length code.
883 uint_least8_t dlc = msg->len | 0x40;
884 if (msg->flags & CAN_FLAG_RTR)
885 dlc |= 0x10;
886 if (msg->flags & CAN_FLAG_IDE)
887 dlc |= 0x20;
888 if (nif != 1)
889 dlc |= 0x80;
890 *bp = dlc;
891 bp++;
892 nbytes++;
893 // Write the interface indicator.
894 if (nif != 1) {
895 *bp = nif;
896 bp++;
897 nbytes++;
898 }
899 // Write the CAN identifier.
900 if (msg->flags & CAN_FLAG_IDE) {
901 stle_u32(bp, msg->id & CAN_MASK_EID);
902 bp += 4;
903 nbytes += 4;
904 } else {
905 stle_u16(bp, msg->id & CAN_MASK_BID);
906 bp += 2;
907 nbytes += 2;
908 }
909 // Copy the frame payload.
910 memcpy(bp, msg->data, msg->len);
911 bp += msg->len;
912 nbytes += msg->len;
913 // Write the time stamp.
914 int_least64_t usec =
915 timespec_diff_usec(&can->send_next, &can->send_time);
916 stle_u16(bp, (uint_least16_t)(usec / 100));
917 nbytes += 2;
918
919 assert(nbytes + 2 <= CO_WTM_MAX_LEN);
920 wtm->send_nbytes = nbytes;
921
922 return 0;
923}
924
925int
927{
928 assert(wtm);
929 assert(wtm->nif && wtm->nif <= CO_WTM_MAX_NIF);
930
931 if (co_wtm_flush(wtm) == -1)
932 return -1;
933 wtm->send_buf[3] = 0x10;
934 wtm->send_buf[4] = 0x80 + wtm->nif;
935 wtm->send_nbytes = 5;
936 return co_wtm_flush(wtm);
937}
938
939int
940co_wtm_send_diag_can_req(co_wtm_t *wtm, uint_least8_t nif)
941{
942 assert(wtm);
943
944 if (!nif || nif > CO_WTM_MAX_NIF) {
946 return -1;
947 }
948
949 if (co_wtm_flush(wtm) == -1)
950 return -1;
951 wtm->send_buf[3] = 0x12;
952 wtm->send_buf[4] = nif;
953 wtm->send_nbytes = 5;
954 return co_wtm_flush(wtm);
955}
956
957int
958co_wtm_send_diag_wtm_req(co_wtm_t *wtm, uint_least8_t nif)
959{
960 assert(wtm);
961
962 if (!nif || nif > CO_WTM_MAX_NIF) {
964 return -1;
965 }
966
967 if (co_wtm_flush(wtm) == -1)
968 return -1;
969 wtm->send_buf[3] = 0x12;
970 wtm->send_buf[4] = 0x80 + nif;
971 wtm->send_nbytes = 5;
972 return co_wtm_flush(wtm);
973}
974
975int
976co_wtm_send_diag_can_rst(co_wtm_t *wtm, uint_least8_t nif)
977{
978 assert(wtm);
979
980 if (!nif || nif > CO_WTM_MAX_NIF) {
982 return -1;
983 }
984
985 if (co_wtm_flush(wtm) == -1)
986 return -1;
987 wtm->send_buf[3] = 0x14;
988 wtm->send_buf[4] = nif;
989 wtm->send_nbytes = 5;
990 return co_wtm_flush(wtm);
991}
992
993int
994co_wtm_send_diag_wtm_rst(co_wtm_t *wtm, uint_least8_t nif)
995{
996 assert(wtm);
997
998 if (!nif || nif > CO_WTM_MAX_NIF) {
1000 return -1;
1001 }
1002
1003 if (co_wtm_flush(wtm) == -1)
1004 return -1;
1005 wtm->send_buf[3] = 0x14;
1006 wtm->send_buf[4] = 0x80 + nif;
1007 wtm->send_nbytes = 5;
1008 return co_wtm_flush(wtm);
1009}
1010
1011int
1012co_wtm_send_diag_ac(co_wtm_t *wtm, uint_least32_t ac)
1013{
1014 assert(wtm);
1015 assert(wtm->nif && wtm->nif <= CO_WTM_MAX_NIF);
1016
1017 if (co_wtm_flush(wtm) == -1)
1018 return -1;
1019 wtm->send_buf[3] = 0x15;
1020 wtm->send_buf[4] = 0x80 + wtm->nif;
1021 stle_u32(wtm->send_buf + 5, ac);
1022 wtm->send_nbytes = 9;
1023 return co_wtm_flush(wtm);
1024}
1025
1026int
1028{
1029 assert(wtm);
1030
1031 // Do not flush if there is no header.
1032 if (wtm->send_nbytes < 4)
1033 return 0;
1034 uint_least8_t len = (uint_least8_t)(wtm->send_nbytes - 4);
1035 wtm->send_nbytes = 0;
1036
1037 // Fill in the header fields.
1038 wtm->send_buf[0] = 0x55;
1039 wtm->send_buf[1] = len;
1040 wtm->send_buf[2] = wtm->send_nseq++;
1041 // Compute the CRC checksum.
1042 uint_least16_t crc = co_crc(0xffff, wtm->send_buf, 4 + len);
1043 stle_u16(wtm->send_buf + 4 + len, crc);
1044
1045 // Invoke the user-specified callback function to send the generic
1046 // frame.
1047 if (!wtm->send_func) {
1049 return -1;
1050 }
1051 return wtm->send_func(wtm, wtm->send_buf, 4 + len + 2, wtm->send_data)
1052 ? -1
1053 : 0;
1054}
1055
1056void
1058 const co_wtm_t *wtm, co_wtm_send_func_t **pfunc, void **pdata)
1059{
1060 assert(wtm);
1061
1062 if (pfunc)
1063 *pfunc = wtm->send_func;
1064 if (pdata)
1065 *pdata = wtm->send_data;
1066}
1067
1068void
1070{
1071 assert(wtm);
1072
1073 wtm->send_func = func;
1074 wtm->send_data = data;
1075}
1076
1077static int
1078co_wtm_send_diag_can_res(co_wtm_t *wtm, uint_least8_t nif)
1079{
1080 assert(wtm);
1081 assert(nif && nif <= CO_WTM_MAX_NIF);
1082 struct co_wtm_can *can = &wtm->can[nif - 1];
1083
1084 if (co_wtm_flush(wtm) == -1)
1085 return -1;
1086 wtm->send_buf[3] = 0x13;
1087 wtm->send_buf[4] = nif;
1088 wtm->send_buf[5] = ((can->st & 0xf) << 4) | (can->err & 0xf);
1089 wtm->send_buf[6] = can->load;
1090 stle_u16(wtm->send_buf + 7, can->ec);
1091 stle_u16(wtm->send_buf + 9, can->foc);
1092 stle_u16(wtm->send_buf + 11, can->coc);
1093 wtm->send_nbytes = 13;
1094 return co_wtm_flush(wtm);
1095}
1096
1097static int
1099{
1100 assert(wtm);
1101
1102 if (co_wtm_flush(wtm) == -1)
1103 return -1;
1104 wtm->send_buf[3] = 0x13;
1105 wtm->send_buf[4] = 0x80 + wtm->nif;
1106 wtm->send_buf[5] = wtm->quality;
1107 wtm->send_nbytes = 6;
1108 return co_wtm_flush(wtm);
1109}
1110
1111static void
1112co_wtm_diag_ac(co_wtm_t *wtm, uint_least32_t ac)
1113{
1114 assert(wtm);
1115 assert(wtm->diag_ac_ind);
1116
1117 wtm->diag_ac_ind(wtm, ac, wtm->diag_ac_data);
1118}
1119
1120static void
1121default_wtm_diag_ac_ind(co_wtm_t *wtm, uint_least32_t ac, void *data)
1122{
1123 (void)wtm;
1124 (void)data;
1125
1126#if LELY_NO_STDIO
1127 (void)ac;
1128#else
1129 diag(DIAG_WARNING, 0, "received WTM abort code %08" PRIX32 ": %s", ac,
1130 co_wtm_ac_str(ac));
1131#endif
1132}
1133
1134static uint_least32_t
1135co_wtm_recv_can(co_wtm_t *wtm, const void *buf, size_t nbytes)
1136{
1137 assert(wtm);
1138 assert(buf);
1139 assert(nbytes);
1140
1141 uint_least32_t ac = 0;
1142 for (const uint_least8_t *bp = buf; nbytes;) {
1143 struct can_msg msg = CAN_MSG_INIT;
1144 // Obtain the data length code.
1145 uint_least8_t dlc = *bp;
1146 bp++;
1147 nbytes--;
1148 msg.len = dlc & 0x0f;
1149 if (msg.len > CAN_MAX_LEN) {
1150 ac = CO_WTM_AC_CAN;
1151 goto error;
1152 }
1153 if (dlc & 0x10)
1154 msg.flags |= CAN_FLAG_RTR;
1155 // Obtain the CAN interface indicator.
1156 uint_least8_t nif = 1;
1157 if (dlc & 0x80) {
1158 if (nbytes < 1) {
1159 ac = CO_WTM_AC_CAN;
1160 goto error;
1161 }
1162 nif = *bp;
1163 bp++;
1164 nbytes--;
1165 }
1166 // Obtain the CAN identifier.
1167 if (dlc & 0x20) {
1168 if (nbytes < 4) {
1169 ac = CO_WTM_AC_CAN;
1170 goto error;
1171 }
1172 msg.id = ldle_u32(bp) & CAN_MASK_EID;
1173 bp += 4;
1174 nbytes -= 4;
1175 msg.flags |= CAN_FLAG_IDE;
1176 } else {
1177 if (nbytes < 2) {
1178 ac = CO_WTM_AC_CAN;
1179 goto error;
1180 }
1181 msg.id = ldle_u16(bp) & CAN_MASK_BID;
1182 bp += 2;
1183 nbytes -= 2;
1184 }
1185 // Obtain the frame payload.
1186 if (nbytes < msg.len) {
1187 ac = CO_WTM_AC_CAN;
1188 goto error;
1189 }
1190 memcpy(msg.data, bp, msg.len);
1191 bp += msg.len;
1192 nbytes -= msg.len;
1193 // Obtain the time stamp.
1194 uint_least16_t ts = 0;
1195 if (dlc & 0x40) {
1196 if (nbytes < 2) {
1197 ac = CO_WTM_AC_CAN;
1198 goto error;
1199 }
1200 ts = ldle_u16(bp);
1201 bp += 2;
1202 nbytes -= 2;
1203 }
1204 // Ignore CAN frames with an invalid interface indicator.
1205 if (!nif || nif > CO_WTM_MAX_NIF)
1206 continue;
1207 // Update the CAN interface timer.
1208 struct timespec *tp = NULL;
1209 if (dlc & 0x40) {
1210 tp = &wtm->can[nif - 1].recv_time;
1211 timespec_add_usec(tp, ts * 100);
1212 }
1213 // Invoke the user-specified callback function.
1214 if (wtm->recv_func) {
1215 int errc = get_errc();
1216 // clang-format off
1217 if (wtm->recv_func(wtm, nif, tp, &msg,
1218 wtm->recv_data)) {
1219 // clang-format on
1220 // Convert the error number to a WTM abort code.
1221 if (!ac) {
1222 ac = get_errnum() == ERRNUM_NOMEM
1225 }
1226 set_errc(errc);
1227 }
1228 }
1229 }
1230
1231error:
1232 return ac;
1233}
1234
1235#endif // !LELY_NO_CO_WTM
This header file is part of the CAN library; it contains CAN bus error definitions.
@ CAN_STATE_BUSOFF
The bus off state (TX/RX error count >= 256).
Definition err.h:34
@ CAN_STATE_PASSIVE
The error passive state (TX/RX error count < 256).
Definition err.h:32
@ CAN_STATE_ACTIVE
The error active state (TX/RX error count < 128).
Definition err.h:30
@ CAN_FLAG_IDE
The Identifier Extension (IDE) flag.
Definition msg.h:43
@ CAN_FLAG_RTR
The Remote Transmission Request (RTR) flag (unavailable in CAN FD format frames).
Definition msg.h:48
#define CAN_MASK_EID
The mask used to extract the 29-bit Extended Identifier from a CAN frame.
Definition msg.h:34
#define CAN_MAX_LEN
The maximum number of bytes in the payload of a CAN format frame.
Definition msg.h:72
#define CAN_MASK_BID
The mask used to extract the 11-bit Base Identifier from a CAN frame.
Definition msg.h:31
#define CAN_MSG_INIT
The static initializer for can_msg.
Definition msg.h:113
This header file is part of the CANopen library; it contains the Cyclic Redundancy Check (CRC) declar...
uint_least16_t co_crc(uint_least16_t crc, const uint_least8_t *bp, size_t n)
Computes a CRC-16 checksum.
Definition crc.c:28
This header file is part of the utilities library; it contains the diagnostic declarations.
@ DIAG_WARNING
A warning.
Definition diag.h:55
void diag(enum diag_severity severity, int errc, const char *format,...)
Emits a diagnostic message.
Definition diag.c:171
This header file is part of the utilities library; it contains the byte order (endianness) function d...
uint_least32_t ldle_u32(const uint_least8_t src[4])
Loads a 32-bit unsigned integer in little-endian byte order.
Definition endian.h:596
uint_least16_t ldle_u16(const uint_least8_t src[2])
Loads a 16-bit unsigned integer in little-endian byte order.
Definition endian.h:516
void stle_u16(uint_least8_t dst[2], uint_least16_t x)
Stores a 16-bit unsigned integer in little-endian byte order.
Definition endian.h:504
void stle_u32(uint_least8_t dst[4], uint_least32_t x)
Stores a 32-bit unsigned integer in little-endian byte order.
Definition endian.h:582
@ ERRNUM_NOSYS
Function not supported.
Definition errnum.h:184
@ ERRNUM_NOMEM
Not enough space.
Definition errnum.h:172
@ ERRNUM_INVAL
Invalid argument.
Definition errnum.h:132
int get_errc(void)
Returns the last (thread-specific) native error code set by a system call or library function.
Definition errnum.c:932
void set_errc(int errc)
Sets the current (thread-specific) native error code to errc.
Definition errnum.c:944
int errno2c(int errnum)
Transforms a standard C error number to a native error code.
Definition errnum.c:46
errnum_t get_errnum(void)
Returns the last (thread-specific) platform-independent error number set by a system call or library ...
Definition errnum.h:418
void set_errnum(errnum_t errnum)
Sets the current (thread-specific) platform-independent error number to errnum.
Definition errnum.h:424
#define MIN(a, b)
Returns the minimum of a and b.
Definition util.h:57
#define MAX(a, b)
Returns the maximum of a and b.
Definition util.h:65
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....
This header file is part of the C11 and POSIX compatibility library; it includes <string....
A CANopen Wireless Transmission Media (WTM) interface.
Definition wtm.c:90
co_wtm_diag_can_ind_t * diag_can_ind
A pointer to the indication function invoked when a CAN communication quality reset message is receiv...
Definition wtm.c:118
uint_least8_t send_buf[CO_WTM_MAX_LEN]
The buffer used to send byte streams.
Definition wtm.c:150
size_t send_nbytes
The number of bytes in send_buf.
Definition wtm.c:152
void * diag_wtm_con_data
A pointer to the user-specified data for diag_wtm_con.
Definition wtm.c:113
co_wtm_diag_ac_ind_t * diag_ac_ind
A pointer to the callback function invoked when an abort code is generated or received.
Definition wtm.c:132
co_wtm_diag_can_con_t * diag_can_con
A pointer to the confirmation function invoked when a CAN communication quality response is received.
Definition wtm.c:104
struct co_wtm_can can[CO_WTM_MAX_NIF]
The CAN interfaces.
Definition wtm.c:99
void * diag_ac_data
A pointer to the user-specified data for diag_ac_ind.
Definition wtm.c:134
uint_least8_t quality
The link quality percentage (in the range [0..100], or 0xff if the information is not available).
Definition wtm.c:97
void * recv_data
A pointer to the user-specified data for recv_func.
Definition wtm.c:138
size_t recv_nbytes
The number of bytes in recv_buf.
Definition wtm.c:146
void * diag_can_ind_data
A pointer to the user-specified data for diag_can_ind.
Definition wtm.c:120
co_wtm_recv_func_t * recv_func
A pointer to the callback function invoked by co_wtm_recv().
Definition wtm.c:136
co_wtm_diag_wtm_con_t * diag_wtm_con
A pointer to the confirmation function invoked when a WTM communication quality response is received.
Definition wtm.c:111
void * send_data
A pointer to the user-specified data for send_func.
Definition wtm.c:142
co_wtm_diag_wtm_ind_t * diag_wtm_ind
A pointer to the indication function invoked when a WTM communication quality reset message is receiv...
Definition wtm.c:125
co_wtm_send_func_t * send_func
A pointer to the callback function invoked by co_wtm_send().
Definition wtm.c:140
void * diag_wtm_ind_data
A pointer to the user-specified data for diag_wtm_ind.
Definition wtm.c:127
uint_least8_t recv_buf[CO_WTM_MAX_LEN]
The buffer used to receive byte streams.
Definition wtm.c:144
void * diag_can_con_data
A pointer to the user-specified data for diag_can_con.
Definition wtm.c:106
uint_least8_t send_nseq
The sequence number for sent generic frames.
Definition wtm.c:154
uint_least8_t nif
The WTM interface indicator.
Definition wtm.c:92
uint_least8_t recv_nseq
The sequence number for received generic frames.
Definition wtm.c:148
A CAN or CAN FD format frame.
Definition msg.h:87
uint_least8_t data[CAN_MSG_MAX_LEN]
The frame payload (in case of a data frame).
Definition msg.h:102
uint_least32_t id
The identifier (11 or 29 bits, depending on the CAN_FLAG_IDE flag).
Definition msg.h:89
uint_least8_t flags
The flags (any combination of CAN_FLAG_IDE, CAN_FLAG_RTR, CAN_FLAG_FDF, CAN_FLAG_BRS and CAN_FLAG_ESI...
Definition msg.h:94
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:100
A CAN device.
Definition can.c:60
A CANopen WTM CAN interface.
Definition wtm.c:46
struct timespec send_time
The current time of the CAN frame sender.
Definition wtm.c:84
uint_least8_t err
The last detected error (0 if no error was detected, one of CAN_ERROR_BIT, CAN_ERROR_STUFF,...
Definition wtm.c:59
struct timespec recv_time
The current time of the CAN frame receiver.
Definition wtm.c:82
uint_least8_t st
The current CAN controller status (one of CAN_STATE_ACTIVE, CAN_STATE_PASSIVE or CAN_STATE_BUSOFF,...
Definition wtm.c:52
struct timespec send_next
The time at which the next frame is sent.
Definition wtm.c:86
uint_least16_t foc
The FIFO overrun counter (in the range [0..0xfffe], or 0xffff if the information is not available).
Definition wtm.c:75
uint_least8_t load
The current busload percentage (in the range [0..100], or 0xff if the information is not available).
Definition wtm.c:64
uint_least16_t coc
The CAN controller overrun counter (in the range [0..0xfffe], or 0xffff if the information is not ava...
Definition wtm.c:80
uint_least16_t ec
The number of detected errors that led to the increase of one of the CAN controller internal error co...
Definition wtm.c:70
A time type with nanosecond resolution.
Definition time.h:88
This header file is part of the utilities library; it contains the time function declarations.
void timespec_add_usec(struct timespec *tp, uint_least64_t usec)
Adds usec microseconds to the time at tp.
Definition time.h:149
int_least64_t timespec_diff_usec(const struct timespec *t1, const struct timespec *t2)
Returns the time difference (in microseconds) between *t1 and *t2.
Definition time.h:231
void co_wtm_get_diag_ac_ind(const co_wtm_t *wtm, co_wtm_diag_ac_ind_t **pind, void **pdata)
Retrieves the indication function invoked when an abort code is generated or received by a CANopen WT...
Definition wtm.c:501
int co_wtm_set_diag_wtm(co_wtm_t *wtm, uint_least8_t quality)
Sets the diagnostic parameters of a WTM interface.
Definition wtm.c:402
int co_wtm_send_diag_wtm_rst(co_wtm_t *wtm, uint_least8_t nif)
Sends a WTM communication quality reset message.
Definition wtm.c:994
void co_wtm_get_diag_can_ind(const co_wtm_t *wtm, co_wtm_diag_can_ind_t **pcon, void **pdata)
Retrieves the indication function invoked when a CAN communication quality reset message is received ...
Definition wtm.c:459
void co_wtm_set_diag_wtm_ind(co_wtm_t *wtm, co_wtm_diag_wtm_ind_t *con, void *data)
Sets the indication function invoked when a WTM communication quality reset message is received by a ...
Definition wtm.c:492
int co_wtm_get_time(const co_wtm_t *wtm, uint_least8_t nif, struct timespec *tp)
Retrieves the current time of a CANopen WTM interface.
Definition wtm.c:794
void co_wtm_destroy(co_wtm_t *wtm)
Destroys a CANopen Wireless Transmission Media (WTM) interface.
Definition wtm.c:319
static uint_least32_t co_wtm_recv_can(co_wtm_t *wtm, const void *buf, size_t nbytes)
Processes a generic frame containing CAN messages.
Definition wtm.c:1135
static void default_wtm_diag_ac_ind(co_wtm_t *wtm, uint_least32_t ac, void *data)
The default diagnostic indication function.
Definition wtm.c:1121
int co_wtm_send_alive(co_wtm_t *wtm)
Sends a keep-alive message from a CANopen WTM interface.
Definition wtm.c:926
void co_wtm_get_diag_wtm_con(const co_wtm_t *wtm, co_wtm_diag_wtm_con_t **pcon, void **pdata)
Retrieves the confirmation function invoked when a WTM communication quality response is received by ...
Definition wtm.c:438
void co_wtm_get_diag_wtm_ind(const co_wtm_t *wtm, co_wtm_diag_wtm_ind_t **pcon, void **pdata)
Retrieves the indication function invoked when a WTM communication quality reset message is received ...
Definition wtm.c:480
int co_wtm_send_diag_ac(co_wtm_t *wtm, uint_least32_t ac)
Sends a diagnostic abort message from a CANopen WTM interface.
Definition wtm.c:1012
void co_wtm_set_diag_can_ind(co_wtm_t *wtm, co_wtm_diag_can_ind_t *con, void *data)
Sets the indication function invoked when a CAN communication quality reset message is received by a ...
Definition wtm.c:471
co_wtm_t * co_wtm_create(void)
Creates a new CANopen Wireless Transmission Media (WTM) interface.
Definition wtm.c:294
int co_wtm_send_diag_can_req(co_wtm_t *wtm, uint_least8_t nif)
Sends a CAN communication quality request.
Definition wtm.c:940
void co_wtm_set_diag_ac_ind(co_wtm_t *wtm, co_wtm_diag_ac_ind_t *ind, void *data)
Sets the indication function invoked when an abort code is generated or received by a CANopen WTM int...
Definition wtm.c:513
void co_wtm_set_recv_func(co_wtm_t *wtm, co_wtm_recv_func_t *func, void *data)
Sets the callback function invoked when a CAN frame is received by a CANopen WTM interface.
Definition wtm.c:785
static int co_wtm_send_diag_wtm_res(co_wtm_t *wtm)
Sends a communication quality response for a WTM interface.
Definition wtm.c:1098
static int co_wtm_send_diag_can_res(co_wtm_t *wtm, uint_least8_t nif)
Sends a communication quality response for a CAN interface.
Definition wtm.c:1078
void co_wtm_set_send_func(co_wtm_t *wtm, co_wtm_send_func_t *func, void *data)
Sets the callback function used to send byte streams from a CANopen WTM interface.
Definition wtm.c:1069
void co_wtm_recv(co_wtm_t *wtm, const void *buf, size_t nbytes)
Receives and processes a byte stream with a CANopen WTM interface.
Definition wtm.c:522
#define CO_WTM_MAX_NIF
The maximum value of a CAN/WTM interface indicator.
Definition wtm.c:43
void co_wtm_get_diag_can_con(const co_wtm_t *wtm, co_wtm_diag_can_con_t **pcon, void **pdata)
Retrieves the confirmation function invoked when a CAN communication quality response is received by ...
Definition wtm.c:417
void co_wtm_get_recv_func(const co_wtm_t *wtm, co_wtm_recv_func_t **pfunc, void **pdata)
Retrieves the callback function invoked when a CAN frame is received by a CANopen WTM interface.
Definition wtm.c:773
static void co_wtm_diag_ac(co_wtm_t *wtm, uint_least32_t ac)
Invokes the diagnostic indication function.
Definition wtm.c:1112
int co_wtm_send(co_wtm_t *wtm, uint_least8_t nif, const struct can_msg *msg)
Sends a CAN frame from a CANopen WTM interface.
Definition wtm.c:844
int co_wtm_send_diag_wtm_req(co_wtm_t *wtm, uint_least8_t nif)
Sends a WTM communication quality request.
Definition wtm.c:958
int co_wtm_send_diag_can_rst(co_wtm_t *wtm, uint_least8_t nif)
Sends a CAN communication quality reset message.
Definition wtm.c:976
int co_wtm_flush(co_wtm_t *wtm)
Flushes the current send buffer of a CANopen WTM interface.
Definition wtm.c:1027
void co_wtm_set_diag_can_con(co_wtm_t *wtm, co_wtm_diag_can_con_t *con, void *data)
Sets the confirmation function invoked when a CAN communication quality response is received by a CAN...
Definition wtm.c:429
void co_wtm_get_send_func(const co_wtm_t *wtm, co_wtm_send_func_t **pfunc, void **pdata)
Retrieves the callback function used to send byte streams from a CANopen WTM interface.
Definition wtm.c:1057
int co_wtm_set_diag_can(co_wtm_t *wtm, uint_least8_t nif, uint_least8_t st, uint_least8_t err, uint_least8_t load, uint_least16_t ec, uint_least16_t foc, uint_least16_t coc)
Sets the diagnostic parameters of a CAN interface.
Definition wtm.c:351
uint_least8_t co_wtm_get_nif(const co_wtm_t *wtm)
Returns the interface indicator of a CANopen WTM interface.
Definition wtm.c:328
int co_wtm_set_nif(co_wtm_t *wtm, uint_least8_t nif)
Sets the interface indicator of a CANopen WTM interface.
Definition wtm.c:336
int co_wtm_set_time(co_wtm_t *wtm, uint_least8_t nif, const struct timespec *tp)
Sets the current time of a CANopen WTM interface.
Definition wtm.c:810
void co_wtm_set_diag_wtm_con(co_wtm_t *wtm, co_wtm_diag_wtm_con_t *con, void *data)
Sets the confirmation function invoked when a WTM communication quality response is received by a CAN...
Definition wtm.c:450
const char * co_wtm_ac_str(uint_least32_t ac)
Returns a string describing a CANopen WTM abort code.
Definition wtm.c:183
This header file is part of the CANopen library; it contains the Wireless Transmission Media (WTM) de...
#define CO_WTM_AC_DATA_CTL
CANopen WTM abort code: Data cannot be transferred or stored to the application because of local cont...
Definition wtm.h:57
void co_wtm_diag_can_con_t(co_wtm_t *wtm, uint_least8_t nif, uint_least8_t st, uint_least8_t err, uint_least8_t load, uint_least16_t ec, uint_least16_t foc, uint_least16_t coc, void *data)
The type of a CANopen WTM diagnostic confirmation function, invoked when a CAN communication quality ...
Definition wtm.h:144
#define CO_WTM_AC_DATA
CANopen WTM abort code: Data cannot be transferred or stored to the application.
Definition wtm.h:51
void co_wtm_diag_can_ind_t(co_wtm_t *wtm, uint_least8_t nif, void *data)
The type of a CANopen WTM diagnostic indication function, invoked when a CAN communication quality re...
Definition wtm.h:170
void co_wtm_diag_wtm_ind_t(co_wtm_t *wtm, void *data)
The type of a CANopen WTM diagnostic indication function, invoked when a WTM communication quality re...
Definition wtm.h:180
#define CO_WTM_AC_TYPE
CANopen WTM abort code: Message type not valid or unknown.
Definition wtm.h:99
#define CO_WTM_AC_DATA_DEV
CANopen WTM abort code: Data cannot be transferred or stored to the application because of the presen...
Definition wtm.h:63
#define CO_WTM_AC_DIAG_CAN
CANopen WTM abort code: Diagnostic data generation for requested CAN interface not supported.
Definition wtm.h:81
#define CO_WTM_AC_DIAG
CANopen WTM abort code: Diagnostic data generation not supported.
Definition wtm.h:75
#define CO_WTM_AC_DIAG_WTM
CANopen WTM abort code: Diagnostic data generation for requested WTM interface not supported.
Definition wtm.h:87
int co_wtm_send_func_t(co_wtm_t *wtm, const void *buf, size_t nbytes, void *data)
The type of a CANopen WTM send callback function, invoked when a byte stream needs to be sent.
Definition wtm.h:222
#define CO_WTM_AC_HARDWARE
CANopen WTM abort code: Access failed due to a hardware error.
Definition wtm.h:45
#define CO_WTM_AC_NO_DATA
CANopen WTM abort code: No data available.
Definition wtm.h:66
#define CO_WTM_AC_IF_DOWN
CANopen WTM abort code: Requested interface disabled.
Definition wtm.h:72
#define CO_WTM_AC_NO_IF
CANopen WTM abort code: Requested interface not implemented.
Definition wtm.h:69
#define CO_WTM_AC_ERROR
CANopen WTM abort code: General error.
Definition wtm.h:36
#define CO_WTM_AC_PREAMBLE
CANopen WTM abort code: Invalid generic frame preamble.
Definition wtm.h:93
#define CO_WTM_AC_SEQ
CANopen WTM abort code: Invalid sequence counter in generic frame.
Definition wtm.h:96
#define CO_WTM_AC_NO_MEM
CANopen WTM abort code: Out of memory.
Definition wtm.h:42
void co_wtm_diag_ac_ind_t(co_wtm_t *wtm, uint_least32_t ac, void *data)
The type of a CANopen WTM diagnostic indication function, invoked when an abort code is generated or ...
Definition wtm.h:190
#define CO_WTM_AC_CRC
CANopen WTM abort code: CRC error (Generic frame).
Definition wtm.h:105
#define CO_WTM_AC_CAN
CANopen WTM abort code: CAN telegram essentials invalid.
Definition wtm.h:108
int co_wtm_recv_func_t(co_wtm_t *wtm, uint_least8_t nif, const struct timespec *tp, const struct can_msg *msg, void *data)
The type of a CANopen WTM receive callback function, invoked when a CAN frame is received.
Definition wtm.h:206
void co_wtm_diag_wtm_con_t(co_wtm_t *wtm, uint_least8_t nif, uint_least8_t quality, void *data)
The type of a CANopen WTM diagnostic confirmation function, invoked when a WTM communication quality ...
Definition wtm.h:159
#define CO_WTM_AC_TIMEOUT
CANopen WTM abort code: Diagnostic protocol timed out limit reached.
Definition wtm.h:39
#define CO_WTM_AC_FRAME
CANopen WTM abort code: General generic frame error.
Definition wtm.h:90
#define CO_WTM_AC_PAYLOAD
CANopen WTM abort code: Payload field in generic frame invalid.
Definition wtm.h:102
#define CO_WTM_MAX_LEN
The maximum size of a CANopen WTM generic frame (4 (header) + 255 (payload) + 2 (CRC checksum) = 261)...
Definition wtm.h:33