/* Example of CAN for PISO-CAN200/400 Cards
 *
 *    Author: Golden Wang
 *
 *    This program is free software; you can redistribute it and/or modify
 *    it under the terms of the GNU General Public License as published by
 *    the Free Software Foundation; either version 2, or (at your option)
 *    any later version.
 *
 *    This program is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *    GNU General Public License for more details.
 *
 *    You should have received a copy of the GNU General Public License
 *    along with this program; if not, write to the Free Software Foundation,
 *    Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/

/* File level history (record changes for this file here.)
 *
 *    v 0.0.0 25 Mar 2010 by Golden Wang
 *         create, blah blah...
*/

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <signal.h>
#include <libgen.h>

#include <sys/types.h>
#include <sys/socket.h>
#include <sys/ioctl.h>
#include <sys/uio.h>
#include <linux/can.h>
#include <net/if.h>

extern int optind, opterr, optopt;
#define PF_CAN 29

static int skt1 = -1;
static int skt2 = -1;
static int running = 1;
int ret;

void print_usage(char *prg)
{
	fprintf(stderr, "Usage: %s [can-interface]\n", prg);
}

void sigterm(int signo)
{
	printf("got signal %d\n", signo);
	running = 0;
}

int main(int argc, char **argv)
{
	int family = PF_CAN, type = SOCK_RAW, proto = CAN_RAW;
	int opt;
	struct sockaddr_can addr1, addr2;
	struct ifreq ifr1, ifr2;
	struct can_frame frame1, frame2;
	int nbytes, i = 0, test_times = 10;
	int verbose = 0;

	signal(SIGTERM, sigterm);
	signal(SIGHUP, sigterm);

	if (optind == argc) 
	{
		print_usage(basename(argv[0]));
		exit(0);
	}
	
	//printf("optind = %d, argc = %d, argv[%d] = %s, argv[%d] = %s, times = %d\n", optind, argc, optind, argv[optind], optind + 1,argv[optind+1], atoi(argv[optind+2]));
	if(argc == 4)
		test_times = atoi(argv[optind+2]);
	else
		test_times = 10;

	if(test_times > 10 || test_times < 1)
		test_times = 10;

	printf("interface = %s, family = PF_CAN, type = SOCK_RAW, proto = CAN_RAW\n", argv[optind]);

	/* init Port1 */
	if ((skt1 = socket(PF_CAN, SOCK_RAW, CAN_RAW)) < 0) 
	{
		perror("socket");
		return 1;
	}

	addr1.can_family = family;
	strcpy(ifr1.ifr_name, argv[optind]);
	ioctl(skt1, SIOCGIFINDEX, &ifr1);
	addr1.can_ifindex = ifr1.ifr_ifindex;

	if (bind(skt1, (struct sockaddr *)&addr1, sizeof(addr1)) < 0) 
	{
		perror("bind");
		return 1;
	}

	/* init Port2 */
	if ((skt2 = socket(PF_CAN, SOCK_RAW, CAN_RAW)) < 0) 
	{
		perror("socket");
		return 1;
	}

	addr2.can_family = family;
	strcpy(ifr2.ifr_name, argv[optind+1]);
	ioctl(skt2, SIOCGIFINDEX, &ifr2);
	addr2.can_ifindex = ifr2.ifr_ifindex;

	if (bind(skt2, (struct sockaddr *)&addr2, sizeof(addr2)) < 0) 
	{
		perror("bind");
		return 1;
	}

	/* test */
	//while (running) 
	while (test_times--) 
	{
		printf("Test Times %d\n", test_times);
		/* send from Port 1 first */
		frame1.can_id = 0x123 + test_times;
        	frame1.data[0] = 0x01;
		frame1.data[1] = 0x02;
		frame1.data[2] = 0x03;
		frame1.data[3] = 0x04;
		frame1.data[4] = 0x05;
		frame1.data[5] = 0x06;
		frame1.data[6] = 0x07;
		frame1.data[7] = 0x08;
		frame1.can_dlc = 8;
		ret = write(skt1, &frame1, sizeof(frame1));

		printf("Port1(%s) Send CAN ID : 0x%x Length : %d Data : ", ifr1.ifr_name, frame1.can_id, frame1.can_dlc);
		for(i = 0; i < frame1.can_dlc; i++)
		{
			printf("%02X ",frame1.data[i]);
		}
	
		printf("\n");

		/* recv from Port 2 */
		if ((nbytes = read(skt2, &frame2, sizeof(frame2))) < 0) 
		{
			perror("read");
			return 1;
		}

		printf("Port2(%s) Recv CAN ID : 0x%03X ", ifr2.ifr_name, frame2.can_id & CAN_EFF_MASK);

		if (frame2.can_id & CAN_RTR_FLAG) 
		{
			printf("remote request");
		} 
		else 
		{
			printf("Length : %d Data :", frame2.can_dlc);

			for (i = 0; i < frame2.can_dlc; i++) 
			{
				printf(" %02X", frame2.data[i]);
			}
		}

		printf("\n\n");
               
		/* send from Port 2 */
		frame2.can_id = 0x100;

		printf("Port2(%s) Send CAN ID : 0x%x Length : %d Data : ", ifr2.ifr_name, frame2.can_id, frame2.can_dlc);
		for(i = 0; i < frame2.can_dlc; i++)
		{
			printf("%02X ",frame2.data[i]);
		}
	
		printf("\n");

                ret = write(skt2, &frame2, sizeof(frame2));


		/* recv from Port 1 */
		if ((nbytes = read(skt1, &frame1, sizeof(frame1))) < 0) 
		{
			perror("read");
			return 1;
		}

		printf("Port1(%s) Recv CAN ID : 0x%03X ", ifr1.ifr_name, frame1.can_id & CAN_EFF_MASK);

		if (frame1.can_id & CAN_RTR_FLAG) 
		{
			printf("remote request");
		} 
		else 
		{
			printf("Length : %d Data :", frame1.can_dlc);

			for (i = 0; i < frame1.can_dlc; i++) 
			{
				printf(" %02X", frame1.data[i]);
			}
		}

		printf("\n\n");
	}

	return 0;
}
