
#include "base_core_user.h"
#include "function.h"
#include "stdio.h"
#include "string.h"
#include "function_interface.h"

/*
见教育新版，基站协议section5.3 
白名单保存是连续的,如果检测到为空 0x000000的元素就表示后续没有了
所以特别注意：删除白名单后将其填写0xaaaaaaa(当然这样做就要避免全a的sn号，)
*/
#define		LIST_MAX						200
#define 	LIST_CNT_OF_1ZONE		10
#define 	ZONE_MAX						(LIST_MAX/LIST_CNT_OF_1ZONE)
 
unsigned char list[LIST_MAX][4];
unsigned char list_valid_cnt=0;
unsigned char list_request_flag=0;
unsigned char list_sn[4];



////--------------------------- 授权相关 ----------------------------------------------------
/*
删除白名单:
a，删除单个名单 --给单个键盘发授权
b, 删除所有名单 --广播发送授权
实现：
连续发送xx次授权命令;
*/
#define 	DELETE_MULTI				//20200909 add by Gavin add delete multi whitelist
#define 	DELETE_MULTI_MAX		30

struct wlist_STR{
	unsigned short link_sdk_timer;
	unsigned char link_sdk_flag;
	unsigned char auth_type;
	unsigned short auth_resend_times;
	#ifdef DELETE_MULTI
	unsigned char auth_keypad_sn[DELETE_MULTI_MAX][4];
	unsigned char auth_keypad_cnt;	//删除的个数
	unsigned char auth_keypad_cur;	//授权发送轮询
	#else
	unsigned char auth_keypad_sn[4];
	#endif
};

struct wlist_STR wlist;

/*
* 删除所有名单时:写第一区;b,基站与sdk断连
*/
void auth_all_keypad(void)
{
	unsigned short i;
	wlist.auth_type =2;
	wlist.auth_resend_times=0;
	
	for(i=0;i<LIST_MAX;i++) 
		memset(list[i],0,4);	
}

/*
* 删除单个白名单时
*/
void auth_special_keypad(const unsigned char *sn)
{
	#ifdef DELETE_MULTI
	unsigned char i;
	for(i=0;i<DELETE_MULTI_MAX;i++)
		memcpy(wlist.auth_keypad_sn+i,sn+(i<<2),4);
	
	#else
	memcpy(wlist.auth_keypad_sn,sn,4);	
	#endif
	wlist.auth_type =1;
	wlist.auth_resend_times=0;
}


/*
* 授权参考键盘协议5.3.1
*/
unsigned char whitelist__tx_authcode_to_keypad(void)
{
		unsigned char tmp[32];
		if(!function.whitelist__SW || (wlist.auth_type==0) ) return 0;
		tmp[0]=0x1A+2;
		base_core.get_match_code(tmp+1);//match code 		
		tmp[5]=0x30;	
		tmp[6]=0; //broadcast for default;
		tmp[7]=0;		
		tmp[8]=20;			
		tmp[9]=0x04;
		memset(tmp+10,0,19);	//设置从tmp10开始后的18个数为0
		if(wlist.auth_type==1){//指定sn
			tmp[6]=0xff;
			tmp[7]=0xff;	
			#ifdef DELETE_MULTI
			if(wlist.auth_keypad_cur >= wlist.auth_keypad_cnt)
				wlist.auth_keypad_cur=0;
			tmp[14]=wlist.auth_keypad_sn[wlist.auth_keypad_cur][0];	//SN
			tmp[15]=wlist.auth_keypad_sn[wlist.auth_keypad_cur][1];
			tmp[16]=wlist.auth_keypad_sn[wlist.auth_keypad_cur][2];
			tmp[17]=wlist.auth_keypad_sn[wlist.auth_keypad_cur][3];	
			wlist.auth_keypad_cur++;
			#else
			tmp[14]=wlist.auth_keypad_sn[0];	//SN
			tmp[15]=wlist.auth_keypad_sn[1];
			tmp[16]=wlist.auth_keypad_sn[2];
			tmp[17]=wlist.auth_keypad_sn[3];
			#endif
		}		
		//send 	
		base_core.send_rf_data(tmp,base_core.get_mainRF_hard_id());		
		return 1;
}



