/******************************************************************************
版权所有：	
文件名称：	at_cmd.c
文件版本：	01.01
创建作者：	xxxxxx
创建日期：	2014-06-10
功能说明：	AT指令处理实现文件.	
								
其它说明：
修改记录：
*/

#include "at_cmd.h"
#ifndef __KERNEL__

#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 sys_open		open
#define sys_close		close
#define sys_ioctl		ioctl
#define sys_write		write
#define sys_read		read
#define sys_select	select
#define printk			printf

#else

#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/fs.h>
#include <linux/sched.h>
#include <linux/interrupt.h>
#include <linux/kthread.h>
#include <linux/delay.h>
#include <linux/wait.h> 
#include <asm/uaccess.h>
#include <asm/io.h>
#include <asm/ioctls.h>
#include <linux/syscalls.h> 
#include <termios.h>

#endif 


/******************************************************************************
函数名称：	at_cmd_send_and_ret
函数版本：	01.01
创建作者：	xxxxxx
创建日期：	2014-06-10
函数说明：	发送AT指令，并返回内容.						
参数说明：	
						serialname:指定使用哪一个串口发送AT指令
						cmd: AT指令
						len:指令长度.	
						result: 返回的内容
返回值：  	成功返回0，失败返回负数。
修改记录：	
*/   
int at_cmd_send_and_ret(char *serialname, char *cmd, int len, char *result)
{
	int fd = 0; 
	int i = 0;
	int j = 0;
	int ret = 0;
	fd_set fds;
	struct timeval tv;
	char buf[512];
	char ch[]={'>', 0x00};
	
	memset(buf, 0, sizeof(buf));
	fd = sys_open(serialname, O_RDWR, 0);
	if(fd < 0 ) 
	{
		printk("open %s error\n", serialname);	
		return -1;
	}
 
	//发送AT指令
	ret= sys_write(fd, cmd, strlen(cmd)); 
	if(ret < 0)
	{
		printk("write error(%d)\n", ret);	
		goto end;	 
	}
	
	//等待AT指令响应
	while(1)
	{
		FD_ZERO(&fds);
		FD_SET(fd, &fds);
	
		tv.tv_sec = 0;
		tv.tv_usec =500000;	
		
		ret = sys_select(fd+1, &fds, NULL, NULL, &tv);
 
		if(ret > 0) 
		{
			//读取响应数据
			ret = sys_read(fd, buf+i, sizeof(buf)-i-1);
			
			if(ret > 0)
			{
				memcpy(result+j, buf+i, ret);
				j = j + ret;
				buf[i+ret] = 0;
				//printk("%s", buf+i);
				//AT指令响应OK表示成功
				if(strstr(buf, "OK") || strstr(buf, ch))
				{
					//printk("%s", buf);
					ret = 0;
					break;
				}
			}
			
			//防止数组越界.目前只使用AT,AT+CIMI两条指令，是不会越界的.
			i = i + ret;	
			if(i >= (sizeof(buf)-1))
			{
				i = 0;
				memset(buf, 0, sizeof(buf));
			}	
				
		} else {
			
			ret = -1;	
			break;
		}
	}

end:
	
	sys_close(fd);	
	
	return ret;
}

/******************************************************************************
函数名称：	at_cmd_send
函数版本：	01.01
创建作者：	xxxxxx
创建日期：	2014-06-10
函数说明：	发送AT指令.						
参数说明：	
						serialname:指定使用哪一个串口发送AT指令.
						cmd: AT指令
						len:指令长度.	
返回值：  	成功返回0，失败返回负数。
修改记录：	
*/
int at_cmd_send(char *serialname, char *cmd, int len)
{
	int fd = 0; 
	int i = 0;
	int ret = 0;
	fd_set fds;
	struct timeval tv;
	char buf[512];
	char ch[]={'>', 0x00};
	
	memset(buf, 0, sizeof(buf));
	fd = sys_open(serialname, O_RDWR , 0);
	if(fd < 0 ) 
	{
		printk("open %s error\n", serialname);	
		return -1;
	}
	
	//发送AT指令
	ret= sys_write(fd, cmd, strlen(cmd)); 
	if(ret < 0)
	{
		printk("write error(%d)\n", ret);	
		goto end;	 
	}
	
	//等待AT指令响应
	while(1)
	{
		FD_ZERO(&fds);
		FD_SET(fd, &fds);
	
		//tv.tv_sec = 0;
		//tv.tv_usec =500000;	
		tv.tv_sec = 1;
		tv.tv_usec =0;	
		
		ret = sys_select(fd+1, &fds, NULL, NULL, &tv);
 
		if(ret > 0) 
		{
			//读取响应数据
			ret = sys_read(fd, buf+i, sizeof(buf)-i-1);
			
			if(ret > 0)
			{
				buf[i+ret] = 0;
				//printk("%s", buf+i);
				//AT指令响应OK表示成功
				if(strstr(buf, "OK") || strstr(buf, ch))
				{
					//printk("%s", buf);
					ret = 0;
					break;
				}
			}
			
			//防止数组越界.目前只使用AT,AT+CIMI两条指令，是不会越界的.
			i = i + ret;	
			if(i >= (sizeof(buf)-1))
			{
				i = 0;
				memset(buf, 0, sizeof(buf));
			}	
				
		} else {
			
			ret = -1;	
			break;
		}
	}


end:	
	sys_close(fd);	
	
	return ret;
}

