
#include "base_pc_protocol.h"
#include "platform_interface.h"
#include "function_interface.h"
#include "function.h"
#include "base_core.h"
#include "base_core_user.h"
#include "gen_lgpkt_ch_intf.h"
#include "func_multipkt_up_intf.h"
#include "fast_beacon_intf.h"
#include "stop_beacon_intf.h"

//----------------------0x61 ---------------------------------------------
#define 	_0x61_READ_BASE_CONFIG	    1
#define 	_0x61_WRITE_BASE_CONFIG	    2
#define 	_0x61_READ_HD_INFO			3
#define 	_0x61_WRITE_HD_INFO			4
#define 	_0x61_READ_MAC				5
#define 	_0x61_WRITE_MAC				6
#define 	_0x61_DFU					7

#define 	_0x61_SOFT_DOG				9 
#define 	_0x61_CHAN_ASSESS			10
#define 	_0x61_AUX_CONFIG			11
#define 	_0x61_TCPIP_CONFIG			12 
#define 	_0x61_BASE_TEST				13 
#define 	_0x61_WHITE_LIST			14 	// whitelist
#define		_0x61_READ_OEM				15
#define		_0x61_WRITE_OEM				16
#define 	_0x61_DETELE_CAP_SN		    17
#define 	_0x61_MGNT_KPLIST			18
#define 	_0x61_LGPKT_SPLIT			19

#define		_0x61_UPDATE_KP				22
#define 	_0x61_READ_AES_CONFIG		23//23//17  //通讯加密读
#define 	_0x61_BASE_PKTUP			23	//sdk询问基站多包数据
#define 	_0x61_WRITE_AES_CONFIG	    24//18 
#define 	_0x61_READ_CRC_CONFIG		25	
#define 	_0x61_WRITE_CRC_CONFIG	    26 
#define		_0x61_BASE_SINGLE_PKT		27

#define		_0x61_SDK_EXIT		        33

/*
基站回应来自pc的0x61命令 */
void pc_cmd_0x61_ack(unsigned char type,const unsigned char *ack_buf,unsigned char type_data_len)
{
		unsigned char tmp[64]; //whitelist 需要的buf长些

		mem_set(tmp,sizeof(tmp)/sizeof(tmp[0]),0);
		tmp[0]= 31;
		tmp[1]= 0xE1;
		tmp[2]= get_base_id();//pc2bs_Bb.bs_id;
		tmp[3]= type;
		mem_cpy( ack_buf,tmp+4,type_data_len);
		
		//send to pc 
		base_tx_to_pc_sub(tmp);
}



