/******************************************************************************
版权所有：	
文件名称：	gprs_recv_proc.c
文件版本：	01.01
创建作者：	xxxxxx
创建日期：	2014-06-10
功能说明：	GPRS接收处理
其它说明：
修改记录：
*/
#ifdef GPRS_FUNC

#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 <asm/semaphore.h>
#include <linux/if.h> 
#include <linux/tcp.h>
#include <termios.h>
#include <linux/syscalls.h>
#include "gprs_vs_func.h"
#include "gh_vs.h"
#include "gprs_aux.h"

#define GPRS_CHNL   6          // 最后一个串口

extern struct completion *g_exit_completion_gprs_net_IEC_proc;
extern struct completion *g_exit_completion_gprs_net_aux_proc;
extern int main_mod_is_exit(void);
//接收数据处理回调函数
void (*g_IEC_Recv)(unsigned char cDat, unsigned char chnl);
extern int g_vsfd;

static struct completion g_exit_completion_gprs;
static struct completion g_exit_completion_gprs_aux;
struct gprs_info g_gprs_info; //GPRS状态信息

int g_gh_vs_is_idle = 1; //虚拟串口空闲标志.1表示空闲,0表示不空闲
int g_update_dz = 0; //更新定值标志.注意是内部的资源的复位，不是重新创建任务
int g_update_gprs_driver = 0; //更新GPRS驱动标志.注意是内部的资源的复位，不是重新创建任务

static int g_gprs_init_flag = 0;//GPRS初始化标志





/******************************************************************************
函数名称：	gprs_net_IEC_proc
函数版本：	01.01
创建作者：	xxxxxx
创建日期：	2014-06-10
函数说明：	GPRS处理任务。
参数说明：	无
返回值：  	成功返回0，失败返回负数。
修改记录：	
*/
int gprs_net_IEC_proc(void *arg)
{
	struct timeval tv;
	fd_set rset;
	int ret = 0;
	int i = 0;
	static unsigned char buf[256];
	
	g_exit_completion_gprs_net_IEC_proc = &g_exit_completion_gprs;

begin:	
	//虚拟串口空闲,任务就休眠
	if(g_gh_vs_is_idle)
	{
		msleep(100);
		if(main_mod_is_exit())
		{
			complete_and_exit(&g_exit_completion_gprs, 0);	
		}	
		goto begin;
	}	
		
	//打开虚拟串口
	ret = gprs_vs_open();	
	
	if(ret < 0)  //虚拟串口被占用，需要重新尝试打开
	{
		msleep(100);
		if(main_mod_is_exit())
		{
			complete_and_exit(&g_exit_completion_gprs, 0);	
		}			
		goto begin;
	}


	while(1)
	{
		tv.tv_sec = 0;
		tv.tv_usec = 500000;
		FD_ZERO(&rset); 
		FD_SET(g_vsfd, &rset);		
			
		ret = sys_select(g_vsfd+1, &rset, NULL, NULL, &tv); 

		//有数据可读
		if(ret > 0)
		{
			//读取数据
			ret = gprs_vs_read(buf, sizeof(buf));
			
			
			//处理101规约报文
			if(g_IEC_Recv)
			{
				
				for(i=0; i<ret ;i++)
				{
					//g_IEC_Recv(buf[i], GPRS_CHNL);				
				}
			}
			#if 0
		 	//测试代码
			printk("\nIEC RECV:");
			for(i = 0; i < ret; i++)
			{
				printk("%02x ", (unsigned char)buf[i]);	
			}		
			printk("\n");
			#endif 	 
					
		}
		
		
		//检查是否退出
		if(main_mod_is_exit())
		{
			gprs_vs_close();
			complete_and_exit(&g_exit_completion_gprs, 0);	
			break;
		}
		
		//释放资源,关闭虚拟串口,重新打开虚拟串口
		if(g_update_dz)
		{
			gprs_vs_close();
			g_update_dz = 0;
			goto begin;
		}
		
		//升级GPRS驱动,需要关闭虚拟串口,重新打开虚拟串口
		if(g_update_gprs_driver)
		{
			gprs_vs_close();
			g_update_gprs_driver = 0;
			msleep(10000);//让GPRS模块有足够的时间启动
			goto begin;
		}
			
	}
	
	return 0;	
}
 