/*
*called by 2.5ms;
*/
void whitelist__2ms5_call(void)
{
	if(!function.whitelist__SW) return;
	
	//a,
	if(base_core.get_sdk_connect_status() ){//online
//		if(wlist.link_sdk_flag)
//			wlist.link_sdk_flag=0;
	}
	else{
		if(wlist.link_sdk_flag==0){
			wlist.link_sdk_flag=1;
			auth_all_keypad();//授权
		}
	}
		
	//b,执行发送授权
	if(!wlist.auth_type) return;
	if(++wlist.auth_resend_times<200)
		whitelist__tx_authcode_to_keypad();
	else{
		wlist.auth_type=0;
		wlist.auth_resend_times=0;
		memset(wlist.auth_keypad_sn,0,4);
	}
}
//---------------------------- 授权 end ------------------------------------------------------------------






/*
计算一个区内有效list的个数
*/
static unsigned char calc_valid_list_cnt(const unsigned char *ptr)
{		
		unsigned short i,j;
		unsigned char cnt=0;
	
		for(i=0;i<LIST_CNT_OF_1ZONE;i++){			
			j= i<<2;		
			if( (ptr[j]==0)&&(ptr[j+1]==0)&&(ptr[j+2]==0)&&(ptr[j+3]==0) )
				continue;			
			cnt++;
		}//for
		return cnt;
}


/*
根据区号计算出对应list的位置
*/
static unsigned short get_offset(unsigned char zone)
{
		return (zone*10);
}


/*
写list子函数
offset: 写入的位置在总list中的偏移量
ptr:要写入的数据指针
cnt:要写入的list个数！！
*/
static void write_list_sub(unsigned char offset,const unsigned char *ptr,unsigned char cnt)
{
		unsigned short i;
		for(i=0;i<cnt;i++)
			memcpy(list[offset+i],ptr+(i<<2),4);//mem_cpy(ptr+(i<<2),list[offset+i],4);			
		list_valid_cnt +=cnt;	//总有效数增加
}
	

/*
初始化白名单相关参数
*/
void whitelist_init(void)
{
		unsigned short i;
	
		list_request_flag=0;
		list_valid_cnt =0;		//valid conter =0;
		for(i=0;i<LIST_MAX;i++) 
			memset(list[i],0,4);	
	
		wlist.auth_type=0;
		wlist.auth_resend_times=0;
		wlist.link_sdk_flag =0;
		wlist.link_sdk_timer=0;
}



/*--------------------------------------------------------------------------------------
读取指定区号的白名单数据，保存到ptr指针
一个区最多保存10个SN号
*/
static unsigned char whitelist_read_1zone(unsigned char zone,unsigned char *ptr)
{ 
		unsigned short i,j,offset;	
		if(zone>=ZONE_MAX) return 0;
	
		offset =get_offset(zone);			//得到起始位置			
		for(i=0;i<LIST_CNT_OF_1ZONE;i++){
			j =i<<2;
			memcpy(ptr+j,list[offset+i],4);//mem_cpy(list[offset+i],ptr+j,4);
		}//for
		return 1;	
}


/*
写指定区号的白名单
*/
static unsigned char whitelist_write_1zone(unsigned char zone,const unsigned char *ptr)
{
		unsigned short offset,cnt;	
		if(zone>=ZONE_MAX) return 0;
		
		//写第一区时，将所有区都清空		
		if(zone==0){
			whitelist_init();
			auth_all_keypad();//授权
		}

		cnt =calc_valid_list_cnt(ptr);//得到有效list个数
		offset =get_offset(zone);			//得到起始位置 
		write_list_sub(offset,ptr,cnt);
		return 1;
}


/*
增加白名单 1个--最多1区 
增加白名单时不指定区号!!!!!!!!
return:
	10个list的写入执行结果，成功或失败  10个bit
*/
static unsigned short whitelist_add(const unsigned char *ptr)
{
		unsigned char i,cnt,remain_cnt;
		unsigned short reslt_bit=0xffff;
	
		cnt =calc_valid_list_cnt(ptr);//得到有效list个数
		if( list_valid_cnt + cnt <= LIST_MAX)
			write_list_sub(list_valid_cnt,ptr,cnt);		
		else{
			//增加的list个数超出当前空白list个数，不能全部写入!
			remain_cnt = LIST_MAX -list_valid_cnt;//得到list中剩余个数
			write_list_sub(list_valid_cnt,ptr,remain_cnt);
			//不能写入的就标记错误
			for(i=remain_cnt;i<cnt;i++)//
				reslt_bit &= ~(1<<i); 
		}
		
		return reslt_bit;
}



/*
查找指定的list,返回位置指针
return:NULL-没有在名单里
	*unsigned char 
*/
unsigned char *search_special_list(const unsigned char *ptr)
{
		unsigned short i;
		 
		for(i=0;i<list_valid_cnt;i++)//遍历有效list,查找指定list
			//if(mem_compare(ptr,list[i],4) ) return list[i];
			if(memcmp(ptr,list[i],4)==0 )	return list[i];	
		return NULL;
}


