clinuxcan-bussocketcanlegato

SocketCAN read from socket only returns 11cobid


I am trying to read from a socketCAN and the msg is always filtered for the 11bit identifier. This should be a problem fixable with setting the rpoper flags for the 29bit identifier but I can`t find where if anyone can help...

    struct can_frame message;
    struct sockaddr_can addr;
    struct ifreq ifr;
    int   fd = -1;                  // file descriptor (it´s a socket)

    if((fd = socket(PF_CAN, SOCK_RAW, CAN_RAW)) < 0)
    {
        LE_INFO("cannot open socket");
        return;
    }
    strcpy(ifr.ifr_name, "can0");
    ioctl(fd, SIOCGIFINDEX, &ifr);
    addr.can_family = AF_CAN;
    addr.can_ifindex = ifr.ifr_ifindex;
    if(bind(fd, (struct sockaddr *)&addr, sizeof(addr)) < 0)
    {
        printf("cannot bind socket\n");
        return;
    }

    uint8_t nbytes;

    message.can_id |= CAN_EFF_FLAG;

    while(1)
    {
        nbytes = read(fd, &message, sizeof(struct can_frame));

        if (nbytes < 0) {
                perror("can raw socket read");
                return;
        }

        /* paranoid check ... */
        if (nbytes < sizeof(struct can_frame)) {
                fprintf(stderr, "read: incomplete CAN frame\n");
                return;
        }

        printf("READ COB_ID:%x\n",message.can_id | CAN_EFF_FLAG);
        
    }
    return;

I am sending a CAN frame with idx x901 and this is what is printed:

READ COB_ID:80000101

READ COB_ID:80000101

READ COB_ID:80000101

I have troubleshooted this in many different ways and it seems that the C code is working as it should, but I suspect the problem to be with the kernel module for either mcp251x which is not correctly receiving the extended flag? Or it may be with some initialization I need to do before running the kernel module???

Thank you in advance to anyone who can help.


Solution

  • Your understanding of CAN flags and filtering is not correct. Take a look at extract from linux can.h:

    /* special address description flags for the CAN_ID */
    #define CAN_EFF_FLAG 0x80000000U /* EFF/SFF is set in the MSB */
    #define CAN_RTR_FLAG 0x40000000U /* remote transmission request */
    #define CAN_ERR_FLAG 0x20000000U /* error message frame */
    
    /* valid bits in CAN ID for frame formats */
    #define CAN_SFF_MASK 0x000007FFU /* standard frame format (SFF) */
    #define CAN_EFF_MASK 0x1FFFFFFFU /* extended frame format (EFF) */
    #define CAN_ERR_MASK 0x1FFFFFFFU /* omit EFF, RTR, ERR flags */
    

    Here is an example that works for both SFF and EFF messages:

    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <unistd.h>
    
    #include <net/if.h>
    #include <sys/ioctl.h>
    #include <sys/socket.h>
    
    #include <linux/can.h>
    #include <linux/can/raw.h>
    
    int main(int argc, char **argv)
    {
        struct can_frame message;
        struct sockaddr_can addr;
        struct ifreq ifr;
        int   fd = -1;                  // file descriptor (it´s a socket)
    
        if((fd = socket(PF_CAN, SOCK_RAW, CAN_RAW)) < 0)
        {
            printf("cannot open socket");
            return -9;
        }
        strcpy(ifr.ifr_name, "vcan0");
        ioctl(fd, SIOCGIFINDEX, &ifr);
        addr.can_family = AF_CAN;
        addr.can_ifindex = ifr.ifr_ifindex;
        if(bind(fd, (struct sockaddr *)&addr, sizeof(addr)) < 0)
        {
            printf("cannot bind socket\n");
            return -1;
        }
    
        u_int8_t nbytes;
    
        message.can_id |= CAN_EFF_FLAG | CAN_RTR_FLAG | CAN_EFF_MASK;
    
        while(1)
        {
            nbytes = read(fd, &message, sizeof(struct can_frame));
    
            if (nbytes < 0) {
                    perror("can raw socket read");
                    return -2;
            }
    
            /* paranoid check ... */
            if (nbytes < sizeof(struct can_frame)) {
                    fprintf(stderr, "read: incomplete CAN frame\n");
                    return -3;
            }
    
            printf("READ COB_ID: %x\n", message.can_id & CAN_EFF_MASK);
    
        }
    
        return 0;
    }
    

    Now sending these messages:

    cansend vcan0 00000123#FFFFFFFFFFFFFFFF
    cansend vcan0 12345678#FFFFFFFFFFFFFFFF
    

    gives correct output:

    READ COB_ID: 123
    READ COB_ID: 12345678