
#include "base_pc_protocol.h"
#include "platform.h"
#include "function_interface.h"
#include "base_core.h"
#include "base_core_user.h"
#include "func_down_beacon_intf.h"
#include "func_multipkt_up_intf.h"


//-------------------------------------- id mode -----------------------------------------------------------
/*
处理id 模式下的键盘数据
return：
	0- fail
	1- OK	*/
unsigned char keypad_id_mode(const unsigned char *rxkp,unsigned char rf_id)
{		
		unsigned char tmp[64];
		unsigned char offset,len,type;	
		unsigned char dist_offset =3;
	
		mem_set(tmp,sizeof(tmp)/sizeof(tmp[0]),0);
		offset=5;
		len=4;
		
		switch(rxkp[4]){//switch output: type and len 
			
			case 0:	//测试模式
				//------20200401--测验题没有状态报告
				if( vote_beacon.sys_mode ==14){
					type=0x0D;
					len=9;
				}
				else//--------------				
				type=0x0A;				
				break;				
			case 1: //单值
				type=0x01;
				break;				
			case 2://单选多选
				type=0x02;	
				break;				
			case 3://评分
				len=10;
				type=0x03;
				break;				
			case 4://排序
				len=7;
				type=0x05;
				break;
			case 5://键盘协议 3.2.6字符串, id+SN扫描测试无法收齐????????
				len=20;
				type=0x06;
				break;
			case 20://批次单值结果
			case 21://批次评分结果
			case 22://批次单选多选结果
			case 23://另选他人结果
			case 24://批次排序结果
			case 25://批次填空结果
			case 26://另选他人结果
			case 27://备用
			case 28://备用
				len=21;
				type=0x04;
				offset=4;//8;
				break;
			case 33://服务申请	//20200513 //支持键盘请求,	
				type=0x0C;
//				len =4;
//				offset=4;						
				len=3; 
				offset=5;
				tmp[3] =0x02;	//specially 				
				dist_offset=4;
				break;
			
			case 34://发言控制
			case 35://主席控制
				len=4;
				type=0x0C;
				offset=4;//8;
	//			bs_kp.rx_kp_buf[8] -= 31;			//Gavin?
				break;
			
			case 15://多包申请
				len=4;
				type=0x0C;
				offset=4;//8;
	//			bs_kp.rx_kp_buf[8]=1; //Gavin?
				break;				
			case 16://see keypad protocol 3.4.1  //登录信息，比如快速配对，自由配对...
				len=20;
				type=0x0B;
				function.fastmatch__success_check(rxkp+2);//fastmatch_success_check(rxkp+6);
				break;
			
			default: 
				return 0;//break; //error!!!!!
		}//switch		
			
		tmp[0]=type;
		tmp[1]=rxkp[2];
		tmp[2]=rxkp[3];
		//copy rxkp to tmp pointer,from tmp+2;
		mem_cpy(rxkp+offset,tmp+dist_offset,len);	//mem_cpy(rxkp+offset,tmp+3,len);
		
		//特殊处理-------20200630------
		if( rxkp[4]==15){//多包申请
			tmp[3]=1;
		}
		
		if( (rxkp[4]==34)||(rxkp[4]==35) ){//发言控制 //主席控制
			if(tmp[3]>=31)
				tmp[3] -=31;
		}	
		//--------------------------------	
		
		if(vote_data_store(tmp)==0) return 0;
		#ifdef _DBG_2G4_KP_
		_debug_core__record_rxkp_info(rxkp);
		#endif	
		
		//record the keypad id/sn, using in base ack the keypad 
		if( keypad_idsn_save(&rxkp[2],2,rf_id) ==0) return 0;
		
		return 1;
}

