0

I am cross-compiling using CMAKE for an embedded arm device, and having some issues with it defining PF_CAN and AF_CAN. I have been advised to use

sys/socket.h

but it doesn't contain the defines and can't really tell if it's pointing to it indirectly.

This is my current program (super simple)

/* A simple SocketCAN example */

#include <cstdlib>
#include <stdio.h>
#include <cstring>
#include <sys/time.h>
#include <sys/types.h>
#include <sys/stat.h>

#include <arpa/inet.h>
#include <netdb.h>
#include <netinet/in.h>
#include <unistd.h> 
#include <pthread.h>
#include <assert.h>
#include <errno.h>
#include <iostream>

#include <sys/socket.h>  // i tried linux/socket.h and get some other errors, so I am confused.
#include <pthread.h>
#include <net/if.h>
#include <string.h>
#include <net/if.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <assert.h>
#include <linux/can.h>
#include <linux/can/raw.h>

int soc;
int read_can_port;

int open_port(const char *port)
{
    ifreq ifr;
    sockaddr_can addr;
   /* open socket */
soc = socket(PF_CAN, SOCK_RAW, CAN_RAW);
if(soc < 0)
{
    return (-1);
}
addr.can_family = AF_CAN;
strcpy(ifr.ifr_name, port);
if (ioctl(soc, SIOCGIFINDEX, &ifr) < 0)
{
    return (-1);
}
addr.can_ifindex = ifr.ifr_ifindex;
fcntl(soc, F_SETFL, O_NONBLOCK);
if (bind(soc, (struct sockaddr *)&addr, sizeof(addr)) < 0)
{
    return (-1);
}
return 0;
}
int send_port(struct can_frame *frame)
{
   int retval;
   retval = write(soc, frame, sizeof(struct can_frame));
    if (retval != sizeof(struct can_frame))
    {
    return (-1);
    }
    else
    {
    return (0);
    }
}
/* this is just an example, run in a thread */
void read_port()
{
    struct can_frame frame_rd;
    int recvbytes = 0;
read_can_port = 1;
while(read_can_port)
{
    struct timeval timeout = {1, 0};
    fd_set readSet;
    FD_ZERO(&readSet);
    FD_SET(soc, &readSet);
    if (select((soc + 1), &readSet, NULL, NULL, &timeout) >= 0)
    {
        if (!read_can_port)
        {
            break;
        }
        if (FD_ISSET(soc, &readSet))
        {
            recvbytes = read(soc, &frame_rd, sizeof(struct can_frame));
            if(recvbytes)
            {
                printf("dlc = %d, data = %s\n",           
 frame_rd.can_dlc,frame_rd.data);
            }
        }
    }
}
}
int close_port()
{
close(soc);
return 0;
}
int main(void)
{
std::cout << "Hello World! " << std::endl;

open_port("can0”");
read_port();
return 0;
}

This is my output when I run make:

HelloWorld.cpp:45: error: 'PF_CAN' was not declared in this scope HelloWorld.cpp:45: error: 'PF_CAN' was not declared in this scope

wegunterjr
  • 141
  • 2
  • 9
  • I tried adding the #include (and that got the same result. When I move them lower in the list, it fails with the PF_CAN and AF_CAN error I already listed. – wegunterjr Oct 21 '16 at 18:02

2 Answers2

0

The solution was to add

#ifndef AF_CAN 
#define AF_CAN 29
#endif

This allowed the project to build with no errors. Also, ran the project on the actual target device and it ran normally.

wegunterjr
  • 141
  • 2
  • 9
0

I've just run into the same problem and had to add the following in my code:

#ifndef PF_CAN 
#define PF_CAN 29 
#endif 
#ifndef AF_CAN 
#define AF_CAN PF_CAN 
#endif 

These values are the standard Controller Area Network Protocol Family and Address Family values normally defined in bits/socket.h.

I figured out WHY I needed to do this and think it needs sharing for when others run into the problem because it'll be a similar reason.

In my case it was because /opt/freescale/usr/local/gcc-4.3.50-eglibc-2.8.50/powerpc-linux-gnu/powerpc-linux-gnu/libc/usr/include/linux/socket.h defines these values but they are no longer exposed due to the following compilation macro that encapsulates them:

#if defined(__KERNEL__) || !defined(__GLIBC__) || (__GLIBC__ < 2)

A subsequent comment in the code, "This mess will go away with glibc", hints that much of the library was expected to change with glibc updates; unfortunately the toolchain did NOT provide these definitions anywhere else so they needed to be defined in my code.

ie. If you're using an older toolchain and you can't find these values in bits/socket.h, it might be time to update your toolchain or you'll need to define these values yourself like I had to.

Lokiel
  • 1
  • 2