LCOV - code coverage report
Current view: top level - AP_HAL_SITL - CAN_Multicast.cpp (source / functions) Hit Total Coverage
Test: lcov.info Lines: 25 28 89.3 %
Date: 2026-09-09 11:02:08 Functions: 3 3 100.0 %

          Line data    Source code
       1             : /*
       2             :   multicast UDP transport for SITL CAN
       3             :  */
       4             : #include "CAN_Multicast.h"
       5             : #include "SITL_Multicast.h"
       6             : 
       7             : #if HAL_NUM_CAN_IFACES
       8             : 
       9             : #include <net/if.h>
      10             : #include <unistd.h>
      11             : #include <sys/ioctl.h>
      12             : #include <errno.h>
      13             : #include <stdlib.h>
      14             : #include <sys/socket.h>
      15             : #include <netinet/in.h>
      16             : #include <netinet/udp.h>
      17             : #include <arpa/inet.h>
      18             : #include <fcntl.h>
      19             : #include <AP_Math/crc.h>
      20             : 
      21             : #define MCAST_ADDRESS_BASE "239.65.82.0"
      22             : #define MCAST_PORT 57732U
      23             : #define MCAST_MAGIC 0x2934U
      24             : #define MCAST_FLAG_CANFD 0x0001
      25             : #define MCAST_MAX_PKT_LEN 74 // 64 byte data + 10 byte header
      26             : 
      27             : struct PACKED mcast_pkt {
      28             :     uint16_t magic;
      29             :     uint16_t crc;
      30             :     uint16_t flags;
      31             :     uint32_t message_id;
      32             :     uint8_t data[MCAST_MAX_PKT_LEN-10];
      33             : };
      34             : 
      35             : /*
      36             :   initialise multicast transport
      37             :  */
      38           5 : bool CAN_Multicast::init(uint8_t instance)
      39             : {
      40             :     // setup incoming multicast socket
      41           5 :     char address[] = MCAST_ADDRESS_BASE;
      42             : 
      43           5 :     address[strlen(address)-1] = '0' + instance;
      44           5 :     sock.set_multicast_interface_address(sitl_multicast_interface_address());
      45           5 :     return sock.connect(address, sitl_can_multicast_port(MCAST_PORT));
      46             : }
      47             : 
      48             : /*
      49             :   send a CAN frame
      50             :  */
      51       18063 : bool CAN_Multicast::send(const AP_HAL::CANFrame &frame)
      52             : {
      53       18063 :     struct mcast_pkt pkt {};
      54       18063 :     pkt.magic = MCAST_MAGIC;
      55       18063 :     pkt.flags = 0;
      56             : #if HAL_CANFD_SUPPORTED
      57       18063 :     if (frame.canfd) {
      58           0 :         pkt.flags |= MCAST_FLAG_CANFD;
      59             :     }
      60             : #endif
      61       18063 :     pkt.message_id = frame.id;
      62       18063 :     const uint8_t data_length = AP_HAL::CANFrame::dlcToDataLength(frame.dlc);
      63       18063 :     memcpy(pkt.data, frame.data, data_length);
      64       18063 :     pkt.crc = crc16_ccitt((uint8_t*)&pkt.flags, data_length+6, 0xFFFFU);
      65             : 
      66       18063 :     return sock.send((void*)&pkt, data_length+10) == data_length+10;
      67             : }
      68             : 
      69             : /*
      70             :   receive a CAN frame
      71             :  */
      72       80842 : bool CAN_Multicast::receive(AP_HAL::CANFrame &frame)
      73             : {
      74             :     struct mcast_pkt pkt;
      75       80842 :     ssize_t ret = sock.recv((void*)&pkt, sizeof(pkt), 0);
      76       80842 :     if (ret < 10) {
      77       80690 :         return false;
      78             :     }
      79         152 :     if (pkt.magic != MCAST_MAGIC) {
      80           0 :         return false;
      81             :     }
      82         152 :     if (pkt.crc != crc16_ccitt((uint8_t*)&pkt.flags, ret-4, 0xFFFFU)) {
      83           0 :         return false;
      84             :     }
      85             : 
      86             :     // run constructor to initialise
      87         152 :     new(&frame) AP_HAL::CANFrame(pkt.message_id, pkt.data, ret-10, (pkt.flags & MCAST_FLAG_CANFD) != 0);
      88             : 
      89         152 :     if (sem_handle != nullptr) {
      90         152 :         sem_handle->signal();
      91             :     }
      92             : 
      93         152 :     return true;
      94             : }
      95             : 
      96             : #endif // HAL_NUM_CAN_IFACES

Generated by: LCOV version 1.14