/*
删除指定的list
*/
static unsigned short whitelist_delete(const unsigned char *ptr)
{
		unsigned short i;
		unsigned char cnt;
	  unsigned short reslt_bit=0xffff;
		unsigned char *pos;
	
		cnt =calc_valid_list_cnt(ptr);//得到有效list个数
		#ifdef 	DELETE_MULTI
		if(cnt>DELETE_MULTI_MAX)
			cnt = DELETE_MULTI_MAX;
		wlist.auth_keypad_cnt = cnt;
		#endif
		for(i=0;i<cnt;i++){
			if( (pos =search_special_list(ptr+(i<<2)) ) ==NULL)
				reslt_bit &= ~(1<<i);//没有搜索到，标记错误
			else{//search ok
				//send auth code to keypad 
				auth_special_keypad(ptr);
				memset(pos,0xaa,4);//mem_set(pos,4,0xaa);//!!!!! 写特殊值，存在小bug!!!					
			}
		}//for
		
		return reslt_bit;
}



//----------------------------------------
/*
基站回复键盘的白名单申请
called by 基站发送信标函数中！
*/
unsigned char  base_confirm_keypad_whitelist_request(void)
{
		unsigned char tmp[40];
		//if( !function.whitelist__SW)return 0; 
		if( !list_request_flag) return 0;
		list_request_flag=0;
	
		tmp[0] =32;
		base_core.get_match_code(tmp+1);
		tmp[5] =0x1A;
		tmp[6] =0x01; //基站信息?				 
		memcpy(tmp+7,list_sn,4);//mem_cpy(list_sn,tmp+7,4);//4byte SN  前4还是后4 ???
		tmp[11] =base_core.get_main_rf_chan();	//bs_manage.bs_cfg.chan;			
		//send	
		base_core.send_rf_data(tmp,base_core.get_whitelistRF_hard_id()); 
		return 1;
}


/*
基站记录白名单申请
*/
unsigned char keypad_idsn_record_whitelist_request(const unsigned char *rxkp)
{
		if( (rxkp[2]==11)&&(rxkp[9]==3)){
			memcpy(list_sn,rxkp+3,4);//mem_cpy(rxkp+3,list_sn,4);
			list_request_flag =1;//0;
			return 1;
		}
		return 0;
}



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

		memset(tmp,0,sizeof(tmp)/sizeof(tmp[0]));//mem_set(tmp,sizeof(tmp)/sizeof(tmp[0]),0);
		tmp[0]= 60;
		tmp[1]= 0xE1;
		tmp[2]= base_core.get_id();//get_base_id();//pc2bs_Bb.bs_id;
		tmp[3]= 14;//type;
		memcpy( tmp+4,ack_buf,type_data_len);//mem_cpy( ack_buf,tmp+4,type_data_len);	
		//send to pc 
		base_core.send_data_to_pc(tmp);//user__base_tx_to_pc_sub(tmp);
}



/*
白名单功能总入口
input:来自pc/SDK的数据

*/
void whitelist_enter(const unsigned char *rxpc)
{
		unsigned short result_bit;
		unsigned char i;
		unsigned char ack_buf[64];
		
			switch(rxpc[4]){
				case 2://write 
					whitelist_write_1zone(rxpc[5],rxpc+6);//写了之后再去读出来报告给pc			
				case 1:	
					if(whitelist_read_1zone(rxpc[5],ack_buf+2)==0)
						memset(ack_buf+2,0,40);//mem_set(ack_buf+2,40,0);//mem_set(rxpc+2,40,0);
					ack_buf[0] =1;
					ack_buf[1] =rxpc[5];					
					//pc_cmd_0x61_ack(_0x61_WHITE_LIST,ack_buf,42);
					whitelist_ack_pc(ack_buf,42);
					break;

				case 4:	//add sn
					result_bit =whitelist_add(rxpc+6);	
					goto _0x61_WHITE_LIST_JUMP;
//						break;
				
				case 5:	//delete
					result_bit =whitelist_delete(rxpc+6);
				_0x61_WHITE_LIST_JUMP:					
					ack_buf[0] =2;//mode
					ack_buf[1] =((result_bit&0x3ff)==0x3ff)?1:0;//status
					for(i=0;i<10;i++)
						ack_buf[2+i] =(result_bit>>i)&0x01;
					//pc_cmd_0x61_ack(_0x61_WHITE_LIST,ack_buf,12);
					whitelist_ack_pc(ack_buf,12);
					break;
				
					default:break;
			}//sw	
			
}