/*
* case _0x61_AUX_CONFIG的子函数处理
*/
static void _0x61_AUX_CONFIG_sub(const unsigned char *rxpc)
{
		unsigned char ack_buf[64];
	
		ack_buf[0] =rxpc[4];
		switch(rxpc[4]){
			case 2: //write log moe and base name 					
				mem_cpy(rxpc+5,&base_name_log_mode.head_addr+1,BASE_NAME_LOG_MODE_LEN);			
				assert_base_log_mode();			
				base_write_e2prom(STORE_BASE_NAME_ADDR,&base_name_log_mode.head_addr+1,BASE_NAME_LOG_MODE_LEN);				
				ack_buf[0] =1;
			case 1: //read log_mode and base name  base_name_log_mode					
				mem_cpy(&base_name_log_mode.head_addr+1,ack_buf+1,BASE_NAME_LOG_MODE_LEN);	//used ack pc			
				pc_cmd_0x61_ack(_0x61_AUX_CONFIG,ack_buf,BASE_NAME_LOG_MODE_LEN+1);
				break;

			case 4://write multi channal parameter!!,add by Gavin 20190718
				mem_cpy(rxpc+5,&multi_freq_setup.head_addr+1,MULTI_FREQ_LEN);
				if(function.lock_rf_count)
					multi_freq_setup.chan_count=function.lock_rf_count;
				if( (multi_freq_setup.chan_count==0) ||(multi_freq_setup.chan_count>4) )//模块数不能为零,至少也有一个
					multi_freq_setup.chan_count=1;
					//sdk设置的无线模块个数不能大于硬件实际模块个数
				if(multi_freq_setup.chan_count >multi.hard_rf_modual_cnt)
					multi_freq_setup.chan_count =	multi.hard_rf_modual_cnt;
				
				process_setup_multi_chan(multi_freq_setup.chan_freq[0]);//update single channel 
				//base_write_e2prom(STORE_MULTI_CHAN_ADDR,&multi_freq_setup.head_addr+1,MULTI_FREQ_LEN);	//write e2prom				
				ack_buf[0] =4;
			case 3://read multi channal parameter!!
				if(function.base_type ==TYPE_C100) break;
				if(function.base_type ==TYPE_CRS200) break;
				if(function.base_type ==TYPE_EVS100) break;
				mem_cpy(&multi_freq_setup.head_addr+1,ack_buf+1,MULTI_FREQ_LEN);
				pc_cmd_0x61_ack(_0x61_AUX_CONFIG,ack_buf,MULTI_FREQ_LEN+1);
				break;
			
			//AUX_ATT
			case 12:	//write 
				if(!function.aux_att__SW)	break;
				mem_cpy(rxpc+5,&aux_att.head_addr+1,AUX_ATT_LEN);
				base_write_e2prom(STORE_AUX_ATT_ADDR,&aux_att.head_addr+1,AUX_ATT_LEN);
			case 11: //read
				if(!function.aux_att__SW)	break;
				ack_buf[0] =11;
				mem_cpy(&aux_att.head_addr+1,ack_buf+1,AUX_ATT_LEN);					
				pc_cmd_0x61_ack(_0x61_AUX_CONFIG,ack_buf,AUX_ATT_LEN+1);
				break;				
			
			//#ifdef AUX_BEATS			//教育新版-基站部分V0.9  section5.2.3		
			case 10://write //SDK定时10S向基站设置一次.....
				if(!function.aux_beat__SW)	break;
				if(rxpc[5]==1)
					aux_beats.net_timer= 30; //30*0.5S=15S					
			case 9: //读取免配对SN号模式下的网络状态	
				if(!function.aux_beat__SW)	break;
				ack_buf[0] =9;
				ack_buf[1] = (aux_beats.net_timer>0);
				pc_cmd_0x61_ack(_0x61_AUX_CONFIG,ack_buf,2);					
				break;				
			//#endif				
			
//			case 16: //write
//				fastmatch_lowerPA.lower_PA =rxpc[5];
//			case 15:
//				ack_buf[0] =15;
//				ack_buf[1] =fastmatch_lowerPA.lower_PA;
//			  pc_cmd_0x61_ack(_0x61_AUX_CONFIG,ack_buf,2);	
//				break;			
			case 16: //write
				function.fastmatch__lowPA_setup(rxpc);
			case 15:
				function.fastmatch__lowPA_ack();
				break;
			
			//NFC 
			case 20:			
			case 19:
				//function.nfc__pc_interaction(rxpc);
				break;			
			
			//read/wrtie ext basic beacon ;include base multi channel info
			case 22: //write
				mem_cpy(rxpc+5,&basic_ext_beacon.head_addr+1,BASIC_EXT_BEACON_LEN);
				//base_write_e2prom(STORE_BASIC_EXT_BEACON_ADDR,&basic_ext_beacon.head_addr+1,BASIC_EXT_BEACON_LEN);//20200415不保存基础扩展信标，				
				if( basic_ext_beacon.base_count!=0)
					set_ext_basicbeacon_startup_flag(1); //startup BASE send Ext beacon and Gen beacon
				else
					set_ext_basicbeacon_startup_flag(0); 
			case 21:
				ack_buf[0] =21;
				mem_cpy(&basic_ext_beacon.head_addr+1,ack_buf+1,BASIC_EXT_BEACON_LEN);			
				pc_cmd_0x61_ack(_0x61_AUX_CONFIG,ack_buf,BASIC_EXT_BEACON_LEN+1);	
				break;				
			case 24: //write log moe and base name 					
				mem_cpy(rxpc+5,&base_name_setup.head_addr+1,AUX_NAME_LEN);	
                assert_base_log_mode();	
                function.network__set_name(base_name_setup.base_name, 12);	
                function.network__set_netseq_change();            
				base_write_e2prom(STORE_BASE_NAME_ADDR,&base_name_setup.head_addr+1,AUX_NAME_LEN);				
				ack_buf[0] =23;
			case 23: //read log_mode and base name  base_name_log_mode					
				mem_cpy(&base_name_setup.head_addr+1,ack_buf+1,AUX_NAME_LEN);	//used ack pc			
				pc_cmd_0x61_ack(_0x61_AUX_CONFIG,ack_buf,AUX_NAME_LEN+1);
				break;
            case 26: //write base password					
				mem_cpy(rxpc+5,&base_pwd_setup.head_addr+1,AUX_PWD_LEN);
                if((base_pwd_setup.base_pwd[0]*256+base_pwd_setup.base_pwd[1])>60000)
                {
                    base_pwd_setup.base_pwd[0] = 0xEA;
                    base_pwd_setup.base_pwd[1] = 0x60;
                }
                function.network__set_pwd(base_pwd_setup.base_pwd[0]*256+base_pwd_setup.base_pwd[1]);
                function.network__set_netseq_change();
				base_write_e2prom(STORE_BASE_PWD_ADDR,&base_pwd_setup.head_addr+1,AUX_PWD_LEN);
				ack_buf[0] =25;
			case 25: //read base password					
				mem_cpy(&base_pwd_setup.head_addr+1,ack_buf+1,AUX_PWD_LEN);	//used ack pc			
				pc_cmd_0x61_ack(_0x61_AUX_CONFIG,ack_buf,AUX_PWD_LEN+1);
				break;
#if MD_SPECIAL_STOP_PRO
		case 30:
		case 31:	
		case 32:
		case 33:	
			core__stop_beacon_intf.rxpc(rxpc);
			break;
#endif
		case 35://设置基站名称是否可见
			network_set_nameview(rxpc[5]);
			base_write_e2prom(STORE_BASE_NAME_VIEW,rxpc+5,1);
		case 34:
			ack_buf[0] =rxpc[4];
			ack_buf[1] = network_get_nameview();
			pc_cmd_0x61_ack(_0x61_AUX_CONFIG,ack_buf,1+1);		
			break;
		
#if MD_FAST_BEACON
            case 29:
                core__fast_beacon_intf.rxpc(rxpc);
                break;
#endif
			default:
				function.user_pc_0x61cmd_type0x0B(rxpc);
				break;
		}//sw		
}