/******************************************************************************
函数名称：	gprs_net_get_gprs_info
函数版本：	01.01
创建作者：	xxxxxx
创建日期：	2014-06-10
函数说明：	获取内部GPRS信息.						
参数说明：	
					 
返回值：  	成功返回信息的字节数。
修改记录：	
*/
int gprs_net_get_gprs_info(void) 
{
	int num = 0;
	int ret = 0;
	int i = 0 ;
	extern unsigned char strGprsInf[30][24];
	extern int g_aux_csq ;
	
	memset(strGprsInf, 0, sizeof(strGprsInf));
	ret = sys_ioctl(g_vsfd, GH_VS_GET_GPRSINFO, (uint32_t)&g_gprs_info);
	if(ret == 0)
	{
 
 			
		if(g_gprs_info.module_state)
		{
			strcpy(strGprsInf[num++],"模块状态 :正常");
		}
		else
		{
			strcpy(strGprsInf[num++],"模块状态 :异常");
	
		}
	
		if(g_gprs_info.sim_state)
		{
			strcpy(strGprsInf[num++],"SIM卡状态:正常");
		}
		else
		{
			strcpy(strGprsInf[num++],"SIM卡状态:异常");
	
		}

		if(g_gprs_info.ppp_state)
		{
			strcpy(strGprsInf[num++],"PPP拨号  :正常");
		}
		else
		{
			strcpy(strGprsInf[num++],"PPP拨号  :异常");
			g_gprs_info.localip = 0;
	
		}	
		
		sprintf(strGprsInf[num++],"%d.%d.%d.%d",(g_gprs_info.localip >> 24 & 0xFF), (g_gprs_info.localip >> 16 & 0xFF), (g_gprs_info.localip >> 8 & 0xFF), (g_gprs_info.localip >> 0 & 0xFF));			
		
		for(i=0;i<4;i++)
		{
			
			if(g_gprs_info.target_con_state[i])
			{
				sprintf(strGprsInf[num++],"CH%d:正常 %d", i+1, g_gprs_info.port[i]);	
			}
			else
			{
				sprintf(strGprsInf[num++],"CH%d:异常 %d", i+1, g_gprs_info.port[i]);			
			}
			sprintf(strGprsInf[num++],"%d.%d.%d.%d", (int)(g_gprs_info.ip[i] >> 24 & 0xFF), (int)(g_gprs_info.ip[i] >> 16 & 0xFF), (int)(g_gprs_info.ip[i] >> 8 & 0xFF), (int)(g_gprs_info.ip[i] >> 0 & 0xFF));	
		}

	 	if(g_aux_csq < 0) //第二个串口没有发送过AT+CSQ指令，用g_gprs_info.csq作为信号质量
	 	{
	 		sprintf(strGprsInf[num++],"信号强度 :%2d",g_gprs_info.csq);
	 	}
		else
		{
			sprintf(strGprsInf[num++],"信号强度 :%2d",g_aux_csq);
		}
		//获取IP地址
		//gprs_net_get_ip();	
		strcpy(strGprsInf[num++],"频段:自适应");
		sprintf(strGprsInf[num++], "发送流量:(%llu B)", g_gprs_info.tx_flowcnt);
		sprintf(strGprsInf[num++], "接收流量:(%llu B)", g_gprs_info.rx_flowcnt);
	
	}
	return num;
}


/******************************************************************************
函数名称：	gprs_net_init
函数版本：	01.01
创建作者：	xxxxxx
创建日期：	2014-06-10
函数说明：	GPRS初始化。
参数说明：	无
返回值：  	成功返回0，失败返回负数。
修改记录：	
*/
int gprs_net_init(void)
{
	pid_t pid=0;
	struct task_struct * ts;
	struct sched_param sp;
	//int ret = 0;	

	if(g_gprs_init_flag)	
	{
		return 0;
	}
	
	g_update_dz = 0; //清标志
	init_completion(&g_exit_completion_gprs);
	init_completion(&g_exit_completion_gprs_aux);
	
	//创建gprs_IEC_proc处理任务
	pid = kernel_thread(gprs_net_IEC_proc, NULL,CLONE_FS | CLONE_FILES | CLONE_SIGHAND);
	ts = find_task_by_vpid(pid);
	if(ts == NULL)
	{
		printk("%s:pid=%d,ts=%p\r\n",__func__,pid,ts);
		return -1;
	}
		
	// 设置调度策略和优先级
	sp.sched_priority = 12;
	sched_setscheduler(ts,SCHED_FIFO,&sp);		
	// 设置进程名字
	set_task_comm(ts, "gprs_IEC_proc");		


	//清零
	memset(&g_gprs_info, 0, sizeof(g_gprs_info));
	//置初始化标志
	g_gprs_init_flag = 1;	
	
	return 0;	
}

#endif
