#include <sys/ioctl.h>
#include <net/if.h>
#include <linux/can.h>
#include <linux/can/raw.h>
#include <pthread.h>

#include <stdio.h>
#include <string.h>

#ifndef PF_CAN
#define PF_CAN 29
#endif

#ifndef AF_CAN
#define AF_CAN PF_CAN
#endif

int main(char *argv[], int argc)
{
	int s,res;
	pthread_t id;
	unsigned long nbytes;
	struct sockaddr_can addr;
	struct ifreq ifr;
	struct can_frame frame;
	char senddata[80] = { "test" };
	int  len;
	int  index;

	s = socket(PF_CAN,SOCK_RAW,CAN_RAW); // Create a socket with PF_CAN family, SOCK_RAW and CAN_RAW protocol

	strcpy((char *)(ifr.ifr_name),"can0"); // Use can0
	res = ioctl(s,SIOCGIFINDEX,&ifr); // Control device and get information
	printf("ioctl:%d\n", res);
	printf("can0 can_ifindex = %x\n",ifr.ifr_ifindex);

	int loopback = 0; /* 0 = disabled, 1 = enabled (default) */
    setsockopt(s, SOL_CAN_RAW, CAN_RAW_LOOPBACK, &loopback, sizeof(loopback)); // Setting lookback options
	printf("set can0 sock loopback unable:%d\n", res);

	int recv_own_msgs = 0; /* 0 = disabled (default), 1 = enabled */
    res = setsockopt(s, SOL_CAN_RAW, CAN_RAW_RECV_OWN_MSGS, // Setting receiver own massages options
               &recv_own_msgs, sizeof(recv_own_msgs));
	printf("set can0 do not receiver own massage:%d\n", res);

	addr.can_family = AF_CAN; // Use AF_CAN protocol family 
	addr.can_ifindex = ifr.ifr_ifindex;  // frame index
	res = bind(s,(struct sockaddr*)&addr,sizeof(addr)); // Binding sock
	printf("bind can0 sock:%d\n", res);

	frame.can_id = 0x123;
	len = strlen(senddata) - 1;
	
	while (1) {
		strncpy(frame.data, senddata, 5);
		frame.can_dlc = strlen(frame.data);
		nbytes = sendto(s, &frame, sizeof(struct can_frame), 0, (struct sockaddr*)&addr, sizeof(addr));
		if (nbytes != -1) {
			printf("Send success: %d  %s\n", nbytes, senddata);
			usleep(500000);
			nbytes = recvfrom(s, &frame, sizeof(struct can_frame), 0, (struct sockaddr *)&addr, &len);
			if (nbytes != -1) {
				printf("Recv message: %d  %s\n", nbytes, frame.data);
			}
		}
	}

	return 0;
}
