/************************************************************************************************************** * altobeam RTOS * * 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 int g_ProductTestGlobal; extern struct atbmwifi_common g_hw_prv; extern struct atbmwifi_ieee80211_supported_band atbmwifi_band_2ghz; extern void etf_v2_scan_end(struct atbmwifi_common *hw_priv, struct atbmwifi_vif *vif ); extern int wpa_wsc_tx_process(atbm_void *ctx, int type, const atbm_uint8 *buf, atbm_size_t len); atbm_void atbmwifi_wpa_event_process_scan_end(struct atbmwifi_common *hw_priv, atbm_uint32 scan_status,atbm_uint32 interfaceId); atbm_void sta_scan_start_timer_func(atbm_void *data1,atbm_void *data2); atbm_void atbmwifi_sta_join_timeout(atbm_void *data1,atbm_void *data2); atbm_void smartconfig_start_timer_func(atbm_void *arg); int smartconfig_magic_scan_done(struct atbmwifi_vif *priv); atbm_void atbmwifi_stop_smartconfig(struct atbmwifi_vif *priv ); extern atbm_void wpas_wps_timeout(void *eloop_ctx, atbm_void *timeout_ctx); extern atbm_void ieee80211_ba_session_work(struct atbm_work_struct *work); static ATBM_BOOL wmm_flag = 0; ATBM_BOOL atbm_wmm_status_get(atbm_void) { return wmm_flag; } atbm_void atbm_wmm_status_set(ATBM_BOOL flag) { wmm_flag = flag; wifi_printk(WIFI_ALWAYS,"ATBM: wmm is %s\n", wmm_flag?"Support":"not Suppport"); return; } atbm_void atbmwifi_enable_sta_filter_retry(struct atbmwifi_vif *priv) { priv->link_id_db[ATBMWIFI__MAX_STA_IN_AP_MODE].status = ATBMWIFI__LINK_HARD; atbm_memset(&priv->link_id_db[ATBMWIFI__MAX_STA_IN_AP_MODE].sta_retry,0xff,sizeof(priv->link_id_db[ATBMWIFI__MAX_STA_IN_AP_MODE].sta_retry.last_rx_seq)); return; } atbm_void atbmwifi_disable_sta_filter_retry(struct atbmwifi_vif *priv) { priv->link_id_db[ATBMWIFI__MAX_STA_IN_AP_MODE].status = ATBMWIFI__LINK_OFF; atbm_memset(&priv->link_id_db[ATBMWIFI__MAX_STA_IN_AP_MODE].sta_retry,0xff,sizeof(priv->link_id_db[ATBMWIFI__MAX_STA_IN_AP_MODE].sta_retry.last_rx_seq)); return; } int atbm_join_work(struct atbm_work_struct *work) { struct atbmwifi_vif *priv=(struct atbmwifi_vif *)work; /*先发送join ,再发送auth 认证报文*/ atbmwifi_join_start(priv); return 0; } int atbm_event_handler(struct atbm_work_struct *work) { return 0; } atbm_void atbm_sta_set_tim_work(struct atbm_work_struct *work) { return; } atbm_void atbmwifi_init_scan_req(struct atbmwifi_vif *priv, enum ATBM_SCAN_TYPE type){ struct atbm_scan_req *req = ATBM_NULL; struct atbmwifi_common *hw_priv; struct atbmwifi_ieee80211_channel *channels; int n_channels, c_channels = 0, r_channels; atbm_uint8 numOfProbeRequests, maxTransmitRate, minChannelTime, maxChannelTime; atbm_uint8 band; atbm_uint8 numOfSSIDs; #if CONFIG_P2P atbm_uint8 atbmwifi_ieee80211_channel p2p_scan_chans[3] = { {.hw_value = 1, .max_power = 30}, {.hw_value = 6, .max_power = 30}, {.hw_value = 11, .max_power = 30} }; #endif #if CONFIG_5G_SUPPORT struct atbmwifi_ieee80211_channel avail_5g_channels[30]; #endif int i; hw_priv = priv->hw_priv; switch(type){ case ATBM_SCAN_24G_ACTIVE: if(!priv->scan_no_connect){ numOfSSIDs = 1; } case ATBM_SCAN_24G_WPS: channels = hw_priv->bands[ATBM_IEEE80211_BAND_2GHZ]->channels; n_channels = hw_priv->bands[ATBM_IEEE80211_BAND_2GHZ]->n_channels; maxTransmitRate = WSM_TRANSMIT_RATE_1; minChannelTime = 45; maxChannelTime = 75; band = WSM_PHY_BAND_2_4G; numOfProbeRequests = 2; break; case ATBM_SCAN_24G_PASSAVE: channels = hw_priv->bands[ATBM_IEEE80211_BAND_2GHZ]->channels; n_channels = hw_priv->bands[ATBM_IEEE80211_BAND_2GHZ]->n_channels; maxTransmitRate = WSM_TRANSMIT_RATE_1; minChannelTime = 120; maxChannelTime = 150; band = WSM_PHY_BAND_2_4G; numOfProbeRequests = 0; break; #if CONFIG_5G_SUPPORT case ATBM_SCAN_5G_PASSAVE: case ATBM_SCAN_5G_PASSAVE_DFS: channels = hw_priv->bands[ATBM_NL80211_BAND_5GHZ]->channels; n_channels = hw_priv->bands[ATBM_NL80211_BAND_5GHZ]->n_channels; maxTransmitRate = WSM_TRANSMIT_RATE_6; minChannelTime = 120; maxChannelTime = 150; band = WSM_PHY_BAND_5G; numOfProbeRequests = 0; atbm_memset(priv->scan.dfs_map, 0, sizeof(priv->scan.dfs_map)); break; case ATBM_SCAN_5G_ACTIVE: if(!priv->scan_no_connect){ numOfSSIDs = 1; } case ATBM_SCAN_5G_WPS: channels = hw_priv->bands[ATBM_NL80211_BAND_5GHZ]->channels; n_channels = hw_priv->bands[ATBM_NL80211_BAND_5GHZ]->n_channels; maxTransmitRate = WSM_TRANSMIT_RATE_6; minChannelTime = 45; maxChannelTime = 75; band = WSM_PHY_BAND_5G; numOfProbeRequests = 2; break; case ATBM_SCAN_5G_ACTIVE_DFS: if(!priv->scan_no_connect){ numOfSSIDs = 1; } n_channels = 0; for(i = 0; i < hw_priv->bands[ATBM_NL80211_BAND_5GHZ]->n_channels; i++){ if(atbm_test_bit(hw_priv->bands[ATBM_NL80211_BAND_5GHZ]->channels[i].hw_value, priv->scan.dfs_map)){ avail_5g_channels[n_channels].hw_value = hw_priv->bands[ATBM_NL80211_BAND_5GHZ]->channels[i].hw_value; avail_5g_channels[n_channels].max_power = hw_priv->bands[ATBM_NL80211_BAND_5GHZ]->channels[i].max_power; n_channels++; } } channels = &avail_5g_channels; maxTransmitRate = WSM_TRANSMIT_RATE_6; minChannelTime = 45; maxChannelTime = 75; band = WSM_PHY_BAND_5G; numOfProbeRequests = 2; break; #endif #if CONFIG_P2P case ATBM_SCAN_P2P: numOfSSIDs = 1; channels = p2p_scan_chans; n_channels = 3; maxTransmitRate = WSM_TRANSMIT_RATE_1; minChannelTime = 45; maxChannelTime = 75; band = WSM_PHY_BAND_2_4G; numOfProbeRequests = 2; break; #endif default: wifi_printk(WIFI_ALWAYS, "Unknown Scan type %d\n", type); } do{ if(n_channels == 0){ break; } r_channels = (n_channels - c_channels) > ATBM_MAX_SCAN_CHANNELS ? ATBM_MAX_SCAN_CHANNELS : (n_channels - c_channels); wifi_printk(WIFI_DBG_MSG, "ch %d %d %d\n", n_channels, c_channels, r_channels); req = atbm_kzalloc(sizeof(struct atbm_scan_req) + numOfSSIDs*sizeof(struct wsm_ssid) + n_channels*sizeof(struct wsm_scan_ch), GFP_KERNEL); req->scan.ssids = (struct wsm_ssid *)(req + 1); req->scan.ch = (struct wsm_scan_ch *)(req->scan.ssids + numOfSSIDs); req->scan.scanType = WSM_SCAN_TYPE_FOREGROUND; req->scan.scanFlags =0; req->scan.numOfProbeRequests = numOfProbeRequests; req->scan.probeDelay = 10; req->scan.maxTransmitRate = maxTransmitRate; req->scan.band = band; if (priv->join_status == ATBMWIFI__JOIN_STATUS_STA) { req->scan.scanType = WSM_SCAN_TYPE_BACKGROUND; req->scan.scanFlags = WSM_SCAN_FLAG_FORCE_BACKGROUND; if (priv->if_id) req->scan.scanFlags |= WSM_FLAG_MAC_INSTANCE_1; else req->scan.scanFlags &= ~WSM_FLAG_MAC_INSTANCE_1; } if (priv->if_id){ req->scan.scanFlags |= WSM_FLAG_MAC_INSTANCE_1; }else{ req->scan.scanFlags &= ~WSM_FLAG_MAC_INSTANCE_1; } if(numOfSSIDs > 0){ atbm_memcpy(req->scan.ssids->ssid ,&priv->ssid[0], priv->ssid_length); req->scan.ssids->length = priv->ssid_length; } for(i = 0; i < r_channels; i++){ req->scan.ch[i].number = channels[c_channels+i].hw_value; req->scan.ch[i].txPowerLevel = channels[c_channels+i].max_power; req->scan.ch[i].minChannelTime = 55; req->scan.ch[i].maxChannelTime= 105; } req->scan.numOfChannels = r_channels; req->req_type = type; wifi_printk(WIFI_DBG_MSG, "Wifi add scan req %x type %d ch %d\n", req, req->req_type, req->scan.numOfChannels); atbm_list_add_tail(&req->list, &priv->scan.scan_req_list); c_channels += r_channels; }while(c_channels < n_channels); if(req){ req->scan_end = ATBM_TRUE; } } int atbm_req_scan_start(struct atbmwifi_vif *priv){ int ret = -1; struct atbm_scan_req *req; struct wsm_template_frame frame; if(!atbm_list_empty(&priv->scan.scan_req_list)){ req = atbm_list_first_entry(&priv->scan.scan_req_list, struct atbm_scan_req, list); priv->scan.cur_scan_req = req; wifi_printk(WIFI_ALWAYS, "Wifi start scan req band %d type %d ch %d\n", req->scan.band, req->req_type, req->scan.numOfChannels); frame.frame_type = WSM_FRAME_TYPE_PROBE_REQUEST; frame.disable =0; frame.rate=0; frame.skb = atbmwifi_ieee80211_send_probe_req(priv,ATBM_NULL,priv->extra_ie,priv->extra_ie_len,0); if (!frame.skb) return -ATBM_ENOMEM; ret = wsm_set_template_frame(priv->hw_priv, &frame, priv->if_id); atbm_dev_kfree_skb(frame.skb); if(ret){ wifi_printk(WIFI_SCAN,"%s fail \n",__FUNCTION__); return ret; } ret = wsm_scan(priv->hw_priv, &req->scan, priv->if_id); if(ret){ wifi_printk(WIFI_SCAN,"%s fail \n",__FUNCTION__); //add by wp ,scan fail priv->scan.in_progress = 0; priv->scan.ApScan_in_process = 0; //atbmwifi_wpa_event_queue((atbm_void*)hw_priv,(atbm_void*)1,(atbm_void*)priv->if_id, // WPA_EVENT__SUPPLICANT_SCAN_END,ATBM_WPA_EVENT_NOACK); } return ret; }else{ priv->scan.cur_scan_req = ATBM_NULL; } return ret; } void atbm_clear_scan_req(struct atbmwifi_vif *priv){ struct atbm_scan_req *req, *tmp; atbm_list_for_each_entry_safe(req, tmp, &priv->scan.scan_req_list, list, struct atbm_scan_req){ atbm_list_del(req); atbm_kfree(req); } priv->scan.cur_scan_req = ATBM_NULL; atbm_memset(priv->scan.dfs_map, 0, sizeof(priv->scan.dfs_map)); } int atbmwifi_scan_start(struct atbmwifi_vif *priv){ int ret = -1; #if CONFIG_WPS struct wpa_supplicant *wpa_s = (struct wpa_supplicant *)priv->appdata; #endif if(priv->scan.in_progress) return -1; priv->scan.status = 0; priv->scan.if_id = priv->if_id; priv->scan.in_progress = 1; #if CONFIG_P2P if(priv->p2p_scan){ atbmwifi_init_scan_req(priv, ATBM_SCAN_P2P); goto scan_start; } #endif #if CONFIG_WPS if(wpa_s->wps_mode != WPS_MODE_UNKNOWN){ atbmwifi_init_scan_req(priv, ATBM_SCAN_24G_WPS); atbmwifi_init_scan_req(priv, ATBM_SCAN_5G_WPS); goto scan_start; } #endif #if FAST_CONNECT_MODE if(priv->fast_connect && priv->fast_channel){ atbmwifi_init_scan_req(priv, ATBM_SCAN_FAST_LINK); priv->fast_connect = 0; goto scan_start; } #endif atbmwifi_init_scan_req(priv, ATBM_SCAN_24G_ACTIVE); #if CONFIG_5G_SUPPORT atbmwifi_init_scan_req(priv, ATBM_SCAN_5G_PASSAVE_DFS); #endif scan_start: ret = atbm_req_scan_start(priv); if(ret){ return ret; } atbmwifi_event_uplayer(priv,ATBM_WIFI_SCANSTART_EVENT,0); return ret; } int atbmwifi_scan_start_etf(struct atbmwifi_vif *priv) { int ret; struct atbmwifi_common *hw_priv = _atbmwifi_vifpriv_to_hwpriv(priv); struct wsm_ssid ssids; struct wsm_scan_ch ch[2]; struct wsm_scan scan = { .scanType = WSM_SCAN_TYPE_FOREGROUND, .scanFlags =0, .numOfProbeRequests = 1, .probeDelay = 0, .numOfChannels = atbmwifi_band_2ghz.n_channels, }; priv->scan.status = 0; priv->scan.if_id = priv->if_id; priv->scan.in_progress = 1; scan.maxTransmitRate = hw_priv->etf_rate; scan.band = WSM_PHY_BAND_2_4G; if (priv->join_status == ATBMWIFI__JOIN_STATUS_STA) { scan.scanType = WSM_SCAN_TYPE_BACKGROUND; scan.scanFlags = WSM_SCAN_FLAG_FORCE_BACKGROUND; if (priv->if_id) scan.scanFlags |= WSM_FLAG_MAC_INSTANCE_1; else scan.scanFlags &= ~WSM_FLAG_MAC_INSTANCE_1; } scan.autoScanInterval = (0xba << 24)|(120 * 1024); /* 30 seconds, -70 rssi */ scan.numOfProbeRequests = 50; scan.numOfChannels =1; scan.numOfSSIDs = 1; scan.probeDelay = 5; scan.scanFlags = 0; /* bit 0 set => forced background scan */ scan.scanType =WSM_SCAN_TYPE_FOREGROUND; scan.ssids = &ssids; scan.ssids->length = 0; atbm_memcpy(ssids.ssid,"tttttttt",8); scan.ssids = &ssids; if(priv->scan_no_connect){ scan.ssids->length = 0; } scan.ch = &ch[0]; scan.ch[0].number = hw_priv->etf_channel; scan.ch[0].minChannelTime= 5; scan.ch[0].maxChannelTime= 100; scan.ch[0].txPowerLevel= 3; ret = wsm_scan(hw_priv, &scan, priv->if_id); if(ret){ wifi_printk(WIFI_SCAN,"%s fail \n",__func__); } //atbmwifi_event_uplayer(priv,ATBM_WIFI_SCANSTART_EVENT,0); return ret; } int atbm_scan_work(struct atbm_work_struct *work) { struct atbmwifi_vif *priv=(struct atbmwifi_vif *)work; if(!priv->scan.in_progress) { if(g_ProductTestGlobal == 1) { wifi_printk(WIFI_DBG_ERROR,"[%s]:atbmwifi_scan_start_etf \n",__FUNCTION__); atbmwifi_scan_start_etf(priv); } else { wifi_printk(WIFI_DBG_ERROR,"[%s] atbmwifi_scan_start \n",__FUNCTION__); atbmwifi_scan_start(priv); } } return 0; } atbm_void atbmwifi_wpa_event_scan_expire(struct atbmwifi_vif *priv) { //struct atbmwifi_common *hw_priv=_atbmwifi_vifpriv_to_hwpriv(priv); wifi_printk(WIFI_DBG_ERROR,"%s %d\n",__func__,__LINE__); //peterjiang@20200518, if station is off, can't do station scan if(priv->iftype == ATBM_NUM_NL80211_IFTYPES){ wifi_printk(WIFI_DBG_ERROR,"%s station is off, can not do scan, cancel scan timer\n",__func__); atbmwifi_eloop_cancel_timeout(sta_scan_start_timer_func, (atbm_void *)priv, ATBM_NULL); return; } //ATBM_WARN_ON(wsm_stop_scan(hw_priv,priv->scan.if_id ? 1 : 0)); if(priv->scan.in_progress){ priv->scan.status = -ATBM_ETIMEDOUT; wifi_printk(WIFI_DBG_MSG,"atbm: sta_scan_start_timer_func(), timeout\n"); } if(!priv->scan.in_progress){ atbmwifi_sta_scan(priv); } } atbm_void sta_scan_start_timer_func(atbm_void *data1,atbm_void *data2) { atbmwifi_wpa_event_queue((atbm_void*)data1,data2,ATBM_NULL, WPA_EVENT__SUPPLICANT_SCAN_EXPIRE,ATBM_WPA_EVENT_NOACK); } atbm_void atbmwifi_scan_comlete(struct atbmwifi_vif *priv) { struct atbmwifi_common *hw_priv=_atbmwifi_vifpriv_to_hwpriv(priv); #if CONFIG_WPS struct wpa_supplicant *wpa_s = (struct wpa_supplicant *)priv->appdata; #endif if(priv == ATBM_NULL){ wifi_printk(WIFI_DBG_ERROR,"atbm: atbmwifi_scan_comlete(), priv is ATBM_NULL.\n"); atbm_SleepMs(100); return; } #if CONFIG_WPS if(priv->pin) wpa_s->scan_runs++; #endif priv->scan.in_progress = 0; priv->scan.ApScan_in_process = 0; /*For AP ScanEnd Flag */ hw_priv->ApScan_process_flag=0; if(!priv->enabled){ wifi_printk(WIFI_DBG_MSG,"atbm: atbmwifi_scan_comlete(), priv disabled.\n"); return ; } if(hw_priv->bStartTx) { if(hw_priv->bStartTxWantCancel == 0) { wifi_printk(WIFI_SCAN,"## wsm_start_scan_etf ##\n"); //wsm_start_scan_etf(hw_priv, priv); } else { hw_priv->bStartTx = 0; hw_priv->bStartTxWantCancel = 0; if(hw_priv->etf_test_v2){ hw_priv->etf_test_v2 = 0; wifi_printk(WIFI_SCAN,"## start timer etf_tx_end_work ##\n"); etf_v2_scan_end(hw_priv,priv); } } return; } #if CONFIG_P2P if(priv->p2p_scan) p2p_scan_result(); #endif // atbm_CancelTimer(&priv->scan_expire_timer); atbmwifi_eloop_cancel_timeout(sta_scan_start_timer_func, (atbm_void *)priv, ATBM_NULL); if(priv->scan.status != ATBMWIFI_SCAN_CONNECT_AP_SUCCESS){ wifi_printk(WIFI_SCAN,"scan fail again [%d]s, scan_no_connect=%d\n",priv->scan_expire, priv->scan_no_connect); if(priv->scan_no_connect){ goto __end; } #if CONFIG_P2P if(priv->p2p_scan || priv->p2p_join){ atbmwifi_eloop_register_timeout(0, 200, sta_scan_start_timer_func,(atbm_void *)priv,ATBM_NULL); }else #endif { //peterjiang@20200518, increase scan expire priv->scan_expire+=2; if(priv->scan_expire > 60){ priv->scan_expire = 60; } atbmwifi_eloop_register_timeout(0,priv->scan_expire*1000,sta_scan_start_timer_func,(atbm_void *)priv,ATBM_NULL); } } else { if(priv->scan_no_connect == 0){ //if the first scan success, if(priv->connect_expire==0){ priv->scan_expire = 5; priv->connect_expire = 1; } else { if(priv->scan_expire < 60){ priv->scan_expire += 5; } else { priv->scan_expire = 10; } } wifi_printk(WIFI_SCAN|WIFI_CONNECT,"sta_join_work \n"); #if CONFIG_WPS if(wpa_s->wps_mode != WPS_MODE_UNKNOWN){ wifi_printk(WIFI_WPS|WIFI_CONNECT, "WPS: scan end\n"); if(wpa_s->wps_ap_cnt == 0){ wifi_printk(WIFI_WPS, "WPS: not found AP.scan again\n"); //peterjiang@20200424, wps ap is not found, we need to do scan again. atbmwifi_eloop_register_timeout(0,priv->scan_expire*1000,sta_scan_start_timer_func,(atbm_void *)priv,ATBM_NULL); goto __end; } if(wpa_s->wps_ap_cnt > 1){ wifi_printk(WIFI_WPS, "WPS: overlap(%d)\n", wpa_s->wps_ap_cnt); atbmwps_cancel(priv); goto __end; } } #endif // atbmwifi_event_uplayer(priv,ATBM_WIFI_JOIN_EVENT,0); atbm_queue_work(hw_priv,priv->join_work); } } __end: atbmwifi_event_uplayer(priv,ATBM_WIFI_SCANDONE_EVENT,0); priv->scan_no_connect=priv->scan_no_connect_back; if(priv->scan.scan_smartconfig){ wifi_printk(WIFI_DBG_MSG,"atbm: atbmwifi_scan_comlete() ssc.\n"); smartconfig_magic_scan_done(priv); } wifi_printk(WIFI_DBG_MSG,"atbm: atbmwifi_scan_comlete() <===\n"); return; } static atbm_void __atbmwifi_autoconnect(atbm_void *data1,atbm_void *data2) { struct atbmwifi_vif *priv = (struct atbmwifi_vif *)data1; if(priv->scan.scan_smartconfig){ return; } priv->auto_connect_when_lost = 0; wifi_printk(WIFI_ALWAYS,"autoconnect\n"); priv->scan_no_connect=0; if(priv->scan_expire < 60){ priv->scan_expire += 5; } else { priv->scan_expire = 10; } priv->assoc_ok = 0; wpa_connect_ap(priv); } int atbmwifi_autoconnect(struct atbmwifi_vif *priv, int time) { // atbmwifi_event_uplayer(priv,ATBM_WIFI_PRE_ASSOC_EVENT,0); atbmwifi_wpa_event_queue((atbm_void*)priv,time,ATBM_NULL,WPA_EVENT__SUPPLICANT_CONNECT_FAIL,ATBM_WPA_EVENT_NOACK); return 0; } void atbmwifi_wpa_event_connect_fail(struct atbmwifi_vif *priv, int time) { atbmwifi_eloop_cancel_timeout(__atbmwifi_autoconnect, priv, ATBM_NULL); atbmwifi_eloop_register_timeout(time, 0,__atbmwifi_autoconnect, priv, ATBM_NULL); } atbm_void atbmwifi_wpa_event_process_scan_end(struct atbmwifi_common *hw_priv, atbm_uint32 scan_status,atbm_uint32 interfaceId) { struct atbm_scan_req * req; struct atbmwifi_vif *priv = ATBM_NULL; priv = _atbmwifi_hwpriv_to_vifpriv(hw_priv,interfaceId); if(priv == ATBM_NULL){ wifi_printk(WIFI_WPA,"scan_end priv err\n"); return; } if(scan_status == 0){ wifi_printk(WIFI_WPA,"scan timeout\n"); ATBM_WARN_ON(wsm_stop_scan(hw_priv,priv->scan.if_id ? 1 : 0)); if(priv->scan.in_progress){ priv->scan.status = -ATBM_ETIMEDOUT; wifi_printk(WIFI_DBG_MSG,"atbm: sta_scan_start_timer_func(), timeout\n"); } } if(scan_status == 1){ if(!priv->scan_no_connect && priv->scan.status == ATBMWIFI_SCAN_CONNECT_AP_SUCCESS){ atbm_clear_scan_req(priv); atbmwifi_scan_comlete(priv); }else if(priv->scan.cur_scan_req){ atbm_list_del(&priv->scan.cur_scan_req->list); if(priv->scan.cur_scan_req->req_type == ATBM_SCAN_5G_PASSAVE_DFS && priv->scan.cur_scan_req->scan_end){ atbmwifi_init_scan_req(priv, ATBM_SCAN_5G_ACTIVE_DFS); } atbm_kfree(priv->scan.cur_scan_req); if(atbm_req_scan_start(priv)){ atbmwifi_scan_comlete(priv); } }else{ atbmwifi_scan_comlete(priv); } } if(scan_status == 0){ priv->scan_expire+=3; if(priv->scan_expire > 30){ priv->scan_expire = 10; } if(!priv->scan.in_progress) atbmwifi_sta_scan(priv); } return; } atbm_void atbmwifi_scan_complete_cb(struct atbmwifi_common *hw_priv, int interface_link_id,struct wsm_scan_complete *arg) { atbmwifi_wpa_event_queue((atbm_void*)hw_priv,(atbm_void*)1,(atbm_void*)interface_link_id, WPA_EVENT__SUPPLICANT_SCAN_END,ATBM_WPA_EVENT_NOACK); } int atbmwifi_sta_scan(struct atbmwifi_vif *priv) { int ret=0; struct atbmwifi_common *hw_priv = _atbmwifi_vifpriv_to_hwpriv(priv); if (priv->join_status == ATBMWIFI__JOIN_STATUS_AP) return -ATBM_EOPNOTSUPP; priv->scan.if_id = priv->if_id; atbm_queue_work(hw_priv,priv->scan.scan_work); return ret; } atbm_void atbmwifi_join_complete(struct atbmwifi_vif *priv) { #if CONFIG_SAE struct wpa_supplicant *wpa_s = (struct wpa_supplicant *)priv->appdata; #endif if(!priv->enabled){ return ; } #if CONFIG_SAE wpa_s->sae_start = 1; #endif wifi_printk(WIFI_ALWAYS,"sta_join_ ATBM_IEEE80211_STYPE_AUTH\n"); atbmwifi_enable_sta_filter_retry(priv); wpa_prepare_auth(priv); return; } atbm_void atbmwifi_join_start(struct atbmwifi_vif *priv) { int ret; struct atbmwifi_common *hw_priv = _atbmwifi_vifpriv_to_hwpriv(priv); struct wsm_operational_mode mode ; struct wsm_join join ; /*Station & Ap Must be stay the same channle num,otherwise it's be combination fail*/ if(atbmwifi_iee80211_check_combination(priv,(atbm_uint8)priv->bss.channel_num) == ATBM_FALSE){ return; } mode.power_mode = wsm_power_mode_quiescent; mode.disableMoreFlagUsage = ATBM_TRUE; atbm_memset(&join, 0, sizeof(join)); join.mode = WSM_JOIN_MODE_BSS; join.preambleType = WSM_JOIN_PREAMBLE_SHORT; /*Do Scan one time Before join Bss*/ join.probeForJoin = 1; /* dtimPeriod will be updated after association */ join.dtimPeriod = 1; join.beaconInterval = priv->bss.sta_priv.beacon_interval; join.channelNumber = priv->bss.channel_num; join.channel_type= priv->bss.channel_type; priv->config.channel_index = priv->bss.channel_num; if (priv->if_id) join.flags |= WSM_FLAG_MAC_INSTANCE_1; else join.flags &= ~WSM_FLAG_MAC_INSTANCE_1; join.flags |= WSM_FLAG_JOIN_F_FORCE_JOIN; join.band = WSM_PHY_BAND_2_4G; join.basicRateSet = 7; /*1, 2, 5.5 mbps*/ atbm_memcpy(&join.bssid[0], priv->bssid, sizeof(priv->bssid)); join.ssidLength = priv->ssid_length; atbm_memcpy(&join.ssid[0], priv->ssid, join.ssidLength); wsm_set_operational_mode(hw_priv, &mode, priv->if_id); wsm_set_block_ack_policy(hw_priv, ATBMWIFI__TX_BLOCK_ACK_ENABLED_FOR_ALL_TID, ATBMWIFI__RX_BLOCK_ACK_ENABLED_FOR_ALL_TID, priv->if_id); #if FAST_CONNECT_NO_SCAN if(priv->fast_conn_noscan){ join.probeForJoin = 0; priv->fast_conn_noscan = 0; } #endif wifi_printk(WIFI_CONNECT,"wsm_join\n"); ret=wsm_join(hw_priv, &join, priv->if_id); if(ret == 0){ #if 0 //FAST_CONNECT_NO_SCAN /*Some AP need disconn before auth while some may cause other problems*/ if(priv->fast_conn_noscan){ // atbmwifi_ieee80211_tx_mgmt_deauth(priv,priv->bss.bssid,priv->bss.bssid,ATBM_WLAN_REASON_DEAUTH_LEAVING); priv->fast_conn_noscan = 0; } #endif priv->join_status = ATBMWIFI__JOIN_STATUS_STA; priv->disable_beacon_filter = ATBM_TRUE; atbmwifi_join_complete(priv); //start connect timeout atbmwifi_eloop_register_timeout(0,ATBM_WIFI_AUTH_TIMEOUT,atbmwifi_sta_join_timeout,(atbm_void *)priv,ATBM_NULL); }else{ wifi_printk(WIFI_ALWAYS,"wsm_join cmd send fail\n"); } //atbmwifi_update_filtering(priv); return; } atbm_void atbmwifi_sta_join_timeout(atbm_void *data1,atbm_void *data2) { struct atbmwifi_vif *priv=(struct atbmwifi_vif *)data1; wifi_printk(WIFI_DBG_ERROR,"atbmwifi_sta_join_timeout() \n"); atbmwifi_autoconnect(priv, priv->scan_expire); } atbm_uint32 atbmwifi_rate_mask_to_wsm(struct atbmwifi_common *hw_priv, enum atbmwifi_ieee80211_band band, atbm_uint32 rates) { atbm_uint32 ret = 0; int i; struct atbmwifi_ieee80211_rate * bitrates = hw_priv->bands[band]->bitrates; for (i = 0; i < 32; ++i) { if (rates & BIT(i)) ret |= BIT(bitrates[i].hw_value); } return ret; } int atbmwifi_rx_assoc_rsp(struct atbmwifi_vif *priv,struct atbm_buff *skb) { struct atbmwifi_ieee80211_mgmt *mgmt; atbm_uint16 capab_info, status_code, aid; struct atbmwifi_ieee802_11_elems elems; #if (CONFIG_WPS || CONFIG_SAE) struct wpa_supplicant *wpa_s = (struct wpa_supplicant *)priv->appdata; #endif atbm_uint8 *pos; mgmt = (struct atbmwifi_ieee80211_mgmt *) ATBM_OS_SKB_DATA(skb); wifi_printk(WIFI_CONNECT,"atbmwifi_rx_assoc_rsp\n"); capab_info = atbm_le16_to_cpu(mgmt->u.assoc_resp.capab_info); status_code = atbm_le16_to_cpu(mgmt->u.assoc_resp.status_code); aid = atbm_le16_to_cpu(mgmt->u.assoc_resp.aid); pos = mgmt->u.assoc_resp.variable; atbm_ieee802_11_parse_elems(pos, skb->dlen - (pos - (atbm_uint8 *) mgmt), &elems); if (status_code == ATBM_WLAN_STATUS_ASSOC_REJECTED_TEMPORARILY && elems.timeout_int && elems.timeout_int_len == 5 && elems.timeout_int[0] == ATBM_WLAN_TIMEOUT_ASSOC_COMEBACK) { atbm_uint32 tu, ms; tu = get_unaligned_le32(elems.timeout_int + 1); ms = tu * 1024 / 1000; wifi_printk(WIFI_CONNECT,"%pM rejected association temporarily; " "comeback duration %u TU (%u ms)\n", mgmt->sa, tu, ms); if (ms > 5) // return 0; } if (status_code != ATBM_WLAN_STATUS_SUCCESS){ #if CONFIG_SAE if (wpa_s->sae_pmksa_caching && atbmwifi_wpa_key_mgmt_sae(wpa_s->key_mgmt)){ wpa_printf(MSG_DEBUG, "PMKSA caching attempt rejected - drop PMKSA cache entry and fall back to SAE authentication"); if (wpa_s->wpa && wpa_s->wpa->cur_pmksa) { wpa_printf(MSG_DEBUG, "RSN: Cancelling PMKSA caching attempt"); wpa_s->wpa->cur_pmksa = ATBM_NULL; pmksa_cache_flush(wpa_s->wpa->pmksa, &priv->config, ATBM_NULL, 0); } } #endif wifi_printk(WIFI_CONNECT,"%pM denied association (code=%d)\n", mgmt->sa, status_code); return -1; } #if CONFIG_WPS else{ atbm_memcpy(wpa_s->bssid, mgmt->bssid, ATBM_ETH_ALEN); } #endif return 0; } /*success return 0. fail return -1*/ int atbmwifi_assoc_success(struct atbmwifi_vif *priv,struct atbm_buff *skb) { struct atbmwifi_ieee80211_mgmt *mgmt; struct atbmwifi_common *hw_priv = _atbmwifi_vifpriv_to_hwpriv(priv); struct atbmwifi_cfg *config = atbmwifi_get_config(priv); struct wsm_association_mode association_mode; struct wsm_set_bss_params bss_params; #if CONFIG_WPS struct wpa_supplicant *wpa_s = (struct wpa_supplicant *)priv->appdata; #endif struct atbmwifi_ieee802_11_elems elems; struct atbmwifi_ieee80211_supported_band *sband; atbm_uint16 capab_info, status_code, aid; int ret = 0; atbm_uint8 *pos; atbm_uint32 rates, basic_rates; int i,j; ATBM_BOOL have_higher_than_11mbit = ATBM_FALSE; int min_rate = 30, min_rate_index = -1; atbm_uint16 ap_ht_cap_flags; mgmt =(struct atbmwifi_ieee80211_mgmt *)ATBM_OS_SKB_DATA(skb); capab_info = atbm_le16_to_cpu(mgmt->u.assoc_resp.capab_info); status_code = atbm_le16_to_cpu(mgmt->u.assoc_resp.status_code); aid = atbm_le16_to_cpu(mgmt->u.assoc_resp.aid); priv->bss.aid = aid; wifi_printk(WIFI_CONNECT, "RX AssocRsp (capab=0x%x " "status=%d aid=%d)\n", capab_info, status_code, (atbm_uint16)(aid & ~(BIT(15) | BIT(14)))); pos = mgmt->u.assoc_resp.variable; atbm_ieee802_11_parse_elems(pos, skb->dlen - (pos - (atbm_uint8 *) mgmt), &elems); sband = hw_priv->bands[priv->bss.sta_priv.band]; rates = 0; basic_rates = 0; for (i = 0; i < elems.supp_rates_len; i++) { int rate = (elems.supp_rates[i] & 0x7f) * 5; ATBM_BOOL is_basic = !!(elems.supp_rates[i] & 0x80); if (rate > 110) have_higher_than_11mbit = ATBM_TRUE; for (j = 0; j < sband->n_bitrates; j++) { if (sband->bitrates[j].bitrate == rate) { rates |= BIT(j); if (is_basic) basic_rates |= BIT(j); if (rate < min_rate) { min_rate = rate; min_rate_index = j; } break; } } } for (i = 0; i < elems.ext_supp_rates_len; i++) { int rate = (elems.ext_supp_rates[i] & 0x7f) * 5; ATBM_BOOL is_basic = !!(elems.ext_supp_rates[i] & 0x80); if (rate > 110) have_higher_than_11mbit = ATBM_TRUE; for (j = 0; j < sband->n_bitrates; j++) { if (sband->bitrates[j].bitrate == rate) { rates |= BIT(j); if (is_basic) basic_rates |= BIT(j); if (rate < min_rate) { min_rate = rate; min_rate_index = j; } break; } } } /* cf. IEEE 802.11 9.2.12 */ if (sband->band == ATBM_IEEE80211_BAND_2GHZ && have_higher_than_11mbit) priv->bss.sta_priv.rate_11g=ATBM_TRUE; if (elems.ht_cap_elem && !(config->flags & ATBM_IEEE80211_STA_DISABLE_11N)) atbmwifi_ieee80211_ht_cap_ie_to_sta_ht_cap(sband, elems.ht_cap_elem, &priv->bss.sta_priv.rate.ht_cap); ap_ht_cap_flags = priv->bss.sta_priv.rate.ht_cap.cap; if (elems.ht_info_elem && !(config->flags & ATBM_IEEE80211_STA_DISABLE_11N)){ atbmwifi_ieee80211_enable_ht(elems.ht_info_elem, priv, ap_ht_cap_flags, ATBM_FALSE); #if BW_40M_SUPPORT atbmwifi_iee80211_unify_channel_type(priv, priv->bss.channel_type); #endif } if (elems.wmm_param){ priv->bss.sta_priv.wmm_used = 1; }else{ priv->bss.sta_priv.wmm_used = 0; } priv->bss.sta_priv.rate.ht = atbm_is_ht(priv->bss.channel_type); priv->bss.sta_priv.rate.channel_type = priv->bss.channel_type; #if RATE_CONTROL_MODE if(priv->bss.rc_priv == ATBM_NULL){ priv->bss.rc_priv = mac80211_ratectrl->alloc_sta(); } mac80211_ratectrl->sta_rate_init(&priv->bss.sta_priv.rate,priv->bss.rc_priv); #endif association_mode.greenfieldMode = MODE_11N_MIXED; association_mode.flags = WSM_ASSOCIATION_MODE_SNOOP_ASSOC_FRAMES | WSM_ASSOCIATION_MODE_USE_PREAMBLE_TYPE | WSM_ASSOCIATION_MODE_USE_HT_MODE | WSM_ASSOCIATION_MODE_USE_BASIC_RATE_SET | WSM_ASSOCIATION_MODE_USE_MPDU_START_SPACING; association_mode.preambleType = priv->bss.sta_priv.short_preamble ? WSM_JOIN_PREAMBLE_SHORT : WSM_JOIN_PREAMBLE_LONG; association_mode.basicRateSet = atbm_cpu_to_le32( atbmwifi_rate_mask_to_wsm(hw_priv, priv->bss.sta_priv.band, priv->bss.sta_priv.rate.basic_rates)); association_mode.mpduStartSpacing = 0; if(wsm_set_association_mode(hw_priv, &association_mode, priv->if_id)){ ret = -1; goto __error; } if(wsm_keep_alive_period(hw_priv, KEEP_ALIVE_PERIOD /* sec */, priv->if_id)){ ret = -2; goto __error; } bss_params.operationalRateSet = atbm_cpu_to_le32( atbmwifi_rate_mask_to_wsm(hw_priv, priv->bss.sta_priv.band, priv->bss.sta_priv.rate.support_rates)); bss_params.beaconLostCount = DEFAULT_BEACON_LOSS_CNT; bss_params.aid = priv->bss.aid; if(wsm_set_bss_params(hw_priv, &bss_params, priv->if_id)){ ret = -3; goto __error; } if(wsm_set_beacon_wakeup_period(hw_priv, priv->bss.sta_priv.beacon_interval * priv->bss.dtim_period > MAX_BEACON_SKIP_TIME_MS ? 1 : priv->bss.dtim_period, 0, priv->if_id)){ ret = -4; goto __error; } if (priv->bss.sta_priv.rate.ht) { /* Statically enabling block ack for TX/RX */ wsm_set_block_ack_policy(hw_priv, hw_priv->ba_tid_tx_mask, hw_priv->ba_tid_rx_mask,priv->if_id); } #if ATBM_DRIVER_PROCESS_BA if(hw_priv->driver_setup_ba){ atbm_spin_lock_init(&priv->bss.sta_priv.lock); if(!priv->bss.sta_priv.ampdu_mlme.init){ atbm_os_mutexLockInit(&priv->bss.sta_priv.ampdu_mlme.mtx); priv->bss.sta_priv.ampdu_mlme.work = atbm_init_work(hw_priv, ieee80211_ba_session_work, &priv->bss.sta_priv); priv->bss.sta_priv.ampdu_mlme.init = 1; } priv->bss.sta_priv.priv = priv; atbm_memcpy(priv->bss.sta_priv.mac, priv->bss.bssid, ATBM_ETH_ALEN); priv->bss.sta_priv.link_id = 0; for (i = 0; i < STA_TID_NUM; i++) { /* * timer_to_tid must be initialized with identity mapping * to enable session_timer's data differentiation. See * sta_rx_agg_session_timer_expired for usage. */ priv->bss.sta_priv.timer_to_tid[i] = i; priv->bss.sta_priv.rx_token[i] = -1; priv->bss.sta_priv.ampdu_mlme.trylimit[i] = 0; priv->bss.sta_priv.ampdu_mlme.timestamp[i] = atbm_GetOsTimeMs(); } } #endif priv->assoc_ok = 1; /*cancel connect timeout*/ atbmwifi_eloop_cancel_timeout(atbmwifi_sta_join_timeout, (atbm_void *)priv, ATBM_NULL); atbmwifi_event_uplayer(priv,ATBM_WIFI_ASSOC_EVENT,(atbm_uint8*)skb); #if CONFIG_WPS if(wpa_s->wps_mode != WPS_MODE_UNKNOWN){ #if CONFIG_P2P if(priv->p2p_join) priv->auto_connect_when_lost = 0; #endif if(wpa_wsc_tx_process(wpa_s, ATBM_IEEE802_1X_TYPE_EAPOL_START, ATBM_NULL, 0) < 0) wifi_printk(WIFI_WPS, "WPS: eapol start failed.\n"); } #endif __error: wifi_printk(WIFI_CONNECT|WIFI_DBG_ERROR,"connectap %s ret=%d \n",ret?"error":"success",ret); return status_code; } /*SUCCESS return linkid;fail return 0*/ int sta_add_linkid(struct atbmwifi_vif *priv, atbm_uint8 *sta_mac) { int link_id = 0; /* link_id = sta_alloc_linkid(priv, sta_mac); if(link_id ==0){ wifi_printk(WIFI_CONNECT,"%s Error \n",__FUNCTION__); return 0; } priv->link_id_db[link_id-1].status = ATBMWIFI__LINK_HARD; atbmwifi_link_id_lmac(priv,link_id); */ /*STA mode not need to add linkid, in lmac LMC_ActivateInterface TxLinkEnabled = 0x8001;*/ return link_id; } int sta_del_linkid(struct atbmwifi_vif *priv, atbm_uint8 * staMacAddr) { // int link_id =0; /* wifi_printk(WIFI_DBG_MSG,"[sta]:%s++\n",__FUNCTION__); link_id = atbmwifi_find_link_id(priv, staMacAddr); if((link_id <= ATBMWIFI__MAX_STA_IN_AP_MODE) && link_id>0){ _atbmwifi_unmap_link(priv, link_id); priv->link_id_db[link_id-1].status = ATBMWIFI__LINK_OFF; wifi_printk(WIFI_DBG_MSG,"[sta]:%d link_id %d\n",__FUNCTION__,link_id); } */ return 0; } atbm_void sta_connect_complete(struct atbmwifi_vif *priv) { return; } atbm_void sta_deauth(struct atbmwifi_vif *priv) { struct atbmwifi_common *hw_priv = priv->hw_priv; //struct atbmwifi_cfg *config = atbmwifi_get_config(priv); struct wsm_reset reset = { .reset_statistics = ATBM_TRUE, .link_id = 0, }; struct wsm_operational_mode mode = { .power_mode = wsm_power_mode_quiescent, .disableMoreFlagUsage = ATBM_TRUE, }; /*Disable net interface*/ atbmwifi_event_uplayer(priv,ATBM_WIFI_DISENABLE_NET_EVENT,ATBM_NULL); #if ATBM_DRIVER_PROCESS_BA if(hw_priv->driver_setup_ba){ if(priv->bss.sta_priv.ampdu_mlme.init){ ieee80211_sta_tear_down_BA_sessions(&priv->bss.sta_priv, ATBM_TRUE); atbm_os_DeleteMutex(&priv->bss.sta_priv.ampdu_mlme.mtx); } __atbm_flush(hw_priv, ATBM_FALSE, priv->if_id, BIT(0)); } #endif priv->join_status = ATBMWIFI__JOIN_STATUS_PASSIVE; if(priv->bss.information_elements){ atbm_kfree(priv->bss.information_elements); priv->bss.information_elements = ATBM_NULL; priv->bss.len_information_elements = 0; } #if RATE_CONTROL_MODE if(priv->bss.rc_priv){ mac80211_ratectrl->free_sta(priv->bss.rc_priv); priv->bss.rc_priv = ATBM_NULL; } #endif atbmwifi_del_key(priv,1,0); atbmwifi_del_key(priv,0,0); #if CONFIG_IEEE80211W atbmwifi_del_key(priv,2,0); #endif atbm_memset(priv->connect.gtk, 0, sizeof(priv->connect.gtk)); atbm_memset(priv->connect.ptk, 0, sizeof(priv->connect.ptk)); wsm_reset(hw_priv, &reset, priv->if_id); wsm_set_operational_mode(hw_priv, &mode, priv->if_id); wsm_keep_alive_period(hw_priv, 0, priv->if_id); //wsm_set_output_power(priv->hw_priv,priv->hw_priv->output_power * 10, priv->if_id); wsm_set_block_ack_policy(hw_priv,0, 0, priv->if_id); atbmwifi_set_pm(priv,ATBM_FALSE,0xFF); //atbmwifi_disable_sta_filter_retry(priv); //peterjiang@20200428, notify apply layer, and do disconnect; //wpa_supplicant_event_disassoc(priv); atbmwifi_event_uplayer(priv,ATBM_WIFI_DEASSOC_EVENT,0); #if ATBM_PKG_REORDER wifi_printk(WIFI_CONNECT,"atbm_reorder_func_reset.\n"); atbm_reorder_func_reset(priv,0xff); #endif atbmwifi_eloop_cancel_timeout(atbmwifi_sta_join_timeout, (atbm_void *)priv, ATBM_NULL); if(priv->auto_connect_when_lost){ atbmwifi_autoconnect(priv, priv->scan_expire); } atbm_clear_scan_req(priv); priv->assoc_ok = 0; priv->connect_ok = 0; priv->connect.encrype = 0; atbm_memset(&priv->bss,0,sizeof(struct atbmwifi_cfg80211_bss)); return; } /* ps_enabled[0~1] power save mode ,1 power save ,0 ACTIVE dynamic_ps_timeout [0~127 ms] fast_ps timeout; */ atbm_void atbmwifi_set_pm(struct atbmwifi_vif *priv,ATBM_BOOL ps_enabled,atbm_uint8 dynamic_ps_timeout) { if (ps_enabled == ATBM_FALSE) priv->powersave_mode.pmMode = WSM_PSM_ACTIVE; else if (dynamic_ps_timeout <= 0) priv->powersave_mode.pmMode = WSM_PSM_PS; else priv->powersave_mode.pmMode = WSM_PSM_FAST_PS; wifi_printk(WIFI_PS, "[STA] Aid: %d, Joined: %s, Powersave: %s\n", priv->bss.aid, priv->join_status == ATBMWIFI__JOIN_STATUS_STA ? "yes" : "no", priv->powersave_mode.pmMode == WSM_PSM_ACTIVE ? "WSM_PSM_ACTIVE" : priv->powersave_mode.pmMode == WSM_PSM_PS ? "WSM_PSM_PS" : priv->powersave_mode.pmMode == WSM_PSM_FAST_PS ? "WSM_PSM_FAST_PS" : "UNKNOWN"); /* Firmware requires that value for this 1-byte field must * be specified in units of 500us. Values above the 128ms * threshold are not supported. */ if (dynamic_ps_timeout >= 0x80) priv->powersave_mode.fastPsmIdlePeriod = 0xFF; else priv->powersave_mode.fastPsmIdlePeriod = dynamic_ps_timeout << 1; if (priv->join_status == ATBMWIFI__JOIN_STATUS_STA &&priv->bss.aid &&priv->assoc_ok) wsm_set_pm(priv->hw_priv, &priv->powersave_mode, priv->if_id); return; } int atbm_wifi_free_scaned_list(struct atbmwifi_vif *priv) { return 0; } atbm_void atbmwifi_start_station(struct atbmwifi_vif *priv) { priv->appdata = init_wpa_supplicant(priv); } /* TODO: COMBO: Flush only a particular interface specific parts */ int __atbm_flush(struct atbmwifi_common *hw_priv, ATBM_BOOL drop, int if_id, atbm_uint32 link_id_map) { int i, ret; int retry = 0; struct atbmwifi_vif *priv = _atbmwifi_hwpriv_to_vifpriv(hw_priv, if_id); if(atbm_bh_is_term(hw_priv)){ drop = ATBM_TRUE; } atbmwifi_queue_lock(&hw_priv->tx_queue[0],priv); for (;;) { /* TODO: correct flush handling is required when dev_stop. * Temporary workaround: 2s */ if (drop) { for (i = 0; i < 4; ++i) atbmwifi_queue_clear(&hw_priv->tx_queue[i],if_id); } ret = 0; wsm_vif_lock_tx(priv); if (atbm_unlikely(!atbmwifi_queue_stats_is_empty( &hw_priv->tx_queue_stats, link_id_map, if_id))) { /* Highly unlekely: WSM requeued frames. */ wsm_unlock_tx(hw_priv); if(retry >= 3 * TEST_DTIM_INTV){ wifi_printk(WIFI_ALWAYS,"wait tx flush timeout\n"); drop = ATBM_TRUE; } wifi_printk(WIFI_ALWAYS,"wait tx flush\n"); atbm_mdelay(TEST_BEACON_INTV); retry++; continue; } break; } atbmwifi_queue_unlock(&hw_priv->tx_queue[0],priv); return ret; } atbm_void sta_work_task(struct atbmwifi_vif *priv) { return; } atbm_void atbmwifi_stop_sta(struct atbmwifi_vif *priv) { struct wpa_supplicant *wpa_s = priv->appdata; struct atbmwifi_common *hw_priv = _atbmwifi_vifpriv_to_hwpriv(priv); if(!atbmwifi_is_sta_mode(priv->iftype)) goto sta_off; if(!priv->enabled){ wifi_printk(WIFI_ALWAYS,"atbmwifi_stop_sta drop\n"); goto sta_off; } #if CONFIG_WPS //peterjiang@20200531,fix bug #35766 if((wpa_s != ATBM_NULL) && (wpa_s->wps_mode != WPS_MODE_UNKNOWN)) atbmwifi_eloop_cancel_timeout(wpas_wps_timeout, wpa_s, NULL); #endif //peterjiang@20200518, wifi hungup issue //if scan timer is working, then do station off from webpage, the next scan will happened null pointer atbmwifi_eloop_cancel_timeout(atbmwifi_sta_join_timeout, (atbm_void *)priv, ATBM_NULL); atbmwifi_eloop_cancel_timeout(sta_scan_start_timer_func, (atbm_void *)priv, ATBM_NULL); atbmwifi_ieee80211_connection_loss(priv); atbm_cancel_work(hw_priv, priv->scan.scan_work); atbm_cancel_work(hw_priv, priv->join_work); __atbm_flush(hw_priv, ATBM_FALSE, priv->if_id, 0xff); if(priv->scan_ret.info ){ atbm_kfree(priv->scan_ret.info); priv->scan_ret.info = ATBM_NULL; priv->scan_ret.len =0; } if(priv->extra_ie){ atbm_kfree(priv->extra_ie); priv->extra_ie_len = 0; priv->extra_ie = ATBM_NULL; } priv->auto_connect_when_lost =0; priv->listening = ATBM_FALSE; priv->enabled = 0; /*Here need clear station states*/ sta_deauth(priv); priv->connect.crypto_pairwise=0; priv->connect.crypto_group=0; atbm_memset(&priv->config,0,sizeof(struct atbmwifi_cfg)); atbmwifi_event_uplayer(priv,ATBM_WIFI_DEAUTH_EVENT,ATBM_NULL); /*Disable net interface*/ //atbmwifi_event_uplayer(priv,ATBM_WIFI_DISENABLE_NET_EVENT,ATBM_NULL); atbm_wifi_free_scaned_list(priv); priv->auto_connect_when_lost = 0; priv->join_status = ATBMWIFI__JOIN_STATUS_PASSIVE; free_wpa_supplicant(priv); atbm_mdelay(100); sta_off: priv->iftype = ATBM_NUM_NL80211_IFTYPES; return; } atbm_void atbmwifi_start_sta(struct atbmwifi_vif *priv) { struct atbmwifi_common *hw_priv = _atbmwifi_vifpriv_to_hwpriv(priv); /*Enalbe the current priv,Inital it is zero*/ priv->enabled = 1; priv->scan_expire = INITIAL_SCAN_EXPIRE; /*Initial Station timer*/ //atbm_InitTimer(&priv->scan_expire_timer,sta_scan_start_timer_func,(atbm_void*)priv); //atbm_InitTimer(&priv->smartconfig_expire_timer,smartconfig_start_timer_func,(atbm_void*)priv); //atbm_InitTimer(&priv->connect_expire_timer,atbmwifi_sta_join_timeout,(atbm_void*)priv); //atbm_InitTimer(&priv->chswitch_timer,atbmwifi_sw_chntimeout,(atbm_void *)priv); /*Intial scan/join work queue*/ priv->scan.scan_work = atbm_init_work(hw_priv, atbm_scan_work,priv); priv->join_work = atbm_init_work(hw_priv, atbm_join_work,priv); /*Intial the channel type is CH_OFF_20M*/ priv->bss.channel_type = CH_OFF_20; atbmwifi_start_station(priv); return; } #if CONFIG_P2P int atbm_enable_listening(struct atbmwifi_vif *priv, atbm_uint16 chanNum){ struct atbmwifi_common *hw_priv = _atbmwifi_vifpriv_to_hwpriv(priv); struct wsm_start start = { #ifdef P2P_MULTIVIF .mode = WSM_START_MODE_P2P_DEV | (priv->if_id ? (1 << 4) : 0), #else .mode = WSM_START_MODE_P2P_DEV | (priv->if_id << 4), #endif .band = WSM_PHY_BAND_2_4G, //0:2.4G,1:5G .channelNumber = chanNum, // channel number .beaconInterval = 100, .DTIMPeriod = 1, .probeDelay = 0, .basicRateSet = 0x0F, }; if(priv->if_id == 0) start.channel_type = (atbm_uint32)(hw_priv->channel_type); else start.channel_type = ATBM_NL80211_CHAN_HT20; return wsm_start(hw_priv,&start,0); } int atbm_disable_listening(struct atbmwifi_vif *priv){ struct atbmwifi_common *hw_priv = _atbmwifi_vifpriv_to_hwpriv(priv); int ret; struct wsm_reset reset = { .reset_statistics = ATBM_TRUE, }; priv->join_status = ATBMWIFI__JOIN_STATUS_PASSIVE; ret = wsm_reset(hw_priv, &reset, priv->if_id); if(priv->p2pdata){ } return ret; } #endif