/*处理软件狗子程序
20200908-10调试:
两个SDK对软件狗的处理方法不一致:
1,旧SDK 
	S1,cmd1核对密码再读写操作
2,新DT 
	write:直接cmd3写数据
	read: cmd4读密码核对,然后才读
*/
void _0x61_soft_dog_sub(const unsigned char *rxpc)
{
		unsigned char ack_buf[32],ack_len;
		unsigned char tmp[16],i,rslt=0;
		static unsigned char oem_code_check_rslt=0;	
	
		ack_buf[0] =rxpc[4]; //sub type 			
		switch(rxpc[4]){
			case 1://1核对密码
				base_read_e2prom(STORE_OEM_CODE_ADDR,tmp,8); //Gavin				
				if( mem_compare(tmp,rxpc+6,8) ==0 ){
					oem_code_check_rslt =0;
					ack_buf[1] =oem_code_check_rslt;				
					ack_len=2;					
				}
				else{
					oem_code_check_rslt =1; //result
					ack_buf[1] =oem_code_check_rslt;	
					mem_cpy(tmp,ack_buf+2,8);	//将秘钥加载到ack 中;	
					ack_len=2+8;					
				}
				break;
					
			case 2: //读用户区
			case 3:	//写用户区					
				//if( (!oem_code_check_rslt)||(rxpc[5] >4) ){//密码核对不正确或者的区号超出都是错误的
				if( rxpc[5] >4){
					ack_buf[1] =0; //zone
					ack_buf[2] ='L';
					ack_buf[3] ='O';
					ack_buf[4] ='C';
					ack_buf[5] ='K';
					ack_len=6;
				}else{
					ack_buf[0] = 2;
					ack_buf[1] = rxpc[5];	//area 0-3
					if( rxpc[4] ==2){//read
						platform.e2prom_read(STORE_OEM_USER_ADDR+rxpc[5]*16,ack_buf+2,16); 
						//base_read_e2prom(STORE_OEM_USER_ADDR+rxpc[5]*16,ack_buf+2,16); //Gavin 
						ack_len=18;
					}else{//write 
						platform.e2prom_write(STORE_OEM_USER_ADDR+rxpc[5]*16,(unsigned char *)rxpc+6,16); 
						//base_write_e2prom(STORE_OEM_USER_ADDR+rxpc[5]*16,rxpc+6,16); //Gavin	
						mem_cpy(rxpc+6,ack_buf+2,16);
						ack_len=18;
					}				
				}
				break;													
			case 4: //读密码
				base_read_e2prom(STORE_OEM_CODE_ADDR,ack_buf+2,8);	
				ack_buf[0] =3;
				ack_buf[1] =0;
				ack_len=10; //8+2
				break;
			case 5: //写用户区密码
				base_write_e2prom(STORE_OEM_CODE_ADDR,rxpc+6,8);
				if(*(rxpc+6) != '@')
				{
					kernel.custom_rf_sync_code = calc_custom_rf_sync_code(rxpc+6);
					platform.rf_update_sync_code(calc_custom_rf_sync_code(rxpc+6),4,get_main_rf_hard_id() );//platform.rf_update_sync_code(calc_custom_rf_sync_code(rxpc+6),4,get_main_rf_hard_id() );
				}
				else
				{
					kernel.custom_rf_sync_code =0;
					platform.rf_update_sync_code(0xA455,4,get_main_rf_hard_id() );
				}
				ack_buf[0] =3;
				ack_buf[1] =0;
				mem_cpy(rxpc+6,ack_buf+2,8);
				ack_len=10; //8+2
				break;
			case 6: //读芯片UID
				#if 0 //#ifdef RF_MODUAL_MONITOR						
				ack_len= get_rf_error_cnt(ack_buf+2);
				ack_len+=2;
				#else				
				ack_buf[1] =0;
				platform.get_chip_id(ack_buf+2);//chip id length is 12bytes  //Gavin
				ack_len=14;
				#endif
				break;					
			default: rslt =1;break;
		}//sw
		
		if(rslt==0)		pc_cmd_0x61_ack(_0x61_SOFT_DOG,ack_buf,ack_len); 
}