//----------------------------------- sn mode -------------------------------------------------------
/*
处理sn 模式下的键盘数据
sn模式: 
	数据类型固定是20;!!!!
	数据长度固定是16
return：
	0- fail
	1- OK
*/
unsigned char keypad_sn_mode(const unsigned char *rxkp,unsigned char rf_id)
{
		unsigned char tmp[32];
		if( (rxkp[2]==12)&&(rxkp[9]==4) )
			function.broadcast__keypad_request(1);
		
		tmp[0] = 20;//type;
		mem_cpy(rxkp+2,tmp+1,16);
		if(vote_data_store(tmp)==0) return 0;
		
		#ifdef _DBG_2G4_KP_
		_debug_core__record_rxkp_info(rxkp);
		#endif	
		
		//record the keypad id/sn, using in base ack the keypad 
		if( keypad_idsn_save(&rxkp[3],6,rf_id) ==0) return 0;
	
		function.fastmatch__success_check(rxkp+7);	
	
		return 1;
}


//--------------------------------- crs2 mode ---------------------------------------------------
/*
处理CRS2 模式下的键盘数据
return：
	0- fail
	1- OK		*/
unsigned char keypad_crs2_mode(const unsigned char *rxkp,unsigned char rf_id)
{	
		unsigned char len,type;	
		unsigned char tmp[64];//		unsigned char tmp[32];
	
		//开启心跳功能后，定时没有收到心跳就不接收键盘数据！
		if( (function.aux_beat__SW)&&(aux_beats.net_timer==0) )		return 0;
		
		if( (rxkp[2]==12)&&(rxkp[9]==4) )
			function.broadcast__keypad_request(1);
	
		//如果开启了白名单功能 SN从byte7开始，CRS2协议下只有4byte???
		if(  log_mode_is_WHITELIST){//if( function.whitelist__SW){			
				//能龙生产测试模式，开启基站发信标后，不判断键盘白名单
				if( ((function.aux_att__SW)&&(aux_att.base_beacon_sw==0))|| (base_core.get_log_mode()==8) ){
					//a,先判断键盘SN是否在名单里,不在名单里就不做任何处理.
					if(function.whitelist__search_special_list(rxkp+3) ==NULL) 	
						return 0;
				}
				
				//b,检测到有白名单申请，后续无需处理
				if(function.whitelist__keypad_idsn_record_request(rxkp) ) return 0;				
				
//				//c,白名单模式下，对键盘数据的分析
//				if( rxkp[2] ==4 ){
//					type = (rxkp[1] == 0x93)?22:26;
//					len =rxkp[0];//-4;
//					if(len>27)	len =27;			//???				
//				}
//				else{
//					type = 21;//(rxkp[1] == 0x93)?21:25;//20200518
//					len =rxkp[0];//-4;
//					if(len>16)	len =16;	//??				
//				}		
		}	 		
		//else
			
		{//非CRS2协议，即普通SN模式，对键盘数据的分析
				if( rxkp[2] ==4 ){//string
//					if(log_mode_is_WHITELIST)
//						type = (rxkp[1] == 0x93)?22:26; 
//					else
					type = 22;
					len =rxkp[0];
					if(len>27)	len =27;				
				}
				else if(rxkp[2] ==9){//Keypad protocolV0.99 section3.2.3,字符串，带电量,对应基站协议3.2.7
					type = 28;
					len = 27;
				}
				else if( (rxkp[2] ==7) ||(rxkp[2]==8)){//protocol keyapd section3.2.11 对应基站协议3.2.6
					type = 27;
					len = 27;	
				}	
                #if MD_MULTIPKT_UP
                else if(rxkp[2] == 32){
                    //return func__multipkt_up_intf.rx_request(rxkp);
                    if(func__multipkt_up_intf.rx_request(rxkp))
                    {
                        return keypad_idsn_save(&rxkp[3],4,rf_id);  
                    }
                    else
                      return 0;  
                }
                #endif
				else{
					type = 21;
					len =rxkp[0];
					if(len>16)	len =16;									
				}						
		}
        
        tmp[0] =type;
        mem_cpy(rxkp+2,tmp+1,len);
        if(rxkp[17] == 1  && rxkp[2] == 11)//入网申请,20220621
        {
            if((rxkp[15]*256 + rxkp[16])== function.network__get_pwd() || function.network__get_pwd()==0)//密码正确或无密码
            {
                if(vote_data_store(tmp)==0) return 0;
            }
        }
        else
        {
            if(vote_data_store(tmp)==0) return 0;
		}

		
		//record the keypad id/sn, using in base ack the keypad 
		if( keypad_idsn_save(&rxkp[3],4,rf_id) ==0) return 0;
		
		#ifdef _DBG_2G4_KP_
		_debug_core__record_rxkp_info(rxkp);
		#endif
		
		function.fastmatch__success_check(rxkp+15);
		
		return 1;
}





