Files
luban-lite/bsp/peripheral/wireless/atbm603x/hal/smartconfig.c
刘可亮 8bca5e8332 v1.0.4
2024-04-03 16:40:57 +08:00

1420 lines
44 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/**************************************************************************************************************
* altobeam RTOS WSM host interface (HI) implementation
*
* Copyright (c) 2018, altobeam.inc All rights reserved.
*
* The source code contains proprietary information of AltoBeam, and shall not be distributed,
* copied, reproduced, or disclosed in whole or in part without prior written permission of AltoBeam.
*****************************************************************************************************************/
#include "atbm_hal.h"
extern struct atbmwifi_common g_hw_prv;
static atbm_uint32 smt_magic_channel_mask= 0;
int free_legacy_data(void);
atbm_int32 check_smt_rx_done(void);
extern atbm_void AT_WDisConnect_vif(struct atbmwifi_vif *priv,char *pLine);
atbm_void atbmwifi_stop_smartconfig(struct atbmwifi_vif *hw_priv );
atbm_void smartconfig_start_timer_func(atbm_void *data1,atbm_void *data2);
atbm_int32 smartconfig_may_magic_channel(atbm_int32 channel)
{
return smt_magic_channel_mask&BIT(channel);
}
atbm_int32 smartconfig_have_may_magic_channel(void)
{
return smt_magic_channel_mask;
}
atbm_void smartconfig_clear_magic_channel(void)
{
smt_magic_channel_mask=0;
}
atbm_void smartconfig_set_magic_channel(atbm_int32 channel)
{
smt_magic_channel_mask|=BIT(channel);
}
atbm_void smartconfig_scan_start(struct atbmwifi_vif *priv)
{
priv->scan_ret.len = 0;
priv->scan_expire = 2;
priv->scan_no_connect_back = 1;
priv->scan_no_connect = 1;
/*start smartconfig*/
priv->scan.scan_smartconfig = 1;
priv->st_status = CONFIG_ST_START;
atbmwifi_scan_start(priv);
priv->st_status = CONFIG_ST_GET_MAGIC;
}
atbm_int32 smartconfig_start(struct smartconfig_config * st_cfg,int if_id)
{
struct atbmwifi_vif *priv;
atbm_int32 Istate=0;
priv= _atbmwifi_hwpriv_to_vifpriv(&g_hw_prv,if_id);
if(st_cfg == ATBM_NULL){
wifi_printk(WIFI_ALWAYS,"unsupport st_cfg ATBM_NULL!");
return CONFIG_ST_STARTCONFIG_ERR;
}
if((st_cfg->magic_cnt<1)||(st_cfg->magic_cnt>10)){
wifi_printk(WIFI_ALWAYS,"unsupport imagic_cnt %d!",st_cfg->magic_cnt);
return CONFIG_ST_STARTCONFIG_ERR;
}
if((st_cfg->magic_time<20)||(st_cfg->magic_time>500)){
wifi_printk(WIFI_ALWAYS,"unsupport magic_time!");
return CONFIG_ST_STARTCONFIG_ERR;
}
if((st_cfg->payload_time<500)||(st_cfg->payload_time>30000)){
wifi_printk(WIFI_ALWAYS,"unsupport payload_time!");
return CONFIG_ST_STARTCONFIG_ERR;
}
atbm_memcpy(&priv->st_cfg,st_cfg,sizeof(struct smartconfig_config ));
/*disconnect AP*/
#if ATBM_PLATFORM == AK_RTOS_37D
extern int msh_exec(char *cmd, rt_size_t length);
char cmd[10];
strcpy(cmd, "wifi disc");
msh_exec(cmd, strlen(cmd));
#else
AT_WDisConnect(ATBM_NULL);
#endif
atbmwifi_eloop_register_timeout(0,13 * (st_cfg->payload_time + st_cfg->magic_time*14),smartconfig_start_timer_func,(atbm_void *)priv,ATBM_NULL);
if(priv->scan_ret.info){
Istate = atbm_local_irq_save();
atbm_kfree(priv->scan_ret.info);
priv->scan_ret.info = ATBM_NULL;
priv->scan_ret.len =0;
atbm_local_irq_restore(Istate);
}
smartconfig_scan_start(priv);
return CONFIG_ST_START;
}
atbm_int32 smartconfig_stop(int if_id)
{
struct atbmwifi_vif *priv;
priv= _atbmwifi_hwpriv_to_vifpriv(&g_hw_prv,if_id);
atbmwifi_stop_smartconfig(priv);
return priv->st_status;
}
atbm_int32 smartconfig_status(int if_id)
{
struct atbmwifi_vif *priv;
priv= _atbmwifi_hwpriv_to_vifpriv(&g_hw_prv,if_id);
return priv->st_status;
}
/*cnt : 2 ~ 100*/
atbm_int32 smartconfig_magic_channel_cnt(atbm_int32 cnt)
{
return 0;
}
/*ms : 20ms ~ 1000ms*/
atbm_int32 smartconfig_magic_channel_timeout(atbm_int32 ms)
{
return 0;
}
/*ms : 500ms ~ 10000ms*/
atbm_int32 smartconfig_payload_timeout(atbm_int32 ms)
{
return 0;
}
atbm_void atbmwifi_stop_smartconfig(struct atbmwifi_vif *priv )
{
struct atbmwifi_common *hw_priv;
struct wsm_reset reset = { 0 };
hw_priv=_atbmwifi_vifpriv_to_hwpriv(priv);
priv->st_status = CONFIG_ST_IDLE;
priv->scan.scan_smartconfig = 0;
reset.reset_statistics = ATBM_TRUE;
atbmwifi_eloop_cancel_timeout(smartconfig_start_timer_func, (atbm_void *)priv, ATBM_NULL);
if(priv->scan.in_progress){
wsm_stop_scan(hw_priv,0);
atbmwifi_scan_comlete(priv);
}
free_legacy_data();
reset.link_id = 0;
wsm_reset(hw_priv,&reset,0);
}
atbm_void smartconfig_start_timer_func(atbm_void *data1,atbm_void *data2)
{
struct atbmwifi_vif *priv=(struct atbmwifi_vif *)data1;
if(priv->scan.scan_smartconfig){
atbmwifi_stop_smartconfig(priv);
priv->st_status = CONFIG_ST_DONE_FAIL;
}
}
atbm_int32 smartconfig_magic_scan_done(struct atbmwifi_vif *priv)
{
struct atbmwifi_common *hw_priv;
hw_priv=_atbmwifi_vifpriv_to_hwpriv(priv);
if(priv->st_status == CONFIG_ST_SWITCH_PAYLOAD_CH ){
struct wsm_set_chantype arg ;
{
arg.band = 0; //0:2.4G,1:5G
arg.flag = 0; //no use
arg.channelNumber = priv->st_configchannel; // channel number
arg.channelType = CH_OFF_20; // channel type
};
arg.flag |= BIT(4);
wifi_printk(WIFI_ALWAYS,"st_configchannel %d\n",priv->st_configchannel);
wsm_set_chantype_func(hw_priv,&arg,0);
priv->st_status = CONFIG_ST_GET_PAYLOAD;
}
else {
if(priv->st_status == CONFIG_ST_GET_MAGIC){
//may need start scan again
smartconfig_scan_start(priv);
}
}
smartconfig_clear_magic_channel();
return 0;
}
/*********************************************
start of new smartconfig RX code
*******************************************/
#define verbose_debug 0
#define ATBM_CONFIG_ST_GET_MAGIC 1
#define ATBM_CONFIG_ST_GET_PAYLOAD 2
#define HT_PAYLOAD_EXTR_LENGTH 288 //0x120, <20>ܿ<EFBFBD><DCBF><EFBFBD><EFBFBD>ư<EFBFBD><C6B0>ܼ<EFBFBD><DCBC><EFBFBD>
#define HT_PAYLOAD_MAX_LENGTH 1398 //0x120 + 0x400 + 82, <20>ܿ<EFBFBD><DCBF><EFBFBD><EFBFBD>ư<EFBFBD><C6B0>ܼ<EFBFBD><DCBC><EFBFBD>
#define MIN_GROUP_DATA_COUNTER 8 //typically, 72 packet one group, at least receive 30% packets(include interference packets).
#define MIN_MAC_BASE_LEN 64
#define MAX_MAC_BASE_LEN 86
#define MAX_MIN_MAGIC_PAIR_LEN 123 //0x3f + 60
#define MAX_MAC_MAGIC_PAIR_LEN 312 //0xe2 + 86
static const atbm_uint8 smt_mpdu_base_length[] = {60, 62, 68, 70, 76, 78, 80, 82}; //
//const static atbm_uint8 ht_mpdu_base_length[] = {64, 66, 72, 74, 80, 82, 84, 86}; //msdu + mac length. + FCS
//5e bc e2 61 3f dd 83 c2 9c 7e 20 a3 fd 1f 41 9d
static const atbm_uint8 smt_mpdu_pair_length[20] = {0x00, 0x5e, 0xbc, 0xe2, 0x61,0x3f, 0xdd,
0x83, 0xc2, 0x9c, 0x7e,0x20, 0xa3,
0xfd, 0x1f, 0x41, 0x9d }; //<2F><>ǰ<EFBFBD><C7B0><EFBFBD><EFBFBD><EFBFBD><EFBFBD>crc8 of index value<75><65> <20><><EFBFBD><EFBFBD>ʱ<EFBFBD><CAB1><EFBFBD>ټ<EFBFBD><D9BC><EFBFBD>
static atbm_int32 ht_state;
#define HT_CONFIG_ST_GET_MAGIC 1
#define HT_CONFIG_ST_GET_PAYLOAD 2
#define HT_CONFIG_ST_GET_DONE 3
//static int atbm_smt_state = ATBM_CONFIG_ST_GET_MAGIC;
#define SMART_TYPE_CNT 2
enum SMART_TYPE {
ADDR1_TYPE=0,
ADDR3_TYPE=1,
};
struct base_dec_t{
int group_idx;
int len;
int group_counter;
};
struct base_dec_l{
struct base_dec_t base_sec[10][SMART_TYPE_CNT];
int counter[SMART_TYPE_CNT];
int satisfied;
int received;
};
struct base_dec_l base_sec_l;
static atbm_uint8 base_mac_len[SMART_TYPE_CNT] = {0}; /*<2A><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>׼<EFBFBD><D7BC><EFBFBD><EFBFBD>*/
static atbm_uint16 pre_pair_data[2] = {0}; /*<2A><><EFBFBD><EFBFBD>CRC<52><43><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>*/
static atbm_int16 fromds_channel_rssi[14];
static atbm_int16 fromds_channel_paired_counter[14];
static atbm_uint8 fromds_channel = 15; //invalid value
static atbm_uint8 fromds_magic_mask; //bit0, ,1,2,3,4
static atbm_int32 fromds_magic_counter;
static atbm_uint8 cur_group_index = 0; /*<2A><><EFBFBD>浱ǰ<E6B5B1><C7B0><EFBFBD>յ<EFBFBD><D5B5><EFBFBD><EFBFBD><EFBFBD>*/
static atbm_uint8 payload_total_length = 0;
static atbm_uint8 payload_total_xor = 0;
static atbm_uint8 payload_pwd_length = 0;
static atbm_uint8 smt_payload_data[128];
static atbm_uint8 smt_ssid[32];
static atbm_uint8 smt_pwd[64];
static atbm_uint16 group_received_mask = 0;
static atbm_uint8 group_payload[8]; //<2F><>̬<EFBFBD><CCAC><EFBFBD>յ<EFBFBD><D5B5><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>,<2C><><EFBFBD><EFBFBD>ͨ<EFBFBD><CDA8>CRC8У<38><EFBFBD><E9A3AC><EFBFBD><EFBFBD>smt_payload_data<74><61>
static atbm_uint8 group_data_cur_counter = 0; //<2F><>¼ÿ<C2BC><C3BF><EFBFBD><EFBFBD><EFBFBD>ݽ<EFBFBD><DDBD>յ<EFBFBD><D5B5>İ<EFBFBD><C4B0><EFBFBD><EFBFBD><EFBFBD>CRC<52><43><EFBFBD><EFBFBD>Ҫ<EFBFBD><D2AA><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>յ<EFBFBD>һ<EFBFBD><D2BB><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>İ<EFBFBD><C4B0><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>30%; <20><>ֹ<EFBFBD><D6B9><EFBFBD><EFBFBD><EFBFBD>յıȽ<C4B1><C8BD>٣<EFBFBD><D9A3><EFBFBD>ͳ<EFBFBD><CDB3><EFBFBD><EFBFBD>Ϣ<EFBFBD><CFA2>
//static atbm_uint8 group_replace[8]; //ht40_group_dataʹ<61>õ<EFBFBD>replace<63><65>ʽ<EFBFBD><CABD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>յ<EFBFBD><D5B5>Ĵ<EFBFBD><C4B4><EFBFBD> > 1 <20><>replace<63><65> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>replace<63><65><EFBFBD><EFBFBD>Ϊ1<CEAA>İ<EFBFBD><C4B0><EFBFBD> <20><>ֹ<EFBFBD><D6B9><EFBFBD><EFBFBD>ռ<EFBFBD><D5BC><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>buffer
static atbm_uint8 group_data_mask[15]; //<2F><><EFBFBD><EFBFBD>λ<EFBFBD><CEBB>CRC<52><43><EFBFBD><EFBFBD>Ҫ<EFBFBD><D2AA><EFBFBD><EFBFBD>ǰ<EFBFBD><C7B0>ÿ<EFBFBD><C3BF><EFBFBD><EFBFBD><EFBFBD><EFBFBD>λ<EFBFBD><CEBB><EFBFBD><EFBFBD><EFBFBD>ݶ<EFBFBD><DDB6>յ<EFBFBD>
static atbm_uint16 group_mask = 0;
/*
<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ܵ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
<EFBFBD><EFBFBD>һ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
<EFBFBD>ڶ<EFBFBD><EFBFBD><EFBFBD>֮<EFBFBD>󱣴涯̬ˢ<EFBFBD>µ<EFBFBD><EFBFBD><EFBFBD>
*/
//will sort and find the maximum received data.
struct ht40_smt_data
{
atbm_uint8 rdata[4];
unsigned short rdata_counter[4];
};
static struct ht40_smt_data ht40_group_data[8];
//<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʷ<EFBFBD><CAB7><EFBFBD>ݣ<EFBFBD> <20>ϲ<EFBFBD><CFB2>µ<EFBFBD><C2B5><EFBFBD><EFBFBD>ݣ<EFBFBD><DDA3><EFBFBD><EFBFBD>ڻ<EFBFBD><DABB><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
struct ht40_smart_legacy_data_struct
{
atbm_uint8 groups_num; //the counter of group data
atbm_uint8 legacy_depth; //saved how many round data.
atbm_uint8 legacy_policy; //update policy.
atbm_uint8 reserved;
atbm_uint8 *legacy_data_round; //round of legacy data.
struct ht40_smt_data *p_legacy_data;
};
static struct ht40_smart_legacy_data_struct ht40_smt_legacy_data;
void fromap_sort_and_set_data(void);
void fromap_merge_smt_data(atbm_uint8 cur_g_indx, atbm_uint8 score_level);
/*
<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ڴ棬<EFBFBD><EFBFBD><EFBFBD>ڱ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʷ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>
ʹ<EFBFBD>õ<EFBFBD>ǰ<EFBFBD><EFBFBD> + <20><>ʷ<EFBFBD><CAB7><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ַ<EFBFBD>ʽУ<CABD><D0A3><EFBFBD><EFBFBD><EFBFBD><EFBFBD>CRC
*/
int malloc_legacy_data(void)
{
ht40_smt_legacy_data.p_legacy_data = (struct ht40_smt_data *)atbm_kmalloc(sizeof(struct ht40_smt_data )*128, GFP_KERNEL);
ht40_smt_legacy_data.legacy_data_round = (atbm_uint8 *)atbm_kmalloc(sizeof(atbm_uint8)*128, GFP_KERNEL);
if((ht40_smt_legacy_data.p_legacy_data != NULL) && (ht40_smt_legacy_data.legacy_data_round !=NULL ))
{
atbm_memset(ht40_smt_legacy_data.p_legacy_data, '\0', sizeof(struct ht40_smt_data )*128);
atbm_memset(ht40_smt_legacy_data.legacy_data_round, '\0', sizeof(atbm_uint8)*128);
return 0;
}
return -1;
}
int free_legacy_data(void)
{
if(ht40_smt_legacy_data.p_legacy_data != NULL)
{
atbm_kfree(ht40_smt_legacy_data.p_legacy_data);
ht40_smt_legacy_data.p_legacy_data = NULL;
}
if(ht40_smt_legacy_data.legacy_data_round !=NULL)
{
atbm_kfree(ht40_smt_legacy_data.legacy_data_round);
ht40_smt_legacy_data.legacy_data_round = NULL;
}
base_mac_len[ADDR1_TYPE] = 60;
base_mac_len[ADDR3_TYPE] = 60;
ht_state = HT_CONFIG_ST_GET_MAGIC;
return 0;
}
void reset_group_data(atbm_uint8 group_index)
{
atbm_memset(ht40_group_data, '\0', sizeof(ht40_group_data));
// atbm_memset(group_replace, '\0', sizeof(group_replace));
group_data_cur_counter = 0;
if(group_index < 15)
{
group_data_mask[group_index] = 0;
}
if(group_index == 0xff)
{
atbm_memset(group_data_mask, '\0', sizeof(group_data_mask));
}
}
atbm_uint8 smtcrc8(atbm_uint8 *A,atbm_uint8 n)
{
atbm_uint8 i;
atbm_uint8 checksum = 0;
while(n--)
{
for(i=1;i!=0;i*=2)
{
if( (checksum&1) != 0 )
{
checksum /= 2;
checksum ^= 0x8C;
}
else
{
checksum /= 2;
}
if( (*A & i) != 0 )
{
checksum ^= 0x8C;
}
}
A++;
}
return(checksum);
}
int get_strong_channel(void)
{
int target_ch = 0;
int i = 0;
short rssi = -100;
for(i = 1; i< 14; i++)
{
//printf("target_ch:%d rssi:%d cnt:%d\n", i,fromds_channel_rssi[i], fromds_channel_paired_counter[i]);
if((rssi < fromds_channel_rssi[i])&&(fromds_channel_rssi[i] < 0))
{
rssi = fromds_channel_rssi[i] + fromds_channel_paired_counter[i] ;
//printf("target_ch:%d rssi_eva:%d\n", i,rssi);
target_ch = i;
}
}
return target_ch;
}
atbm_void set_base(atbm_uint8 smt_type, int group_index, int len){
int i;
int flag = 0;
wifi_printk(WIFI_ALWAYS, "smt_type:%d group_index:%d len:%d received:%d\n", smt_type, group_index, len, base_sec_l.received);
if(base_sec_l.counter[smt_type] > 0){
for(i = 0; i < base_sec_l.counter[smt_type]; i++){
if(base_sec_l.base_sec[i][smt_type].len == len){
flag = 1;
base_mac_len[smt_type] = len;
if(base_sec_l.received > 20){
base_sec_l.satisfied = 1;
break;
}
if(base_sec_l.base_sec[i][smt_type].group_idx != group_index){
if(base_sec_l.received > 15 && base_mac_len[!smt_type])
{
base_sec_l.satisfied = 1;
}
break;
}
}
}
if(!flag && base_sec_l.counter[smt_type] < 10){
base_sec_l.base_sec[base_sec_l.counter[smt_type]][smt_type].group_counter = 1;
base_sec_l.base_sec[base_sec_l.counter[smt_type]][smt_type].group_idx = group_index;
base_sec_l.base_sec[base_sec_l.counter[smt_type]][smt_type].len = len;
base_sec_l.counter[smt_type]++;
}
}else{
base_sec_l.base_sec[0][smt_type].group_counter = 1;
base_sec_l.base_sec[0][smt_type].group_idx = group_index;
base_sec_l.base_sec[0][smt_type].len = len;
base_sec_l.counter[smt_type]++;
}
base_sec_l.received++;
}
/*
pair data format:
group_num + base_len , sample value: 83 = 1 + 82
CRC8<EFBFBD><EFBFBD>group_num<EFBFBD><EFBFBD>+ base_len, sample value<75><65> 0x5e + 82
note: group_num = group_index + 1
<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>4<EFBFBD><20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʱÿ<CAB1><C3BF><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ܶ<EFBFBD>Ӧ<EFBFBD><D3A6><EFBFBD><EFBFBD>base_len<65><6E> <20><><EFBFBD>ټ<EFBFBD><D9BC><EFBFBD>
*/
atbm_uint8 smt_receive_magic(atbm_uint16 rx_mac_len, atbm_uint8 smt_type, atbm_int32 ch, atbm_int32 rssi) //add1 or add3
{
atbm_uint8 i = 0;
atbm_uint8 try_base_len = 0;
atbm_uint8 try_crc8 = 0;
atbm_uint8 try_group_num = 0; //group_index + 1
// wifi_printk(WIFI_ALWAYS, "smt_receive_magica %d ch:%d, rssi:%d\n",rx_mac_len,ch, rssi);
if(rx_mac_len < MIN_MAC_BASE_LEN)
{
return 0;
}
//<2F>ȱ<EFBFBD><C8B1><EFBFBD>һ<EFBFBD><D2BB><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֵ<EFBFBD><D6B5>save pair data, then compare; <20><>ͬ<EFBFBD><CDAC>group<75><70><EFBFBD><EFBFBD><EFBFBD>ܴ󣬲<DCB4><F3A3ACB2><EFBFBD><E1B4AE>һ<EFBFBD><D2BB><EFBFBD><EFBFBD>scan<61>ŵ<EFBFBD><C5B5>л<EFBFBD><D0BB>ڼ䣬ֻ<E4A3AC>ܼ<EFBFBD><DCBC>һ<E2B5BD><D2BB>ͬ<EFBFBD><CDAC>ͷ
if((rx_mac_len >= MAX_MIN_MAGIC_PAIR_LEN) && (rx_mac_len <= MAX_MAC_MAGIC_PAIR_LEN))
{
pre_pair_data[smt_type] = rx_mac_len;
}
if(pre_pair_data[smt_type] == 0) //<2F><><EFBFBD><EFBFBD>û<EFBFBD><C3BB><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֵ<EFBFBD><D6B5>ֱ<EFBFBD>ӷ<EFBFBD><D3B7><EFBFBD>
{
return 0 ;
}
#if 0
for(i = 0; i< 8; i++) //<2F><><EFBFBD><EFBFBD>base len<65><6E>ͨ<EFBFBD><CDA8><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϣ<EFBFBD><CFA2> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ͷ<EFBFBD><CDB7><EFBFBD><EFBFBD><EFBFBD>ż<EFBFBD>CRCֵ<43><D6B5><EFBFBD>ǹ̶<C7B9><CCB6>ģ<EFBFBD>ͨ<EFBFBD><CDA8><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Լ<EFBFBD><D4BC>ټ<EFBFBD><D9BC>
{
if(rx_mac_len > smt_mpdu_base_length[i] && (rx_mac_len <= smt_mpdu_base_length[i] + 4))
{
try_base_len = smt_mpdu_base_length[i];
try_crc8 = (atbm_uint8)(pre_pair_data - try_base_len);
try_group_num = (atbm_uint8)(rx_mac_len - try_base_len);
wifi_printk(WIFI_ALWAYS, "smt_receive_magica %d try_crc8:%d, try_group_num:%d\n",rx_mac_len, try_crc8, try_group_num);
if(smt_mpdu_pair_length[try_group_num] == try_crc8)
{
base_mac_len[smt_type] = try_base_len;
cur_group_index = try_group_num - 1;
if(cur_group_index < 4)
{
//atbm_smt_state = ATBM_CONFIG_ST_GET_PAYLOAD;
reset_group_data(cur_group_index);
wifi_printk(WIFI_ALWAYS, "magic pair: cnt:%d base_len:%d, group:%d \n", fromds_magic_counter, try_base_len, try_group_num);
//if(smt_type == HT_ADDR1_TYPE)
{
fromds_magic_mask |= (1<<cur_group_index);
fromds_magic_counter++;
fromds_channel_rssi[ch] = rssi;
fromds_channel_paired_counter[ch]++;
if(((fromds_magic_mask & 01) == 0x01)&&(fromds_magic_counter > 15)) //first pairs found.
{
fromds_channel = get_strong_channel();
wifi_printk(WIFI_ALWAYS, "non ht magic done find pair: base_len:%d, g_num:%d ch:%d\n", try_base_len, try_group_num, fromds_channel);
return 1; //avoid 0
}
}
}
}
}
}
#endif
for(i = 0; i< 8; i++)
{
if(rx_mac_len > smt_mpdu_base_length[i] && (rx_mac_len <= smt_mpdu_base_length[i] + 4)){
{
try_base_len = smt_mpdu_base_length[i];
try_crc8 = (atbm_uint8)(pre_pair_data[smt_type] - try_base_len);
try_group_num = (atbm_uint8)(rx_mac_len - try_base_len);
if(smt_mpdu_pair_length[try_group_num] == try_crc8){
set_base(smt_type, try_group_num, try_base_len);
cur_group_index = try_group_num - 1;
fromds_magic_mask |= (1<<cur_group_index);
fromds_magic_counter++;
fromds_channel_rssi[ch] = rssi;
fromds_channel_paired_counter[ch]++;
}
}
if(base_sec_l.satisfied){
reset_group_data(cur_group_index);
fromds_channel = get_strong_channel();
wifi_printk(WIFI_ALWAYS, "non ht magic done find pair: base_len:%d %d, g_num:%d ch:%d\n", base_mac_len[0], base_mac_len[1], try_group_num, fromds_channel);
return 1; //avoid 0
}
}
}
return 0;
}
/*
receive group index dynamically:
1, find and update group data index
2, reset group data,as data aways send after group index
*/
atbm_uint8 smt_receive_group_index(atbm_uint16 rx_mac_len, atbm_uint8 smt_type)
{
atbm_uint8 try_crc8 = 0, crc8 = 0;
static atbm_uint8 try_group_num = 0; //group_num = group_index + 1
static atbm_uint8 counter = 0;
if(rx_mac_len < base_mac_len[smt_type])
{
return 0xff;
}
if(rx_mac_len <= (base_mac_len[smt_type] + 0xff)) //group index CRC8 should not exceed 0xff
{
counter = counter + 1;
}else
{
return 0xff;
}
if(counter > 5) //reset group_num after try each 5 packets, pair data not found in following 5 packets, may be fake value.
{
try_group_num = 0;
counter = 0;
}
if((rx_mac_len > base_mac_len[smt_type]) && (rx_mac_len <= (base_mac_len[smt_type] + 16))) //maximum 16 groups
{
try_group_num = (atbm_uint8)(rx_mac_len - base_mac_len[smt_type]); //save pair data, then compare. <20><>ͬ<EFBFBD><CDAC>group<75><70><EFBFBD><EFBFBD><EFBFBD>ܴ󣬲<DCB4><F3A3ACB2><EFBFBD><E1B4AE>һ<EFBFBD><D2BB>
counter = 0; //find key index value, reset counter to 0.
}
if(try_group_num == 0) //group_num = group_index + 1, should not be 0
{
return 0xff ;
}
// printf(" try find pair\n");
if((rx_mac_len >= base_mac_len[smt_type]) && (rx_mac_len <= (base_mac_len[smt_type] + 0xff)))
{
crc8 = smtcrc8(&try_group_num, 1);
try_crc8 = (atbm_uint8)(rx_mac_len - base_mac_len[smt_type]);
if(crc8 == try_crc8)
{
wifi_printk(WIFI_ALWAYS, "Paired g_num:%d g_data_cnt:%d\n", try_group_num, group_data_cur_counter); //data aways follow group info.
if(cur_group_index != (try_group_num - 1)) //debug new group.
{
if(cur_group_index < 16)
{
wifi_printk(WIFI_ALWAYS, "update group pre merge!\n");
fromap_sort_and_set_data();
wifi_printk(WIFI_ALWAYS, "after meger!\n");
fromap_merge_smt_data(cur_group_index, 1); //low level data
}
}
reset_group_data(cur_group_index);
counter = 0;
return (try_group_num - 1);
}
}
return 0xff ;
}
/*<2A>ռ<EFBFBD><D5BC><EFBFBD>ǰ<EFBFBD><C7B0><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>*/
atbm_void smt_put_data_for_sort(atbm_uint8 index, atbm_uint8 len)
{
atbm_uint8 u8iter = 0;
//printf("index:%d\n", index);
//try find the same length.
int flag = 0;
int min_counter_index;
if(index >7)
return;
for(u8iter =0; u8iter < 4; u8iter++)
{
if(len == ht40_group_data[index].rdata[u8iter])
{
ht40_group_data[index].rdata_counter[u8iter] += 5;
flag = 1;
}else{
ht40_group_data[index].rdata_counter[u8iter] = ht40_group_data[index].rdata_counter[u8iter] > 0 \
?(ht40_group_data[index].rdata_counter[u8iter] - 1) : 0;
}
}
if(flag){
return;
}
for(u8iter =0; u8iter < 4; u8iter++)
{
if(ht40_group_data[index].rdata_counter[u8iter] == 0)
{
ht40_group_data[index].rdata[u8iter]= len;
ht40_group_data[index].rdata_counter[u8iter] = 10;
flag = 1;
break;
}
}
if(flag){
return ;
}
wifi_printk(WIFI_ALWAYS, "data full, try replace index:%d len:%x\n", index, len);
min_counter_index = 0;
for(u8iter = 1; u8iter < 4; u8iter++){
if(ht40_group_data[index].rdata_counter[min_counter_index] > ht40_group_data[index].rdata_counter[u8iter]){
min_counter_index = u8iter;
}
}
wifi_printk(WIFI_ALWAYS, "replaced pre min_counter_index : %d len:%x len:%x\n",min_counter_index, ht40_group_data[index].rdata[min_counter_index], len);
ht40_group_data[index].rdata[min_counter_index]= len; //replace current data.
ht40_group_data[index].rdata_counter[min_counter_index] = 10;
// printf("replaced pre len:%x len:%x\n",ht40_group_data[index].rdata[min_counter_index], len);
return;
#if 0
for(u8iter =0; u8iter < 4; u8iter++)
{
if((ht40_group_data[index].rdata_counter[u8iter] == 1)&&(u8iter == group_replace[index]))
{
ht40_group_data[index].rdata[u8iter]= len; //replace current data.
ht40_group_data[index].rdata_counter[u8iter] = 1;
printf("replaced pre len:%x len:%x\n",ht40_group_data[index].rdata[u8iter], len);
group_replace[index]++; //next time will not replace this index data.
if(group_replace[index] == 4)
{
group_replace[index] = 0;
}
return;
}
}
#endif
}
atbm_void fromap_sort_and_set_data(atbm_void)
{
atbm_uint8 u8idx = 0;
atbm_uint16 u8iter = 0;
atbm_uint8 tmp_data = 0;
atbm_uint16 tmp_counter = 0;
//printf("index:%d ",index);
#if 1
for(u8idx = 0; u8idx< 8; u8idx++)
{
for(u8iter = 1; u8iter < 4; u8iter++)
{
if(ht40_group_data[u8idx].rdata_counter[0] < ht40_group_data[u8idx].rdata_counter[u8iter]) //swap for the max score data
{
tmp_data = ht40_group_data[u8idx].rdata[0];
tmp_counter = ht40_group_data[u8idx].rdata_counter[0];
ht40_group_data[u8idx].rdata[0] = ht40_group_data[u8idx].rdata[u8iter];
ht40_group_data[u8idx].rdata_counter[0] = ht40_group_data[u8idx].rdata_counter[u8iter];
ht40_group_data[u8idx].rdata[u8iter] = tmp_data;
ht40_group_data[u8idx].rdata_counter[u8iter] = tmp_counter;
}
}
if(ht40_group_data[u8idx].rdata_counter[0] == 0) //no data any more.
{
wifi_printk(WIFI_ALWAYS, "Warn ht40_gdata u8idx:%d cnt 0,no data continue\n",u8idx);
continue;
}
for(u8iter = 2; u8iter < 4; u8iter++)
{
if(ht40_group_data[u8idx].rdata_counter[1] < ht40_group_data[u8idx].rdata_counter[u8iter]) //swap for the second score data
{
tmp_data = ht40_group_data[u8idx].rdata[1];
tmp_counter = ht40_group_data[u8idx].rdata_counter[1];
ht40_group_data[u8idx].rdata[1] =ht40_group_data[u8idx].rdata[u8iter];
ht40_group_data[u8idx].rdata_counter[1] = ht40_group_data[u8idx].rdata_counter[u8iter];
ht40_group_data[u8idx].rdata[u8iter] = tmp_data;
ht40_group_data[u8idx].rdata_counter[u8iter] = tmp_counter;
}
}
}
#endif
//print data and counter.
for(u8idx = 0; u8idx< 8; u8idx++)
{
wifi_printk(WIFI_ALWAYS, "idx:%d ",u8idx);
for(u8iter =0; u8iter < 2; u8iter++)
{
wifi_printk(WIFI_ALWAYS, "%02x_%d ",ht40_group_data[u8idx].rdata[u8iter], ht40_group_data[u8idx].rdata_counter[u8iter]);
}
wifi_printk(WIFI_ALWAYS, "\n");
}
for(u8idx = 0; u8idx< 8; u8idx++)
{
group_payload[u8idx] = ht40_group_data[u8idx].rdata[0];
}
}
atbm_void fromap_merge_smt_data(atbm_uint8 cur_g_indx, atbm_uint8 score_level)
{
atbm_uint8 i;
atbm_uint8 start_idx, end_idx;
atbm_uint8 update_flag = 0;
atbm_uint8 tmp_crc[2];
atbm_uint8 crc8 = 0;
atbm_uint8 iu8idx = 0;
atbm_uint8 data_pos = 0;
//printf("fromap_merge_smt_data\n");
start_idx = cur_g_indx*8;
end_idx = start_idx + 8;
if(score_level >1)
{
for(iu8idx = 0; iu8idx< 8; iu8idx++)
{
for(i =0; i < 2; i++)
{
if((group_payload[iu8idx] == ht40_group_data[iu8idx].rdata[i])&&(ht40_group_data[iu8idx].rdata_counter[i] > 0))
{
ht40_group_data[iu8idx].rdata_counter[i] = ht40_group_data[iu8idx].rdata_counter[i] + score_level;
}
}
}
}
for(i = start_idx; i < end_idx; i++)
{
if(ht40_group_data[i%8].rdata[0] == ht40_smt_legacy_data.p_legacy_data[i].rdata[2])
{
ht40_group_data[i%8].rdata_counter[0] = ht40_group_data[i%8].rdata_counter[0] + ht40_smt_legacy_data.p_legacy_data[i].rdata_counter[2];
}
if(ht40_group_data[i%8].rdata[0] == ht40_smt_legacy_data.p_legacy_data[i].rdata[3])
{
ht40_group_data[i%8].rdata_counter[0] = ht40_group_data[i%8].rdata_counter[0] + ht40_smt_legacy_data.p_legacy_data[i].rdata_counter[3];
}
if(ht40_group_data[i%8].rdata[1] == ht40_smt_legacy_data.p_legacy_data[i].rdata[2])
{
ht40_group_data[i%8].rdata_counter[1] = ht40_group_data[i%8].rdata_counter[1] + ht40_smt_legacy_data.p_legacy_data[i].rdata_counter[2];
}
if(ht40_group_data[i%8].rdata[1] == ht40_smt_legacy_data.p_legacy_data[i].rdata[3])
{
ht40_group_data[i%8].rdata_counter[1] = ht40_group_data[i%8].rdata_counter[1] + ht40_smt_legacy_data.p_legacy_data[i].rdata_counter[3];
}
}
for(i = start_idx; i < end_idx; i++)
{
if(ht40_smt_legacy_data.legacy_data_round[i] == 0)
{
atbm_memcpy(&ht40_smt_legacy_data.p_legacy_data[i], &ht40_group_data[i%8], 8);
ht40_smt_legacy_data.legacy_data_round[i]++;
wifi_printk(WIFI_ALWAYS, "merge copy for fist time i:%d\n", i);
}else //<2F>ϲ<EFBFBD>ǰ<EFBFBD><C7B0><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>򣬼<EFBFBD><F2A3ACBC><EFBFBD>CRC
{
ht40_smt_legacy_data.p_legacy_data[i].rdata[2] = ht40_group_data[i%8].rdata[0];
ht40_smt_legacy_data.p_legacy_data[i].rdata_counter[2] = ht40_group_data[i%8].rdata_counter[0];
ht40_smt_legacy_data.p_legacy_data[i].rdata[3] = ht40_group_data[i%8].rdata[1];
ht40_smt_legacy_data.p_legacy_data[i].rdata_counter[3] = ht40_group_data[i%8].rdata_counter[1];
ht40_smt_legacy_data.legacy_data_round[i]++;
update_flag = 1;
}
}
wifi_printk(WIFI_ALWAYS, "merge update_flag:%d! 0:only copy, 1:process\n", update_flag);
if(update_flag)
{
//merge 2,3 => 0,1
for(i = start_idx; i < end_idx; i++)
{
if(ht40_smt_legacy_data.p_legacy_data[i].rdata[0] == ht40_smt_legacy_data.p_legacy_data[i].rdata[2])
{
ht40_smt_legacy_data.p_legacy_data[i].rdata_counter[0] = ht40_smt_legacy_data.p_legacy_data[i].rdata_counter[0] + ht40_smt_legacy_data.p_legacy_data[i].rdata_counter[2];
ht40_smt_legacy_data.p_legacy_data[i].rdata[2] = 0;
ht40_smt_legacy_data.p_legacy_data[i].rdata_counter[2] = 0;
}
if(ht40_smt_legacy_data.p_legacy_data[i].rdata[0] == ht40_smt_legacy_data.p_legacy_data[i].rdata[3])
{
ht40_smt_legacy_data.p_legacy_data[i].rdata_counter[0] = ht40_smt_legacy_data.p_legacy_data[i].rdata_counter[0] + ht40_smt_legacy_data.p_legacy_data[i].rdata_counter[3];
ht40_smt_legacy_data.p_legacy_data[i].rdata[3] = 0;
ht40_smt_legacy_data.p_legacy_data[i].rdata_counter[3] = 0;
}
if(ht40_smt_legacy_data.p_legacy_data[i].rdata[1] == ht40_smt_legacy_data.p_legacy_data[i].rdata[2])
{
ht40_smt_legacy_data.p_legacy_data[i].rdata_counter[1] = ht40_smt_legacy_data.p_legacy_data[i].rdata_counter[1] + ht40_smt_legacy_data.p_legacy_data[i].rdata_counter[2];
ht40_smt_legacy_data.p_legacy_data[i].rdata[2] = 0;
ht40_smt_legacy_data.p_legacy_data[i].rdata_counter[2] = 0;
}
if(ht40_smt_legacy_data.p_legacy_data[i].rdata[1] == ht40_smt_legacy_data.p_legacy_data[i].rdata[3])
{
ht40_smt_legacy_data.p_legacy_data[i].rdata_counter[1] = ht40_smt_legacy_data.p_legacy_data[i].rdata_counter[1] + ht40_smt_legacy_data.p_legacy_data[i].rdata_counter[3];
ht40_smt_legacy_data.p_legacy_data[i].rdata[3] = 0;
ht40_smt_legacy_data.p_legacy_data[i].rdata_counter[3] = 0;
}
}
atbm_memcpy((atbm_uint8 *)&ht40_group_data[0], (atbm_uint8 *)&ht40_smt_legacy_data.p_legacy_data[start_idx], sizeof(struct ht40_smt_data)*8);
// atbm_memcpy(&ht40_group_data[0], &ht40_smt_legacy_data.p_legacy_data[start_idx], 8*8);
//printf("merged data copy to current group for sort!\n");
//printf(" \n");
//debug
//print data and counter.
fromap_sort_and_set_data();
//update legacy data
atbm_memcpy(&ht40_smt_legacy_data.p_legacy_data[start_idx], &ht40_group_data[0], sizeof(struct ht40_smt_data)*8);
wifi_printk(WIFI_ALWAYS, "merge data done check crc!\n");
crc8 = smtcrc8(&group_payload[0], 7); //most possible data is sorted data.
tmp_crc[0] = crc8;
tmp_crc[1] = cur_group_index;
crc8 = smtcrc8(&tmp_crc[0], 2);
//patch for index and index crc
if((crc8&0x7f)!= group_payload[7])
{
for( iu8idx = 0; iu8idx< 8; iu8idx++) //try second possible value, each time replace one value.
{
// iterate second possible value
if( ht40_group_data[iu8idx].rdata_counter[1] > 0)
{
group_payload[iu8idx] = ht40_group_data[iu8idx].rdata[1]; //second possible value
}
crc8 = smtcrc8(&group_payload[0], 7); //most possible data
tmp_crc[0] = crc8;
tmp_crc[1] = cur_group_index;
crc8 = smtcrc8(&tmp_crc[0], 2);
if((crc8&0x7f) == group_payload[7])
{
break;
}
group_payload[iu8idx] = ht40_group_data[iu8idx].rdata[0]; //change back data.
}
}
if((crc8&0x7f) == group_payload[7]) //only check low 7 bit of CRC8 value
{
/*printf("group data done group index:%d group rcv counter:%d merged\n",cur_group_index, group_data_cur_counter);
for( iu8idx = 0; iu8idx< 8; iu8idx++)
{
printf("%02x ",group_payload[iu8idx]);
}
*/
data_pos = cur_group_index * 8;
atbm_memcpy(&smt_payload_data[data_pos], group_payload, 8);
group_received_mask |= (1<<cur_group_index);
if(cur_group_index == 0)
{
payload_total_length = smt_payload_data[0]; //get total length
payload_total_xor = smt_payload_data[1]; //get total data XOR
payload_pwd_length = smt_payload_data[2]; //get PWD length.
}
cur_group_index = 0xff;
}
}
}
static atbm_int32 atbm_smt_parse_payload(struct atbmwifi_vif *priv);
static atbm_int32 smt_fun_recv_payload(struct atbmwifi_vif *priv, atbm_uint8 smt_type, atbm_uint16 rxdata_raw)
{
//atbm_uint8 crc_payload[2], crc_data = 0, u8iter =0;
atbm_uint8 crc8 = 0;
atbm_uint16 data_len = 0;
atbm_uint8 data_index = 0;
atbm_uint8 data_pos = 0;
atbm_uint8 iu8idx = 0;
atbm_uint8 tmp_group_index = 0;
atbm_uint8 tmp_crc[2];
if(cur_group_index > 0x10) //invalid group index, try sync group info.
{
tmp_group_index = smt_receive_group_index(rxdata_raw, smt_type);
if(tmp_group_index < 16) //force update current group index
{
cur_group_index = tmp_group_index;
}
return 0;
}
if((base_mac_len[smt_type] == 0) || (rxdata_raw < base_mac_len[smt_type])) //invalid packet length.
{
return 0;
}
tmp_group_index = smt_receive_group_index(rxdata_raw, smt_type); //dynamically checking, may update group index
if((tmp_group_index < 16)&&(tmp_group_index != cur_group_index))
{
cur_group_index = tmp_group_index;
wifi_printk(WIFI_ALWAYS, "Update group index:%d group_data_cur_counter:%d\n",cur_group_index, group_data_cur_counter);
reset_group_data(cur_group_index);
}
if(group_mask & (1 << cur_group_index)){
return 0;
}
data_len = rxdata_raw - base_mac_len[smt_type];
data_index = (atbm_uint8)(data_len >>7);
if(data_index > 7) //each group have 8 data, max data index is 7
{
return 0;
}
group_data_cur_counter = group_data_cur_counter + 1;
smt_put_data_for_sort(data_index, (data_len&0x7f));
group_data_mask[cur_group_index]|= (1<<data_index);
/*
CRC checking takes time, must comply with following rules.
1, MASK of all 8 bits set
2, Enough packets received. if net is clear, will receive most of the target packets,
if net is noisy, will receive many other packets, so set a thresh.
*/
if((group_data_mask[cur_group_index] == 0xff)&&(group_data_cur_counter > MIN_GROUP_DATA_COUNTER))
{
// wifi_printk(WIFI_ALWAYS, "##########line:%d########\n", __LINE__);
// wsm_set_wol_enable(hw_priv, 0, 0);
fromap_sort_and_set_data();
crc8 = smtcrc8(&group_payload[0], 7); //most possible data is sorted data.
tmp_crc[0] = crc8;
tmp_crc[1] = cur_group_index;
crc8 = smtcrc8(&tmp_crc[0], 2);
//patch for index and index crc
if((crc8&0x7f)!= group_payload[7])
{
for( iu8idx = 0; iu8idx< 8; iu8idx++) //try second possible value, each time replace one value.
{
// iterate second possible value
if( ht40_group_data[iu8idx].rdata_counter[1] > 0)
{
group_payload[iu8idx] = ht40_group_data[iu8idx].rdata[1]; //second possible value
}
crc8 = smtcrc8(&group_payload[0], 7); //most possible data
tmp_crc[0] = crc8;
tmp_crc[1] = cur_group_index;
crc8 = smtcrc8(&tmp_crc[0], 2);
if((crc8&0x7f) == group_payload[7])
{
break;
}
group_payload[iu8idx] = ht40_group_data[iu8idx].rdata[0]; //change back data.
}
}
if((crc8&0x7f) == group_payload[7]) //only check low 7 bit of CRC8 value
{
/*
printf("group done index:%d group rcv cnt:%d\n",cur_group_index, group_data_cur_counter);
for( iu8idx = 0; iu8idx< 8; iu8idx++)
{
printf("%02x ",group_payload[iu8idx]);
}
printf("\n");
*/
data_pos = cur_group_index * 8;
atbm_memcpy(&smt_payload_data[data_pos], group_payload, 8);
group_received_mask |= (1<<cur_group_index);
if(cur_group_index == 0)
{
payload_total_length = smt_payload_data[0]; //get total length
payload_total_xor = smt_payload_data[1]; //get total data XOR
payload_pwd_length = smt_payload_data[2]; //get PWD length.
}
fromap_merge_smt_data(cur_group_index, 2); //ʵʱ<CAB5><CAB1><EFBFBD>ݽ<EFBFBD><DDBD><EFBFBD><EFBFBD><EFBFBD>ȷ<EFBFBD><C8B7><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ݷ<EFBFBD><DDB7><EFBFBD><EFBFBD><EFBFBD>ʷ<EFBFBD><CAB7><EFBFBD><EFBFBD><EFBFBD><EFBFBD>, <20><><EFBFBD>Ŷ<EFBFBD><C5B6><EFBFBD><EFBFBD><EFBFBD>
group_mask |= (1 << cur_group_index);
// wifi_printk(WIFI_ALWAYS, "!!!!!!!!!group %d done group_mask:%x!!!!!!!!!!!!\n", cur_group_index, group_mask);
cur_group_index = 0xff;
reset_group_data(cur_group_index);
if(check_smt_rx_done())
{
atbm_smt_parse_payload(priv);
}
}else
{
group_data_mask[cur_group_index] = 0;
atbm_memset(&ht40_group_data[cur_group_index], 0, sizeof(struct ht40_smt_data));
group_data_cur_counter = 0;
wifi_printk(WIFI_ALWAYS, "group data CRC error group index:%d\n",cur_group_index);
cur_group_index = 0xff;
}
}
return 0;
}
atbm_int32 check_smt_rx_done(void)
{
atbm_int32 done_flag = 0;
atbm_uint8 smt_len = 0;
atbm_uint8 smt_group_num = 0;
if(payload_total_length >= 5)
{
smt_len = 3 + ((payload_total_length - 3)*8 + 6)/7; //total smartconfig data length exclude CRC.
smt_group_num = (smt_len + 6)/7; //there is 7 smartconfig data in each group and one byte CRC8 value.
if((group_received_mask & ((1<<smt_group_num) - 1)) == ((1<<smt_group_num) - 1))
{
wifi_printk(WIFI_ALWAYS, "smt payload done, check..!! mask:%d gnum:%d\n", group_received_mask, smt_group_num);
done_flag = 1;
}
}
else
{
done_flag = 0;
}
return done_flag;
}
static atbm_int32 atbm_smt_parse_payload(struct atbmwifi_vif *priv)
{
atbm_uint8 ssid_pwd_len = 0;
atbm_uint8 i = 0, j = 0;
atbm_uint16 valid_bit_len =0;
atbm_uint8 payload_byte_len = 0;
//atbm_uint8 parse_byte_len = 0;
atbm_uint8 smt_counter = 0;
atbm_uint8 total_xor = 0;
atbm_uint8 *bitarrays = NULL; //data convert used. 7bit payload data convert to 8bit smt data
atbm_uint8 *bit2smt_data = NULL;
atbm_uint8 *smt_bits_data = NULL;
atbm_uint8 smt_len = 0, smt_group_num = 0;
atbm_uint8 data_no_crc[128]= {0};
//atbm_uint8 tmp_counter = 0;
atbm_uint8 ssid_len =0, pwd_len = 0;
ssid_pwd_len = payload_total_length - 3; //number of SSID and PWD bytes length.
valid_bit_len = ssid_pwd_len * 8; //number of SSID and PWD bits length.
payload_byte_len = (atbm_uint8)(valid_bit_len + 6)/7; //MAC payload length. 8bits stream convert to 7bit stream
//parse_byte_len = (payload_byte_len * 8 + 6) /7; //MAC payload length add CRC bytes
bitarrays = (atbm_uint8*)atbm_kmalloc(512, GFP_KERNEL);
bit2smt_data = (atbm_uint8*)atbm_kmalloc(128, GFP_KERNEL);
smt_bits_data = (atbm_uint8*)atbm_kmalloc(128, GFP_KERNEL);
if((bitarrays == NULL)||(bit2smt_data == NULL)||(smt_bits_data == NULL))
{
wifi_printk(WIFI_ALWAYS, "HT smt error malloc!\n");
}
/*remove CRC byte from each group: 8 bytes to 7 bytes */
smt_len = 3 + ((payload_total_length - 3)*8 + 6)/7;
smt_group_num = (smt_len + 6)/7;
for (i = 0; i < smt_group_num*8; i++)
{
data_no_crc[smt_counter] = smt_payload_data[i];
if(((i+1) % 8) == 0)
{
continue;
}
smt_counter++;
}
for (i = 0; i < smt_group_num*8; i++)
{
smt_bits_data[i] = data_no_crc[i+3];
}
/* generate bit stream from 7bit MAC payload */
for (i = 0; i < payload_byte_len; i ++) {
for (j = 0; j < 7; j ++) {
bitarrays[i * 7 + j] = (smt_bits_data[i] >> j) & 0x01;
}
}
/* generate 8bit PWD and SSID data from bit stream. */
for(i = 0; i< ssid_pwd_len; i++)
{
for (j = 0, bit2smt_data[i] = 0; j < 8; j++) {
bit2smt_data[i] |= bitarrays[i * 8 + j] << j;
}
}
//PWD LEN<45>黹XOR<4F>ֽ<EFBFBD>1bit<69><74><EFBFBD>ݣ<EFBFBD> bit6λ<36>ô<EFBFBD><C3B4><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>XOR<4F><52>bit
if(smt_payload_data[2]&0x40)
{
smt_payload_data[2]&=0x3f;
smt_payload_data[1]|=0x80;
}
/*check XOR off all data
1, get first data: total length
2, XOR with itself and pwd_len
3, XOR with all other bytes.
*/
total_xor = smt_payload_data[0];
for(i = 1; i < 3; i++)
{
total_xor = total_xor ^ smt_payload_data[i];
}
for(i = 0; i < ssid_pwd_len; i++)
{
total_xor = total_xor ^ bit2smt_data[i];
}
atbm_kfree(bitarrays);
atbm_kfree(smt_bits_data);
bitarrays = NULL;
smt_bits_data = NULL;
if(total_xor == 0)
{
//printf("VVVVV smt done XOR check passed!\n");
pwd_len = smt_payload_data[2];
ssid_len = ssid_pwd_len - pwd_len;
if((pwd_len > 64)||(ssid_len > 32))
{
wifi_printk(WIFI_ALWAYS, "Error length, Smartconfig done XOR check passed!\n");
atbm_kfree(bit2smt_data);
bit2smt_data = NULL;
return 0;
}
atbm_memcpy(smt_ssid, &bit2smt_data[0],ssid_len);
atbm_memcpy(smt_pwd, &bit2smt_data[ssid_len],pwd_len);
//Command_SetPolling(1);
//printf(" \n");
wifi_printk(WIFI_ALWAYS, "XOR passed! ssid :%s pwd:%s\n",smt_ssid, smt_pwd);
//printf(" \n");
atbm_memset(priv->config.password,0,sizeof(priv->config.password));
atbm_memset(priv->config.ssid,0,sizeof(priv->config.ssid));
priv->config.password_len = pwd_len;
atbm_memcpy(priv->config.password,smt_pwd, pwd_len);
priv->config.ssid_len = ssid_len;
atbm_memcpy(priv->config.ssid,smt_ssid, ssid_len);
if(priv->config.password_len >= 8){
priv->config.key_mgmt = ATBM_KEY_WPA2;
priv->config.privacy =1;
}
else if(priv->config.password_len==5){
priv->config.key_mgmt = ATBM_KEY_WEP;
priv->config.privacy =1;
}
else if(priv->config.password_len==13){
priv->config.key_mgmt = ATBM_KEY_WEP;
priv->config.privacy =1;
}
else if(priv->config.password_len==0) {
wifi_printk(WIFI_ALWAYS, "EY_NONE!!");
priv->config.key_mgmt = ATBM_KEY_NONE;
priv->config.privacy =0;
}
else {
wifi_printk(WIFI_ALWAYS, "<ERROR> smartconfig key len error %d\n",priv->config.password_len);
}
ht_state = HT_CONFIG_ST_GET_DONE;
atbm_kfree(bit2smt_data);
bit2smt_data = NULL;
cur_group_index = 0xff;
reset_group_data(cur_group_index);
atbmwifi_wpa_event_queue((atbm_void*)priv,ATBM_NULL,
ATBM_NULL,WPA_EVENT__SMARTCONFIG_SUCCESS,ATBM_WPA_EVENT_NOACK);
return 1;
}
atbm_kfree(bit2smt_data);
bit2smt_data = NULL;
wifi_printk(WIFI_ALWAYS, "Warning! smartconfig total_xor:%d\n", total_xor);
return 0;
}
#define DEBUG_SIMU_CASE 1
atbm_void fromap_smartconfig_start(void)
{
malloc_legacy_data(); // will free late
fromds_magic_mask = 0;
fromds_magic_counter = 0;
fromds_channel = 15;
group_received_mask = 0;
cur_group_index = 0;
payload_total_length = 0;
payload_total_xor = 0;
payload_pwd_length = 0;
group_mask = 0;
atbm_memset(&base_sec_l, 0, sizeof(base_sec_l));
atbm_memset(fromds_channel_rssi, '\0', sizeof(fromds_channel_rssi));
atbm_memset(fromds_channel_paired_counter, '\0', sizeof(fromds_channel_paired_counter));
atbm_memset(pre_pair_data, 0, sizeof(pre_pair_data));
atbm_memset(smt_payload_data, '\0', sizeof(smt_payload_data));
atbm_memset(ht40_group_data, '\0', sizeof(ht40_group_data));
// atbm_memset(group_replace, '\0', sizeof(group_replace));
base_mac_len[ADDR1_TYPE] = 0;
base_mac_len[ADDR3_TYPE] = 0;
smartconfig_clear_magic_channel();
ht_state = HT_CONFIG_ST_GET_MAGIC;
//atbm_smt_state = ATBM_CONFIG_ST_GET_MAGIC
}
atbm_uint16 packets[4] = {172, 79, 174, 81};
atbm_uint16 first[4] = { 0 };
const atbm_uint8 atbm_smart_config_magic_mac[3][6] ={
{0x01,0x00,0x5e,0x7f,0xff,0x01},//magic
{0x01,0x00,0x5e,0x7f,0xff,0x02},//checksum
{0x01,0x00,0x5e,0x7f,0xff,0x03},//payload
};
atbm_int32 atbm_smt_ht_rx_handler(struct atbmwifi_vif *priv,char * data,int rx_mac_len,int channel, int rssi)
{
atbm_uint8 smt_magic_rev_type = 0;
atbm_uint8 smt_type;
if(rx_mac_len < HT_PAYLOAD_EXTR_LENGTH + 60)
return 0;
if(rx_mac_len > HT_PAYLOAD_MAX_LENGTH)
return 0;
if(!memcmp(atbm_smart_config_magic_mac[0],&data[4],5)){
smt_type = ADDR1_TYPE;
}else if(!memcmp(atbm_smart_config_magic_mac[0],&data[4+12],5)){
smt_type = ADDR3_TYPE;
}else{
return 0;
}
rx_mac_len = rx_mac_len - HT_PAYLOAD_EXTR_LENGTH; //all packet contains this extra length.
if(ht_state == (int)(HT_CONFIG_ST_GET_MAGIC)){
smt_magic_rev_type = smt_receive_magic(rx_mac_len, smt_type, channel, rssi);
if(smt_magic_rev_type){
if(priv->st_status < CONFIG_ST_SWITCH_PAYLOAD_CH){
priv->st_status = CONFIG_ST_SWITCH_PAYLOAD_CH;//compatible with atbm smartconfig
//patch: if 11b signal, try used the strong signal channel.
if(fromds_channel < 14)
{
channel = fromds_channel;
}
priv->st_configchannel = channel;
wifi_printk(WIFI_ALWAYS, "will fixch: g_hw_prv.st_status:%d, channel:%d \n", priv->st_status, channel);
atbm_SleepMs(50);
if(priv->st_status < CONFIG_ST_SWITCH_PAYLOAD_CH)
{
wifi_printk(WIFI_ALWAYS, "will fixch: g_hw_prv.st_status:%d, channel:%d \n", priv->st_status, channel);
priv->st_status = CONFIG_ST_SWITCH_PAYLOAD_CH;//compatible with atbm smartconfig
priv->st_configchannel = channel;
}
}
//ew_rx_last_time= hal_get_os_second_time();
if(priv->st_status == CONFIG_ST_GET_PAYLOAD)
{
ht_state = ATBM_CONFIG_ST_GET_PAYLOAD; //compatible with ew
}
}
//Smart_config_rssi_thresh(ht_rssi[smt_type] - 25); //-28 -49 test shows
}
else if(ht_state == (int)(ATBM_CONFIG_ST_GET_PAYLOAD)){
smt_fun_recv_payload(priv, smt_type, rx_mac_len);
}
return 0;
}
/*********************************************
End of new smartconfig RX code
*******************************************/
atbm_void atbm_ht_smt_setting(atbm_void)
{
fromap_smartconfig_start();
}
atbm_int32 smartconfig_start_rx(struct atbmwifi_vif *priv,struct atbm_buff *skb,int channel )
{
// wifi_printk(WIFI_ALWAYS, "smartconfig_rx1 len %d,st %d\n",ATBM_OS_SKB_LEN(skb),hw_priv->st_status);
#if 1
atbm_int32 rssi = 0;
struct atbmwifi_ieee80211_rx_status *hw_hdr = ATBM_IEEE80211_SKB_RXCB(skb);
rssi = hw_hdr->signal;
//printf("rssi:%d\n", rssi);
atbm_smt_ht_rx_handler(priv,(char *) ATBM_OS_SKB_DATA(skb), ATBM_OS_SKB_LEN(skb),channel, rssi);
#else
if(hw_priv->st_status == CONFIG_ST_GET_MAGIC){
smartconfig_step_1(hw_priv,(char *)ATBM_OS_SKB_DATA(skb),ATBM_OS_SKB_LEN(skb),channel);
}
else if(hw_priv->st_status == CONFIG_ST_GET_PAYLOAD){
smartconfig_step_2(hw_priv,(char *)ATBM_OS_SKB_DATA(skb),ATBM_OS_SKB_LEN(skb));
//ew_smartconfig_step_save_fifo(skb, channel);
}
#endif
return 0;
}
atbm_void atbm_wifi_smart_config_rx(struct atbmwifi_common *hw_priv,struct atbm_buff *skb,int channel )
{
//smartconfig_start_rx(hw_priv,skb,channel);
//TODO: add custom data hander
//custom_datahandler(ATBM_OS_SKB_DATA(skb), ATBM_OS_SKB_LEN(skb));
wifi_printk(WIFI_DBG_ERROR,"atbm_wifi_smart_config_rx: len %d, ch %d\n", ATBM_OS_SKB_LEN(skb), channel);
return;
}
atbm_uint8 atbmwifi_monitor_enable(atbm_uint8 if_id)
{
struct atbmwifi_vif *priv;
priv= _atbmwifi_hwpriv_to_vifpriv(&g_hw_prv,if_id);
if(!atbm_wifi_initialed(priv->if_id)){
wifi_printk(WIFI_DBG_ERROR,"atbm_wifi_initialed err\n");
return -1;
}
AT_WDisConnect_vif(priv,ATBM_NULL);
atbm_mdelay(10);
//atbmwifi_monitor_channel(1);
return 0;
}
atbm_void atbmwifi_monitor_disable(atbm_uint8 if_id)
{
struct atbmwifi_vif *priv;
struct wsm_reset reset;
priv= _atbmwifi_hwpriv_to_vifpriv(&g_hw_prv,if_id);
reset.reset_statistics = ATBM_TRUE;
/*start smartconfig*/
priv->scan.scan_smartconfig = 0;
priv->st_status = CONFIG_ST_IDLE;
wsm_reset(&g_hw_prv,&reset,0);
}
#define WSM_SET_CHANTYPE_STARTCONFIG BIT(4)
atbm_int32 atbmwifi_monitor_channel(atbm_int32 channelnum,atbm_uint8 if_id)
{
struct atbmwifi_vif *priv;
priv= _atbmwifi_hwpriv_to_vifpriv(&g_hw_prv,if_id);
if((channelnum < 1) || (channelnum > 13 )){
wifi_printk(WIFI_ALWAYS, "invalid channel number,range [1~13]\n");
return -1;
}
//
priv->scan_expire = 2;
priv->scan_no_connect_back = 1;
priv->scan_no_connect = 1;
/*start smartconfig*/
priv->scan.scan_smartconfig = 1;
priv->st_status = CONFIG_ST_START;
{
struct wsm_set_chantype arg = {
.band = 0, //0:2.4G,1:5G
.flag = 0, //no use
.channelNumber = channelnum, // channel number
.channelType = CH_OFF_20, // channel type
};
arg.flag |= WSM_SET_CHANTYPE_STARTCONFIG;
if(channelnum <= 11){
arg.channelType = ATBM_NL80211_CHAN_HT40PLUS;//20M
}
else {
arg.channelType = ATBM_NL80211_CHAN_HT40MINUS;//20M
}
wsm_set_chantype_func(&g_hw_prv,&arg,0);
}
return 0;
}
atbm_void smartconfig_success_notify(struct atbmwifi_vif *priv)
{
atbmwifi_stop_smartconfig(priv);
priv->st_status = CONFIG_ST_DONE_SUCCESS;
}