/*----------------------
基站处理来自pc的0x60命令
1,复制相关参数
2，保存到E2prom
3, 回应pc*/
unsigned char pc_cmd_0x61_process(const unsigned char *rxpc)
{
	unsigned char ack_buf[32];
	
	switch(rxpc[3]){
		
		//----1,2 read write base configuare
		case _0x61_WRITE_BASE_CONFIG://write base config
			//a,copy data
			//disable_INT();
			mem_cpy( rxpc+4,&base_config.head_addr+1,BASE_CONFIG_LEN);		
			//enable_INT();			
			assert_base_id();//assert base id 		
			assert_base_channel(); //assert base channal, then set it to RF module;
			process_setup_single_chan(base_config.chan); //syn to multi channel 					
			//b, setup rf power
			platform.rf_set_send_pwr(base_config.rf_pwr,get_main_rf_hard_id());	//get_mainRF_usr_id()
			for(unsigned char i=0;i<multi.hard_rf_modual_cnt;i++){
				platform.rf_set_send_pwr(base_config.rf_pwr,i);
			}
			//c, ack pc
		case _0x61_READ_BASE_CONFIG://read base config
			pc_cmd_0x61_ack(_0x61_READ_BASE_CONFIG,&base_config.head_addr+1,BASE_CONFIG_LEN);
			break;
	
		 //-----3,4 read write hardware info
		case	_0x61_WRITE_HD_INFO:
			//disable_INT();
			mem_cpy( rxpc+4,&base_hdinfo.head_addr+1,BASE_HDINFO_LEN);		
			//enable_INT();
			set_base_hard_firmware_info();//function.version_info(); //设置固定的硬件信息
			base_write_e2prom(STORE_BASE_HDINFO_ADDR,&base_hdinfo.head_addr+1,BASE_HDINFO_LEN);
		case	_0x61_READ_HD_INFO:
			pc_cmd_0x61_ack(_0x61_READ_HD_INFO,&base_hdinfo.head_addr+1,BASE_HDINFO_LEN);
			break;		
		
		//----5,6 read write match code 	
		case _0x61_WRITE_MAC://write match code
			//disable_INT();
			mem_cpy( rxpc+4,&base_mac.head_addr+1,BASE_MAC_LEN);		
			//enable_INT();
			base_write_e2prom(STORE_BASE_MAC_ADDR,&base_mac.head_addr+1,BASE_MAC_LEN);
		case _0x61_READ_MAC://read match code			
			get_base_match_code(ack_buf);//20200401 add by Gavin; 增加免配对模式log_mode=3;=6;
			pc_cmd_0x61_ack(_0x61_READ_MAC,ack_buf,BASE_MAC_LEN);
			//pc_cmd_0x61_ack(_0x61_READ_MAC,&base_mac.head_addr+1,BASE_MAC_LEN);
			break;		
			
		//-------7 base DFU
		case _0x61_DFU://基站升级
			ack_buf[0] =1;		
			platform.e2prom_write(STORE_DFU_ADDR,ack_buf,1);//base_write_e2prom(STORE_DFU_ADDR,ack_buf,1); //write 1 as flag,use and reset in bootloader!!
			
			platform.system_reset(); //执行此命令后，mcu复位，之后的ack pc实际是不会执行
			pc_cmd_0x61_ack(_0x61_DFU,ack_buf,1);
			break;
		
		//-------9 software dog 
		case _0x61_SOFT_DOG:
			_0x61_soft_dog_sub(rxpc);
			break;
		
		//-------10 信道评估
		case _0x61_CHAN_ASSESS:
			if( (rxpc[4]==1)||(rxpc[4]==2)){//exit or enter	
				ack_buf[0]=(rxpc[4]==1)?0:1;
				pc_cmd_0x61_ack(_0x61_CHAN_ASSESS,ack_buf,1); 
		  }
			else if( rxpc[4]==4){ //swtich channel auto	同频点检测 //Gavin
					function.monitor__auto_search_freq_enter();
			}				
			break;
		
		//------11 通用附加配置
		case _0x61_AUX_CONFIG: //0x0B
			_0x61_AUX_CONFIG_sub(rxpc);
			break;
		
		//-------12 TCP IP设置
		case _0x61_TCPIP_CONFIG:
			//function.tcpip__config_enter(rxpc);
			//_0x61_tcpip_sub(rxpc);
			break;
		
		//-------13 基站测试
		case _0x61_BASE_TEST:
			//if( !function.basetest__get_status()) break;		
			function.basetest__rx_and_ack_pc(rxpc,ack_buf);					
			pc_cmd_0x61_ack(_0x61_BASE_TEST,ack_buf,9);	
			break;
		
		//-------14 白名单功能 whitelist 
		case _0x61_WHITE_LIST:
//			if( !function.whitelist__SW) break;	//白名单功能没有开启就不处理		
//			function.whitelist__enter(rxpc);
			break;
        
        case _0x61_LGPKT_SPLIT://5.3.5
			#if (MD_GEN_LGPKT_CH)
                core__gen_lgpkt_intf.rx_pc(rxpc);		
			#endif	
			
			break;
		
		//--------15,16 读写 OEM 
		case _0x61_READ_OEM:
			break;		
		case _0x61_WRITE_OEM:			
			break;
		
		//-----------22 update keyapd firmeware
		case _0x61_UPDATE_KP:
			if( vote_beacon.sys_mode != 0 && rxpc[5]!=30){// 只有非短信广播的多包下载才退出当前业务，短信广播可以接受但不能改变当前业务 20220517
				vote_beacon.sys_mode =0;        //退出当前业务！ add by Gavin 2020.12.21
                mem_set(vote_beacon.vbuf,5,0);
			}
			function.update__kp_enter(rxpc);
			break;
	
//		//--------23,24 AES config 
//		case _0x61_READ_AES_CONFIG:
//		case _0x61_WRITE_AES_CONFIG:
//			function.aes__config_enter(rxpc);			
//			if(rxpc[3] ==_0x61_WRITE_AES_CONFIG)//20210324 设置AES时关联配置crc_flag
//				set_keypad_crc_config( (rxpc[4]!=0)?1:0 );
//			break;		
        
        #if MD_MULTIPKT_UP
		case _0x61_BASE_PKTUP:
			func__multipkt_up_intf.rx_pc(rxpc);
			break;
		#endif    
            
		//keypad CRC switch
		case _0x61_WRITE_CRC_CONFIG://	26 
			set_keypad_crc_config(rxpc[4]);
			
		case _0x61_READ_CRC_CONFIG://		25
			ack_buf[0]= kernel.keypad_crc_flag; //get_keypad_crc_config();//rxpc[4];
			pc_cmd_0x61_ack(_0x61_READ_CRC_CONFIG,ack_buf,1);
			break;
		
		
		default:
			function.user_pc_0x61cmd(rxpc);
			break;
	}//sw
	
	return 1;
}