/*--------------------------------------------------------------------------
开辟一个缓冲器用于处理键盘的无线数据！！！
*/
#define 	KPRX_NODE_SIZE		15		//节点个数，即缓冲区长度
#define 	KPRX_DATA_SIZE  	65//64	//数据的最大长度
struct fifo_queue_STR  kprx_queue;
unsigned char kprx_buf[KPRX_NODE_SIZE][KPRX_DATA_SIZE];
/*
*/
void kprx_init_queue(void)
{
	queue_init(&kprx_queue,(unsigned char**)kprx_buf,KPRX_NODE_SIZE,KPRX_DATA_SIZE);	
}

/*
基站接收键盘数据，将键盘数据保存到 队列中
被 无线中断函数调用 */
unsigned char keypad_rf_data_save( unsigned char *rf_data)	
{	
	#ifdef MAINLOOP_PROCESS_VOTE
	return queue_in(&kprx_queue,rf_data,KPRX_NODE_SIZE,KPRX_DATA_SIZE);	
	#else
	keypad_rf_data_process_NO_fifo(rf_data);
	return 1;
	#endif
}

/*
从缓冲区中取出键盘数据 
input: rf_data[0] =len */
unsigned char keypad_rf_data_fetch(unsigned char *rf_data)	
{	
	unsigned char ret_val;
	PLATFORM_DISABLE_IRQ();//platform.disable_interrupt();	
	ret_val =queue_out(&kprx_queue,rf_data,KPRX_NODE_SIZE,KPRX_DATA_SIZE);
	PLATFORM_ENABLE_IRQ();//platform.enable_interrupt();
	return ret_val;
}

