#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <termios.h>
#include <time.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/select.h>
#include <string.h>
#include <sys/ioctl.h>

#define TTYDEVNAME	"/dev/ttyS4"
#define BAUDRATE		B38400

int speed_arr[] = {B115200, B57600, B38400, B19200, B9600, B4800, B2400, B1200, B300};
int name_arr[] = {115200, 57600, 38400, 19200, 9600, 4800, 2400, 1200, 300};

int tcgetattr_to_ioctl(void)
{
	int fd, flag, rd_num = 0;
	struct termios newtios, oldtios;
	struct timeval timeout;
	speed_t baud_rate_i, baud_rate_o;
	char recv_buf[256];
	int baudrate = 115200;
	char dev_file[32];
	int len;
	unsigned char send_msg_flag = 0;
	fd_set fds;
	int ret=0;
	int i=0;
	int size = sizeof(speed_arr) / sizeof(int);

 
 	
	for( i = 0; i < size; i++)
	{
		if(BAUDRATE == speed_arr[i])
		{
			baudrate = name_arr[i];
			break;
		}

	}	


  

   fd = open(TTYDEVNAME, O_RDWR | O_NONBLOCK);

	if(fd < 0)
	{
		printf("can not open %s!\n", TTYDEVNAME);
		exit(1);
	}
	else
		printf("open %s ok! baudrate = %d\n", TTYDEVNAME, baudrate);

	memset(&oldtios, 0, sizeof(oldtios));
	ret = tcgetattr(fd, &oldtios);
	
	if(ret == 0)
	{
		printf("tcgetattr old termios is:\n");
		printf("oldtios.c_iflag=0x%08x;\n", oldtios.c_iflag);
		printf("oldtios.c_oflag=0x%08x;\n", oldtios.c_oflag);
		printf("oldtios.c_cflag=0x%08x;\n", oldtios.c_cflag);
		printf("oldtios.c_lflag=0x%08x;\n", oldtios.c_lflag);
		printf("oldtios.c_line=0x%08x;\n", oldtios.c_line);	
	}
	newtios = oldtios;	
	memset(&oldtios, 0, sizeof(oldtios));
	ret = ioctl(fd, TCGETA,  &oldtios);
	if(ret == 0)
	{
		printf("ioctl old termios is:\n");
		printf("oldtios.c_iflag=0x%08x;\n", oldtios.c_iflag);
		printf("oldtios.c_oflag=0x%08x;\n", oldtios.c_oflag);
		printf("oldtios.c_cflag=0x%08x;\n", oldtios.c_cflag);
		printf("oldtios.c_lflag=0x%08x;\n", oldtios.c_lflag);
		printf("oldtios.c_line=0x%08x;\n", oldtios.c_line);	
	}

	
	


	newtios.c_cflag &= ~CBAUD;
	newtios.c_cflag |= BAUDRATE; 
	newtios.c_cflag &= ~CSIZE;
	newtios.c_cflag |= CS8;
	newtios.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG); /*Input*/
	newtios.c_oflag &= ~OPOST;   /*Output*/
	newtios.c_cflag &= ~CSTOPB;
	newtios.c_cc[VTIME] = 5; // 0.5 seconds
	newtios.c_cc[VMIN] = 1;
	newtios.c_cflag &= ~HUPCL;
	newtios.c_iflag &= ~INPCK;
	newtios.c_iflag |= IGNBRK;
	newtios.c_iflag &= ~ICRNL;
	newtios.c_iflag &= ~IXON;
	newtios.c_lflag &= ~IEXTEN;
	newtios.c_lflag &= ~ECHOK;
	newtios.c_lflag &= ~ECHOCTL;
	newtios.c_lflag &= ~ECHOKE;
	newtios.c_oflag &= ~ONLCR;

	printf("new termios is changed:\n");
	printf("newtios.c_iflag=0x%08x;\n", newtios.c_iflag);
	printf("newtios.c_oflag=0x%08x;\n", newtios.c_oflag);
	printf("newtios.c_cflag=0x%08x;\n", newtios.c_cflag);
	printf("newtios.c_lflag=0x%08x;\n", newtios.c_lflag);
	printf("newtios.c_line=0x%08x;\n", newtios.c_line);
	//tcflush(fd, TCIFLUSH); /* Update the options and do it NOW */
	tcsetattr(fd, TCSAFLUSH, &newtios);

 	ret = tcgetattr(fd, &newtios);
	if(ret == 0)
	{
		printf("now tcgetattr termios is:\n");
		printf("newtios.c_iflag=0x%08x;\n", newtios.c_iflag);
		printf("newtios.c_oflag=0x%08x;\n", newtios.c_oflag);
		printf("newtios.c_cflag=0x%08x;\n", newtios.c_cflag);
		printf("newtios.c_lflag=0x%08x;\n", newtios.c_lflag);
		printf("newtios.c_line=0x%08x;\n", newtios.c_line);
	}

	ret = ioctl(fd, TCGETA,  &newtios);
	if(ret == 0)
	{
		printf("now ioctl termios is:\n");
		printf("newtios.c_iflag=0x%08x;\n", newtios.c_iflag);
		printf("newtios.c_oflag=0x%08x;\n", newtios.c_oflag);
		printf("newtios.c_cflag=0x%08x;\n", newtios.c_cflag);
		printf("newtios.c_lflag=0x%08x;\n", newtios.c_lflag);
		printf("newtios.c_line=0x%08x;\n", newtios.c_line);
	}

	while(1)
	{
	    memset(recv_buf, 0x00, sizeof(recv_buf));

	    printf("Input AT cammand:\n");

	    fflush(stdin);
	    
	    
		if(fgets(recv_buf, 254, stdin) == NULL)
			continue;
		//printf("read from stdin: %s\n", recv_buf);
		if((!memcmp(recv_buf, "quit", 4) || !memcmp(recv_buf, "exit", 4)))
			break;
			
		if(memcmp(recv_buf, "AT", 2) && memcmp(recv_buf, "at", 2))
			continue;
			
		
		len = strlen(recv_buf);
		recv_buf[--len] = 0x00;

		
		recv_buf[len++] = 0x0D;
		recv_buf[len++] = 0x0A;
		

		tcflush(fd, TCIFLUSH);

		//printf("wrtie length: %d data: %s(%d) ", len, recv_buf,send_msg_flag);
		if(write(fd, recv_buf, len) <= 0)
			continue;

		FD_ZERO(&fds);
		FD_SET(fd, &fds);

		timeout.tv_sec = 0;
		timeout.tv_usec =100000;

		while(1)
		{
			select(fd+1, &fds, NULL, NULL, &timeout);
	
			if(!FD_ISSET(fd, &fds))
				break;
	
			//if(!memcmp(recv_buf, "AT^HCMGS=", 9))
			//	send_msg_flag = 1;
	
			memset(recv_buf, 0x00, sizeof(recv_buf));
			rd_num = read(fd, recv_buf, sizeof(recv_buf));
			
			if(rd_num > 0)
			{
				
				#if 0
				int i=0;
				printf("\n");
				for(i=0; i<rd_num; i++)
				{
					printf("%02x ", recv_buf[i]);
				}	
				
				printf("\n");
				
				printf("read length: %d\n"
						"data: %s\n", rd_num, recv_buf);
						
				#endif		
				printf("\n%s\n", recv_buf);
				
			}
		}
						
		 	
	}
	close(fd);

	return 0;
}

int main(void)
{

	tcgetattr_to_ioctl();
	return 0;	
}