#ifndef RF_5G8
volatile unsigned int error_cnt;
void keypad_rf_data_process_NO_fifo(unsigned char *tmp)
{		
		unsigned char modual_id,*keypad_buf;
//		unsigned char tmp[64+1];
//	
//		if(!keypad_rf_data_fetch(tmp) ){			
//			return;
//		}
            
        #if MD_MULTIPKT_UP
		if( func__multipkt_up_intf.rx_data(tmp) ) return;
		#endif
    
		if(tmp[1] <4) return; //避免后续执行keypad_buf[0]-4出错!!!

		//monitor same freq
		if( (function.fastmatch__get_status() ==0) && (function.monitor__rf_data(tmp+1)!=0) )//if( function.monitor__SW &&(function.monitor__rf_data(tmp)!=0) )
			return;	
		
		//AES 解密出错，数据丢弃！！！
		if( !function.aes__rf_Decrypt(tmp+1) )return ;
		if( (modual_id = conver_id(tmp[0])) ==0xff) return ;//硬件id转换成内部id，处理更方便	
		keypad_buf = tmp+1;	//用指针更灵活!!
		
			
		//crc16全校验功能
		if( keypad_crc_check() && \
			 ( (keypad_buf[5]==0x91)||(keypad_buf[5]==0x92)||(keypad_buf[5]==0x93)||(keypad_buf[5]==0x94) ) ){
			unsigned short crc;	
			if(function.crc16_keypad__SW==2){ //22bytes的CRC
				crc =(keypad_buf[27]<<8)+keypad_buf[28];
				//a,0x00不校验
				//if( ((crc =(keypad_buf[27]<<8)+keypad_buf[28])>0x00)&&(crc !=crc16(keypad_buf+5,22)) )return ;
				//b,所有数据都校验，包括0x00!!
				if( crc !=crc16(keypad_buf+5,22) )return ;

			}
			else if(function.crc16_keypad__SW==3){	//22 or 26 bytes 
				crc = (keypad_buf[27]<<8)+keypad_buf[28];
				if( crc !=crc16(keypad_buf+5,22) ){
					crc =(keypad_buf[31]<<8)+keypad_buf[32];
					if( crc !=crc16(keypad_buf+5,26) )return ;				
				}				
			}
			else{	//26Bytes的CRC
				crc =(keypad_buf[31]<<8)+keypad_buf[32];
				if( crc !=crc16(keypad_buf+5,26) )return ;
			}
			
		}
		#if UPDATE_KP_2
		if(	(keypad_buf[5]!=0x91)&&(keypad_buf[5]!=0x92)&&(keypad_buf[5]!=0x93)&&(keypad_buf[5]!=0x94) ){
			if(function.updatekp__SW && function.update__save_keypad_ack_data(keypad_buf) ){
				refresh_rcvRF_indicate();
				return;
			}
		}
		#endif
		
		if(!function.no_matchcode__SW){
			if( ((keypad_buf[5]==0x93)&&(keypad_buf[6]==14)) ||
				log_mode_is_free_match || log_mode_is_WHITELIST ){
					//考勤,免配对模式，白名单模式都不验证配对码;
			}
			else{
				if(mem_compare(keypad_buf+1,base_mac.match_code,BASE_MAC_LEN) ==0) 
					return;
			}
			//remove match code ,之后的数据和协议byte完全吻合，便于阅读比对 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
			mem_cpy(keypad_buf+5,keypad_buf+1,keypad_buf[0]-4);
			keypad_buf[0] -=4;				
		}
		
		
		//-----是基站数据 //2020.04.14
		if(keypad_buf[1]<0x80){	
			//此处做 :a同频检测;b多基站检测			
			return;
		}
		
		//led2_indicate rx	
		refresh_rcvRF_indicate();//led2_indicate_rf();				
	
		if( keypad_buf[1] ==0x91){
			keypad_id_mode(keypad_buf,modual_id);
		}
		else if( keypad_buf[1] ==0x92){//sn mode
			keypad_sn_mode(keypad_buf,modual_id);
		}		
		else if((function.crs2__SW)&& ( (keypad_buf[1] ==0x93)||(keypad_buf[1] ==0x94)) ){ //crs2
			keypad_crs2_mode(keypad_buf,modual_id);
		}	
        #if (MD_DOWN_BEACON)
		else if(keypad_buf[1] ==0xB7){
			func__down_beacon_intf.kp_rx(keypad_buf);						
		}
		#endif	
		else{ //transfer to pc //键盘转发数据给pc,基站不做处理
			//来自键盘的考勤数据:08 fb 3c 04 80 74 11 e2 fd; 此数据可能不能到达这里!!!??
			if( (keypad_buf[0] ==0x18)&&
				(keypad_buf[1] ==keypad_buf[2])&&(keypad_buf[1] ==keypad_buf[3])&&
				(keypad_buf[1] ==keypad_buf[4])&&(keypad_buf[1] ==keypad_buf[5])
			){
				error_cnt++;
				return;
			}
			function.user_keypad_transfer2pc(keypad_buf);
			
			//如果是键盘升级模式，并且是键盘回应的升级相关数据，就需要转发给pc 
			if(function.updatekp__SW && function.update__save_keypad_ack_data(keypad_buf) )return; //应该将此函数移到 function.user_keypad_transfer2pc(keypad_buf);中去处理？
			
			keypad_transfer2pc_data_save(keypad_buf);//store to transfer buffer 
//			tmp[0] =tmp[0]; //debug only
		}
}
#endif //

/*
基站处理来自键盘 数据 总入口 
将键盘数据分成4中类型：
	id 模式
	sn 模式
	CRS2 模式
	转发至pc的数据
called by main loop		*/
void keypad_rf_data_process(void)
{		
//		unsigned char modual_id,*keypad_buf;
		unsigned char tmp[64+1];
	
		if(!keypad_rf_data_fetch(tmp) ){			
			return;
		}
		
		keypad_rf_data_process_NO_fifo(tmp);
}



/*
初始化 键盘相关
a, 初始化接收键盘的队列
b,初始化转发给键盘的数据队列
called by main init	*/
void base_process_keyapad_init(void)
{
		#ifdef RF_5G8
		base_process_5G8_keyapd_init_queue();
		#endif
	
		kprx_init_queue();	
		transfer2kp_init_queue();	//pc transfer to keyapd queue init.						
		keypad_idsn_clear();
		base_send_beacon_switch(1);		//开启基站发送信标数据
	
}



